From 6058ede3ae983c53d1d6f5352d4235bafce3499a Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Mon, 1 Jun 2020 12:58:31 +0430 Subject: [PATCH] Build win32 artifacts using meson As a part of meson migration, this builds hb-shape dependencies using meson subprojects and removes different unrelated mingw files we've put on source root about things that aren't really our concern. This also simplifies all the instructions we've put in README.mingw.md and makes it easy to build the project on distros that no mingw libraries (such i686-win32-{freetype,glib,...} are packaged. The known catch is however lack of hb-view as its need for build of cairo which apparently isn't that straightforward. --- .ci/build-win32.sh | 15 +++++++++ .ci/win32-cross-file.txt | 20 ++++++++++++ .ci/win64-cross-file.txt | 20 ++++++++++++ .circleci/config.yml | 28 ++++++++--------- Makefile.am | 19 ------------ README.mingw.md | 29 ++++-------------- RELEASING.md | 6 +--- meson-mingw-cross.txt | 17 ----------- meson.build | 3 ++ mingw-configure.sh | 28 ----------------- mingw-ldd.py | 56 ---------------------------------- mingw-meson.sh | 33 -------------------- mingw32.sh | 2 -- mingw64.sh | 2 -- subprojects/fontconfig.wrap | 1 + subprojects/freetype2.wrap | 1 + subprojects/glib.wrap | 1 + subprojects/libffi.wrap | 3 +- subprojects/proxy-libintl.wrap | 1 + subprojects/zlib.wrap | 1 + 20 files changed, 84 insertions(+), 202 deletions(-) create mode 100755 .ci/build-win32.sh create mode 100644 .ci/win32-cross-file.txt create mode 100644 .ci/win64-cross-file.txt delete mode 100644 meson-mingw-cross.txt delete mode 100755 mingw-configure.sh delete mode 100755 mingw-ldd.py delete mode 100644 mingw-meson.sh delete mode 100755 mingw32.sh delete mode 100755 mingw64.sh diff --git a/.ci/build-win32.sh b/.ci/build-win32.sh new file mode 100755 index 000000000..019efff6a --- /dev/null +++ b/.ci/build-win32.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -e + +meson --cross-file=.ci/win32-cross-file.txt win32build --wrap-mode=forcefallback -Dtests=disabled \ + -Dglib=enabled -Dfreetype=enabled -Dgdi=enabled $@ +ninja -Cwin32build -j8 # building with all the cores won't work fine with CricleCI for some reason + +rm -rf win32build/harfbuzz-win32 +mkdir win32build/harfbuzz-win32 +cp win32build/util/hb-*.exe win32build/harfbuzz-win32 +find win32build -name '*.dll' -exec cp {} win32build/harfbuzz-win32 \; +i686-w64-mingw32-strip win32build/harfbuzz-win32/*.{dll,exe} +rm -f harfbuzz-win32.zip +(cd win32build/harfbuzz-win32 && zip ../../harfbuzz-win32.zip -r .) +echo "harfbuzz-win32.zip is ready." diff --git a/.ci/win32-cross-file.txt b/.ci/win32-cross-file.txt new file mode 100644 index 000000000..982a909b7 --- /dev/null +++ b/.ci/win32-cross-file.txt @@ -0,0 +1,20 @@ +[host_machine] +system = 'windows' +cpu_family = 'x86' +cpu = 'i686' +endian = 'little' + +[properties] +c_args = [] +c_link_args = ['-static-libgcc', '-Wl,-Bstatic', '-lpthread'] +cpp_args = [] +cpp_link_args = ['-static-libgcc', '-static-libstdc++', '-Wl,-Bstatic', '-lpthread'] + +[binaries] +c = 'i686-w64-mingw32-gcc' +cpp = 'i686-w64-mingw32-g++' +ar = 'i686-w64-mingw32-ar' +ld = 'i686-w64-mingw32-ld' +objcopy = 'i686-w64-mingw32-objcopy' +strip = 'i686-w64-mingw32-strip' +windres = 'i686-w64-mingw32-windres' diff --git a/.ci/win64-cross-file.txt b/.ci/win64-cross-file.txt new file mode 100644 index 000000000..e906e085e --- /dev/null +++ b/.ci/win64-cross-file.txt @@ -0,0 +1,20 @@ +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[properties] +c_args = [] +c_link_args = ['-static-libgcc', '-Wl,-Bstatic', '-lpthread'] +cpp_args = [] +cpp_link_args = ['-static-libgcc', '-static-libstdc++', '-Wl,-Bstatic', '-lpthread'] + +[binaries] +c = 'x86_64-w64-mingw32-gcc' +cpp = 'x86_64-w64-mingw32-g++' +ar = 'x86_64-w64-mingw32-ar' +ld = 'x86_64-w64-mingw32-ld' +objcopy = 'x86_64-w64-mingw32-objcopy' +strip = 'x86_64-w64-mingw32-strip' +windres = 'x86_64-w64-mingw32-windres' diff --git a/.circleci/config.yml b/.circleci/config.yml index dd7bd2752..d65140b8f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -204,31 +204,23 @@ jobs: - run: make -j32 - run: UBSAN_OPTIONS=print_stacktrace=1 make check || .ci/fail.sh | asan_symbolize | c++filt - fedora-O0-debug-outoftreebuild-mingw: + fedora-O0-debug-outoftreebuild: docker: - image: fedora steps: - checkout - - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which diffutils glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python python-pip mingw32-gcc-c++ mingw64-gcc-c++ mingw32-glib2 mingw32-cairo mingw32-freetype mingw64-glib2 mingw64-cairo mingw64-freetype glibc-devel.i686 || true + - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which diffutils glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python python-pip || true - run: NOCONFIGURE=1 ./autogen.sh - run: mkdir build && cd build && CFLAGS="-O0" CXXFLAGS="-O0" CPPFLAGS="-DHB_DEBUG" ../configure --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 && make -j32 && (HB_TEST_SUBSET_FUZZER_TIMEOUT=15 make check || ../.ci/fail.sh) - - run: pip install pefile - - run: mkdir winbuild32 && cd winbuild32 && ../mingw32.sh && make -j32 && make dist-win && cp harfbuzz-*-win32.zip harfbuzz-win32.zip - - run: mkdir winbuild64 && cd winbuild64 && ../mingw64.sh && make -j32 && make dist-win && cp harfbuzz-*-win64.zip harfbuzz-win64.zip - - store_artifacts: - path: winbuild32/harfbuzz-win32.zip - destination: harfbuzz-win32.zip - - store_artifacts: - path: winbuild64/harfbuzz-win64.zip - destination: harfbuzz-win64.zip - meson-gcc: + meson-gcc-mingw: docker: - image: ubuntu:19.10 steps: - checkout - - run: apt update && apt install -y ninja-build binutils meson gcc g++ pkg-config ragel gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-pip - - run: pip3 install fonttools meson --upgrade + - run: apt update && apt install -y ninja-build binutils meson gcc g++ pkg-config ragel gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-pip git g++-mingw-w64-i686 zip + - run: pip3 install fonttools --upgrade + - run: pip3 install git+https://github.com/mesonbuild/meson # use C linker, remove when meson 0.55 is released - run: meson build && ninja -Cbuild test && rm -rf build # test amalgam build - run: meson build -Damalgam=true && ninja -Cbuild && rm -rf build @@ -236,6 +228,10 @@ jobs: - run: meson build --unity on && ninja -Cbuild && rm -rf build # test experimental APIs - run: meson build -Dexperimental_api=true && ninja -Cbuild test && rm -rf build + # mingw + - run: .ci/build-win32.sh + - store_artifacts: + path: harfbuzz-win32.zip crosscompile-notest-djgpp: docker: @@ -279,9 +275,9 @@ workflows: - clang-msan - clang-tsan - clang-ubsan - - fedora-O0-debug-outoftreebuild-mingw + - fedora-O0-debug-outoftreebuild - - meson-gcc + - meson-gcc-mingw # crosscompiles # they can't be test thus are without tests diff --git a/Makefile.am b/Makefile.am index 79c271591..4a2a8c8eb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,6 @@ EXTRA_DIST = \ autogen.sh \ harfbuzz.doap \ README.md \ - README.mingw.md \ README.python.md \ BUILD.md \ CONFIG.md \ @@ -29,10 +28,6 @@ EXTRA_DIST = \ subprojects/zlib.wrap \ meson-cc-tests/intel-atomic-primitives-test.c \ meson-cc-tests/solaris-atomic-operations.c \ - mingw-configure.sh \ - mingw-ldd.py \ - mingw32.sh \ - mingw64.sh \ $(NULL) MAINTAINERCLEANFILES = \ @@ -97,18 +92,4 @@ $(gpg_file): $(sha256_file) release-files: $(tar_file) $(sha256_file) $(gpg_file) -dist-win: - @case $(host_triplet) in *-w64-mingw32) ;; *) echo "Error: Requires mingw build. See README.mingw.md.">&2; exit 1 ;; esac - @DIR=$(PACKAGE_TARNAME)-$(VERSION)-win`case $(host_triplet) in i686-*) echo 32 ;; x86_64-*) echo 64 ;; esac`; \ - $(RM) -r $$DIR; $(MKDIR_P) $$DIR || exit 1; \ - cp util/.libs/hb-{shape,view,subset}.exe $$DIR && \ - $(top_srcdir)/mingw-ldd.py $$DIR/hb-view.exe | grep -v 'not found' | cut -d '>' -f 2 | xargs cp -t $$DIR && \ - cp src/.libs/libharfbuzz{,-subset}-0.dll $$DIR && \ - chmod a+x $$DIR/*.{exe,dll} && \ - $(STRIP) $$DIR/*.{exe,dll} && \ - zip -r $$DIR.zip $$DIR && \ - $(RM) -r $$DIR && \ - echo "$$DIR.zip is ready." - - -include $(top_srcdir)/git.mk diff --git a/README.mingw.md b/README.mingw.md index 76d1a8754..b9943d7ae 100644 --- a/README.mingw.md +++ b/README.mingw.md @@ -9,23 +9,14 @@ steps are recommended: 2. And `mingw-w64` compiler. With `brew` on macOS, you can have it like `brew install mingw-w64`. On Fedora, with `dnf install mingw32-gcc-c++`, or `dnf install mingw64-gcc-c++` for the - 64-bit Windows. + 64-bit Windows. Use `apt install g++-mingw-w64` on Debian. -3. Install cross-compiled dependency packages. Alternatively see [^1] below. - On Fedora that would be `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype` - for 32-bit, or `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype` for 64-bit. +3. See how `.ci/build-win32.sh` uses meson or run that script anyway. -5. `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild` +Now you can use hb-shape by `(cd win32build/harfbuzz-win32 && wine hb-shape.exe)` +but if you like to shape with the Microsoft Uniscribe, -6. Run `../mingw32.sh` for 32-bit build, or `../mingw64.sh` for 64-bit. This configures - HarfBuzz for cross-compiling. It enables Uniscribe backend as well. - -7. `make` - -Now you can use hb-shape using `wine util/hb-shape.exe` but if you like to shape with -the Microsoft Uniscribe, - -8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your +4. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your Windows installation (assuming you have a 64-bit installation, otherwise `C:\Windows\System32\usp10.dll`) that it is not a DirectWrite proxy ([for more info](https://en.wikipedia.org/wiki/Uniscribe)). @@ -35,14 +26,6 @@ the Microsoft Uniscribe, Put the DLL in the folder you are going to run the next command, -9. `WINEDLLOVERRIDES="usp10=n" wine util/hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe` +5. `WINEDLLOVERRIDES="usp10=n" wine hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe` (`0061,0062,0063` means `abc`, use test/shaping/hb-unicode-decode to generate ones you need) - - -[^1] Download and put [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ) - in your `~/.local/i686-w64-mingw32`. Then replace all the instances of - `/home/behdad/.local/i586-mingw32msvc` and `/home/behdad/.local/i686-w64-mingw32` - with `<$HOME>/.local/i686-w64-mingw32` on that folder. - (`<$HOME>` replace it with `/home/XXX` or `/Users/XXX` on macOS) - You shouldn't replace the instances of those inside binary files. diff --git a/RELEASING.md b/RELEASING.md index c15126a5f..a26350b36 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -44,11 +44,7 @@ HarfBuzz release walk-through checklist: 9. Tag the release and sign it: Eg. "git tag -s 1.4.7 -m 1.4.7". Enter your GPG password again. -10. Build win32 bundle. - - a. Build Win32 binaries. See [README.mingw.md](README.mingw.md). - - b. Run "make dist-win" to build Win32 bundle. +10. Build win32 bundle. See [README.mingw.md](README.mingw.md). 11. Quickly double-check the size of the .tar.xz and .zip files against their previous releases to make sure nothing bad happened. diff --git a/meson-mingw-cross.txt b/meson-mingw-cross.txt deleted file mode 100644 index 00de34474..000000000 --- a/meson-mingw-cross.txt +++ /dev/null @@ -1,17 +0,0 @@ -[binaries] -c = '@host@-gcc' -cpp = '@host@-g++' -ar = '@host@-ar' -ranlib = '@host@-ranlib' -strip = '@host@-strip' -windres = '@host@-windres' -pkgconfig = 'pkg-config' - -[host_machine] -system = 'windows' -cpu_family = '@cpu@' -cpu = '@cpu@' -endian = 'little' - -[properties] -cpp_args = ['-D_WIN32_WINNT=0x0601', '-O2', '-pipe', '-march=@arch@'] diff --git a/meson.build b/meson.build index 26b20b6ce..15144e9e8 100644 --- a/meson.build +++ b/meson.build @@ -134,6 +134,9 @@ if cairo_dep.found() if cpp.has_header('cairo-ft.h') and \ cpp.has_function('cairo_ft_font_face_create_for_ft_face', dependencies: cairo_dep) cairo_ft_dep = cairo_dep + else + # Not-found dependency + cairo_ft_dep = dependency('', required: false) endif endif else diff --git a/mingw-configure.sh b/mingw-configure.sh deleted file mode 100755 index 3281ce382..000000000 --- a/mingw-configure.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -case $1 in - i686 | x86_64) ;; - *) echo "Usage: $0 i686|x86_64" >&2; exit 1 ;; -esac - -target=$1-w64-mingw32 -shift - -exec "$(dirname "$0")"/configure \ - --build=`../config.guess` \ - --host=$target \ - --prefix=$HOME/.local/$target \ - CC= \ - CXX= \ - CPP= \ - LD= \ - CFLAGS="-static-libgcc" \ - CXXFLAGS="-static-libgcc -static-libstdc++" \ - CPPFLAGS="-I$HOME/.local/$target/include" \ - LDFLAGS=-L$HOME/.local/$target/lib \ - PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig:/usr/$target/sys-root/mingw/lib/pkgconfig/ \ - PKG_CONFIG_PATH=$HOME/.local/$target/share/pkgconfig:/usr/$target/sys-root/mingw/share/pkgconfig/ \ - PATH=$HOME/.local/$target/bin:/usr/$target/sys-root/mingw/bin:/usr/$target/bin:$PATH \ - --without-icu \ - --with-uniscribe \ - "$@" diff --git a/mingw-ldd.py b/mingw-ldd.py deleted file mode 100755 index f5556ab4b..000000000 --- a/mingw-ldd.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 - -# Copied from https://github.com/xantares/mingw-ldd/blob/master/mingw-ldd.py -# Modified to point to right prefix location on Fedora. - -# WTFPL - Do What the Fuck You Want to Public License -import pefile -import os -import sys - - -def get_dependency(filename): - deps = [] - pe = pefile.PE(filename) - for imp in pe.DIRECTORY_ENTRY_IMPORT: - deps.append(imp.dll.decode()) - return deps - - -def dep_tree(root, prefix=None): - if not prefix: - arch = get_arch(root) - #print('Arch =', arch) - prefix = '/usr/'+arch+'-w64-mingw32/sys-root/mingw/bin' - #print('Using default prefix', prefix) - dep_dlls = dict() - - def dep_tree_impl(root, prefix): - for dll in get_dependency(root): - if dll in dep_dlls: - continue - full_path = os.path.join(prefix, dll) - if os.path.exists(full_path): - dep_dlls[dll] = full_path - dep_tree_impl(full_path, prefix=prefix) - else: - dep_dlls[dll] = 'not found' - - dep_tree_impl(root, prefix) - return (dep_dlls) - - -def get_arch(filename): - type2arch= {pefile.OPTIONAL_HEADER_MAGIC_PE: 'i686', - pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS: 'x86_64'} - pe = pefile.PE(filename) - try: - return type2arch[pe.PE_TYPE] - except KeyError: - sys.exit ('Error: unknown architecture') - -if __name__ == '__main__': - filename = sys.argv[1] - for dll, full_path in dep_tree(filename).items(): - print(' ' * 7, dll, '=>', full_path) - diff --git a/mingw-meson.sh b/mingw-meson.sh deleted file mode 100644 index 9e871a3d2..000000000 --- a/mingw-meson.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -# Usage: ./mingw-meson.sh prefix host -# host being i686 or x86_64 - -case $2 in - i686 | x86_64) ;; - *) echo "Usage: $0 prefix i686|x86_64" >&2; exit 1 ;; -esac - -cpu=$2 -host=$2-w64-mingw32 -if test "x$2" = "xx86_64" ; then - arch=x86-64 -else - arch=i686 -fi - -rm -rf builddir && mkdir builddir && cd builddir && cp ../meson-mingw-cross.txt . - -sed -i -e "s/@cpu_family@/$cpu/g;s/@cpu@/$cpu/g;s/@host@/$host/g;s/@arch@/$arch/g" meson-mingw-cross.txt - -meson .. \ - --prefix=$1 \ - --libdir=lib \ - --buildtype=release \ - --strip \ - --cross-file meson-mingw-cross.txt \ - --default-library shared \ - -Dgraphite=enabled - -ninja -ninja install diff --git a/mingw32.sh b/mingw32.sh deleted file mode 100755 index 77edffa98..000000000 --- a/mingw32.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -exec "$(dirname "$0")"/mingw-configure.sh i686 "$@" diff --git a/mingw64.sh b/mingw64.sh deleted file mode 100755 index 28724a48e..000000000 --- a/mingw64.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -exec "$(dirname "$0")"/mingw-configure.sh x86_64 "$@" diff --git a/subprojects/fontconfig.wrap b/subprojects/fontconfig.wrap index 083a49d6a..6b18b2b4c 100644 --- a/subprojects/fontconfig.wrap +++ b/subprojects/fontconfig.wrap @@ -1,5 +1,6 @@ [wrap-git] directory=fontconfig url=https://github.com/centricular/fontconfig.git +depth=1 push-url=git@github.com:centricular/fontconfig.git revision=meson diff --git a/subprojects/freetype2.wrap b/subprojects/freetype2.wrap index 3151539c8..7c88f89cb 100644 --- a/subprojects/freetype2.wrap +++ b/subprojects/freetype2.wrap @@ -1,5 +1,6 @@ [wrap-git] directory=freetype2 url=https://github.com/centricular/freetype2.git +depth=1 push-url=git@github.com:centricular/freetype2.git revision=meson diff --git a/subprojects/glib.wrap b/subprojects/glib.wrap index a23da5c2f..7a4eae175 100644 --- a/subprojects/glib.wrap +++ b/subprojects/glib.wrap @@ -1,5 +1,6 @@ [wrap-git] directory=glib url=https://gitlab.gnome.org/GNOME/glib.git +depth=1 push-url=git@gitlab.gnome.org:GNOME/glib.git revision=2.58.1 diff --git a/subprojects/libffi.wrap b/subprojects/libffi.wrap index 3d15e2a8a..466ca81b6 100644 --- a/subprojects/libffi.wrap +++ b/subprojects/libffi.wrap @@ -1,4 +1,5 @@ [wrap-git] directory=libffi -url=https://github.com/centricular/libffi.git +url=https://gitlab.freedesktop.org/gstreamer/meson-ports/libffi.git +depth=1 revision=meson diff --git a/subprojects/proxy-libintl.wrap b/subprojects/proxy-libintl.wrap index b53c8f7c3..5e1e19a4a 100644 --- a/subprojects/proxy-libintl.wrap +++ b/subprojects/proxy-libintl.wrap @@ -1,4 +1,5 @@ [wrap-git] directory=proxy-libintl url=https://github.com/frida/proxy-libintl.git +depth=1 revision=0.1 diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap index de1e861e1..b62b63a66 100644 --- a/subprojects/zlib.wrap +++ b/subprojects/zlib.wrap @@ -1,4 +1,5 @@ [wrap-git] directory=zlib url=https://github.com/centricular/zlib.git +depth=1 revision=meson