diff options
-rw-r--r-- | .github/workflows/nightly.yml | 24 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rwxr-xr-x | contrib/mingw-bundledlls | 150 | ||||
-rw-r--r-- | distribute.mk.in | 14 |
4 files changed, 171 insertions, 19 deletions
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 40254a6..428825a 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -201,6 +201,8 @@ jobs: make -C build-wincon check TESTSUITEFLAGS="--verbose" - name: Prepare Distribution Directory + env: + MINGW_BUNDLEDLLS_SEARCH_PATH: /mingw32/bin run: | mkdir temp-bin/ cd temp-bin/ @@ -210,9 +212,8 @@ jobs: cp -r /mingw32/share/doc/sciteco/* ./ cp ../COPYING ../ChangeLog ./ cp /mingw32/bin/gspawn-win32-helper*.exe ./ - # FIXME: See above. We currently link dynamically. - cp /mingw32/bin/{libglib-2.0-0,libpcre2-8-0,libintl-8,libiconv-2,libwinpthread-1,libgcc_s_dw2-1}.dll ./ - cp /mingw32/bin/libstdc++-6.dll ./ + # Collect DLLs for all included binaries + for f in *.exe; do ../contrib/mingw-bundledlls --copy $f; done zip -9 -r ../sciteco-pdcurses_nightly_win32.zip . - name: Archive Windows Distribution (PDCurses) uses: pyTooling/Actions/releaser/composite@v0.4.5 @@ -272,6 +273,8 @@ jobs: run: make check TESTSUITEFLAGS="--verbose" - name: Prepare Distribution Directory + env: + MINGW_BUNDLEDLLS_SEARCH_PATH: /mingw32/bin run: | mkdir temp-bin cd temp-bin @@ -284,15 +287,8 @@ jobs: cp -r /mingw32/share/doc/sciteco/* ./ cp ../COPYING ../ChangeLog ./ cp /mingw32/bin/gspawn-win32-helper*.exe ./ - cp /mingw32/bin/{libglib-2.0-0,libpcre2-8-0,libintl-8,libiconv-2,libwinpthread-1,libgcc_s_dw2-1}.dll ./ - cp /mingw32/bin/{libgtk-3-0,libgdk-3-0,libgdk_pixbuf-2.0-0,libatk-1.0-0}.dll ./ - cp /mingw32/bin/{libgobject-2.0-0,libgmodule-2.0-0,libgio-2.0-0,libffi-8}.dll ./ - cp /mingw32/bin/{libpango-1.0-0,libpangocairo-1.0-0,libpangowin32-1.0-0,libpangoft2-1.0-0}.dll ./ - cp /mingw32/bin/{libthai-0,libdatrie-1,libharfbuzz-0,libgraphite2,libfribidi-0,libepoxy-0}.dll ./ - cp /mingw32/bin/{libfontconfig-1,libexpat-1}.dll ./ - cp /mingw32/bin/{libfreetype-6,libbrotlidec,libbrotlicommon,libbz2-1,zlib1}.dll ./ - cp /mingw32/bin/{libcairo-2,libcairo-gobject-2,libpixman-1-0,libstdc++-6}.dll ./ - cp /mingw32/bin/{libpng16-16,librsvg-2-2,libxml2-2}.dll ./ + # Collect DLLs for all included binaries + for f in *.exe; do ../contrib/mingw-bundledlls --copy $f; done #mkdir share #cp /mingw32/share/loader.cache share/ #glib-compile-schemas /mingw32/share/glib-2.0/schemas @@ -312,6 +308,10 @@ jobs: cp /mingw32/lib/gdk-pixbuf-2.0/2.10.0/loaders/{libpixbufloader-svg.dll,libpixbufloader-png.dll} \ lib/gdk-pixbuf-2.0/2.10.0/loaders/ cp ../win32/loaders.cache lib/gdk-pixbuf-2.0/2.10.0/ + # Collect DLLs for all pixbuf loaders + for f in lib/gdk-pixbuf-2.0/2.10.0/loaders/*.dll; do + ../contrib/mingw-bundledlls --copy $f + done zip -9 -r ../sciteco-gtk3_nightly_win32.zip . - name: Archive Windows Distribution (GTK+ 3) uses: pyTooling/Actions/releaser/composite@v0.4.5 diff --git a/Makefile.am b/Makefile.am index 93de15f..6cee9d6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,6 +20,8 @@ EXTRA_DIST += ico/sciteco-256.png ico/sciteco.ico EXTRA_DIST += win32/loaders.cache +EXTRA_DIST += contrib/mingw-bundledlls + # Distribute entire Scintilla/Scinterm/Lexilla directory and # do some manual cleanup. dist-hook: diff --git a/contrib/mingw-bundledlls b/contrib/mingw-bundledlls new file mode 100755 index 0000000..2b4fb2b --- /dev/null +++ b/contrib/mingw-bundledlls @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 + +# The MIT License (MIT) +# +# Copyright (c) 2015 Martin Preisler +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +import subprocess +import os.path +import argparse +import shutil + +# The mingw path matches where Fedora 21 installs mingw32; this is the default +# fallback if no other search path is specified in $MINGW_BUNDLEDLLS_SEARCH_PATH +DEFAULT_PATH_PREFIXES = [ + "", "/usr/bin", "/usr/i686-w64-mingw32/sys-root/mingw/bin", "/mingw64/bin", + "/usr/i686-w64-mingw32/sys-root/mingw/lib", + "C:\\msys64\\mingw64\\bin" +] + +env_path_prefixes = os.environ.get('MINGW_BUNDLEDLLS_SEARCH_PATH', None) +if env_path_prefixes is not None: + path_prefixes = [path for path in env_path_prefixes.split(os.pathsep) if path] +else: + path_prefixes = DEFAULT_PATH_PREFIXES + +# This blacklist may need extending +blacklist = [ + "advapi32.dll", "kernel32.dll", "msvcrt.dll", "ole32.dll", "user32.dll", + "ws2_32.dll", "comdlg32.dll", "gdi32.dll", "imm32.dll", "oleaut32.dll", + "shell32.dll", "winmm.dll", "winspool.drv", "wldap32.dll", + "ntdll.dll", "d3d9.dll", "mpr.dll", "crypt32.dll", "dnsapi.dll", + "shlwapi.dll", "version.dll", "iphlpapi.dll", "msimg32.dll", "setupapi.dll", + "opengl32.dll", "dwmapi.dll", "uxtheme.dll", "secur32.dll", "gdiplus.dll", + "usp10.dll", "comctl32.dll", "wsock32.dll", "netapi32.dll", "userenv.dll", + "avicap32.dll", "avrt.dll", "psapi.dll", "mswsock.dll", "glu32.dll", + "bcrypt.dll", "rpcrt4.dll", "hid.dll", + # directx 3d 11 + "d3d11.dll", "dxgi.dll" +] + + +def find_full_path(filename, path_prefixes): + for path_prefix in path_prefixes: + path = os.path.join(path_prefix, filename) + path_low = os.path.join(path_prefix, filename.lower()) + if os.path.exists(path): + return path + if os.path.exists(path_low): + return path_low + + else: + raise RuntimeError( + "Can't find " + filename + ". If it is an inbuilt Windows DLL, " + "please add it to the blacklist variable in the script and send " + "a pull request!" + ) + + +def gather_deps(path, path_prefixes, seen): + ret = [path] + output = subprocess.check_output(["objdump", "-p", path]).decode( + "utf-8", "replace").split("\n") + for line in output: + if not line.startswith("\tDLL Name: "): + continue + + dep = line.split("DLL Name: ")[1].strip() + ldep = dep.lower() + + if ldep in blacklist: + continue + + if ldep in seen: + continue + + dep_path = find_full_path(dep, path_prefixes) + seen.add(ldep) + subdeps = gather_deps(dep_path, path_prefixes, seen) + ret.extend(subdeps) + + return ret + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "exe_file", + help="EXE or DLL file that you need to bundle dependencies for" + ) + parser.add_argument( + "--copy", + action="store_true", + help="In addition to printing out the dependencies, also copy them next to the exe_file" + ) + parser.add_argument( + "--upx", + action="store_true", + help="Only valid if --copy is provided. Run UPX on all the DLLs and EXE." + ) + args = parser.parse_args() + + if args.upx and not args.copy: + raise RuntimeError("Can't run UPX if --copy hasn't been provided.") + + all_deps = set(gather_deps(args.exe_file, path_prefixes, set())) + all_deps.remove(args.exe_file) + + print("\n".join(all_deps)) + + if args.copy: + print("Copying enabled, will now copy all dependencies next to the exe_file.\n") + + parent_dir = os.path.dirname(os.path.abspath(args.exe_file)) + + for dep in all_deps: + target = os.path.join(parent_dir, os.path.basename(dep)) + + try: + print("Copying '%s' to '%s'" % (dep, target)) + shutil.copy(dep, parent_dir) + + except shutil.SameFileError: + print("Dependency '%s' was already in target directory, " + "skipping..." % (dep)) + + if args.upx: + subprocess.call(["upx", target]) + + +if __name__ == "__main__": + main() diff --git a/distribute.mk.in b/distribute.mk.in index e5dc0ac..0d6942c 100644 --- a/distribute.mk.in +++ b/distribute.mk.in @@ -130,14 +130,14 @@ mingw-binary : @PACKAGE@-@PACKAGE_VERSION@-win32.zip temp-bin/.teco_ini cp @srcdir@/COPYING @srcdir@/ChangeLog temp-bin/ rm -rf temp-install/ -# cp /usr/i686-w64-mingw32/bin/intl.dll \ -# /usr/i686-w64-mingw32/bin/libglib-2.0-0.dll \ -# /usr/i686-w64-mingw32/bin/pdcurses.dll \ -# temp-bin/ - cp /usr/i686-w64-mingw32/bin/gspawn-win32-helper-console.exe \ + cp /usr/i686-w64-mingw32/bin/gspawn-win32-helper*.exe \ temp-bin/ - i686-w64-mingw32-strip -s temp-bin/gspawn-win32-helper-console.exe - cd temp-bin/; zip -r ../$@ . + # Collect DLLs for all included binaries + for f in temp-bin/*.exe; do \ + MINGW_BUNDLEDLLS_SEARCH_PATH=/usr/i686-w64-mingw32/bin \ + @srcdir@/contrib/mingw-bundledlls --copy $$f; \ + done + cd temp-bin/; zip -9 -r ../$@ . rm -rf temp-bin/ clean: |