Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/winegcc/winegcc.c
8730 views
1
/*
2
* MinGW wrapper: makes gcc behave like MinGW.
3
*
4
* Copyright 2000 Manuel Novoa III
5
* Copyright 2000 Francois Gouget
6
* Copyright 2002 Dimitrie O. Paun
7
*
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
12
*
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21
*
22
* DESCRIPTION
23
*
24
* all options for gcc start with '-' and are for the most part
25
* single options (no parameters as separate argument).
26
* There are of course exceptions to this rule, so here is an
27
* exhaustive list of options that do take parameters (potentially)
28
* as a separate argument:
29
*
30
* Compiler:
31
* -x language
32
* -o filename
33
* -aux-info filename
34
*
35
* Preprocessor:
36
* -D name
37
* -U name
38
* -I dir
39
* -MF file
40
* -MT target
41
* -MQ target
42
* (all -i.* arg)
43
* -include file
44
* -imacros file
45
* -idirafter dir
46
* -iwithprefix dir
47
* -iwithprefixbefore dir
48
* -isystem dir
49
* -A predicate=answer
50
*
51
* Linking:
52
* -l library
53
* -Xlinker option
54
* -u symbol
55
*
56
* Misc:
57
* -b machine
58
* -V version
59
* -G num (see NOTES below)
60
*
61
* NOTES
62
* There is -G option for compatibility with System V that
63
* takes no parameters. This makes "-G num" parsing ambiguous.
64
* This option is synonymous to -shared, and as such we will
65
* not support it for now.
66
*
67
* Special interest options
68
*
69
* Assembler Option
70
* -Wa,option
71
*
72
* Linker Options
73
* object-file-name -llibrary -nostartfiles -nodefaultlibs
74
* -nostdlib -s -static -static-libgcc -static-libstdc++
75
* -shared -shared-libgcc -symbolic -Wl,option
76
* -Xlinker option -u symbol --image-base -fuse-ld
77
*
78
* Directory Options
79
* -Bprefix -Idir -I- -Ldir -specs=file
80
*
81
* Target Options
82
* -b machine -V version
83
*
84
* Please note that the Target Options are relevant to everything:
85
* compiler, linker, assembler, preprocessor.
86
*
87
*/
88
89
#include "config.h"
90
91
#include <assert.h>
92
#include <stdio.h>
93
#include <stdlib.h>
94
#include <stdarg.h>
95
#include <stdbool.h>
96
#include <string.h>
97
#include <errno.h>
98
#include <ctype.h>
99
#include <limits.h>
100
#include <sys/types.h>
101
#include "../tools.h"
102
103
static const char* app_loader_template =
104
"#!/bin/sh\n"
105
"\n"
106
"appname=\"%s\"\n"
107
"# determine the application directory\n"
108
"appdir=''\n"
109
"case \"$0\" in\n"
110
" */*)\n"
111
" # $0 contains a path, use it\n"
112
" appdir=`dirname \"$0\"`\n"
113
" ;;\n"
114
" *)\n"
115
" # no directory in $0, search in PATH\n"
116
" saved_ifs=$IFS\n"
117
" IFS=:\n"
118
" for d in $PATH\n"
119
" do\n"
120
" IFS=$saved_ifs\n"
121
" if [ -x \"$d/$appname\" ]; then appdir=\"$d\"; break; fi\n"
122
" done\n"
123
" ;;\n"
124
"esac\n"
125
"\n"
126
"# figure out the full app path\n"
127
"if [ -n \"$appdir\" ]; then\n"
128
" apppath=\"$appdir/$appname\"\n"
129
" WINEDLLPATH=\"$appdir:$WINEDLLPATH\"\n"
130
" export WINEDLLPATH\n"
131
"else\n"
132
" apppath=\"$appname\"\n"
133
"fi\n"
134
"\n"
135
"# determine the WINELOADER\n"
136
"if [ ! -x \"$WINELOADER\" ]; then WINELOADER=\"wine\"; fi\n"
137
"\n"
138
"# and try to start the app\n"
139
"exec \"$WINELOADER\" \"$apppath\" \"$@\"\n"
140
;
141
142
static const char *output_file_name;
143
static struct strarray output_debug_files;
144
static const char *output_implib;
145
static const char *output;
146
static int keep_generated = 0;
147
static int verbose;
148
const char *temp_dir = NULL;
149
struct strarray temp_files = { 0 };
150
151
static const char *bindir;
152
static const char *libdir;
153
static const char *includedir;
154
static const char *cc_cmd;
155
static const char *wine_objdir;
156
static const char *winebuild;
157
static const char *lib_suffix;
158
static const char *sysroot;
159
static const char *isysroot;
160
static const char *target_alias;
161
static const char *target_version;
162
static struct target target;
163
static struct strarray prefix_dirs;
164
static struct strarray path_dirs;
165
static struct strarray lib_path_dirs;
166
167
static enum processor { proc_cc, proc_cxx, proc_cpp } processor = proc_cc;
168
169
enum file_type { file_na, file_other, file_obj, file_res, file_rc, file_arh, file_dll, file_so, file_spec };
170
171
static bool is_pe;
172
static bool is_static;
173
static bool is_shared;
174
static bool is_unicode_app;
175
static bool is_win16_app;
176
static bool is_arm64x;
177
static bool use_msvcrt;
178
static bool use_pic = true;
179
static bool use_build_id;
180
static bool nostdinc;
181
static bool nostdlib;
182
static bool nostartfiles;
183
static bool nodefaultlibs;
184
static bool noshortwchar;
185
static bool data_only;
186
static bool fake_module;
187
static bool large_address_aware;
188
static bool wine_builtin;
189
static bool unwind_tables;
190
static bool strip;
191
static bool compile_only;
192
static bool skip_link;
193
static bool no_default_config;
194
static int force_pointer_size;
195
196
static const char *image_base;
197
static const char *section_align;
198
static const char *file_align;
199
static const char *subsystem;
200
static const char *entry_point;
201
static struct strarray file_args;
202
static struct strarray linker_args;
203
static struct strarray compiler_args;
204
static struct strarray winebuild_args;
205
static struct strarray delayimports;
206
207
208
static void cleanup_output_files(void)
209
{
210
if (output_file_name) unlink( output_file_name );
211
if (output_implib) unlink( output_implib );
212
STRARRAY_FOR_EACH( file, &output_debug_files) unlink( file );
213
}
214
215
static void clean_temp_files(void)
216
{
217
if (!keep_generated) remove_temp_files();
218
}
219
220
/* clean things up when aborting on a signal */
221
static void exit_on_signal( int sig )
222
{
223
exit(1); /* this will call the atexit functions */
224
}
225
226
static void error(const char* s, ...)
227
{
228
va_list ap;
229
230
va_start(ap, s);
231
fprintf(stderr, "winegcc: ");
232
vfprintf(stderr, s, ap);
233
va_end(ap);
234
exit(2);
235
}
236
237
static void create_file(const char* name, int mode, const char* fmt, ...)
238
{
239
va_list ap;
240
FILE *file;
241
242
if (verbose) printf("Creating file %s\n", name);
243
va_start(ap, fmt);
244
if ( !(file = fopen(name, "w")) )
245
error("Unable to open %s for writing\n", name);
246
vfprintf(file, fmt, ap);
247
va_end(ap);
248
fclose(file);
249
chmod(name, mode);
250
}
251
252
static enum file_type get_file_type(const char* filename)
253
{
254
/* see tools/winebuild/res32.c: check_header for details */
255
static const char res_sig[] = { 0,0,0,0, 32,0,0,0, 0xff,0xff, 0,0, 0xff,0xff, 0,0, 0,0,0,0, 0,0, 0,0, 0,0,0,0, 0,0,0,0 };
256
static const char elf_sig[4] = "\177ELF";
257
static const char ar_sig[8] = "!<arch>\n";
258
char buf[sizeof(res_sig)];
259
int fd, cnt;
260
261
fd = open( filename, O_RDONLY );
262
if (fd == -1) return file_na;
263
cnt = read(fd, buf, sizeof(buf));
264
close( fd );
265
if (cnt == -1) return file_na;
266
267
if (cnt == sizeof(res_sig) && !memcmp(buf, res_sig, sizeof(res_sig))) return file_res;
268
if (strendswith(filename, ".o")) return file_obj;
269
if (strendswith(filename, ".obj")) return file_obj;
270
if (strendswith(filename, ".a")) return file_arh;
271
if (strendswith(filename, ".res")) return file_res;
272
if (strendswith(filename, ".so")) return file_so;
273
if (strendswith(filename, ".dylib")) return file_so;
274
if (strendswith(filename, ".def")) return file_spec;
275
if (strendswith(filename, ".spec")) return file_spec;
276
if (strendswith(filename, ".rc")) return file_rc;
277
if (cnt >= sizeof(elf_sig) && !memcmp(buf, elf_sig, sizeof(elf_sig))) return file_so; /* ELF lib */
278
if (cnt >= sizeof(ar_sig) && !memcmp(buf, ar_sig, sizeof(ar_sig))) return file_arh;
279
if (cnt >= sizeof(unsigned int) &&
280
(*(unsigned int *)buf == 0xfeedface || *(unsigned int *)buf == 0xcefaedfe ||
281
*(unsigned int *)buf == 0xfeedfacf || *(unsigned int *)buf == 0xcffaedfe))
282
return file_so; /* Mach-O lib */
283
284
return file_other;
285
}
286
287
static char* try_lib_path(const char *dir, const char *arch_dir, const char* library,
288
const char* ext, enum file_type expected_type)
289
{
290
char *fullname;
291
enum file_type type;
292
293
/* first try a subdir named from the library we are looking for */
294
fullname = strmake("%s/%s%s/lib%s%s", dir, library, arch_dir, library, ext);
295
if (verbose > 1) fprintf(stderr, "Try %s...", fullname);
296
type = get_file_type(fullname);
297
if (verbose > 1) fprintf(stderr, type == expected_type ? "FOUND!\n" : "no\n");
298
if (type == expected_type) return fullname;
299
free( fullname );
300
301
fullname = strmake("%s/lib%s%s", dir, library, ext);
302
if (verbose > 1) fprintf(stderr, "Try %s...", fullname);
303
type = get_file_type(fullname);
304
if (verbose > 1) fprintf(stderr, type == expected_type ? "FOUND!\n" : "no\n");
305
if (type == expected_type) return fullname;
306
free( fullname );
307
return 0;
308
}
309
310
static enum file_type guess_lib_type(const char* dir, const char* library, char** file)
311
{
312
const char *arch_dir = "";
313
const char *suffix = lib_suffix ? lib_suffix : ".a";
314
315
if (!is_pe)
316
{
317
/* Unix shared object */
318
if ((*file = try_lib_path(dir, "", library, ".so", file_so)))
319
return file_so;
320
321
/* Mach-O (Darwin/Mac OS X) Dynamic Library behaves mostly like .so */
322
if ((*file = try_lib_path(dir, "", library, ".dylib", file_so)))
323
return file_so;
324
}
325
else
326
{
327
arch_dir = get_arch_dir( target );
328
if (!strcmp( suffix, ".a" )) /* try Mingw-style .dll.a import lib */
329
{
330
if ((*file = try_lib_path(dir, arch_dir, library, ".dll.a", file_arh)))
331
return file_arh;
332
}
333
}
334
335
/* static archives */
336
if ((*file = try_lib_path(dir, arch_dir, library, suffix, file_arh)))
337
return file_arh;
338
339
return file_na;
340
}
341
342
static enum file_type get_lib_type(struct strarray path, const char *library, char** file)
343
{
344
STRARRAY_FOR_EACH( str, &path )
345
{
346
enum file_type type = guess_lib_type(str, library, file);
347
if (type != file_na) return type;
348
}
349
return file_na;
350
}
351
352
static const char *find_binary( const char *name )
353
{
354
char *file_name, *args;
355
struct strarray dirs = empty_strarray;
356
357
if (strchr( name, '/' )) return name;
358
359
file_name = xstrdup( name );
360
if ((args = strchr( file_name, ' ' ))) *args++ = 0;
361
362
strarray_addall( &dirs, prefix_dirs );
363
strarray_addall( &dirs, path_dirs );
364
STRARRAY_FOR_EACH( dir, &dirs )
365
{
366
struct stat st;
367
char *prog = strmake( "%s/%s%s", dir, file_name, EXEEXT );
368
if (stat( prog, &st ) == 0 && S_ISREG( st.st_mode ) && (st.st_mode & 0111))
369
return args ? strmake( "%s %s", prog, args ) : prog;
370
free( prog );
371
}
372
return NULL;
373
}
374
375
static int spawn(struct strarray args, int ignore_errors)
376
{
377
int status;
378
const char *cmd;
379
380
cmd = args.str[0] = find_binary( args.str[0] );
381
if (verbose) strarray_trace( args );
382
383
if ((status = strarray_spawn( args )) && !ignore_errors)
384
{
385
if (status > 0) error("%s failed\n", cmd);
386
else perror("winegcc");
387
exit(3);
388
}
389
390
return status;
391
}
392
393
394
struct tool_names
395
{
396
const char *base;
397
const char *llvm_base;
398
const char *deflt;
399
};
400
401
static const struct tool_names tool_cc = { "gcc", "clang --driver-mode=gcc", CC };
402
static const struct tool_names tool_cxx = { "g++", "clang --driver-mode=g++", CXX };
403
static const struct tool_names tool_cpp = { "cpp", "clang --driver-mode=cpp", CPP };
404
static const struct tool_names tool_ld = { "ld", "ld.lld", LD };
405
static const struct tool_names tool_objcopy = { "objcopy", "llvm-objcopy" };
406
407
static void add_clang_options( const char *target_name, struct strarray *ret )
408
{
409
if (target_name)
410
{
411
strarray_add( ret, "-target" );
412
strarray_add( ret, target_name );
413
}
414
strarray_add( ret, "-Wno-unused-command-line-argument" );
415
strarray_add( ret, "-fuse-ld=lld" );
416
if (no_default_config) strarray_add( ret, "--no-default-config" );
417
}
418
419
static struct strarray build_tool_name( const char *target_name, struct tool_names tool )
420
{
421
const char *path, *str;
422
struct strarray ret;
423
424
if (cc_cmd && !strncmp( tool.llvm_base, "clang", 5 ))
425
{
426
ret = strarray_fromstring( cc_cmd, " " );
427
if (target.platform == PLATFORM_WINDOWS) add_clang_options( target_name, &ret );
428
return ret;
429
}
430
431
if (target_name && target_version)
432
str = strmake( "%s-%s-%s", target_name, tool.base, target_version );
433
else if (target_name)
434
str = strmake( "%s-%s", target_name, tool.base );
435
else if (target_version)
436
str = strmake("%s-%s", tool.base, target_version);
437
else
438
str = tool.deflt && *tool.deflt ? tool.deflt : tool.base;
439
440
if ((path = find_binary( str ))) return strarray_fromstring( path, " " );
441
442
if (target_version)
443
str = strmake( "%s-%s", tool.llvm_base, target_version );
444
else
445
str = tool.llvm_base;
446
447
if (!(path = find_binary( str ))) error( "Could not find %s\n", tool.base );
448
449
ret = strarray_fromstring( path, " " );
450
if (!strncmp( tool.llvm_base, "clang", 5 )) add_clang_options( target_name, &ret );
451
return ret;
452
}
453
454
static struct strarray get_translator(void)
455
{
456
switch(processor)
457
{
458
case proc_cpp:
459
return build_tool_name( target_alias, tool_cpp );
460
case proc_cc:
461
return build_tool_name( target_alias, tool_cc );
462
case proc_cxx:
463
return build_tool_name( target_alias, tool_cxx );
464
}
465
assert(0);
466
return empty_strarray;
467
}
468
469
static int try_link( struct strarray link_tool, const char *cflags )
470
{
471
const char *in = make_temp_file( "try_link", ".c" );
472
const char *out = make_temp_file( "try_link", ".out" );
473
const char *err = make_temp_file( "try_link", ".err" );
474
struct strarray link = empty_strarray;
475
int sout = -1, serr = -1;
476
int ret;
477
478
create_file( in, 0644, "int %s(void){return 1;}\n", is_pe ? "mainCRTStartup" : "main");
479
480
strarray_addall( &link, link_tool );
481
strarray_add( &link, "-o" );
482
strarray_add( &link, out );
483
strarray_addall( &link, strarray_fromstring( cflags, " " ) );
484
strarray_add( &link, in );
485
486
sout = dup( fileno(stdout) );
487
freopen( err, "w", stdout );
488
serr = dup( fileno(stderr) );
489
freopen( err, "w", stderr );
490
ret = spawn( link, 1 );
491
if (sout >= 0)
492
{
493
dup2( sout, fileno(stdout) );
494
close( sout );
495
}
496
if (serr >= 0)
497
{
498
dup2( serr, fileno(stderr) );
499
close( serr );
500
}
501
return ret;
502
}
503
504
static struct strarray get_link_args( const char *output_name )
505
{
506
struct strarray link_args = get_translator();
507
struct strarray flags = empty_strarray;
508
char *version;
509
510
strarray_addall( &link_args, linker_args );
511
512
if (verbose > 1) strarray_add( &flags, "-v" );
513
514
switch (target.platform)
515
{
516
case PLATFORM_APPLE:
517
strarray_add( &flags, "-bundle" );
518
strarray_add( &flags, "-multiply_defined" );
519
strarray_add( &flags, "suppress" );
520
if (image_base)
521
{
522
strarray_add( &flags, "-image_base" );
523
strarray_add( &flags, image_base );
524
}
525
/* On Mac, change -s into -Wl,-x. ld's -s switch is deprecated,
526
* and it doesn't work on Tiger with MH_BUNDLEs anyway */
527
if (strip) strarray_add( &flags, "-Wl,-x" );
528
strarray_addall( &link_args, flags );
529
return link_args;
530
531
case PLATFORM_SOLARIS:
532
{
533
char *mapfile = make_temp_file( output_name, ".map" );
534
create_file( mapfile, 0644, "text = A%s;\ndata = A%s;\n", section_align, section_align );
535
strarray_add( &flags, strmake("-Wl,-M,%s", mapfile) );
536
}
537
break;
538
539
case PLATFORM_ANDROID:
540
/* the Android loader requires a soname for all libraries */
541
strarray_add( &flags, strmake( "-Wl,-soname,%s.so", output_name ));
542
break;
543
544
case PLATFORM_MINGW:
545
case PLATFORM_CYGWIN:
546
strarray_add( &link_args, "-nodefaultlibs" );
547
strarray_add( &link_args, "-nostartfiles" );
548
549
if (is_shared || is_win16_app)
550
{
551
strarray_add( &flags, "-shared" );
552
strarray_add( &flags, "-Wl,--kill-at" );
553
}
554
555
if (is_unicode_app) strarray_add( &flags, "-municode" );
556
strarray_add( &flags, strmake( "-Wl,--subsystem,%s", subsystem ) );
557
558
strarray_add( &flags, "-Wl,--exclude-all-symbols" );
559
strarray_add( &flags, "-Wl,--nxcompat" );
560
strarray_add( &flags, "-Wl,--dynamicbase" );
561
strarray_add( &flags, "-Wl,--disable-auto-image-base" );
562
563
if (image_base) strarray_add( &flags, strmake("-Wl,--image-base,%s", image_base ));
564
565
if (large_address_aware && target.cpu == CPU_i386)
566
strarray_add( &flags, "-Wl,--large-address-aware" );
567
568
if (entry_point)
569
strarray_add( &flags, strmake( "-Wl,--entry,%s%s", target.cpu == CPU_i386 ? "_" : "", entry_point ));
570
571
STRARRAY_FOR_EACH( file, &output_debug_files )
572
if (strendswith(file, ".pdb")) strarray_add(&link_args, strmake("-Wl,--pdb=%s", file));
573
574
if (use_build_id)
575
strarray_add( &link_args, "-Wl,--build-id");
576
577
if (output_implib)
578
strarray_add(&link_args, strmake("-Wl,--out-implib,%s", output_implib));
579
580
if (strip) strarray_add( &link_args, "-s" );
581
582
if (!try_link( link_args, "-Wl,-Xlink=-filealign:0x1000,-Xlink=-align:0x1000,-Xlink=-driver" ))
583
/* lld from llvm 10 does not support mingw style --file-alignment,
584
* but it's possible to use msvc syntax
585
* the -driver option is needed to silence a warning about using -align */
586
strarray_add( &link_args, strmake( "-Wl,-Xlink=-filealign:%s,-Xlink=-align:%s,-Xlink=-driver",
587
file_align, section_align ));
588
else if (!try_link( link_args, "-Wl,--file-alignment,0x1000,--section-alignment,0x1000" ))
589
strarray_add( &link_args, strmake( "-Wl,--file-alignment,%s,--section-alignment,%s",
590
file_align, section_align ));
591
strarray_addall( &link_args, flags );
592
return link_args;
593
594
case PLATFORM_WINDOWS:
595
strarray_add( &link_args, "-nodefaultlibs" );
596
strarray_add( &link_args, "-nostdlib" );
597
598
if (is_shared || is_win16_app)
599
{
600
strarray_add( &flags, "-shared" );
601
strarray_add( &flags, "-Wl,-kill-at" );
602
}
603
if (is_unicode_app) strarray_add( &flags, "-municode" );
604
if (nostartfiles) strarray_add( &flags, "-nostartfiles" );
605
if (image_base) strarray_add( &flags, strmake("-Wl,-base:%s", image_base ));
606
607
if (large_address_aware && target.cpu == CPU_i386)
608
strarray_add( &flags, "-Wl,-largeaddressaware" );
609
610
if (entry_point) strarray_add( &flags, strmake( "-Wl,-entry:%s", entry_point ));
611
612
if ((version = strchr( subsystem, ':' ))) subsystem = strmake( "%.*s,%s", (int)(version - subsystem), subsystem, version + 1 );
613
strarray_add( &flags, "-Xlinker" );
614
strarray_add( &flags, strmake( "-subsystem:%s", subsystem ) );
615
616
STRARRAY_FOR_EACH( file, &output_debug_files )
617
{
618
if (strendswith(file, ".pdb"))
619
{
620
strarray_add(&link_args, "-Wl,-debug");
621
strarray_add(&link_args, strmake("-Wl,-pdb:%s", file));
622
}
623
else strarray_add( &link_args, "-Wl,-debug:dwarf" );
624
}
625
626
if (strip)
627
strarray_add( &link_args, "-s" );
628
else if (!output_debug_files.count)
629
strarray_add( &link_args, "-Wl,-debug:dwarf" );
630
631
if (use_build_id)
632
strarray_add( &link_args, "-Wl,-build-id");
633
634
if (output_implib)
635
strarray_add(&link_args, strmake("-Wl,-implib:%s", output_implib));
636
else
637
strarray_add(&link_args, strmake("-Wl,-implib:%s", make_temp_file( output_name, ".lib" )));
638
639
strarray_add( &link_args, strmake( "-Wl,-filealign:%s,-align:%s,-driver", file_align, section_align ));
640
strarray_add( &link_args, "-Wl,-merge:.CRT=.rdata" );
641
642
strarray_addall( &link_args, flags );
643
return link_args;
644
645
default:
646
if (image_base)
647
{
648
if (!try_link( link_args, strmake("-Wl,-Ttext-segment=%s", image_base)) )
649
strarray_add( &flags, strmake("-Wl,-Ttext-segment=%s", image_base) );
650
}
651
if (!try_link( link_args, "-Wl,-z,max-page-size=0x1000"))
652
strarray_add( &flags, "-Wl,-z,max-page-size=0x1000");
653
break;
654
}
655
656
if (use_build_id)
657
strarray_add( &link_args, "-Wl,--build-id");
658
659
/* generic Unix shared library flags */
660
661
if (strip) strarray_add( &link_args, "-s" );
662
strarray_add( &link_args, "-shared" );
663
strarray_add( &link_args, "-Wl,-Bsymbolic" );
664
if (!noshortwchar && target.cpu == CPU_ARM)
665
strarray_add( &flags, "-Wl,--no-wchar-size-warning" );
666
if (!try_link( link_args, "-Wl,-z,defs" ))
667
strarray_add( &flags, "-Wl,-z,defs" );
668
669
strarray_addall( &link_args, flags );
670
return link_args;
671
}
672
673
static const char *get_multiarch_dir( struct target target )
674
{
675
switch (target.cpu)
676
{
677
case CPU_i386: return "/i386-linux-gnu";
678
case CPU_x86_64: return "/x86_64-linux-gnu";
679
case CPU_ARM: return "/arm-linux-gnueabi";
680
case CPU_ARM64: return "/aarch64-linux-gnu";
681
default:
682
assert(0);
683
}
684
return NULL;
685
}
686
687
static char *get_lib_dir(void)
688
{
689
const char *stdlibpath[] = { libdir, LIBDIR, "/usr/lib", "/usr/local/lib", "/lib" };
690
const char *bit_suffix, *other_bit_suffix, *build_multiarch, *target_multiarch, *winecrt0;
691
const char *root = sysroot ? sysroot : "";
692
unsigned int i;
693
struct stat st;
694
size_t build_len, target_len;
695
696
bit_suffix = get_target_ptr_size( target ) == 8 ? "64" : "32";
697
other_bit_suffix = get_target_ptr_size( target ) == 8 ? "32" : "64";
698
winecrt0 = strmake( "/wine%s/libwinecrt0.a", get_arch_dir( target ));
699
build_multiarch = get_multiarch_dir( get_default_target() );
700
target_multiarch = get_multiarch_dir( target );
701
build_len = strlen( build_multiarch );
702
target_len = strlen( target_multiarch );
703
704
for (i = 0; i < ARRAY_SIZE(stdlibpath); i++)
705
{
706
const char *root = (i && sysroot) ? sysroot : "";
707
char *p, *buffer;
708
709
if (!stdlibpath[i]) continue;
710
buffer = xmalloc( strlen(root) + strlen(stdlibpath[i]) +
711
strlen("/arm-linux-gnueabi") + strlen(winecrt0) + 1 );
712
strcpy( buffer, root );
713
strcat( buffer, stdlibpath[i] );
714
p = buffer + strlen(buffer);
715
while (p > buffer && p[-1] == '/') p--;
716
strcpy( p, winecrt0 );
717
if (!stat( buffer, &st )) goto found;
718
if (p > buffer + 2 && (!memcmp( p - 2, "32", 2 ) || !memcmp( p - 2, "64", 2 )))
719
{
720
p -= 2;
721
strcpy( p, winecrt0 );
722
if (!stat( buffer, &st )) goto found;
723
}
724
strcpy( p, bit_suffix );
725
strcat( p, winecrt0 );
726
if (!stat( buffer, &st )) goto found;
727
strcpy( p, target_multiarch );
728
strcat( p, winecrt0 );
729
if (!stat( buffer, &st )) goto found;
730
731
strcpy( buffer, root );
732
strcat( buffer, stdlibpath[i] );
733
p = buffer + strlen(buffer);
734
while (p > buffer && p[-1] == '/') p--;
735
strcpy( p, winecrt0 );
736
737
/* try to fixup each parent dirs named lib, lib32 or lib64 with target bitness suffix */
738
while (p > buffer)
739
{
740
p--;
741
while (p > buffer && *p != '/') p--;
742
if (*p != '/') break;
743
744
/* try s/$build_cpu/$target_cpu/ on multiarch */
745
if (get_default_target().cpu != target.cpu &&
746
!memcmp( p, build_multiarch, build_len ) && p[build_len] == '/')
747
{
748
memmove( p + target_len, p + build_len, strlen( p + build_len ) + 1 );
749
memcpy( p, target_multiarch, target_len );
750
if (!stat( buffer, &st )) goto found;
751
memmove( p + build_len, p + target_len, strlen( p + target_len ) + 1 );
752
memcpy( p, build_multiarch, build_len );
753
}
754
755
if (memcmp( p + 1, "lib", 3 )) continue;
756
if (p[4] == '/')
757
{
758
memmove( p + 6, p + 4, strlen( p + 4 ) + 1 );
759
memcpy( p + 4, bit_suffix, 2 );
760
if (!stat( buffer, &st )) goto found;
761
memmove( p + 4, p + 6, strlen( p + 6 ) + 1 );
762
}
763
else if (!memcmp( p + 4, other_bit_suffix, 2 ) && p[6] == '/')
764
{
765
memcpy( p + 4, bit_suffix, 2 );
766
if (!stat( buffer, &st )) goto found;
767
memmove( p + 4, p + 6, strlen( p + 6 ) + 1 );
768
if (!stat( buffer, &st )) goto found;
769
memmove( p + 6, p + 4, strlen( p + 4 ) + 1 );
770
memcpy( p + 4, other_bit_suffix, 2 );
771
}
772
}
773
774
free( buffer );
775
continue;
776
777
found:
778
buffer[strlen(buffer) - strlen(winecrt0)] = 0;
779
return buffer;
780
}
781
return strmake( "%s%s", root, LIBDIR );
782
}
783
784
/* add compatibility defines to make non-PE platforms more Windows-like */
785
static struct strarray get_compat_defines( int gcc_defs )
786
{
787
struct strarray args = empty_strarray;
788
789
if (processor != proc_cpp)
790
{
791
if (gcc_defs && !wine_objdir && !noshortwchar)
792
{
793
strarray_add(&args, "-fshort-wchar");
794
strarray_add(&args, "-DWINE_UNICODE_NATIVE");
795
}
796
strarray_add(&args, "-D_REENTRANT");
797
if (use_pic)
798
strarray_add(&args, "-fPIC");
799
else
800
strarray_add(&args, "-fno-PIC");
801
}
802
803
if (get_target_ptr_size( target ) == 8)
804
{
805
strarray_add(&args, "-DWIN64");
806
strarray_add(&args, "-D_WIN64");
807
strarray_add(&args, "-D__WIN64");
808
strarray_add(&args, "-D__WIN64__");
809
}
810
811
strarray_add(&args, "-DWIN32");
812
strarray_add(&args, "-D_WIN32");
813
strarray_add(&args, "-D__WIN32");
814
strarray_add(&args, "-D__WIN32__");
815
strarray_add(&args, "-D__WINNT");
816
strarray_add(&args, "-D__WINNT__");
817
818
if (gcc_defs)
819
{
820
switch (target.cpu)
821
{
822
case CPU_x86_64:
823
case CPU_ARM64:
824
strarray_add(&args, "-D__stdcall=__attribute__((ms_abi))");
825
strarray_add(&args, "-D__cdecl=__stdcall");
826
strarray_add(&args, "-D__fastcall=__stdcall");
827
break;
828
case CPU_i386:
829
strarray_add(&args, "-D__stdcall=__attribute__((__stdcall__)) __attribute__((__force_align_arg_pointer__))");
830
strarray_add(&args, "-D__cdecl=__attribute__((__cdecl__)) __attribute__((__force_align_arg_pointer__))");
831
strarray_add(&args, "-D__fastcall=__attribute__((__fastcall__))");
832
break;
833
case CPU_ARM:
834
strarray_add(&args, "-D__stdcall=__attribute__((pcs(\"aapcs-vfp\")))");
835
strarray_add(&args, "-D__cdecl=__stdcall");
836
strarray_add(&args, "-D__fastcall=__stdcall");
837
break;
838
case CPU_ARM64EC:
839
break;
840
}
841
strarray_add(&args, "-D_stdcall=__stdcall");
842
strarray_add(&args, "-D_cdecl=__cdecl");
843
strarray_add(&args, "-D_fastcall=__fastcall");
844
strarray_add(&args, "-D__declspec(x)=__declspec_##x");
845
strarray_add(&args, "-D__declspec_align(x)=__attribute__((aligned(x)))");
846
strarray_add(&args, "-D__declspec_allocate(x)=__attribute__((section(x)))");
847
strarray_add(&args, "-D__declspec_deprecated=__attribute__((deprecated))");
848
strarray_add(&args, "-D__declspec_dllimport=__attribute__((dllimport))");
849
strarray_add(&args, "-D__declspec_dllexport=__attribute__((dllexport))");
850
strarray_add(&args, "-D__declspec_naked=__attribute__((naked))");
851
strarray_add(&args, "-D__declspec_noinline=__attribute__((noinline))");
852
strarray_add(&args, "-D__declspec_noreturn=__attribute__((noreturn))");
853
strarray_add(&args, "-D__declspec_nothrow=__attribute__((nothrow))");
854
strarray_add(&args, "-D__declspec_novtable=__attribute__(())"); /* ignore it */
855
strarray_add(&args, "-D__declspec_selectany=__attribute__((weak))");
856
strarray_add(&args, "-D__declspec_thread=__thread");
857
}
858
859
strarray_add(&args, "-D__int8=char");
860
strarray_add(&args, "-D__int16=short");
861
strarray_add(&args, "-D__int32=int");
862
if (get_target_ptr_size( target ) == 8)
863
strarray_add(&args, "-D__int64=long");
864
else
865
strarray_add(&args, "-D__int64=long long");
866
867
return args;
868
}
869
870
static void compile( struct strarray files, const char *output_name, int compile_only )
871
{
872
struct strarray comp_args = get_translator();
873
unsigned int j;
874
int gcc_defs = 0;
875
struct strarray gcc;
876
struct strarray gpp;
877
878
if (force_pointer_size)
879
strarray_add( &comp_args, strmake("-m%u", 8 * force_pointer_size ) );
880
switch(processor)
881
{
882
case proc_cpp: gcc_defs = 1; break;
883
/* Note: if the C compiler is gcc we assume the C++ compiler is too */
884
/* mixing different C and C++ compilers isn't supported in configure anyway */
885
case proc_cc:
886
case proc_cxx:
887
gcc = build_tool_name( target_alias, tool_cc );
888
gpp = build_tool_name( target_alias, tool_cxx );
889
STRARRAY_FOR_EACH( cc, &comp_args )
890
{
891
STRARRAY_FOR_EACH( str, &gcc )
892
if ((gcc_defs = str[0] != '-' && strendswith(cc, str))) break;
893
if (gcc_defs) break;
894
STRARRAY_FOR_EACH( str, &gpp )
895
if ((gcc_defs = str[0] != '-' && strendswith(cc, str))) break;
896
if (gcc_defs) break;
897
}
898
break;
899
}
900
901
if (!is_pe) strarray_addall( &comp_args, get_compat_defines( gcc_defs ));
902
903
strarray_add(&comp_args, "-D__WINE__");
904
905
/* options we handle explicitly */
906
if (compile_only)
907
strarray_add(&comp_args, "-c");
908
if (output_name)
909
{
910
strarray_add(&comp_args, "-o");
911
strarray_add(&comp_args, output_name);
912
}
913
914
if (verbose > 1) strarray_add( &comp_args, "-v" );
915
916
/* the rest of the pass-through parameters */
917
strarray_addall(&comp_args, compiler_args);
918
919
/* last, but not least, the files */
920
STRARRAY_FOR_EACH( file, &files )
921
{
922
if (file[0] == '-')
923
{
924
/* keep -x and bare '-' (i.e. stdin) options */
925
if (file[1] && file[1] != 'x') continue;
926
}
927
strarray_add(&comp_args, file);
928
}
929
930
/* standard includes come last in the include search path */
931
if (!wine_objdir && !nostdinc)
932
{
933
const char *incl_dirs[] = { INCLUDEDIR, "/usr/include", "/usr/local/include" };
934
const char *root = isysroot ? isysroot : sysroot ? sysroot : "";
935
const char *isystem = gcc_defs ? "-isystem" : "-I";
936
const char *idirafter = gcc_defs ? "-idirafter" : "-I";
937
938
if (use_msvcrt)
939
{
940
if (includedir) strarray_add( &comp_args, strmake( "%s%s/wine/msvcrt", isystem, includedir ));
941
for (j = 0; j < ARRAY_SIZE(incl_dirs); j++)
942
{
943
if (j && !strcmp( incl_dirs[0], incl_dirs[j] )) continue;
944
strarray_add(&comp_args, strmake( "%s%s%s/wine/msvcrt", isystem, root, incl_dirs[j] ));
945
}
946
strarray_add(&comp_args, "-D__MSVCRT__");
947
}
948
if (includedir)
949
{
950
strarray_add( &comp_args, strmake( "%s%s/wine/windows", isystem, includedir ));
951
if (!use_msvcrt) strarray_add( &comp_args, strmake( "%s%s", idirafter, includedir ));
952
}
953
for (j = 0; j < ARRAY_SIZE(incl_dirs); j++)
954
{
955
if (j && !strcmp( incl_dirs[0], incl_dirs[j] )) continue;
956
strarray_add(&comp_args, strmake( "%s%s%s/wine/windows", isystem, root, incl_dirs[j] ));
957
if (!use_msvcrt) strarray_add(&comp_args, strmake( "%s%s%s", idirafter, root, incl_dirs[j] ));
958
}
959
}
960
else if (wine_objdir)
961
strarray_add(&comp_args, strmake("-I%s/include", wine_objdir) );
962
963
spawn(comp_args, 0);
964
}
965
966
static const char* compile_to_object(const char* file, const char* lang)
967
{
968
char *output_name = make_temp_file(get_basename_noext(file), ".o");
969
struct strarray files = empty_strarray;
970
971
if (lang) strarray_add(&files, lang);
972
strarray_add(&files, file);
973
compile(files, output_name, 1);
974
return output_name;
975
}
976
977
/* return the initial set of options needed to run winebuild */
978
static struct strarray get_winebuild_args( const char *target )
979
{
980
const char *binary;
981
struct strarray spec_args = empty_strarray;
982
983
if (!(binary = find_binary( winebuild ))) error( "Could not find winebuild\n" );
984
strarray_add( &spec_args, binary );
985
if (verbose) strarray_add( &spec_args, "-v" );
986
if (keep_generated) strarray_add( &spec_args, "--save-temps" );
987
if (target)
988
{
989
strarray_add( &spec_args, "--target" );
990
strarray_add( &spec_args, target );
991
}
992
if (force_pointer_size)
993
strarray_add(&spec_args, strmake("-m%u", 8 * force_pointer_size ));
994
STRARRAY_FOR_EACH( dir, &prefix_dirs )
995
strarray_add( &spec_args, strmake( "-B%s", dir ));
996
strarray_addall( &spec_args, winebuild_args );
997
return spec_args;
998
}
999
1000
static void fixup_constructors( const char *file )
1001
{
1002
struct strarray args = get_winebuild_args( target_alias );
1003
1004
strarray_add( &args, "--fixup-ctors" );
1005
strarray_add( &args, file );
1006
spawn( args, 0 );
1007
}
1008
1009
static void make_wine_builtin( const char *file )
1010
{
1011
struct strarray args = get_winebuild_args( target_alias );
1012
1013
strarray_add( &args, "--builtin" );
1014
strarray_add( &args, file );
1015
spawn( args, 0 );
1016
}
1017
1018
/* check if there is a static lib associated to a given dll */
1019
static char *find_static_lib( const char *dll )
1020
{
1021
char *lib = strmake("%s.a", dll);
1022
if (get_file_type(lib) == file_arh) return lib;
1023
free( lib );
1024
return NULL;
1025
}
1026
1027
static const char *find_libgcc(void)
1028
{
1029
const char *out = make_temp_file( "find_libgcc", ".out" );
1030
const char *err = make_temp_file( "find_libgcc", ".err" );
1031
struct strarray link = get_translator();
1032
int sout = -1, serr = -1;
1033
char *libgcc, *p;
1034
struct stat st;
1035
size_t cnt;
1036
int ret;
1037
1038
STRARRAY_FOR_EACH( arg, &linker_args )
1039
if (strcmp(arg, "--no-default-config" )) strarray_add( &link, arg );
1040
1041
strarray_add( &link, "-print-libgcc-file-name" );
1042
1043
sout = dup( fileno(stdout) );
1044
freopen( out, "w", stdout );
1045
serr = dup( fileno(stderr) );
1046
freopen( err, "w", stderr );
1047
ret = spawn( link, 1 );
1048
if (sout >= 0)
1049
{
1050
dup2( sout, fileno(stdout) );
1051
close( sout );
1052
}
1053
if (serr >= 0)
1054
{
1055
dup2( serr, fileno(stderr) );
1056
close( serr );
1057
}
1058
1059
if (ret || stat(out, &st) || !st.st_size) return NULL;
1060
1061
libgcc = xmalloc(st.st_size + 1);
1062
sout = open(out, O_RDONLY);
1063
if (sout == -1) return NULL;
1064
cnt = read(sout, libgcc, st.st_size);
1065
close(sout);
1066
libgcc[cnt] = 0;
1067
if ((p = strchr(libgcc, '\n'))) *p = 0;
1068
return libgcc;
1069
}
1070
1071
1072
/* add specified library to the list of files */
1073
static void add_library( struct strarray lib_dirs, struct strarray *files, const char *library )
1074
{
1075
char *static_lib, *fullname = 0;
1076
1077
switch(get_lib_type(lib_dirs, library, &fullname))
1078
{
1079
case file_arh:
1080
strarray_add(files, strmake("-a%s", fullname));
1081
break;
1082
case file_dll:
1083
strarray_add(files, strmake("-d%s", fullname));
1084
if ((static_lib = find_static_lib(fullname)))
1085
{
1086
strarray_add(files, strmake("-a%s",static_lib));
1087
free(static_lib);
1088
}
1089
break;
1090
case file_so:
1091
default:
1092
/* keep it anyway, the linker may know what to do with it */
1093
strarray_add(files, strmake("-l%s", library));
1094
break;
1095
}
1096
free(fullname);
1097
}
1098
1099
/* run winebuild to generate the .spec.o file */
1100
static void build_spec_obj( const char *spec_file, const char *output_file,
1101
const char *target_name, struct strarray files,
1102
struct strarray resources, struct strarray *spec_objs )
1103
{
1104
struct strarray spec_args = get_winebuild_args( target_name );
1105
struct strarray tool;
1106
const char *spec_o_name, *output_name;
1107
1108
/* get the filename from the path */
1109
output_name = get_basename( output_file );
1110
1111
tool = build_tool_name( target_name, tool_cc );
1112
strarray_add( &spec_args, strmake( "--cc-cmd=%s", strarray_tostring( tool, " " )));
1113
if (!is_pe)
1114
{
1115
tool = build_tool_name( target_name, tool_ld );
1116
strarray_add( &spec_args, strmake( "--ld-cmd=%s", strarray_tostring( tool, " " )));
1117
}
1118
1119
spec_o_name = make_temp_file(output_name, ".spec.o");
1120
if (!is_pe)
1121
{
1122
if (use_pic) strarray_add(&spec_args, "-fPIC");
1123
if (use_msvcrt) strarray_add(&spec_args, "-mno-cygwin");
1124
if (unwind_tables) strarray_add( &spec_args, "-fasynchronous-unwind-tables" );
1125
}
1126
strarray_add(&spec_args, is_shared ? "--dll" : "--exe");
1127
if (fake_module)
1128
{
1129
strarray_add(&spec_args, "--fake-module");
1130
strarray_add(&spec_args, "-o");
1131
strarray_add(&spec_args, output_file);
1132
}
1133
else
1134
{
1135
strarray_add(&spec_args, "-o");
1136
strarray_add(&spec_args, spec_o_name);
1137
}
1138
if (spec_file)
1139
{
1140
strarray_add(&spec_args, "-E");
1141
strarray_add(&spec_args, spec_file);
1142
}
1143
else
1144
{
1145
strarray_add(&spec_args, "-F");
1146
strarray_add(&spec_args, output_name);
1147
}
1148
1149
strarray_add( &spec_args, "--subsystem" );
1150
strarray_add( &spec_args, subsystem );
1151
1152
if (!is_shared && large_address_aware) strarray_add( &spec_args, "--large-address-aware" );
1153
1154
if (target.platform == PLATFORM_WINDOWS && target.cpu == CPU_i386)
1155
strarray_add(&spec_args, "--safeseh");
1156
1157
if (entry_point)
1158
{
1159
strarray_add(&spec_args, "--entry");
1160
strarray_add(&spec_args, entry_point);
1161
}
1162
1163
if (!is_pe) STRARRAY_FOR_EACH( imp, &delayimports ) strarray_add(&spec_args, strmake("-d%s", imp));
1164
1165
strarray_addall( &spec_args, resources );
1166
1167
/* add other files */
1168
strarray_add(&spec_args, "--");
1169
STRARRAY_FOR_EACH( file, &files )
1170
{
1171
switch(file[1])
1172
{
1173
case 'd':
1174
case 'a':
1175
case 'o':
1176
strarray_add(&spec_args, file + 2);
1177
break;
1178
}
1179
}
1180
1181
spawn(spec_args, 0);
1182
strarray_add( spec_objs, spec_o_name );
1183
}
1184
1185
/* run winebuild to generate a data-only library */
1186
static void build_data_lib( const char *spec_file, const char *output_file, struct strarray files )
1187
{
1188
struct strarray spec_args = get_winebuild_args( target_alias );
1189
1190
strarray_add(&spec_args, is_shared ? "--dll" : "--exe");
1191
strarray_add(&spec_args, "-o");
1192
strarray_add(&spec_args, output_file);
1193
if (spec_file)
1194
{
1195
strarray_add(&spec_args, "-E");
1196
strarray_add(&spec_args, spec_file);
1197
}
1198
1199
/* add resource files */
1200
STRARRAY_FOR_EACH( file, &files ) if (file[1] == 'r') strarray_add(&spec_args, file);
1201
1202
spawn(spec_args, 0);
1203
}
1204
1205
static void build(struct strarray input_files, const char *output)
1206
{
1207
struct strarray resources = empty_strarray;
1208
struct strarray spec_objs = empty_strarray;
1209
struct strarray lib_dirs = empty_strarray;
1210
struct strarray files = empty_strarray;
1211
struct strarray link_args;
1212
char *output_file;
1213
const char *output_name, *spec_file, *lang;
1214
const char *libgcc = NULL;
1215
int generate_app_loader = 1;
1216
const char *crt_lib = NULL;
1217
1218
/* NOTE: for the files array we'll use the following convention:
1219
* -axxx: xxx is an archive (.a)
1220
* -dxxx: xxx is a DLL (.def)
1221
* -lxxx: xxx is an unsorted library
1222
* -oxxx: xxx is an object (.o)
1223
* -rxxx: xxx is a resource (.res)
1224
* -sxxx: xxx is a shared lib (.so)
1225
* -xlll: lll is the language (c, c++, etc.)
1226
*/
1227
1228
output_file = xstrdup( output ? output : "a.out" );
1229
1230
/* 'winegcc -o app xxx.exe.so' only creates the load script */
1231
if (input_files.count == 1 && strendswith(input_files.str[0], ".exe.so"))
1232
{
1233
create_file(output_file, 0755, app_loader_template, input_files.str[0]);
1234
return;
1235
}
1236
1237
if (is_static) error("Static linking is not supported\n");
1238
1239
/* generate app loader only for .exe */
1240
if (is_shared || is_pe || strendswith(output_file, ".so"))
1241
generate_app_loader = 0;
1242
1243
/* normalize the filename a bit: strip .so, ensure it has proper ext */
1244
if (!strchr(get_basename( output_file ), '.'))
1245
output_file = strmake("%s.%s", output_file, is_shared ? "dll" : "exe");
1246
else if (strendswith(output_file, ".so"))
1247
output_file[strlen(output_file) - 3] = 0;
1248
output_file_name = is_pe ? output_file : strmake( "%s.so", output_file );
1249
1250
/* get the filename from the path */
1251
output_name = get_basename( output_file );
1252
1253
/* prepare the linking path */
1254
if (!wine_objdir)
1255
{
1256
char *lib_dir = get_lib_dir();
1257
strarray_addall( &lib_dirs, lib_path_dirs );
1258
strarray_add( &lib_dirs, strmake( "%s/wine%s", lib_dir, get_arch_dir( target )));
1259
strarray_add( &lib_dirs, lib_dir );
1260
}
1261
else
1262
{
1263
strarray_add(&lib_dirs, strmake("%s/dlls", wine_objdir));
1264
strarray_add(&lib_dirs, strmake("%s/libs", wine_objdir));
1265
strarray_addall(&lib_dirs, lib_path_dirs);
1266
}
1267
1268
/* mark the files with their appropriate type */
1269
spec_file = lang = 0;
1270
STRARRAY_FOR_EACH( file, &input_files )
1271
{
1272
if (file[0] != '-')
1273
{
1274
switch(get_file_type(file))
1275
{
1276
case file_spec:
1277
if (spec_file)
1278
error("Only one spec file can be specified\n");
1279
spec_file = file;
1280
break;
1281
case file_rc:
1282
/* FIXME: invoke wrc to build it */
1283
error("Can't compile .rc file at the moment: %s\n", file);
1284
break;
1285
case file_res:
1286
strarray_add(&files, strmake("-r%s", file));
1287
break;
1288
case file_obj:
1289
strarray_add(&files, strmake("-o%s", file));
1290
break;
1291
case file_arh:
1292
if (use_msvcrt)
1293
{
1294
char *p = get_basename( file );
1295
if (!strncmp(p, "libmsvcr", 8) || !strncmp(p, "libucrt", 7)) crt_lib = file;
1296
}
1297
strarray_add(&files, strmake("-a%s", file));
1298
break;
1299
case file_so:
1300
strarray_add(&files, strmake("-s%s", file));
1301
break;
1302
case file_na:
1303
error("File does not exist: %s\n", file);
1304
break;
1305
default:
1306
file = compile_to_object(file, lang);
1307
strarray_add(&files, strmake("-o%s", file));
1308
break;
1309
}
1310
}
1311
else if (file[1] == 'l')
1312
add_library( lib_dirs, &files, file + 2 );
1313
else if (file[1] == 'x')
1314
lang = file;
1315
else if(file[1] == 'W')
1316
strarray_add(&files, file);
1317
}
1318
1319
/* add the default libraries, if needed */
1320
1321
if (!wine_objdir && !nodefaultlibs)
1322
{
1323
if (!strncmp( subsystem, "windows", 7 ))
1324
{
1325
add_library(lib_dirs, &files, "shell32");
1326
add_library(lib_dirs, &files, "comdlg32");
1327
add_library(lib_dirs, &files, "gdi32");
1328
}
1329
add_library(lib_dirs, &files, "advapi32");
1330
add_library(lib_dirs, &files, "user32");
1331
add_library(lib_dirs, &files, "winecrt0");
1332
if (target.platform == PLATFORM_WINDOWS)
1333
add_library(lib_dirs, &files, "compiler-rt");
1334
if (use_msvcrt)
1335
{
1336
if (!crt_lib)
1337
{
1338
if (strncmp( output_name, "msvcr", 5 ) &&
1339
strncmp( output_name, "ucrt", 4 ) &&
1340
strcmp( output_name, "crtdll.dll" ))
1341
add_library(lib_dirs, &files, "ucrtbase");
1342
}
1343
else strarray_add(&files, strmake("-a%s", crt_lib));
1344
}
1345
if (is_win16_app) add_library(lib_dirs, &files, "kernel");
1346
add_library(lib_dirs, &files, "kernel32");
1347
add_library(lib_dirs, &files, "ntdll");
1348
}
1349
1350
/* set default entry point, if needed */
1351
if (!entry_point)
1352
{
1353
if (!strcmp( subsystem, "native" ))
1354
entry_point = (is_pe && target.cpu == CPU_i386) ? "DriverEntry@8" : "DriverEntry";
1355
else if (use_msvcrt && !is_shared && !is_win16_app)
1356
entry_point = is_unicode_app ? "wmainCRTStartup" : "mainCRTStartup";
1357
}
1358
1359
/* run winebuild to generate the .spec.o file */
1360
if (data_only)
1361
{
1362
build_data_lib( spec_file, output_file, files );
1363
return;
1364
}
1365
1366
STRARRAY_FOR_EACH( file, &files ) if (file[1] == 'r') strarray_add( &resources, file );
1367
1368
build_spec_obj( spec_file, output_file, target_alias, files, resources, &spec_objs );
1369
if (is_arm64x)
1370
{
1371
const char *suffix = strchr( target_alias, '-' );
1372
if (!suffix) suffix = "";
1373
build_spec_obj( spec_file, output_file, strmake( "aarch64%s", suffix ),
1374
files, empty_strarray, &spec_objs );
1375
}
1376
1377
if (fake_module) return; /* nothing else to do */
1378
1379
if (is_pe && !entry_point && (is_shared || is_win16_app))
1380
entry_point = target.cpu == CPU_i386 ? "DllMainCRTStartup@12" : "DllMainCRTStartup";
1381
1382
/* link everything together now */
1383
link_args = get_link_args( output_name );
1384
1385
switch (target.platform)
1386
{
1387
case PLATFORM_MINGW:
1388
case PLATFORM_CYGWIN:
1389
libgcc = find_libgcc();
1390
if (!libgcc) libgcc = "-lgcc";
1391
break;
1392
default:
1393
break;
1394
}
1395
1396
strarray_add(&link_args, "-o");
1397
strarray_add(&link_args, output_file_name);
1398
1399
STRARRAY_FOR_EACH( dir, &lib_dirs ) strarray_add(&link_args, strmake("-L%s", dir));
1400
1401
strarray_addall( &link_args, spec_objs );
1402
1403
if (is_pe)
1404
{
1405
STRARRAY_FOR_EACH( imp, &delayimports )
1406
{
1407
if (target.platform == PLATFORM_WINDOWS)
1408
strarray_add(&link_args, strmake("-Wl,-delayload:%s", imp));
1409
else
1410
strarray_add(&link_args, strmake("-Wl,-delayload,%s",imp));
1411
}
1412
}
1413
1414
STRARRAY_FOR_EACH( file, &files )
1415
{
1416
const char* name = file + 2;
1417
switch(file[1])
1418
{
1419
case 'l':
1420
strarray_add(&link_args, strmake("-l%s", name));
1421
break;
1422
case 's':
1423
case 'o':
1424
strarray_add(&link_args, name);
1425
break;
1426
case 'a':
1427
if (!use_msvcrt && !lib_suffix && strchr(name, '/'))
1428
{
1429
const char *p = get_basename( name );
1430
1431
/* don't link to ntdll or ntoskrnl in non-msvcrt mode
1432
* since they export CRT functions */
1433
if (!strcmp( p, "libntdll.a" )) break;
1434
if (!strcmp( p, "libntoskrnl.a" )) break;
1435
}
1436
strarray_add(&link_args, name);
1437
break;
1438
case 'W':
1439
strarray_add(&link_args, file);
1440
break;
1441
}
1442
}
1443
1444
if (!nostdlib && !is_pe)
1445
{
1446
strarray_add(&link_args, "-ldl");
1447
strarray_add(&link_args, "-lm");
1448
strarray_add(&link_args, "-lc");
1449
}
1450
1451
if (libgcc) strarray_add(&link_args, libgcc);
1452
1453
atexit( cleanup_output_files );
1454
1455
spawn(link_args, 0);
1456
1457
STRARRAY_FOR_EACH( file, &output_debug_files )
1458
{
1459
struct strarray tool, objcopy;
1460
1461
if (strendswith(file, ".pdb")) continue;
1462
objcopy = build_tool_name(target_alias, tool_objcopy);
1463
1464
tool = empty_strarray;
1465
strarray_addall( &tool, objcopy );
1466
strarray_add(&tool, "--only-keep-debug");
1467
strarray_add(&tool, output_file_name);
1468
strarray_add(&tool, file);
1469
spawn(tool, 1);
1470
1471
tool = empty_strarray;
1472
strarray_addall( &tool, objcopy );
1473
strarray_add(&tool, "--strip-debug");
1474
strarray_add(&tool, output_file_name);
1475
spawn(tool, 1);
1476
1477
tool = empty_strarray;
1478
strarray_addall( &tool, objcopy );
1479
strarray_add(&tool, "--add-gnu-debuglink");
1480
strarray_add(&tool, file);
1481
strarray_add(&tool, output_file_name);
1482
spawn(tool, 0);
1483
}
1484
1485
if (output_implib && !is_pe)
1486
{
1487
struct strarray tool, implib_args;
1488
1489
if (!spec_file)
1490
error("--out-implib requires a .spec or .def file\n");
1491
1492
implib_args = get_winebuild_args( target_alias );
1493
tool = build_tool_name( target_alias, tool_cc );
1494
strarray_add( &implib_args, strmake( "--cc-cmd=%s", strarray_tostring( tool, " " )));
1495
tool = build_tool_name( target_alias, tool_ld );
1496
strarray_add( &implib_args, strmake( "--ld-cmd=%s", strarray_tostring( tool, " " )));
1497
1498
strarray_add(&implib_args, "--implib");
1499
strarray_add(&implib_args, "-o");
1500
strarray_add(&implib_args, output_implib);
1501
strarray_add(&implib_args, "--export");
1502
strarray_add(&implib_args, spec_file);
1503
1504
spawn(implib_args, 0);
1505
}
1506
1507
if (!is_pe) fixup_constructors( output_file_name );
1508
else if (wine_builtin) make_wine_builtin( output_file_name );
1509
1510
/* create the loader script */
1511
if (generate_app_loader)
1512
create_file(output_file, 0755, app_loader_template, strmake("%s.so", output_name));
1513
}
1514
1515
1516
static void forward(void)
1517
{
1518
struct strarray args = get_translator();
1519
1520
strarray_addall(&args, compiler_args);
1521
strarray_addall(&args, linker_args);
1522
spawn(args, 0);
1523
}
1524
1525
static int is_linker_arg(const char* arg)
1526
{
1527
static const char* link_switches[] =
1528
{
1529
"-nostdlib", "-s", "-static", "-static-libgcc", "-static-libstdc++",
1530
"-shared", "-shared-libgcc", "-symbolic", "-framework", "--coverage",
1531
"-fprofile-generate", "-fprofile-use"
1532
};
1533
unsigned int j;
1534
1535
switch (arg[1])
1536
{
1537
case 'R':
1538
case 'z':
1539
case 'u':
1540
return 1;
1541
case 'W':
1542
if (strncmp("-Wl,", arg, 4) == 0) return 1;
1543
break;
1544
case 'X':
1545
if (strcmp("-Xlinker", arg) == 0) return 1;
1546
break;
1547
case 'a':
1548
if (strcmp("-arch", arg) == 0) return 1;
1549
break;
1550
case 'f':
1551
if (strncmp("-fuse-ld=", arg, 9) == 0) return 1;
1552
break;
1553
case 'r':
1554
if (strncmp("-rtlib=", arg, 7) == 0) return 1;
1555
break;
1556
}
1557
1558
for (j = 0; j < ARRAY_SIZE(link_switches); j++)
1559
if (strcmp(link_switches[j], arg) == 0) return 1;
1560
1561
return 0;
1562
}
1563
1564
static int is_option( struct strarray args, int i, const char *option, const char **option_arg )
1565
{
1566
if (!strcmp( args.str[i], option ))
1567
{
1568
if (args.count == i) error( "option %s requires an argument\n", args.str[i] );
1569
*option_arg = args.str[i + 1];
1570
return 1;
1571
}
1572
if (!strncmp( args.str[i], option, strlen(option) ) && args.str[i][strlen(option)] == '=')
1573
{
1574
*option_arg = args.str[i] + strlen(option) + 1;
1575
return 1;
1576
}
1577
return 0;
1578
}
1579
1580
static struct strarray read_args_from_file( const char *name )
1581
{
1582
struct strarray args = empty_strarray;
1583
char *input_buffer = NULL, *iter, *end, *opt, *out;
1584
struct stat st;
1585
int fd;
1586
1587
if ((fd = open( name, O_RDONLY | O_BINARY )) == -1) error( "Cannot open %s\n", name );
1588
fstat( fd, &st );
1589
if (st.st_size)
1590
{
1591
input_buffer = xmalloc( st.st_size + 1 );
1592
if (read( fd, input_buffer, st.st_size ) != st.st_size) error( "Cannot read %s\n", name );
1593
}
1594
close( fd );
1595
end = input_buffer + st.st_size;
1596
for (iter = input_buffer; iter < end; iter++)
1597
{
1598
char quote = 0;
1599
while (iter < end && isspace(*iter)) iter++;
1600
if (iter == end) break;
1601
opt = out = iter;
1602
while (iter < end && (quote || !isspace(*iter)))
1603
{
1604
if (*iter == quote)
1605
{
1606
iter++;
1607
quote = 0;
1608
}
1609
else if (*iter == '\'' || *iter == '"') quote = *iter++;
1610
else
1611
{
1612
if (*iter == '\\' && iter + 1 < end) iter++;
1613
*out++ = *iter++;
1614
}
1615
}
1616
*out = 0;
1617
strarray_add( &args, opt );
1618
}
1619
return args;
1620
}
1621
1622
int main(int argc, char **argv)
1623
{
1624
int i, c, next_is_arg = 0;
1625
int raw_compiler_arg, raw_linker_arg, raw_winebuild_arg;
1626
struct strarray args = empty_strarray;
1627
bool is_gui_app = false;
1628
const char* option_arg;
1629
char* str;
1630
1631
init_signals( exit_on_signal );
1632
bindir = get_bindir( argv[0] );
1633
libdir = get_libdir( bindir );
1634
includedir = get_includedir( bindir );
1635
target = init_argv0_target( argv[0] );
1636
path_dirs = strarray_frompath( getenv( "PATH" ));
1637
1638
/* setup tmp file removal at exit */
1639
atexit(clean_temp_files);
1640
1641
/* determine the processor type */
1642
if (strendswith(argv[0], "winecpp")) processor = proc_cpp;
1643
else if (strendswith(argv[0], "++")) processor = proc_cxx;
1644
1645
for (i = 1; i < argc; i++)
1646
if (argv[i][0] == '@')
1647
strarray_addall( &args, read_args_from_file( argv[i] + 1 ));
1648
else
1649
strarray_add( &args, argv[i] );
1650
1651
/* parse options */
1652
for (i = 0; i < args.count; i++)
1653
{
1654
if (args.str[i][0] == '-' && args.str[i][1]) /* option, except '-' alone is stdin, which is a file */
1655
{
1656
/* determine if this switch is followed by a separate argument */
1657
next_is_arg = 0;
1658
option_arg = 0;
1659
switch(args.str[i][1])
1660
{
1661
case 'x': case 'o': case 'D': case 'U':
1662
case 'I': case 'A': case 'l': case 'u':
1663
case 'b': case 'V': case 'G': case 'L':
1664
case 'B': case 'R': case 'z':
1665
if (args.str[i][2]) option_arg = &args.str[i][2];
1666
else next_is_arg = 1;
1667
break;
1668
case 'i':
1669
next_is_arg = 1;
1670
break;
1671
case 'a':
1672
if (strcmp("-aux-info", args.str[i]) == 0)
1673
next_is_arg = 1;
1674
if (strcmp("-arch", args.str[i]) == 0)
1675
next_is_arg = 1;
1676
break;
1677
case 'X':
1678
if (strcmp("-Xlinker", args.str[i]) == 0)
1679
next_is_arg = 1;
1680
break;
1681
case 'M':
1682
c = args.str[i][2];
1683
if (c == 'F' || c == 'T' || c == 'Q')
1684
{
1685
if (args.str[i][3]) option_arg = &args.str[i][3];
1686
else next_is_arg = 1;
1687
}
1688
break;
1689
case 'f':
1690
if (strcmp("-framework", args.str[i]) == 0)
1691
next_is_arg = 1;
1692
break;
1693
case 't':
1694
next_is_arg = strcmp("-target", args.str[i]) == 0;
1695
break;
1696
case '-':
1697
next_is_arg = (strcmp("--cc-cmd", args.str[i]) == 0 ||
1698
strcmp("--param", args.str[i]) == 0 ||
1699
strcmp("--sysroot", args.str[i]) == 0 ||
1700
strcmp("--target", args.str[i]) == 0 ||
1701
strcmp("--wine-objdir", args.str[i]) == 0 ||
1702
strcmp("--winebuild", args.str[i]) == 0 ||
1703
strcmp("--lib-suffix", args.str[i]) == 0);
1704
break;
1705
}
1706
if (next_is_arg)
1707
{
1708
if (i + 1 >= args.count) error("option -%c requires an argument\n", args.str[i][1]);
1709
option_arg = args.str[i+1];
1710
}
1711
1712
/* determine what options go 'as is' to the linker & the compiler */
1713
raw_linker_arg = is_linker_arg(args.str[i]);
1714
raw_compiler_arg = !raw_linker_arg;
1715
raw_winebuild_arg = 0;
1716
1717
/* do a bit of semantic analysis */
1718
switch (args.str[i][1])
1719
{
1720
case 'B':
1721
str = xstrdup(option_arg);
1722
if (strendswith(str, "/")) str[strlen(str) - 1] = 0;
1723
strarray_add(&prefix_dirs, str);
1724
raw_linker_arg = 1;
1725
break;
1726
case 'b':
1727
target_alias = option_arg;
1728
raw_compiler_arg = 0;
1729
break;
1730
case 'V':
1731
target_version = option_arg;
1732
raw_compiler_arg = 0;
1733
break;
1734
case 'c': /* compile or assemble */
1735
raw_compiler_arg = 0;
1736
if (args.str[i][2] == 0) compile_only = true;
1737
break;
1738
case 'S': /* generate assembler code */
1739
case 'E': /* preprocess only */
1740
if (args.str[i][2] == 0) skip_link = true;
1741
break;
1742
case 'f':
1743
if (strcmp("-fno-short-wchar", args.str[i]) == 0)
1744
noshortwchar = true;
1745
else if (!strcmp("-fasynchronous-unwind-tables", args.str[i]))
1746
unwind_tables = true;
1747
else if (!strcmp("-fno-asynchronous-unwind-tables", args.str[i]))
1748
unwind_tables = false;
1749
else if (!strcmp("-fms-hotpatch", args.str[i]))
1750
raw_linker_arg = 1;
1751
else if (!strcmp("-fPIC", args.str[i]) || !strcmp("-fpic", args.str[i]))
1752
use_pic = true;
1753
else if (!strcmp("-fno-PIC", args.str[i]) || !strcmp("-fno-pic", args.str[i]))
1754
use_pic = false;
1755
break;
1756
case 'i':
1757
if (!strcmp( "-isysroot", args.str[i] )) isysroot = args.str[i + 1];
1758
break;
1759
case 'l':
1760
strarray_add(&file_args, strmake("-l%s", option_arg));
1761
raw_compiler_arg = 0;
1762
break;
1763
case 'L':
1764
strarray_add(&lib_path_dirs, option_arg);
1765
raw_compiler_arg = 0;
1766
break;
1767
case 'M': /* map file generation */
1768
skip_link = true;
1769
break;
1770
case 'm':
1771
if (strcmp("-mno-cygwin", args.str[i]) == 0)
1772
{
1773
use_msvcrt = true;
1774
raw_compiler_arg = 0;
1775
}
1776
if (strcmp("-mcygwin", args.str[i]) == 0)
1777
{
1778
use_msvcrt = false;
1779
raw_compiler_arg = 0;
1780
}
1781
else if (strcmp("-mwindows", args.str[i]) == 0)
1782
{
1783
is_gui_app = true;
1784
raw_compiler_arg = 0;
1785
}
1786
else if (strcmp("-mconsole", args.str[i]) == 0)
1787
{
1788
is_gui_app = false;
1789
raw_compiler_arg = 0;
1790
}
1791
else if (strcmp("-municode", args.str[i]) == 0)
1792
{
1793
is_unicode_app = true;
1794
raw_compiler_arg = 0;
1795
raw_winebuild_arg = 1;
1796
}
1797
else if (strcmp("-mthreads", args.str[i]) == 0)
1798
{
1799
raw_compiler_arg = 0;
1800
}
1801
else if (strcmp("-m16", args.str[i]) == 0)
1802
{
1803
is_win16_app = true;
1804
raw_compiler_arg = 0;
1805
raw_winebuild_arg = 1;
1806
}
1807
else if (strcmp("-m32", args.str[i]) == 0)
1808
{
1809
force_pointer_size = 4;
1810
raw_linker_arg = 1;
1811
}
1812
else if (strcmp("-m64", args.str[i]) == 0)
1813
{
1814
force_pointer_size = 8;
1815
raw_linker_arg = 1;
1816
}
1817
else if (!strcmp("-marm", args.str[i] ) || !strcmp("-mthumb", args.str[i] ))
1818
{
1819
raw_linker_arg = 1;
1820
}
1821
else if (!strcmp("-marm64x", args.str[i] ))
1822
{
1823
is_arm64x = true;
1824
raw_linker_arg = 1;
1825
}
1826
else if (!strncmp("-mcpu=", args.str[i], 6) ||
1827
!strncmp("-mfpu=", args.str[i], 6) ||
1828
!strncmp("-march=", args.str[i], 7))
1829
raw_winebuild_arg = 1;
1830
break;
1831
case 'n':
1832
if (strcmp("-nostdinc", args.str[i]) == 0)
1833
nostdinc = true;
1834
else if (strcmp("-nodefaultlibs", args.str[i]) == 0)
1835
nodefaultlibs = true;
1836
else if (strcmp("-nostdlib", args.str[i]) == 0)
1837
nostdlib = true;
1838
else if (strcmp("-nostartfiles", args.str[i]) == 0)
1839
nostartfiles = true;
1840
break;
1841
case 'o':
1842
output = option_arg;
1843
raw_compiler_arg = 0;
1844
break;
1845
case 'p':
1846
if (strcmp("-pthread", args.str[i]) == 0)
1847
{
1848
raw_compiler_arg = 1;
1849
raw_linker_arg = 1;
1850
}
1851
break;
1852
case 's':
1853
if (strcmp("-static", args.str[i]) == 0)
1854
is_static = true;
1855
else if(strcmp("-save-temps", args.str[i]) == 0)
1856
keep_generated = 1;
1857
else if (strncmp("-specs=", args.str[i], 7) == 0)
1858
raw_linker_arg = 1;
1859
else if(strcmp("-shared", args.str[i]) == 0)
1860
{
1861
is_shared = true;
1862
raw_compiler_arg = raw_linker_arg = 0;
1863
}
1864
else if (strcmp("-s", args.str[i]) == 0)
1865
{
1866
strip = true;
1867
raw_linker_arg = 0;
1868
}
1869
break;
1870
case 't':
1871
if (is_option( args, i, "-target", &option_arg ))
1872
{
1873
target_alias = option_arg;
1874
raw_compiler_arg = raw_linker_arg = 0;
1875
}
1876
break;
1877
case 'v':
1878
if (args.str[i][2] == 0)
1879
{
1880
verbose++;
1881
raw_compiler_arg = raw_linker_arg = 0;
1882
}
1883
break;
1884
case 'W':
1885
if (strncmp("-Wl,", args.str[i], 4) == 0)
1886
{
1887
unsigned int j;
1888
struct strarray Wl = strarray_fromstring(args.str[i] + 4, ",");
1889
for (j = 0; j < Wl.count; j++)
1890
{
1891
if (!strcmp(Wl.str[j], "--image-base") && j < Wl.count - 1)
1892
{
1893
image_base = xstrdup( Wl.str[++j] );
1894
continue;
1895
}
1896
if (!strcmp(Wl.str[j], "--section-alignment") && j < Wl.count - 1)
1897
{
1898
section_align = xstrdup( Wl.str[++j] );
1899
continue;
1900
}
1901
if (!strcmp(Wl.str[j], "--file-alignment") && j < Wl.count - 1)
1902
{
1903
file_align = xstrdup( Wl.str[++j] );
1904
continue;
1905
}
1906
if (!strcmp(Wl.str[j], "--large-address-aware"))
1907
{
1908
large_address_aware = true;
1909
continue;
1910
}
1911
if (!strcmp(Wl.str[j], "--wine-builtin"))
1912
{
1913
wine_builtin = true;
1914
continue;
1915
}
1916
if (!strcmp(Wl.str[j], "--subsystem") && j < Wl.count - 1)
1917
{
1918
subsystem = xstrdup( Wl.str[++j] );
1919
continue;
1920
}
1921
if (!strcmp(Wl.str[j], "--entry") && j < Wl.count - 1)
1922
{
1923
entry_point = xstrdup( Wl.str[++j] );
1924
continue;
1925
}
1926
if (!strcmp(Wl.str[j], "-delayload") && j < Wl.count - 1)
1927
{
1928
strarray_add( &delayimports, Wl.str[++j] );
1929
continue;
1930
}
1931
if (!strcmp(Wl.str[j], "--debug-file") && j < Wl.count - 1)
1932
{
1933
strarray_add( &output_debug_files, xstrdup( Wl.str[++j] ));
1934
continue;
1935
}
1936
if (!strcmp(Wl.str[j], "--whole-archive") ||
1937
!strcmp(Wl.str[j], "--no-whole-archive") ||
1938
!strcmp(Wl.str[j], "--start-group") ||
1939
!strcmp(Wl.str[j], "--end-group"))
1940
{
1941
strarray_add( &file_args, strmake( "-Wl,%s", Wl.str[j] ));
1942
continue;
1943
}
1944
if (!strcmp(Wl.str[j], "--out-implib"))
1945
{
1946
output_implib = xstrdup( Wl.str[++j] );
1947
continue;
1948
}
1949
if (!strcmp( Wl.str[j], "--build-id" ))
1950
{
1951
use_build_id = true;
1952
continue;
1953
}
1954
if (!strcmp(Wl.str[j], "-static")) is_static = true;
1955
strarray_add(&linker_args, strmake("-Wl,%s",Wl.str[j]));
1956
}
1957
raw_compiler_arg = raw_linker_arg = 0;
1958
}
1959
else if (strncmp("-Wb,", args.str[i], 4) == 0)
1960
{
1961
struct strarray Wb = strarray_fromstring(args.str[i] + 4, ",");
1962
STRARRAY_FOR_EACH( arg, &Wb )
1963
{
1964
if (!strcmp(arg, "--data-only")) data_only = true;
1965
if (!strcmp(arg, "--fake-module")) fake_module = true;
1966
else strarray_add( &winebuild_args, arg );
1967
}
1968
raw_compiler_arg = raw_linker_arg = 0;
1969
}
1970
break;
1971
case 'x':
1972
strarray_add(&file_args, args.str[i]);
1973
/* we'll pass these flags ourselves, explicitly */
1974
raw_compiler_arg = raw_linker_arg = 0;
1975
break;
1976
case '-':
1977
if (strcmp("-static", args.str[i]+1) == 0)
1978
is_static = true;
1979
else if (!strcmp( "-no-default-config", args.str[i] + 1 ))
1980
{
1981
no_default_config = true;
1982
raw_compiler_arg = raw_linker_arg = 1;
1983
}
1984
else if (is_option( args, i, "--cc-cmd", &option_arg ))
1985
{
1986
cc_cmd = option_arg;
1987
raw_compiler_arg = raw_linker_arg = 0;
1988
}
1989
else if (is_option( args, i, "--sysroot", &option_arg ))
1990
{
1991
sysroot = option_arg;
1992
raw_linker_arg = 1;
1993
}
1994
else if (is_option( args, i, "--target", &option_arg ))
1995
{
1996
target_alias = option_arg;
1997
raw_compiler_arg = raw_linker_arg = 0;
1998
}
1999
else if (is_option( args, i, "--wine-objdir", &option_arg ))
2000
{
2001
wine_objdir = option_arg;
2002
raw_compiler_arg = raw_linker_arg = 0;
2003
}
2004
else if (is_option( args, i, "--winebuild", &option_arg ))
2005
{
2006
winebuild = option_arg;
2007
raw_compiler_arg = raw_linker_arg = 0;
2008
}
2009
else if (is_option( args, i, "--lib-suffix", &option_arg ))
2010
{
2011
lib_suffix = option_arg;
2012
raw_compiler_arg = raw_linker_arg = 0;
2013
}
2014
break;
2015
}
2016
2017
/* put the arg into the appropriate bucket */
2018
if (raw_linker_arg)
2019
{
2020
strarray_add( &linker_args, args.str[i] );
2021
if (next_is_arg && (i + 1 < args.count))
2022
strarray_add( &linker_args, args.str[i + 1] );
2023
}
2024
if (raw_compiler_arg)
2025
{
2026
strarray_add( &compiler_args, args.str[i] );
2027
if (next_is_arg && (i + 1 < args.count))
2028
strarray_add( &compiler_args, args.str[i + 1] );
2029
}
2030
if (raw_winebuild_arg)
2031
{
2032
strarray_add( &winebuild_args, args.str[i] );
2033
if (next_is_arg && (i + 1 < args.count))
2034
strarray_add( &winebuild_args, args.str[i + 1] );
2035
}
2036
2037
/* skip the next token if it's an argument */
2038
if (next_is_arg) i++;
2039
}
2040
else
2041
{
2042
strarray_add( &file_args, args.str[i] );
2043
}
2044
}
2045
2046
if (target_alias && !parse_target( target_alias, &target ))
2047
error( "Invalid target specification '%s'\n", target_alias );
2048
if (force_pointer_size) set_target_ptr_size( &target, force_pointer_size );
2049
2050
if (processor == proc_cpp) skip_link = true;
2051
2052
is_pe = is_pe_target( target );
2053
if (is_pe) use_msvcrt = true;
2054
if (output && strendswith( output, ".fake" )) fake_module = true;
2055
2056
if (!section_align)
2057
section_align = (target.cpu == CPU_ARM64 || target.cpu == CPU_ARM64EC) ? "0x10000" : "0x1000";
2058
2059
if (!file_align) file_align = section_align;
2060
2061
if (!is_pe && target.cpu != CPU_i386 && target.cpu != CPU_x86_64)
2062
error( "Non-PE builds are not supported on this platform. You need to use something like '--target=%s-windows'.\n",
2063
target.cpu == CPU_ARM ? "arm" : "aarch64" );
2064
2065
if (!subsystem) subsystem = is_gui_app ? "windows" : "console";
2066
if (!strcmp( subsystem, "windows" ) || !strcmp( subsystem, "console" ))
2067
subsystem = strmake( "%s:6.0", subsystem );
2068
2069
if (!winebuild)
2070
{
2071
if (wine_objdir) winebuild = strmake( "%s/tools/winebuild/winebuild%s", wine_objdir, EXEEXT );
2072
else if (!(winebuild = getenv( "WINEBUILD" )))
2073
{
2074
if (bindir) winebuild = strmake( "%s/winebuild%s", bindir, EXEEXT );
2075
else winebuild = "winebuild";
2076
}
2077
}
2078
if (file_args.count == 0 && !fake_module) forward();
2079
else if (!skip_link && !compile_only) build(file_args, output);
2080
else compile(file_args, output, compile_only);
2081
2082
output_file_name = NULL;
2083
output_debug_files.count = 0;
2084
output_implib = NULL;
2085
return 0;
2086
}
2087
2088