diff --git a/tools/makedep.c b/tools/makedep.c index 2a52ecd09c0..f9fbf7f8d8e 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -2787,6 +2787,7 @@ static void output_source_idl( struct makefile *make, struct incl_file *source, output( "\t%s%s -o $@", cmd_prefix( "WIDL" ), tools_path( make, "widl" ) ); output_filenames( target_flags ); output_filename( "--nostdinc" ); + output_filename( "-Ldlls/\\*" ); output_filenames( defines ); output_filenames( get_expanded_make_var_array( make, "EXTRAIDLFLAGS" )); output_filenames( get_expanded_file_local_var( make, obj, "EXTRAIDLFLAGS" )); diff --git a/tools/widl/Makefile.in b/tools/widl/Makefile.in index 7eb74b813a4..32d27060c22 100644 --- a/tools/widl/Makefile.in +++ b/tools/widl/Makefile.in @@ -29,6 +29,8 @@ MANPAGES = widl.man.in widl_EXTRADEFS = \ -DINCLUDEDIR="\"${includedir}\"" \ - -DBIN_TO_INCLUDEDIR=\"`${MAKEDEP} -R ${bindir} ${includedir}`\" + -DDLLDIR="\"${dlldir}\"" \ + -DBIN_TO_INCLUDEDIR=\"`${MAKEDEP} -R ${bindir} ${includedir}`\" \ + -DBIN_TO_DLLDIR=\"`${MAKEDEP} -R ${bindir} ${dlldir}`\" INSTALL_DEV = $(PROGRAMS) diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c index d0fbdcab690..d47e937d70c 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -349,20 +349,6 @@ static void read_pe_importlib(importlib_t *importlib, void *data, unsigned int s read_msft_importlib( importlib, ptr, resdata->Size ); } -static int open_typelib(const char *name) -{ - char *file_name; - int fd; - - file_name = wpp_find_include(name, NULL); - if(!file_name) - return open(name, O_RDONLY | O_BINARY ); - - fd = open(file_name, O_RDONLY | O_BINARY ); - free(file_name); - return fd; -} - static void read_importlib(importlib_t *importlib) { int fd, size; diff --git a/tools/widl/widl.c b/tools/widl/widl.c index 325a55fff8d..2319a495f6a 100644 --- a/tools/widl/widl.c +++ b/tools/widl/widl.c @@ -55,6 +55,7 @@ static const char usage[] = " -h Generate headers\n" " -H file Name of header file (default is infile.h)\n" " -I directory Add directory to the include search path (multiple -I allowed)\n" +" -L directory Add directory to the library search path (multiple -L allowed)\n" " --local-stubs=file Write empty stubs for call_as/local methods to file\n" " -m32, -m64 Set the target architecture (Win32 or Win64)\n" " -N Do not preprocess input\n" @@ -151,6 +152,8 @@ char *temp_name; const char *prefix_client = ""; const char *prefix_server = ""; static const char *includedir; +static const char *dlldir; +static struct strarray dlldirs; static char *output_name; static const char *sysroot = ""; @@ -185,7 +188,7 @@ enum { }; static const char short_options[] = - "b:cC:d:D:EhH:I:m:No:O:pP:rsS:tT:uU:VW"; + "b:cC:d:D:EhH:I:L:m:No:O:pP:rsS:tT:uU:VW"; static const struct long_option long_options[] = { { "acf", 1, ACF_OPTION }, { "app_config", 0, APP_CONFIG_OPTION }, @@ -578,6 +581,7 @@ static void init_argv0_dir( const char *argv0 ) #endif if (!dir) return; includedir = strmake( "%s/%s", get_dirname( dir ), BIN_TO_INCLUDEDIR ); + dlldir = strmake( "%s/%s", get_dirname( dir ), BIN_TO_DLLDIR ); #endif } @@ -680,6 +684,9 @@ static void option_callback( int optc, char *optarg ) case 'I': wpp_add_include_path(optarg); break; + case 'L': + strarray_add( &dlldirs, optarg ); + break; case 'm': if (!strcmp( optarg, "32" )) pointer_size = 4; else if (!strcmp( optarg, "64" )) pointer_size = 8; @@ -742,6 +749,61 @@ static void option_callback( int optc, char *optarg ) } } +static const char *get_pe_dir(void) +{ + switch (target_cpu) + { + case CPU_x86: return "/i386-windows"; + case CPU_x86_64: return "/x86_64-windows"; + case CPU_ARM: return "/arm-windows"; + case CPU_ARM64: return "/aarch64-windows"; + default: return ""; + } +} + +int open_typelib( const char *name ) +{ + static const char *default_dirs[] = { DLLDIR, "/usr/lib/wine", "/usr/local/lib/wine" }; + const char *pe_dir = get_pe_dir(); + int fd; + unsigned int i; + +#define TRYOPEN(str) do { \ + char *file = str; \ + if ((fd = open( file, O_RDONLY | O_BINARY )) != -1) return fd; \ + free( file ); } while(0) + + for (i = 0; i < dlldirs.count; i++) + { + if (strendswith( dlldirs.str[i], "/*" )) /* special case for wine build tree */ + { + int namelen = strlen( name ); + if (strendswith( name, ".dll" )) namelen -= 4; + TRYOPEN( strmake( "%.*s/%.*s/%s", (int)strlen(dlldirs.str[i]) - 2, dlldirs.str[i], + namelen, name, name )); + TRYOPEN( strmake( "%.*s/%.*s/%s.fake", (int)strlen(dlldirs.str[i]) - 2, dlldirs.str[i], + namelen, name, name )); + } + else + { + TRYOPEN( strmake( "%s%s/%s", dlldirs.str[i], pe_dir, name )); + TRYOPEN( strmake( "%s/%s", dlldirs.str[i], name )); + } + } + + if (stdinc) + { + if (dlldir) TRYOPEN( strmake( "%s%s/%s", dlldir, pe_dir, name )); + for (i = 0; i < ARRAY_SIZE(default_dirs); i++) + { + if (i && !strcmp( default_dirs[i], default_dirs[0] )) continue; + TRYOPEN( strmake( "%s%s/%s", default_dirs[i], pe_dir, name )); + } + } + error( "cannot find %s\n", name ); +#undef TRYOPEN +} + int main(int argc,char *argv[]) { int i; diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 6dc19b3dafa..38ffc477115 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -89,6 +89,7 @@ enum stub_mode MODE_Oif /* new-style fully interpreted stubs */ }; extern enum stub_mode get_stub_mode(void); +extern int open_typelib( const char *name ); extern void write_header(const statement_list_t *stmts); extern void write_id_data(const statement_list_t *stmts); diff --git a/tools/widl/widl.man.in b/tools/widl/widl.man.in index 234f512f962..858b04a38e8 100644 --- a/tools/widl/widl.man.in +++ b/tools/widl/widl.man.in @@ -58,6 +58,9 @@ Use old naming conventions. Generate a type library. The default output filename is \fIinfile\fB.tlb\fR. If the output file name ends in \fB.res\fR, a binary resource file containing the type library is generated instead. +.IP "\fB-L \fIpath\fR" +Add a directory to the library search path for imported typelibs. The +option can be specified multiple times. .PP .B UUID file options: .IP "\fB-u\fR"