Files
gimp/build/windows/gitlab-ci/dll_link.py
Jehan 419892c3bd gitlab-ci, build: CI job to package GIMP on Windows from MSYS2 build.
This new job resulted in a package which allows to run GIMP on Windows
(as tested in a VM; at least it starts, I can create a new canvas and
paint). Of course I think this will need to be tweaked a little bit
more, as I'm sure we miss things here and there.

At the very least, even though I add the Python and Luajit binaries,
GIMP on Windows didn't find them. This will need to be investigated.

Also it looks like opening from a remote location may not work. Not sure
if this about a missing GIO module or maybe something which works
differently on Windows (I was not even able to drag'n drop from the
browser!). Anyway this needs to be looked at as well.

Note that gdk-pixbuf-query-loaders is apparently unneeded when GIMP is
built this way (unlike with our crossroad build).

All this to say that this is still an early attempt to full CI build for
Windows.
It doesn't invalidate the crossroad build, because cross-compilation
builds from Linux will always stay very important for Linux developers
to be able to easily fix Windows bugs too; yet the crossroad build has 2
major issues:
1. We haven't figured out yet how to run GObject Introspection tools for
   cross-builds, so the crossroad builds are not full-featured (and this
   is quite a major feature we are missing!).
2. Also I will want to run the installer in the CI at some point and the
   one we use can only run on Windows itself AFAIK. We could try to run
   it through Wine, but still anyway the point 1. is already quite a
   blocker, let's do the simple thing.

Note that we will likely want to move to meson for this build, because
autotools is very slow on Windows. But as long as the few blocker meson
bugs are not fixed, let's stick to the slow yet good build.
2021-05-07 20:04:03 +02:00

122 lines
3.9 KiB
Python
Executable File

#!/usr/bin/python3
################################################################################
# Small python script to retrieve DLL dependencies with objdump
################################################################################
################################################################################
# Usage example
#
# python3 dll_link.py /path/to/run.exe /winenv/ /path/install
#
# In this case, the DLL dependencies for executable run.exe will be extracted
# and copied into /path/install/bin folder. To copy the DLL, the root path to
# Windows environnment should be passed, here /winenv/.
import argparse
import os
import subprocess
import re
import shutil
import sys
################################################################################
# Global variables
# Sets for executable and system DLL
dlls = set()
sys_dlls = set()
# Common paths
bindir = 'bin'
################################################################################
# Functions
# Main function
def main(binary, srcdir, destdir, debug):
find_dependencies(binary, srcdir)
if args.debug:
print("Running in debug mode (no DLL moved)")
if len(dlls) > 0:
sys.stdout.write("Needed DLLs:\n\t- ")
sys.stdout.write("\n\t- ".join(list(dlls)))
print()
if len(sys_dlls) > 0:
sys.stdout.write('System DLLs:\n\t- ')
sys.stdout.write("\n\t- ".join(sys_dlls))
print()
removed_dlls = sys_dlls & dlls
if len(removed_dlls) > 0:
sys.stdout.write('Non installed DLLs:\n\t- ')
sys.stdout.write("\n\t- ".join(removed_dlls))
print()
installed_dlls = dlls - sys_dlls
if len(installed_dlls) > 0:
sys.stdout.write('Installed DLLs:\n\t- ')
sys.stdout.write("\n\t- ".join(installed_dlls))
print()
else:
copy_dlls(dlls - sys_dlls, srcdir, destdir)
def find_dependencies(obj, srcdir):
'''
List DLLs of an object file in a recursive way.
'''
if os.path.exists(obj):
# If DLL exists, extract dependencies.
objdump = None
result = subprocess.run(['file', obj], stdout=subprocess.PIPE)
file_type = result.stdout.decode('utf-8')
if 'PE32+' in file_type:
objdump = 'x86_64-w64-mingw32-objdump'
elif 'PE32' in file_type:
objdump = 'i686-w64-mingw32-objdump'
if objdump is None:
sys.stderr.write('File type of {} unknown: {}\n'.format(obj, file_type))
sys.exit(os.EX_UNAVAILABLE)
elif shutil.which(objdump) is None:
# For native objdump case.
objdump = 'objdump.exe'
if shutil.which(objdump) is None:
sys.stderr.write("Executable doesn't exist: {}\n".format(objdump))
sys.exit(os.EX_UNAVAILABLE)
result = subprocess.run([objdump, '-p', obj], stdout=subprocess.PIPE)
out = result.stdout.decode('utf-8')
# Parse lines with DLL Name instead of lib*.dll directly
for match in re.finditer(r"DLL Name: *(\S+.dll)", out, re.MULTILINE):
dll = match.group(1)
if dll not in dlls:
dlls.add(dll)
next_dll = os.path.join(srcdir, bindir, dll)
find_dependencies(next_dll, srcdir)
else:
# Otherwise, it is a system DLL
sys_dlls.add(os.path.basename(obj))
# Copy a DLL set into the /destdir/bin directory
def copy_dlls(dll_list, srcdir, destdir):
destbin = os.path.join(destdir, bindir)
os.makedirs(destbin, exist_ok=True)
for dll in dll_list:
full_file_name = os.path.join(srcdir, bindir, dll)
if os.path.isfile(full_file_name):
shutil.copy(full_file_name, destbin)
else:
sys.stderr.write("Missing DLL: {}\n".format(full_file_name))
sys.exit(os.EX_DATAERR)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--debug', dest='debug', action = 'store_true', default = False)
parser.add_argument('bin')
parser.add_argument('src')
parser.add_argument('dest')
args = parser.parse_args(sys.argv[1:])
main(args.bin, args.src, args.dest, args.debug)