diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index bde322cef30..2b67d305e82 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -369,6 +369,7 @@ extern FILE *output_file; extern const char *output_file_name; extern struct strarray lib_path; +extern struct strarray tools_path; extern struct strarray as_command; extern struct strarray cc_command; extern struct strarray ld_command; diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index 7d54395860f..f4abb550819 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -83,6 +83,7 @@ const char *output_file_name = NULL; static int fake_module; struct strarray lib_path = { 0 }; +struct strarray tools_path = { 0 }; struct strarray as_command = { 0 }; struct strarray cc_command = { 0 }; struct strarray ld_command = { 0 }; @@ -257,6 +258,7 @@ static const char usage_str[] = "Options:\n" " --as-cmd=AS Command to use for assembling (default: as)\n" " -b, --target=TARGET Specify target CPU and platform for cross-compiling\n" +" -B PREFIX Look for build tools in the PREFIX directory\n" " --cc-cmd=CC C compiler to use for assembling (default: fall back to --as-cmd)\n" " -d, --delay-lib=LIB Import the specified library in delayed mode\n" " -D SYM Ignored for C flags compatibility\n" @@ -316,7 +318,7 @@ enum long_options_values LONG_OPT_VERSION }; -static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:b:d:e:f:hkl:m:o:r:u:vw"; +static const char short_options[] = "B:C:D:E:F:H:I:K:L:M:N:b:d:e:f:hkl:m:o:r:u:vw"; static const struct option long_options[] = { @@ -389,6 +391,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) { switch(optc) { + case 'B': + strarray_add( &tools_path, xstrdup( optarg ), NULL ); + break; case 'D': /* ignored */ break; diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index fe82ad75e94..a73f520cccd 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -281,11 +281,72 @@ int output( const char *format, ... ) return ret; } +static struct strarray get_tools_path(void) +{ + static int done; + static struct strarray dirs; + + if (!done) + { + dirs = strarray_copy( tools_path ); + + /* then append the PATH directories */ + if (getenv( "PATH" )) + { + char *p = xstrdup( getenv( "PATH" )); + while (*p) + { + strarray_add_one( &dirs, p ); + while (*p && *p != PATH_SEPARATOR) p++; + if (!*p) break; + *p++ = 0; + } + } + done = 1; + } + return dirs; +} + +/* find a binary in the path */ +static const char *find_binary( const char *prefix, const char *name ) +{ + struct strarray dirs = get_tools_path(); + unsigned int i, maxlen = 0; + struct stat st; + char *p, *file; + + if (strchr( name, '/' )) return name; + if (!prefix) prefix = ""; + for (i = 0; i < dirs.count; i++) maxlen = max( maxlen, strlen(dirs.str[i]) + 2 ); + file = xmalloc( maxlen + strlen(prefix) + strlen(name) + sizeof(EXEEXT) + 1 ); + + for (i = 0; i < dirs.count; i++) + { + strcpy( file, dirs.str[i] ); + p = file + strlen(file); + if (p == file) *p++ = '.'; + if (p[-1] != '/') *p++ = '/'; + if (*prefix) + { + strcpy( p, prefix ); + p += strlen(p); + *p++ = '-'; + } + strcpy( p, name ); + strcat( p, EXEEXT ); + if (!stat( file, &st ) && S_ISREG(st.st_mode) && (st.st_mode & 0111)) return file; + } + free( file ); + return NULL; +} + void spawn( struct strarray args ) { unsigned int i; int status; + const char *argv0 = find_binary( NULL, args.str[0] ); + if (argv0) args.str[0] = argv0; strarray_add_one( &args, NULL ); if (verbose) for (i = 0; args.str[i]; i++) @@ -302,35 +363,8 @@ void spawn( struct strarray args ) /* find a build tool in the path, trying the various names */ struct strarray find_tool( const char *name, const char * const *names ) { - static char **dirs; - static unsigned int count, maxlen; - - char *p, *file; + const char *file; const char *alt_names[2]; - unsigned int i, len; - struct stat st; - - if (!dirs) - { - char *path; - - /* split the path in directories */ - - if (!getenv( "PATH" )) fatal_error( "PATH not set, cannot find required tools\n" ); - path = xstrdup( getenv( "PATH" )); - for (p = path, count = 2; *p; p++) if (*p == PATH_SEPARATOR) count++; - dirs = xmalloc( count * sizeof(*dirs) ); - count = 0; - dirs[count++] = p = path; - while (*p) - { - while (*p && *p != PATH_SEPARATOR) p++; - if (!*p) break; - *p++ = 0; - dirs[count++] = p; - } - for (i = 0; i < count; i++) maxlen = max( maxlen, strlen(dirs[i])+2 ); - } if (!names) { @@ -341,34 +375,12 @@ struct strarray find_tool( const char *name, const char * const *names ) while (*names) { - len = strlen(*names) + sizeof(EXEEXT) + 1; - if (target_alias) - len += strlen(target_alias) + 1; - file = xmalloc( maxlen + len ); - - for (i = 0; i < count; i++) + if ((file = find_binary( target_alias, *names ))) { - strcpy( file, dirs[i] ); - p = file + strlen(file); - if (p == file) *p++ = '.'; - if (p[-1] != '/') *p++ = '/'; - if (target_alias) - { - strcpy( p, target_alias ); - p += strlen(p); - *p++ = '-'; - } - strcpy( p, *names ); - strcat( p, EXEEXT ); - - if (!stat( file, &st ) && S_ISREG(st.st_mode) && (st.st_mode & 0111)) - { - struct strarray ret = empty_strarray; - strarray_add_one( &ret, file ); - return ret; - } + struct strarray ret = empty_strarray; + strarray_add_one( &ret, file ); + return ret; } - free( file ); names++; } fatal_error( "cannot find the '%s' tool\n", name ); @@ -377,6 +389,7 @@ struct strarray find_tool( const char *name, const char * const *names ) struct strarray get_as_command(void) { struct strarray args; + unsigned int i; if (cc_command.count) { @@ -387,6 +400,8 @@ struct strarray get_as_command(void) if (cpu_option) strarray_add_one( &args, strmake("-mcpu=%s", cpu_option) ); if (fpu_option) strarray_add_one( &args, strmake("-mfpu=%s", fpu_option) ); if (arch_option) strarray_add_one( &args, strmake("-march=%s", arch_option) ); + for (i = 0; i < tools_path.count; i++) + strarray_add_one( &args, strmake("-B%s", tools_path.str[i] )); return args; } diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in index 1b9b1b088b5..12bafd72d30 100644 --- a/tools/winebuild/winebuild.man.in +++ b/tools/winebuild/winebuild.man.in @@ -68,6 +68,10 @@ Specify the target CPU and platform on which the generated code will be built. The target specification is in the standard autoconf format as returned by config.sub. .TP +.BI \-B\ directory +Add the directory to the search path for the various binutils tools +like \fBas\fR, \fBnm\fR and \fBld\fR. +.TP .BI \--cc-cmd= cc-command Specify the C compiler to use to compile assembly files; the default is to instead use the assembler specified with \fB--as-cmd\fR.