Description: Debian-specific makefile.
Forwarded: not-needed
Author: Filip Strömbäck <filip@fprg.se>
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,171 @@
+CXX := c++
+# Build directory.
+BUILD := debbuild
+
+# Defines to set:
+
+# No debug mode, and tell the build that we're the implementation.
+DEFINE := NDEBUG SKIA_IMPLEMENTATION=1
+# We need to tell Skia that we will make a shared library.
+DEFINE := $(DEFINE) SKIA_DLL
+# Enable SKSL
+DEFINE := $(DEFINE) SK_ENABLE_SKSL
+# Gamma.
+DEFINE := $(DEFINE) SK_GAMMA_APPLY_TO_A8
+# Enable codecs.
+DEFINE := $(DEFINE) SK_CODEC_DECODES_JPEG=1 SK_CODEC_DECODES_WEBP=1 SK_CODEC_DECODES_PNG=1
+DEFINE := $(DEFINE) SK_CODEC_ENCODE_JPEG=1 SK_CODEC_ENCODE_WEBP=1 SK_CODEC_ENCODE_PNG=1
+# Tell SKCMS it cannot tail-call on GCC (it fails).
+DEFINE := $(DEFINE) SKCMS_HAS_MUSTTAIL=0 SKCMS_PORTABLE
+
+# Note: We don't compile the PDF renderer, as that requires version 3.0.0 of libharfbuzz.
+
+# Performance flags. Note: We skip no-rtti, since that could cause problems when linking with other code.
+# Note: Other Debian packages go with -O2, so we do -O2 in over -O3
+CXXPERF := -O2 -fvisibility=hidden -fstrict-aliasing -fdata-sections -ffunction-sections -fvisibility-inlines-hidden -fno-exceptions # -fno-rtti
+
+# Make dependencies.
+DEPFLAGS := -g -MMD -MP
+
+# Combine all flags.
+CXXFLAGS := $(CXXFLAGS) -std=c++17 -I. -isystem /usr/include/freetype2 -Imodules/skcms -Ithird_party/vulkanmemoryallocator -fPIC $(CXXPERF) $(addprefix -D,$(DEFINE))
+
+# Linker flags.
+LDFLAGS := $(LDFLAGS) -Wl,--gc-sections
+
+# Libraries to link.
+SHLIBS := dl pthread fontconfig freetype jpeg png z webp webpdemux webpmux vulkan GL EGL expat
+
+# Files to ignore, for various reasons:
+IGNORE :=
+
+# Don't include the _none files that are noop backends for various things.
+IGNORE := $(IGNORE) %_none.cpp %_None.cpp
+# Don't compile android things:
+IGNORE := $(IGNORE) src/android/% src/gpu/android/% src/gpu/ganesh/gl/android/%
+# Don't compile for other platforms:
+IGNORE := $(IGNORE) src/gpu/mtl/% src/gpu/ganesh/iOS/% src/gpu/ganesh/mac/% src/gpu/ganesh/win/% src/gpu/ganesh/webgl/% src/gpu/ganesh/d3d/%
+# No HLSL support, we don't need codegen for it on Linux.
+IGNORE := $(IGNORE) src/sksl/codegen/SkSLSPIRVtoHLSL.cpp
+# WebGL support is limited, we don't have the tint library currently.
+IGNORE := $(IGNORE) src/sksl/codegen/SkSLWGSLValidator.cpp
+# Ignore utilities for non-linux:
+IGNORE := $(IGNORE) src/utils/SkGetExecutablePath_mac.cpp src/utils/SkGetExecutablePath_win.cpp
+IGNORE := $(IGNORE) src/gpu/ganesh/gl/win/% src/gpu/ganesh/gl/epoxy/% src/gpu/ganesh/gl/iOS/% src/gpu/ganesh/gl/mac/% src/gpu/ganesh/gl/webgl/%
+# Maake EGL the "native" interface by disabling the GLX version of it.
+IGNORE := $(IGNORE) src/gpu/ganesh/gl/glx/%
+# Ignore the Dawn backend
+IGNORE := $(IGNORE) src/gpu/graphite/dawn/%
+# We don't support Vello compute at the moment (SK_ENABLE_VELLO_SHADERS need to be defined for that). We could
+# potentially compile it, but it requires Rust compilation as well.
+IGNORE := $(IGNORE) src/gpu/graphite/compute/Vello%
+# Don't compile the data file version of the SkSL::GetModuleData.
+IGNORE := $(IGNORE) src/sksl/SkSLModuleDataFile.cpp
+# Don't include the SKSL lexer program.
+IGNORE := $(IGNORE) src/sksl/lex/Main.cpp
+# Don't compile these codecs, they don't have suitable libraries in Debian.
+IGNORE := $(IGNORE) %/codec/SkRawCodec.cpp %/codec/SkJpegxlCodec.cpp %/codec/SkWuffsCodec.cpp %/codec/SkAvifCodec.cpp %/codec/SkCrabbyAvifCodec.cpp
+# Rust alternative implementations. Currently not relevant.
+IGNORE := $(IGNORE) %/codec/SkCodecColorProfileRust.cpp %/codec/SkPngRustDecoder.cpp %/codec/SkPngRustCodec.cpp %/encode/SkPngRustEncoder.cpp \
+	%/encode/SkPngRustEncoderImpl.cpp
+# Headers to be removed because we have disabled the underlying functionality:
+REMOVE_HEADERS := \
+	include/codec/SkRawDecoder.h \
+	include/codec/SkJpegxlDecoder.h \
+	include/codec/SkAvifDecocer.h
+
+# What files inside ports/ do we need?
+PORTS_FILES := SkDebug_stdio.cpp \
+	SkDiscardableMemory_none.cpp \
+	SkFontConfigInterface.cpp \
+	SkFontConfigInterface_direct.cpp \
+	SkFontConfigInterface_direct_factory.cpp \
+	SkFontHost_FreeType_common.cpp \
+	SkFontHost_FreeType.cpp \
+	SkFontMgr_fontconfig.cpp \
+	SkTypeface_proxy.cpp \
+	SkGlobalInitialization_default.cpp \
+	SkImageGenerator_skia.cpp \
+	SkMemory_malloc.cpp \
+	SkOSFile_posix.cpp \
+	SkOSFile_stdio.cpp
+
+# Extra headers?
+EXTRA_HEADERS := \
+	src/shaders/SkShaderBase.h \
+	src/core/SkReadBuffer.h \
+	src/core/SkWriteBuffer.h \
+	src/core/SkFontDescriptor.h \
+	src/ports/SkFontHost_FreeType_common.h \
+	src/ports/SkTypeface_FreeType.h
+
+# From here and onwards, we compute various things, these are generally not configurable.
+
+# Skia version, for proper .so names.
+FULL_VERSION := $(shell head -n 1 debian/changelog | sed -E 's/^.*\(([0-9.]+)\+[a-z]+-.*\).*$$/\1/')
+MAJOR_VERSION := $(shell head -n 1 debian/changelog | sed -E 's/^.*\(([0-9]+)[.0-9]+\+dfsg-.*\).*$$/\1/')
+
+# Find source files to compile.
+SOURCES := $(shell find src/ -name "*.cpp")
+# We need to handle "ports" separately...
+SOURCES := $(filter-out src/ports/%,$(SOURCES))
+SOURCES := $(filter-out $(IGNORE),$(SOURCES))
+
+SOURCES := $(SOURCES) $(addprefix src/ports/,$(PORTS_FILES))
+SRC_OBJECTS := $(patsubst src/%.cpp,$(BUILD)/%.o,$(SOURCES))
+
+SKCMS := modules/skcms/skcms.cc $(wildcard modules/skcms/src/*.cc)
+SKCMS_OBJECTS := $(patsubst modules/skcms/%.cc,$(BUILD)/skcms/%.o,$(SKCMS))
+
+OBJECTS := $(SRC_OBJECTS) $(SKCMS_OBJECTS)
+DEPS := $(patsubst %.o,%.d,$(OBJECTS))
+
+.PHONY: all
+all: $(BUILD)/libskia.so $(BUILD)/libskia.a
+
+.PHONY: print
+print:
+	@echo "Flags: $(CXXFLAGS)"
+	@echo "Version: $(FULL_VERSION)"
+	@echo "Major version: $(MAJOR_VERSION)"
+	@echo $(SKCMS_OBJECTS)
+
+$(BUILD)/libskia.so: $(OBJECTS)
+	@echo "Linking .so..."
+	$(CXX) -shared $(LDFLAGS) -Wl,--gc-sections -Wl,-z,defs -Wl,-soname,libskia.so.$(MAJOR_VERSION) -o $@ $(OBJECTS) $(addprefix -l,$(SHLIBS))
+
+$(BUILD)/libskia.a: $(OBJECTS)
+	@rm -f $@
+	@echo "Linking .a..."
+	ar rcs $@ $(OBJECTS)
+
+$(SRC_OBJECTS): $(BUILD)/%.o: src/%.cpp extra_headers.stamp
+	@mkdir -p $(dir $@)
+	$(CXX) -c $(CXXFLAGS) -o $@ $(DEPFLAGS) $<
+
+$(SKCMS_OBJECTS): $(BUILD)/skcms/%.o: modules/skcms/%.cc
+	@mkdir -p $(dir $@)
+	$(CXX) -c $(CXXFLAGS) -o $@ $(DEPFLAGS) $<
+
+# Patch headers once, if necessary.
+extra_headers.stamp: $(EXTRA_HEADERS)
+	python3 bin/extra-headers.py --out extra_headers.stamp $^
+
+$(BUILD):
+	mkdir -p $(BUILD)
+
+.PHONY: clean
+clean:
+	rm -rf $(BUILD)
+	if [ -f extra_headers.stamp ]; then bash extra_headers.stamp; rm extra_headers.stamp; fi
+
+.PHONY: install
+install:
+	install -D -m 0755 $(BUILD)/libskia.so $(DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/libskia.so.$(FULL_VERSION)
+	ln -s libskia.so.$(FULL_VERSION) $(DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/libskia.so.$(MAJOR_VERSION)
+	ln -s libskia.so.$(MAJOR_VERSION) $(DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/libskia.so
+	install -D -m 0644 $(BUILD)/libskia.a $(DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/libskia.a
+	python3 bin/install-headers.py --src include/ --dest $(DESTDIR)/usr/include/skia --ignore '.*/android/.*' $(addprefix --ignore ,$(REMOVE_HEADERS))
+	cp modules/skcms/src/skcms_public.h $(DESTDIR)/usr/include/skia/skcms.h
+
+-include $(DEPS)
--- /dev/null
+++ b/bin/install-headers.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+
+import argparse
+import os, os.path
+import re
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--src", help="Source directory for includes", required=True)
+parser.add_argument("--dest", help="Destination path for includes", required=True)
+parser.add_argument("--ignore", help="Ignore files matching regex", action="append")
+args = parser.parse_args()
+
+filemode = 0o644
+
+def update_file(filename):
+    global args, filemode
+
+    if not filename.endswith(".h"):
+        return
+
+    if args.ignore:
+        for i in args.ignore:
+            if re.fullmatch(i, filename):
+                return
+
+    skia_include = re.compile(r'^([ \t]*)# *include *"include/([^"]*)"[ \t]*(//.*)?\n?$')
+    skcms_include = re.compile('^([ \t]*)# *include *"modules/skcms/skcms.h"[ \t]*(//.*)?\n?$')
+
+    dstfile = os.path.join(args.dest, filename[len(args.src):])
+    os.makedirs(os.path.dirname(dstfile), exist_ok=True)
+
+    with open(filename, "r") as src:
+        with open(dstfile, "w") as dst:
+            for line in src:
+                if match := skia_include.fullmatch(line):
+                    dst.write("{}#include <skia/{}>\n".format(match[1], match[2]))
+                elif match := skcms_include.fullmatch(line):
+                    dst.write("{}#include <skia/skcms.h>\n".format(match[1]))
+                else:
+                    dst.write(line)
+
+
+    os.chmod(dstfile, filemode)
+
+for dirname, dirs, files in os.walk(args.src):
+    for f in files:
+        update_file(os.path.join(dirname, f))
--- /dev/null
+++ b/bin/extra-headers.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+
+import argparse
+import os, os.path
+import re
+import shutil
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--out", help="Output file containing actions done", required=True)
+parser.add_argument("files", help="Files to include", nargs='*')
+args = parser.parse_args()
+
+actions = []
+
+def src_to_priv(path):
+    if len(path) <= 4 or path[0:4] != "src/":
+        return None
+
+    return "include/private/" + path[4:]
+
+def make_dirs(path):
+    global actions
+    if os.path.exists(path):
+        return
+    make_dirs(os.path.dirname(path))
+    actions.append("rmdir " + path)
+    os.mkdir(path)
+
+def update_file(files, visited):
+    f = files[0]
+
+    include = re.compile(r'^([ \t]*)# *include *"([^"]*)"[ \t]*\n?$')
+    cls = re.compile(r'^([ \t]*class|[ \t]*struct) *([A-Za-z_:]+ .*\n?)$')
+
+    first_define = re.compile(r'^#define.*DEFINED *\n?$')
+    api_include_inserted = False
+
+    shutil.copyfile(f, f + ".orig")
+    actions.append("mv {}.orig {}".format(f, f))
+    with open(f, "r") as src:
+        create_file = src_to_priv(f)
+        make_dirs(os.path.dirname(create_file))
+        actions.append("rm " + create_file)
+        with open(create_file, "w") as dst:
+            for line in src:
+                match = cls.fullmatch(line)
+                if match:
+                    line = "{} SK_API {}".format(match[1], match[2])
+
+                match = include.fullmatch(line)
+                if match is None:
+                    dst.write(line)
+                else:
+                    replace = src_to_priv(match[2])
+                    if replace:
+                        if match[2] not in visited:
+                            visited.add(match[2])
+                            files.append(match[2])
+
+                        dst.write("{}#include \"{}\"\n".format(match[1], replace))
+                    else:
+                        dst.write(line)
+
+                match = first_define.fullmatch(line)
+                if not api_include_inserted and match:
+                    dst.write('#include "include/private/base/SkAPI.h"\n')
+                    api_include_inserted = True
+
+    with open(f, "w") as src:
+        src.write("#include \"{}\"\n".format(src_to_priv(f)))
+
+
+files = list(args.files)
+visited = set(files)
+
+while len(files) > 0:
+    update_file(files, visited)
+
+    files = files[1:]
+
+with open(args.out, "w") as f:
+    for x in reversed(actions):
+        f.write(x + "\n")
