From: Jacek Caban Subject: [PATCH 2/4] winegcc: Support -delayload on binutils mingw target. Message-Id: <31817399-036a-0667-4000-f26b3b6e3d5a@codeweavers.com> Date: Mon, 7 Oct 2019 18:51:34 +0200 Emulate MSVC-style delayload by creating required delay importlibs from .def files on demand. Signed-off-by: Jacek Caban --- tools/winegcc/utils.c | 12 ++++++++++++ tools/winegcc/utils.h | 1 + tools/winegcc/winegcc.c | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/tools/winegcc/utils.c b/tools/winegcc/utils.c index 3197e46e47..302e517a4f 100644 --- a/tools/winegcc/utils.c +++ b/tools/winegcc/utils.c @@ -297,6 +297,18 @@ file_type get_lib_type(enum target_platform platform, strarray* path, const char return file_na; } +char *find_def_file(strarray* path, const char *library) +{ + unsigned int i; + char *file; + + for (i = 0; i < path->size; i++) + { + if ((file = try_lib_path(path->base[i], "lib", library, ".def", file_def))) return file; + } + error("Could not find def file: %s\n", library); +} + const char *find_binary( const strarray* prefix, const char *name ) { unsigned int i; diff --git a/tools/winegcc/utils.h b/tools/winegcc/utils.h index 3d6b8f3665..e5dc8a2d75 100644 --- a/tools/winegcc/utils.h +++ b/tools/winegcc/utils.h @@ -85,6 +85,7 @@ void create_file(const char* name, int mode, const char* fmt, ...); file_type get_file_type(const char* filename); file_type get_lib_type(enum target_platform platform, strarray* path, const char *library, const char *suffix, char** file); +char *find_def_file(strarray* path, const char *library); const char *find_binary( const strarray* prefix, const char *name ); int spawn(const strarray* prefix, const strarray* arr, int ignore_errors); diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 60e5e60ab8..f0a87492db 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -961,6 +961,26 @@ static void add_library( struct options *opts, strarray *lib_dirs, strarray *fil free(fullname); } +static const char *generate_delay_implib(struct options *opts, strarray *lib_dirs, const char *dll) +{ + strarray *winebuild_args; + const char *delay_implib, *def_file; + + def_file = find_def_file(lib_dirs, dll); + delay_implib = get_temp_file(dll, ".delay.a"); + + winebuild_args = get_winebuild_args(opts); + strarray_add(winebuild_args, "-o"); + strarray_add(winebuild_args, delay_implib); + strarray_add(winebuild_args, "--implib"); + strarray_add(winebuild_args, "--export"); + strarray_add(winebuild_args, def_file); + + spawn(opts->prefix, winebuild_args, 0); + strarray_free(winebuild_args); + return delay_implib; +} + static void build(struct options* opts) { strarray *lib_dirs, *files; @@ -1077,7 +1097,24 @@ static void build(struct options* opts) } } else if (file[1] == 'l') - add_library(opts, lib_dirs, files, file + 2 ); + { + const char *delay_lib = NULL; + if (is_pe) + { + unsigned int i; + for (i = 0; i < opts->delayloads->size; i++) + { + const char *delay_dll = opts->delayloads->base[i]; + size_t len = strlen(file + 2); + if (strncasecmp(file + 2, delay_dll, len)) continue; + if (delay_dll[len] && strcasecmp(delay_dll + len, ".dll")) continue; + delay_lib = generate_delay_implib(opts, lib_dirs, file + 2); + strarray_add(files, strmake("-a%s", delay_lib)); + break; + } + } + if (!delay_lib) add_library(opts, lib_dirs, files, file + 2); + } else if (file[1] == 'x') lang = file; }