diff --git a/setup-build-freetype.py b/setup-build-freetype.py index 9d2ee8c..82ace82 100644 --- a/setup-build-freetype.py +++ b/setup-build-freetype.py @@ -8,8 +8,6 @@ # GCC, Visual Studio Community 2017, ...) import distutils.dir_util -import distutils.file_util -import distutils.spawn import glob import hashlib import os @@ -21,19 +19,33 @@ import urllib.request from os import path import platform +import fileinput # Needed for the GitHub Actions macOS CI runner, which appears to come without CAs. import certifi -FREETYPE_HOST = "https://mirrors.sarata.com/non-gnu/freetype/" -FREETYPE_TARBALL = "freetype-2.13.2.tar.xz" +FREETYPE_HOST = "https://download.savannah.gnu.org/releases/freetype/" +FREETYPE_TARBALL = "freetype-2.13.3.tar.xz" FREETYPE_URL = FREETYPE_HOST + FREETYPE_TARBALL -FREETYPE_SHA256 = "12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d" +FREETYPE_SHA256 = "0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289" HARFBUZZ_HOST = "https://github.com/harfbuzz/harfbuzz/releases/download/8.3.0/" HARFBUZZ_TARBALL = "harfbuzz-8.3.0.tar.xz" HARFBUZZ_URL = HARFBUZZ_HOST + HARFBUZZ_TARBALL HARFBUZZ_SHA256 = "109501eaeb8bde3eadb25fab4164e993fbace29c3d775bcaa1c1e58e2f15f847" +ZLIB_HOST = "https://zlib.net/" +ZLIB_TARBALL = "zlib-1.3.1.tar.xz" +ZLIB_URL = ZLIB_HOST + ZLIB_TARBALL +ZLIB_SH256 = "38ef96b8dfe510d42707d9c781877914792541133e1870841463bfa73f883e32" + +LIBPNG_HOST = "https://download.sourceforge.net/libpng/" +LIBPNG_TARBALL = "libpng-1.6.48.tar.xz" +LIBPNG_URL = LIBPNG_HOST + LIBPNG_TARBALL +LIBPNG_SH256 = "46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03" + +BUILD_ZLIB = os.environ.get("FREETYPEPY_WITH_ZLIB", "") +BUILD_LIBPNG = os.environ.get("FREETYPEPY_WITH_LIBPNG", "") + root_dir = "." build_dir = path.join(root_dir, "build") # CMake requires an absolute path to a prefix. @@ -41,17 +53,20 @@ lib_dir = path.join(prefix_dir, "lib") build_dir_ft = path.join(build_dir, FREETYPE_TARBALL.split(".tar")[0], "build") build_dir_hb = path.join(build_dir, HARFBUZZ_TARBALL.split(".tar")[0], "build") +build_dir_zl = path.join(build_dir, ZLIB_TARBALL.split(".tar")[0], "build") +build_dir_lp = path.join(build_dir, LIBPNG_TARBALL.split(".tar")[0], "build") CMAKE_GLOBAL_SWITCHES = ( "-DCMAKE_COLOR_MAKEFILE=false " '-DCMAKE_PREFIX_PATH="{}" ' '-DCMAKE_INSTALL_PREFIX="{}" ' ).format(prefix_dir, prefix_dir) +CMAKE_PREVENT_REEXPORT = "" # Try to use Ninja to build things if it's available. Much faster. # On Windows, I first need to figure out how to make it aware of VC, bitness, # etc. -if sys.platform != "win32" and distutils.spawn.find_executable("ninja"): +if sys.platform != "win32" and shutil.which("ninja"): CMAKE_GLOBAL_SWITCHES += "-G Ninja " bitness = None @@ -67,6 +82,12 @@ print("# Making a 32 bit build.") bitness = 32 + CMAKE_PREVENT_REEXPORT += "-Wl,--exclude-libs,libharfbuzz " + if BUILD_ZLIB or BUILD_LIBPNG: + CMAKE_PREVENT_REEXPORT += "-Wl,--exclude-libs,libz " + if BUILD_LIBPNG: + CMAKE_PREVENT_REEXPORT += "-Wl,--exclude-libs,libpng " + if sys.platform == "darwin": print("# Making a 64 bit build.") CMAKE_GLOBAL_SWITCHES += ( @@ -77,6 +98,14 @@ ) bitness = 64 + # the library path is needed for the '-hidden-lx' option to work + CMAKE_PREVENT_REEXPORT += "-Wl,-L{} ".format(lib_dir) + CMAKE_PREVENT_REEXPORT += "-Wl,-hidden-lharfbuzz " + if BUILD_ZLIB or BUILD_LIBPNG: + CMAKE_PREVENT_REEXPORT += "-Wl,-hidden-lz " + if BUILD_LIBPNG: + CMAKE_PREVENT_REEXPORT += "-Wl,-hidden-lpng " + if "linux" in sys.platform: c_flags = cxx_flags = "-O2" ld_flags = "" @@ -110,6 +139,12 @@ '-DCMAKE_LD_FLAGS="{}" '.format(ld_flags) ) + CMAKE_PREVENT_REEXPORT += "-Wl,--exclude-libs,libharfbuzz " + if BUILD_ZLIB or BUILD_LIBPNG: + CMAKE_PREVENT_REEXPORT += "-Wl,--exclude-libs,libz " + if BUILD_LIBPNG: + CMAKE_PREVENT_REEXPORT += "-Wl,--exclude-libs,libpng " + def shell(cmd, cwd=None): """Run a shell command specified by cmd string.""" @@ -154,18 +189,26 @@ def ensure_downloaded(url, sha256_sum): distutils.dir_util.mkpath(prefix_dir) distutils.dir_util.mkpath(build_dir_ft) distutils.dir_util.mkpath(build_dir_hb) +if BUILD_ZLIB or BUILD_LIBPNG: + distutils.dir_util.mkpath(build_dir_zl) +if BUILD_LIBPNG: + distutils.dir_util.mkpath(build_dir_lp) ensure_downloaded(FREETYPE_URL, FREETYPE_SHA256) ensure_downloaded(HARFBUZZ_URL, HARFBUZZ_SHA256) +if BUILD_ZLIB or BUILD_LIBPNG: + ensure_downloaded(ZLIB_URL, ZLIB_SH256) +if BUILD_LIBPNG: + ensure_downloaded(LIBPNG_URL, LIBPNG_SH256) -print("# First, build FreeType without Harfbuzz support") +print("# First, build FreeType without additional libraries") shell( "cmake -DBUILD_SHARED_LIBS=OFF " - "-DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE -DFT_WITH_HARFBUZZ=OFF " - "-DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE " - "-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE " - "-DCMAKE_DISABLE_FIND_PACKAGE_ZLIB=TRUE " - "-DCMAKE_DISABLE_FIND_PACKAGE_BrotliDec=TRUE " + "-DFT_DISABLE_HARFBUZZ=TRUE " + "-DFT_DISABLE_PNG=TRUE " + "-DFT_DISABLE_BZIP2=TRUE " + "-DFT_DISABLE_ZLIB=TRUE " + "-DFT_DISABLE_BROTLI=TRUE " "{} ..".format(CMAKE_GLOBAL_SWITCHES), cwd=build_dir_ft, ) @@ -182,19 +225,58 @@ def ensure_downloaded(url, sha256_sum): ) shell("cmake --build . --config Release --target install --parallel", cwd=build_dir_hb) -print("\n# Lastly, rebuild FreeType, this time with Harfbuzz support.") +if BUILD_ZLIB or BUILD_LIBPNG: + print("\n# Next, build zlib.") + # workaround to only build the static library of zlib + # see https://github.com/madler/zlib/issues/359 + with fileinput.input(path.join(path.dirname(build_dir_zl), "CMakeLists.txt"), inplace=True) as f: + for line in f: + if "install(TARGETS zlib zlibstatic" in line: + line = line.replace(" install(TARGETS zlib zlibstatic", " install(TARGETS zlibstatic") + print(line, end='') + + shell( + "cmake " + + # https://stackoverflow.com/questions/3961446 + ("-DCMAKE_POSITION_INDEPENDENT_CODE=ON " if bitness > 32 else "") + + "{} ..".format(CMAKE_GLOBAL_SWITCHES), + cwd=build_dir_zl, + ) + shell("cmake --build . --config Release --target install --parallel", cwd=build_dir_zl) + +if BUILD_LIBPNG: + print("\n# Next, build libpng.") + shell( + "cmake -DPNG_SHARED=OFF " + + # https://stackoverflow.com/questions/3961446 + ("-DCMAKE_POSITION_INDEPENDENT_CODE=ON " if bitness > 32 else "") + + "{} ..".format(CMAKE_GLOBAL_SWITCHES), + cwd=build_dir_lp, + ) + shell("cmake --build . --config Release --target install --parallel", cwd=build_dir_lp) + +print("\n# Lastly, rebuild FreeType, this time with additional libraries support.") +# clean cmake build dir for a clean build +distutils.dir_util.remove_tree(build_dir_ft) +distutils.dir_util.mkpath(build_dir_ft) harfbuzz_includes = path.join(prefix_dir, "include", "harfbuzz") +libpng_includes = path.join(prefix_dir, "include", "libpng16") +zlib_includes = path.join(prefix_dir, "include") shell( "cmake -DBUILD_SHARED_LIBS=ON " - "-DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=FALSE -DFT_WITH_HARFBUZZ=ON " - "-DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE " - "-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE " - "-DCMAKE_DISABLE_FIND_PACKAGE_ZLIB=TRUE " - "-DCMAKE_DISABLE_FIND_PACKAGE_BrotliDec=TRUE " + "-DFT_REQUIRE_HARFBUZZ=TRUE " + + ("-DFT_REQUIRE_PNG=TRUE " if BUILD_LIBPNG else "-DFT_DISABLE_PNG=TRUE ") + + "-DFT_DISABLE_BZIP2=TRUE " + + ("-DFT_REQUIRE_ZLIB=TRUE " if BUILD_ZLIB or BUILD_LIBPNG else "-DFT_DISABLE_ZLIB=TRUE ") + + "-DFT_DISABLE_BROTLI=TRUE " '-DPKG_CONFIG_EXECUTABLE="" ' # Prevent finding system libraries - '-DHARFBUZZ_INCLUDE_DIRS="{}" ' + '-DHarfBuzz_INCLUDE_DIRS="{}" ' + '-DPNG_INCLUDE_DIRS="{}" ' + '-DZLIB_INCLUDE_DIRS="{}" ' + # prevent re-export of symbols from harfbuzz, libpng and zlib + '-DCMAKE_SHARED_LINKER_FLAGS="{}" ' "-DSKIP_INSTALL_HEADERS=ON " - "{} ..".format(harfbuzz_includes, CMAKE_GLOBAL_SWITCHES), + "{} ..".format(harfbuzz_includes, libpng_includes, zlib_includes, CMAKE_PREVENT_REEXPORT, CMAKE_GLOBAL_SWITCHES), cwd=build_dir_ft, ) shell("cmake --build . --config Release --target install --parallel", cwd=build_dir_ft)