Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/makedep.c
8649 views
1
/*
2
* Generate include file dependencies
3
*
4
* Copyright 1996, 2013, 2020 Alexandre Julliard
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include "config.h"
22
23
#include <assert.h>
24
#include <ctype.h>
25
#include <errno.h>
26
#include <fcntl.h>
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <stdarg.h>
30
#include <string.h>
31
#include <sys/types.h>
32
#include <sys/stat.h>
33
34
#include "tools.h"
35
#include "wine/list.h"
36
37
enum incl_type
38
{
39
INCL_NORMAL, /* #include "foo.h" */
40
INCL_SYSTEM, /* #include <foo.h> */
41
INCL_IMPORT, /* idl import "foo.idl" */
42
INCL_IMPORTLIB, /* idl importlib "foo.tlb" */
43
INCL_CPP_QUOTE, /* idl cpp_quote("#include \"foo.h\"") */
44
INCL_CPP_QUOTE_SYSTEM /* idl cpp_quote("#include <foo.h>") */
45
};
46
47
struct dependency
48
{
49
int line; /* source line where this header is included */
50
enum incl_type type; /* type of include */
51
char *name; /* header name */
52
};
53
54
struct file
55
{
56
struct list entry;
57
char *name; /* full file name relative to cwd */
58
void *args; /* custom arguments for makefile rule */
59
unsigned int flags; /* flags (see below) */
60
struct array deps; /* array of struct dependency */
61
};
62
63
struct incl_file
64
{
65
struct list entry;
66
struct list hash_entry;
67
struct file *file;
68
char *name;
69
char *filename;
70
char *basename; /* base target name for generated files */
71
char *sourcename; /* source file name for generated headers */
72
struct incl_file *included_by; /* file that included this one */
73
int included_line; /* line where this file was included */
74
enum incl_type type; /* type of include */
75
unsigned int arch; /* architecture for multi-arch files, otherwise 0 */
76
unsigned int use_msvcrt:1; /* put msvcrt headers in the search path? */
77
unsigned int is_external:1; /* file from external library? */
78
struct incl_file *owner;
79
struct array files; /* array of struct incl_file* */
80
struct strarray dependencies; /* file dependencies */
81
struct strarray importlibdeps; /* importlib dependencies */
82
};
83
84
#define FLAG_GENERATED 0x00000001 /* generated file */
85
#define FLAG_INSTALL 0x00000002 /* file to install */
86
#define FLAG_TESTDLL 0x00000004 /* file is part of a TESTDLL resource */
87
#define FLAG_IDL_PROXY 0x00000100 /* generates a proxy (_p.c) file */
88
#define FLAG_IDL_CLIENT 0x00000200 /* generates a client (_c.c) file */
89
#define FLAG_IDL_SERVER 0x00000400 /* generates a server (_s.c) file */
90
#define FLAG_IDL_IDENT 0x00000800 /* generates an ident (_i.c) file */
91
#define FLAG_IDL_REGISTER 0x00001000 /* generates a registration (_r.res) file */
92
#define FLAG_IDL_TYPELIB 0x00002000 /* generates a typelib (_l.res) file */
93
#define FLAG_IDL_REGTYPELIB 0x00004000 /* generates a registered typelib (_t.res) file */
94
#define FLAG_IDL_HEADER 0x00008000 /* generates a header (.h) file */
95
#define FLAG_IDL_WINMD 0x00010000 /* generates a metadata (.winmd) file */
96
#define FLAG_RC_PO 0x00100000 /* rc file contains translations */
97
#define FLAG_RC_HEADER 0x00200000 /* rc file is a header */
98
#define FLAG_SFD_FONTS 0x00400000 /* sfd file generated bitmap fonts */
99
#define FLAG_C_IMPLIB 0x01000000 /* file is part of an import library */
100
#define FLAG_C_UNIX 0x02000000 /* file is part of a Unix library */
101
#define FLAG_ARM64EC_X64 0x04000000 /* use x86_64 object on ARM64EC */
102
103
static const struct
104
{
105
unsigned int flag;
106
const char *ext;
107
} idl_outputs[] =
108
{
109
{ FLAG_IDL_TYPELIB, "_l.res" },
110
{ FLAG_IDL_REGTYPELIB, "_t.res" },
111
{ FLAG_IDL_CLIENT, "_c.c" },
112
{ FLAG_IDL_IDENT, "_i.c" },
113
{ FLAG_IDL_PROXY, "_p.c" },
114
{ FLAG_IDL_SERVER, "_s.c" },
115
{ FLAG_IDL_REGISTER, "_r.res" },
116
};
117
118
#define HASH_SIZE 197
119
120
static struct list files[HASH_SIZE];
121
static struct list global_includes[HASH_SIZE];
122
123
enum install_rules { INSTALL_LIB, INSTALL_DEV, INSTALL_UNIXLIB, INSTALL_TEST, NB_INSTALL_RULES };
124
static const char *install_targets[NB_INSTALL_RULES] = { "install-lib", "install-dev", "install-unixlib", "install-test" };
125
static const char *install_variables[NB_INSTALL_RULES] = { "INSTALL_LIB", "INSTALL_DEV", "INSTALL_UNIXLIB", "INSTALL_TEST" };
126
127
#define MAX_ARCHS 6
128
129
/* variables common to all makefiles */
130
static struct strarray archs;
131
static struct strarray linguas;
132
static struct strarray dll_flags;
133
static struct strarray unix_dllflags;
134
static struct strarray msvcrt_flags;
135
static struct strarray cpp_flags;
136
static struct strarray lddll_flags;
137
static struct strarray libs;
138
static struct strarray enable_tests;
139
static struct strarray cmdline_vars;
140
static struct strarray subdirs;
141
static struct strarray delay_import_libs;
142
static struct strarray top_install[NB_INSTALL_RULES];
143
static const char *root_src_dir;
144
static const char *tools_dir;
145
static const char *tools_ext;
146
static const char *wine64_dir;
147
static const char *exe_ext;
148
static const char *fontforge;
149
static const char *convert;
150
static const char *flex;
151
static const char *bison;
152
static const char *rsvg;
153
static const char *icotool;
154
static const char *msgfmt;
155
static const char *ln_s;
156
static const char *sed_cmd;
157
static const char *wayland_scanner;
158
static const char *sarif_converter;
159
static const char *compiler_rt;
160
static const char *buildimage;
161
static const char *runtest;
162
static const char *install;
163
static const char *makedep;
164
static const char *make_xftmpl;
165
static const char *sfnt2fon;
166
static const char *winebuild;
167
static const char *winegcc;
168
static const char *widl;
169
static const char *wrc;
170
static const char *wmc;
171
static int so_dll_supported;
172
static int symlinks_supported;
173
static int unix_lib_supported;
174
/* per-architecture global variables */
175
static const char *dll_ext[MAX_ARCHS];
176
static const char *arch_dirs[MAX_ARCHS];
177
static const char *arch_pe_dirs[MAX_ARCHS];
178
static const char *arch_install_dirs[MAX_ARCHS];
179
static const char *strip_progs[MAX_ARCHS];
180
static const char *cc_cmds[MAX_ARCHS];
181
static const char *delay_load_flags[MAX_ARCHS];
182
static struct strarray debug_flags[MAX_ARCHS];
183
static struct strarray target_flags[MAX_ARCHS];
184
static struct strarray extra_cflags[MAX_ARCHS];
185
static struct strarray extra_cflags_extlib[MAX_ARCHS];
186
static struct strarray disabled_dirs[MAX_ARCHS];
187
static unsigned int native_archs[MAX_ARCHS];
188
static unsigned int hybrid_archs[MAX_ARCHS];
189
static struct strarray hybrid_target_flags[MAX_ARCHS];
190
191
struct makefile
192
{
193
/* values determined from input makefile */
194
struct strarray vars;
195
struct strarray include_paths;
196
struct strarray include_args;
197
struct strarray define_args;
198
struct strarray unix_cflags;
199
struct strarray programs;
200
struct strarray scripts;
201
struct strarray imports;
202
struct strarray delayimports;
203
struct strarray extradllflags;
204
struct strarray install[NB_INSTALL_RULES];
205
struct strarray extra_targets;
206
struct strarray extra_imports;
207
struct list sources;
208
struct list includes;
209
const char *src_dir;
210
const char *obj_dir;
211
const char *parent_dir;
212
const char *module;
213
const char *testdll;
214
const char *extlib;
215
const char *staticlib;
216
const char *importlib;
217
const char *unixlib;
218
int data_only;
219
int is_win16;
220
int is_exe;
221
int disabled[MAX_ARCHS];
222
223
/* values generated at output time */
224
struct strarray in_files;
225
struct strarray pot_files;
226
struct strarray test_files;
227
struct strarray sast_files;
228
struct strarray clean_files;
229
struct strarray distclean_files;
230
struct strarray maintainerclean_files;
231
struct strarray unixobj_files;
232
struct strarray font_files;
233
struct strarray debug_files;
234
struct strarray dlldata_files;
235
struct strarray phony_targets;
236
struct strarray dependencies;
237
struct strarray object_files[MAX_ARCHS];
238
struct strarray implib_files[MAX_ARCHS];
239
struct strarray ok_files[MAX_ARCHS];
240
struct strarray res_files[MAX_ARCHS];
241
struct strarray all_targets[MAX_ARCHS];
242
};
243
244
static struct makefile *top_makefile;
245
static struct makefile *include_makefile;
246
static struct makefile **submakes;
247
248
static const char separator[] = "### Dependencies";
249
static const char *output_makefile_name = "Makefile";
250
static const char *input_makefile_name;
251
static const char *input_file_name;
252
static const char *output_file_name;
253
static const char *temp_file_name;
254
static char cwd[PATH_MAX];
255
static int compile_commands_mode;
256
static int silent_rules;
257
static int input_line;
258
static int output_column;
259
static FILE *output_file;
260
261
struct compile_command
262
{
263
struct list entry;
264
const char *cmd;
265
const char *source;
266
const char *obj;
267
struct strarray args;
268
};
269
270
static struct list compile_commands = LIST_INIT( compile_commands );
271
272
struct install_command
273
{
274
struct strarray args; /* command line arguments */
275
struct strarray files; /* source file names */
276
struct strarray targets; /* targets to build if any */
277
const char *dir; /* dest directory */
278
const char *dest; /* dest file name if different from file */
279
};
280
281
static struct array install_commands[NB_INSTALL_RULES];
282
283
static const char *version_vars[] =
284
{
285
"VER_EXTRAVALUES",
286
"VER_FILEDESCRIPTION_STR",
287
"VER_FILESUBTYPE",
288
"VER_FILETYPE",
289
"VER_FILEVERSION",
290
"VER_INTERNALNAME_STR",
291
"VER_LEGALCOPYRIGHT_STR",
292
"VER_OLESELFREGISTER",
293
"VER_PRODUCTVERSION",
294
"VER_VERSION_TRANSLATION",
295
"VER_VERSION_UNICODE_LANG",
296
};
297
298
static const char Usage[] =
299
"Usage: makedep [options]\n"
300
"Options:\n"
301
" -C Generate compile_commands.json along with the makefile\n"
302
" -S Generate Automake-style silent rules\n"
303
" -fxxx Store output in file 'xxx' (default: Makefile)\n";
304
305
306
static void fatal_error( const char *msg, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
307
static void output( const char *format, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
308
309
/*******************************************************************
310
* fatal_error
311
*/
312
static void fatal_error( const char *msg, ... )
313
{
314
va_list valist;
315
va_start( valist, msg );
316
if (input_file_name)
317
{
318
fprintf( stderr, "%s:", input_file_name );
319
if (input_line) fprintf( stderr, "%d:", input_line );
320
fprintf( stderr, " error: " );
321
}
322
else fprintf( stderr, "makedep: error: " );
323
vfprintf( stderr, msg, valist );
324
va_end( valist );
325
exit(1);
326
}
327
328
329
/*******************************************************************
330
* cleanup_files
331
*/
332
static void cleanup_files(void)
333
{
334
if (temp_file_name) unlink( temp_file_name );
335
if (output_file_name) unlink( output_file_name );
336
}
337
338
339
/*******************************************************************
340
* exit_on_signal
341
*/
342
static void exit_on_signal( int sig )
343
{
344
exit( 1 ); /* this will call the atexit functions */
345
}
346
347
348
/*******************************************************************
349
* output
350
*/
351
static void output( const char *format, ... )
352
{
353
int ret;
354
va_list valist;
355
356
va_start( valist, format );
357
ret = vfprintf( output_file, format, valist );
358
va_end( valist );
359
if (ret < 0) fatal_perror( "output" );
360
if (format[0] && format[strlen(format) - 1] == '\n') output_column = 0;
361
else output_column += ret;
362
}
363
364
365
/*******************************************************************
366
* strarray_get_value
367
*
368
* Find a value in a name/value pair string array.
369
*/
370
static const char *strarray_get_value( struct strarray array, const char *name )
371
{
372
int pos, res, min = 0, max = array.count / 2 - 1;
373
374
while (min <= max)
375
{
376
pos = (min + max) / 2;
377
if (!(res = strcmp( array.str[pos * 2], name ))) return array.str[pos * 2 + 1];
378
if (res < 0) min = pos + 1;
379
else max = pos - 1;
380
}
381
return NULL;
382
}
383
384
385
/*******************************************************************
386
* strarray_set_value
387
*
388
* Define a value in a name/value pair string array.
389
*/
390
static void strarray_set_value( struct strarray *array, const char *name, const char *value )
391
{
392
int i, pos, res, min = 0, max = array->count / 2 - 1;
393
394
while (min <= max)
395
{
396
pos = (min + max) / 2;
397
if (!(res = strcmp( array->str[pos * 2], name )))
398
{
399
/* redefining a variable replaces the previous value */
400
array->str[pos * 2 + 1] = value;
401
return;
402
}
403
if (res < 0) min = pos + 1;
404
else max = pos - 1;
405
}
406
strarray_add( array, NULL );
407
strarray_add( array, NULL );
408
for (i = array->count - 1; i > min * 2 + 1; i--) array->str[i] = array->str[i - 2];
409
array->str[min * 2] = name;
410
array->str[min * 2 + 1] = value;
411
}
412
413
414
/*******************************************************************
415
* output_filename
416
*/
417
static void output_filename( const char *name )
418
{
419
if (output_column + strlen(name) + 1 > 100)
420
{
421
output( " \\\n" );
422
output( " " );
423
}
424
else if (output_column) output( " " );
425
output( "%s", name );
426
}
427
428
429
/*******************************************************************
430
* output_filenames
431
*/
432
static void output_filenames( struct strarray array )
433
{
434
STRARRAY_FOR_EACH( str, &array ) output_filename( str );
435
}
436
437
438
/*******************************************************************
439
* output_multifiles_command
440
*/
441
static void output_multifiles_command( struct strarray files, const char *command, struct strarray args )
442
{
443
static const unsigned int max_cmdline = 30000; /* to be on the safe side */
444
unsigned int len = 0;
445
446
if (!files.count) return;
447
output( "\t%s", command );
448
output_filenames( args );
449
STRARRAY_FOR_EACH( file, &files )
450
{
451
if (len > max_cmdline)
452
{
453
output( "\n" );
454
output( "\t%s", command );
455
output_filenames( args );
456
len = 0;
457
}
458
output_filename( file );
459
len += strlen( file ) + 1;
460
}
461
output( "\n" );
462
}
463
464
465
/*******************************************************************
466
* get_extension
467
*/
468
static char *get_extension( char *filename )
469
{
470
char *ext = strrchr( filename, '.' );
471
if (ext && strchr( ext, '/' )) ext = NULL;
472
return ext;
473
}
474
475
476
/*******************************************************************
477
* get_base_name
478
*/
479
static const char *get_base_name( const char *name )
480
{
481
char *base;
482
if (!strchr( name, '.' )) return name;
483
base = xstrdup( name );
484
*strrchr( base, '.' ) = 0;
485
return base;
486
}
487
488
489
/*******************************************************************
490
* replace_filename
491
*/
492
static char *replace_filename( const char *path, const char *name )
493
{
494
const char *p;
495
char *ret;
496
size_t len;
497
498
if (!path) return xstrdup( name );
499
if (!(p = strrchr( path, '/' ))) return xstrdup( name );
500
len = p - path + 1;
501
ret = xmalloc( len + strlen( name ) + 1 );
502
memcpy( ret, path, len );
503
strcpy( ret + len, name );
504
return ret;
505
}
506
507
508
/*******************************************************************
509
* replace_substr
510
*/
511
static char *replace_substr( const char *str, const char *start, size_t len, const char *replace )
512
{
513
size_t pos = start - str;
514
char *ret = xmalloc( pos + strlen(replace) + strlen(start + len) + 1 );
515
memcpy( ret, str, pos );
516
strcpy( ret + pos, replace );
517
strcat( ret + pos, start + len );
518
return ret;
519
}
520
521
522
/*******************************************************************
523
* get_root_relative_path
524
*
525
* Get relative path from obj dir to root.
526
*/
527
static const char *get_root_relative_path( struct makefile *make )
528
{
529
const char *dir = make->obj_dir;
530
char *ret, *p;
531
unsigned int dotdots = 0;
532
533
if (!dir) return ".";
534
while (*dir)
535
{
536
dotdots++;
537
while (*dir && *dir != '/') dir++;
538
while (*dir == '/') dir++;
539
}
540
assert(dotdots);
541
ret = xmalloc( 3 * dotdots );
542
for (p = ret; dotdots; dotdots--, p += 3) memcpy( p, "../", 3 );
543
p[-1] = 0; /* remove trailing slash */
544
return ret;
545
}
546
547
548
/*******************************************************************
549
* concat_paths
550
*/
551
static char *concat_paths( const char *base, const char *path )
552
{
553
int i, len;
554
char *ret;
555
556
if (!base || !base[0]) return xstrdup( path && path[0] ? path : "." );
557
if (!path || !path[0]) return xstrdup( base );
558
if (path[0] == '/') return xstrdup( path );
559
560
len = strlen( base );
561
while (len && base[len - 1] == '/') len--;
562
while (len && !strncmp( path, "..", 2 ) && (!path[2] || path[2] == '/'))
563
{
564
for (i = len; i > 0; i--) if (base[i - 1] == '/') break;
565
if (i == len - 2 && !memcmp( base + i, "..", 2 )) break; /* we can't go up if we already have ".." */
566
if (i != len - 1 || base[i] != '.')
567
{
568
path += 2;
569
while (*path == '/') path++;
570
}
571
/* else ignore "." element */
572
while (i > 0 && base[i - 1] == '/') i--;
573
len = i;
574
}
575
if (!len && base[0] != '/') return xstrdup( path[0] ? path : "." );
576
ret = xmalloc( len + strlen( path ) + 2 );
577
memcpy( ret, base, len );
578
ret[len++] = '/';
579
strcpy( ret + len, path );
580
return ret;
581
}
582
583
584
/*******************************************************************
585
* escape_cstring
586
*/
587
static const char *escape_cstring( const char *str )
588
{
589
char *ret;
590
unsigned int i = 0, j = 0;
591
592
if (!strpbrk( str, "\\\"" )) return str;
593
ret = xmalloc( 2 * strlen(str) + 1 );
594
while (str[i])
595
{
596
if (str[i] == '\\' || str[i] == '"') ret[j++] = '\\';
597
ret[j++] = str[i++];
598
}
599
ret[j] = 0;
600
return ret;
601
}
602
603
604
/*******************************************************************
605
* is_native_arch_disabled
606
*
607
* Check if the makefile was disabled for a PE arch that matches the native arch.
608
*/
609
static int is_native_arch_disabled( struct makefile *make )
610
{
611
unsigned int arch;
612
613
if (archs.count == 1) return 0;
614
if (!so_dll_supported) return 1;
615
616
for (arch = 1; arch < archs.count; arch++)
617
if (make->disabled[arch] && !strcmp( archs.str[0], archs.str[arch] ))
618
return 1;
619
return 0;
620
}
621
622
623
/*******************************************************************
624
* is_subdir_other_arch
625
*
626
* Check if the filename is in a subdirectory named from a different arch.
627
* Used to avoid building asm files for the wrong platform.
628
*/
629
static int is_subdir_other_arch( const char *name, unsigned int arch )
630
{
631
const char *dir, *p = strrchr( name, '/' );
632
633
if (!p || p == name) return 0;
634
dir = get_basename( strmake( "%.*s", (int)(p - name), name ));
635
if (!strcmp( dir, "arm64" )) dir = "aarch64";
636
if (!strcmp( dir, "amd64" )) dir = "x86_64";
637
if (native_archs[arch] && !strcmp( dir, archs.str[native_archs[arch]] )) return 0;
638
return strcmp( dir, archs.str[arch] );
639
}
640
641
642
/*******************************************************************
643
* get_link_arch
644
*/
645
static int get_link_arch( const struct makefile *make, unsigned int arch, unsigned int *link_arch )
646
{
647
unsigned int hybrid_arch = hybrid_archs[arch];
648
649
if (native_archs[arch]) return 0;
650
if (hybrid_arch && make->disabled[hybrid_arch]) hybrid_arch = 0;
651
if (make->disabled[arch] && !hybrid_arch) return 0;
652
*link_arch = hybrid_arch ? hybrid_arch : arch;
653
return 1;
654
}
655
656
657
/*******************************************************************
658
* is_multiarch
659
*
660
* Check if arch is one of the PE architectures in multiarch.
661
* Also return TRUE for native arch iff there's no PE architecture, not even "none".
662
*/
663
static int is_multiarch( unsigned int arch )
664
{
665
return archs.count == 1 || (arch && strcmp( archs.str[arch], "none" ));
666
}
667
668
669
/*******************************************************************
670
* is_using_msvcrt
671
*
672
* Check if the files of a makefile use msvcrt by default.
673
*/
674
static int is_using_msvcrt( struct makefile *make )
675
{
676
return make->module || make->testdll;
677
}
678
679
680
/*******************************************************************
681
* arch_module_name
682
*/
683
static char *arch_module_name( const char *module, unsigned int arch )
684
{
685
return strmake( "%s%s%s", arch_dirs[arch], module, dll_ext[arch] );
686
}
687
688
689
/*******************************************************************
690
* arch_make_variable
691
*/
692
static char *arch_make_variable( const char *name, unsigned int arch )
693
{
694
return arch ? strmake( "$(%s_%s)", archs.str[arch], name ) : strmake( "$(%s)", name );
695
}
696
697
698
/*******************************************************************
699
* obj_dir_path
700
*/
701
static char *obj_dir_path( const struct makefile *make, const char *path )
702
{
703
return concat_paths( make->obj_dir, path );
704
}
705
706
707
/*******************************************************************
708
* src_dir_path
709
*/
710
static char *src_dir_path( const struct makefile *make, const char *path )
711
{
712
if (make->src_dir) return concat_paths( make->src_dir, path );
713
return obj_dir_path( make, path );
714
}
715
716
717
/*******************************************************************
718
* root_src_dir_path
719
*/
720
static char *root_src_dir_path( const char *path )
721
{
722
return concat_paths( root_src_dir, path );
723
}
724
725
726
/*******************************************************************
727
* tools_dir_path
728
*/
729
static char *tools_dir_path( const char *path )
730
{
731
if (tools_dir) return strmake( "%s/tools/%s", tools_dir, path );
732
return strmake( "tools/%s", path );
733
}
734
735
736
/*******************************************************************
737
* tools_path
738
*/
739
static char *tools_path( const char *name )
740
{
741
return strmake( "%s/%s%s", tools_dir_path( name ), name, tools_ext );
742
}
743
744
745
/*******************************************************************
746
* tools_base_path
747
*/
748
static char *tools_base_path( const char *name )
749
{
750
return strmake( "%s%s", tools_dir_path( name ), tools_ext );
751
}
752
753
754
/*******************************************************************
755
* strarray_addall_path
756
*/
757
static void strarray_addall_path( struct strarray *array, const char *dir, struct strarray added )
758
{
759
STRARRAY_FOR_EACH( str, &added ) strarray_add( array, concat_paths( dir, str ));
760
}
761
762
763
/*******************************************************************
764
* get_line
765
*/
766
static char *get_line( FILE *file )
767
{
768
static char *buffer;
769
static size_t size;
770
771
if (!size)
772
{
773
size = 1024;
774
buffer = xmalloc( size );
775
}
776
if (!fgets( buffer, size, file )) return NULL;
777
input_line++;
778
779
for (;;)
780
{
781
char *p = buffer + strlen(buffer);
782
/* if line is larger than buffer, resize buffer */
783
while (p == buffer + size - 1 && p[-1] != '\n')
784
{
785
buffer = xrealloc( buffer, size * 2 );
786
if (!fgets( buffer + size - 1, size + 1, file )) break;
787
p = buffer + strlen(buffer);
788
size *= 2;
789
}
790
if (p > buffer && p[-1] == '\n')
791
{
792
*(--p) = 0;
793
if (p > buffer && p[-1] == '\r') *(--p) = 0;
794
if (p > buffer && p[-1] == '\\')
795
{
796
*(--p) = 0;
797
/* line ends in backslash, read continuation line */
798
if (!fgets( p, size - (p - buffer), file )) return buffer;
799
input_line++;
800
continue;
801
}
802
}
803
return buffer;
804
}
805
}
806
807
808
/*******************************************************************
809
* hash_filename
810
*/
811
static unsigned int hash_filename( const char *name )
812
{
813
/* FNV-1 hash */
814
unsigned int ret = 2166136261u;
815
while (*name) ret = (ret * 16777619) ^ *name++;
816
return ret % HASH_SIZE;
817
}
818
819
820
/*******************************************************************
821
* add_file
822
*/
823
static struct file *add_file( const char *name )
824
{
825
struct file *file = xmalloc( sizeof(*file) );
826
memset( file, 0, sizeof(*file) );
827
file->name = xstrdup( name );
828
return file;
829
}
830
831
832
/*******************************************************************
833
* add_dependency
834
*/
835
static void add_dependency( struct file *file, const char *name, enum incl_type type )
836
{
837
struct dependency *dep = ARRAY_ADD( &file->deps, struct dependency );
838
839
dep->line = input_line;
840
dep->type = type;
841
dep->name = xstrdup( name );
842
}
843
844
845
/*******************************************************************
846
* find_src_file
847
*/
848
static struct incl_file *find_src_file( const struct makefile *make, const char *name )
849
{
850
struct incl_file *file;
851
852
if (make == include_makefile)
853
{
854
unsigned int hash = hash_filename( name );
855
856
LIST_FOR_EACH_ENTRY( file, &global_includes[hash], struct incl_file, hash_entry )
857
if (!strcmp( name, file->name )) return file;
858
return NULL;
859
}
860
861
LIST_FOR_EACH_ENTRY( file, &make->sources, struct incl_file, entry )
862
if (!strcmp( name, file->name )) return file;
863
return NULL;
864
}
865
866
/*******************************************************************
867
* find_include_file
868
*/
869
static struct incl_file *find_include_file( const struct makefile *make, const char *name )
870
{
871
struct incl_file *file;
872
873
LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry )
874
{
875
const char *filename = file->filename;
876
if (!filename) continue;
877
if (make->obj_dir && strlen(make->obj_dir) < strlen(filename))
878
{
879
filename += strlen(make->obj_dir);
880
while (*filename == '/') filename++;
881
}
882
if (!strcmp( name, filename )) return file;
883
}
884
return NULL;
885
}
886
887
/*******************************************************************
888
* add_include
889
*
890
* Add an include file if it doesn't already exists.
891
*/
892
static struct incl_file *add_include( struct makefile *make, struct incl_file *parent,
893
const char *name, int line, enum incl_type type )
894
{
895
struct incl_file *include;
896
897
LIST_FOR_EACH_ENTRY( include, &make->includes, struct incl_file, entry )
898
if (!parent->use_msvcrt == !include->use_msvcrt && !strcmp( name, include->name ))
899
goto found;
900
901
include = xmalloc( sizeof(*include) );
902
memset( include, 0, sizeof(*include) );
903
include->name = xstrdup(name);
904
include->included_by = parent;
905
include->included_line = line;
906
include->type = type;
907
include->use_msvcrt = parent->use_msvcrt;
908
list_add_tail( &make->includes, &include->entry );
909
found:
910
*ARRAY_ADD( &parent->files, struct incl_file * ) = include;
911
return include;
912
}
913
914
915
/*******************************************************************
916
* add_generated_source
917
*
918
* Add a generated source file to the list.
919
*/
920
static struct incl_file *add_generated_source( struct makefile *make, const char *name,
921
const char *filename, unsigned int arch )
922
{
923
struct incl_file *file = xmalloc( sizeof(*file) );
924
925
name = strmake( "%s%s", arch_dirs[arch], name );
926
memset( file, 0, sizeof(*file) );
927
file->file = add_file( name );
928
file->arch = arch;
929
file->name = xstrdup( name );
930
file->basename = xstrdup( filename ? filename : name );
931
file->filename = obj_dir_path( make, file->basename );
932
file->file->flags = FLAG_GENERATED;
933
file->use_msvcrt = is_using_msvcrt( make );
934
list_add_tail( &make->sources, &file->entry );
935
if (make == include_makefile)
936
{
937
unsigned int hash = hash_filename( name );
938
list_add_tail( &global_includes[hash], &file->hash_entry );
939
}
940
return file;
941
}
942
943
944
/*******************************************************************
945
* skip_spaces
946
*/
947
static char *skip_spaces( const char *p )
948
{
949
while (*p == ' ' || *p == '\t') p++;
950
return (char *)p;
951
}
952
953
954
/*******************************************************************
955
* parse_include_directive
956
*/
957
static void parse_include_directive( struct file *source, char *str )
958
{
959
char quote, *include, *p = skip_spaces( str );
960
961
if (*p != '\"' && *p != '<' ) return;
962
quote = *p++;
963
if (quote == '<') quote = '>';
964
include = p;
965
while (*p && (*p != quote)) p++;
966
if (!*p) fatal_error( "malformed include directive '%s'\n", str );
967
*p = 0;
968
add_dependency( source, include, (quote == '>') ? INCL_SYSTEM : INCL_NORMAL );
969
}
970
971
972
/*******************************************************************
973
* parse_pragma_directive
974
*/
975
static void parse_pragma_directive( struct file *source, char *str )
976
{
977
char *flag, *p = str;
978
979
if (*p != ' ' && *p != '\t') return;
980
p = strtok( skip_spaces( p ), " \t" );
981
if (strcmp( p, "makedep" )) return;
982
983
while ((flag = strtok( NULL, " \t" )))
984
{
985
if (!strcmp( flag, "depend" ))
986
{
987
while ((p = strtok( NULL, " \t" ))) add_dependency( source, p, INCL_NORMAL );
988
return;
989
}
990
else if (!strcmp( flag, "install" )) source->flags |= FLAG_INSTALL;
991
else if (!strcmp( flag, "testdll" )) source->flags |= FLAG_TESTDLL;
992
993
if (strendswith( source->name, ".idl" ))
994
{
995
if (!strcmp( flag, "header" )) source->flags |= FLAG_IDL_HEADER;
996
else if (!strcmp( flag, "proxy" )) source->flags |= FLAG_IDL_PROXY;
997
else if (!strcmp( flag, "client" )) source->flags |= FLAG_IDL_CLIENT;
998
else if (!strcmp( flag, "server" )) source->flags |= FLAG_IDL_SERVER;
999
else if (!strcmp( flag, "ident" )) source->flags |= FLAG_IDL_IDENT;
1000
else if (!strcmp( flag, "typelib" )) source->flags |= FLAG_IDL_TYPELIB;
1001
else if (!strcmp( flag, "register" )) source->flags |= FLAG_IDL_REGISTER;
1002
else if (!strcmp( flag, "regtypelib" )) source->flags |= FLAG_IDL_REGTYPELIB;
1003
else if (!strcmp( flag, "winmd" )) source->flags |= FLAG_IDL_WINMD;
1004
}
1005
else if (strendswith( source->name, ".rc" ))
1006
{
1007
if (!strcmp( flag, "header" )) source->flags |= FLAG_RC_HEADER;
1008
else if (!strcmp( flag, "po" )) source->flags |= FLAG_RC_PO;
1009
}
1010
else if (strendswith( source->name, ".sfd" ))
1011
{
1012
if (!strcmp( flag, "font" ))
1013
{
1014
struct strarray *array = source->args;
1015
1016
if (!array)
1017
{
1018
source->args = array = xmalloc( sizeof(*array) );
1019
*array = empty_strarray;
1020
source->flags |= FLAG_SFD_FONTS;
1021
}
1022
strarray_add( array, xstrdup( strtok( NULL, "" )));
1023
return;
1024
}
1025
}
1026
else
1027
{
1028
if (!strcmp( flag, "implib" )) source->flags |= FLAG_C_IMPLIB;
1029
if (!strcmp( flag, "unix" )) source->flags |= FLAG_C_UNIX;
1030
if (!strcmp( flag, "arm64ec_x64" )) source->flags |= FLAG_ARM64EC_X64;
1031
}
1032
}
1033
}
1034
1035
1036
/*******************************************************************
1037
* parse_cpp_directive
1038
*/
1039
static void parse_cpp_directive( struct file *source, char *str )
1040
{
1041
str = skip_spaces( str );
1042
if (*str++ != '#') return;
1043
str = skip_spaces( str );
1044
1045
if (!strncmp( str, "include", 7 ))
1046
parse_include_directive( source, str + 7 );
1047
else if (!strncmp( str, "import", 6 ) && strendswith( source->name, ".m" ))
1048
parse_include_directive( source, str + 6 );
1049
else if (!strncmp( str, "pragma", 6 ))
1050
parse_pragma_directive( source, str + 6 );
1051
}
1052
1053
1054
/*******************************************************************
1055
* parse_idl_file
1056
*/
1057
static void parse_idl_file( struct file *source, FILE *file )
1058
{
1059
char *buffer, *include;
1060
1061
input_line = 0;
1062
1063
while ((buffer = get_line( file )))
1064
{
1065
char quote;
1066
char *p = skip_spaces( buffer );
1067
1068
if (!strncmp( p, "importlib", 9 ))
1069
{
1070
p = skip_spaces( p + 9 );
1071
if (*p++ != '(') continue;
1072
p = skip_spaces( p );
1073
if (*p++ != '"') continue;
1074
include = p;
1075
while (*p && (*p != '"')) p++;
1076
if (!*p) fatal_error( "malformed importlib directive\n" );
1077
*p = 0;
1078
add_dependency( source, include, INCL_IMPORTLIB );
1079
continue;
1080
}
1081
1082
if (!strncmp( p, "import", 6 ))
1083
{
1084
p = skip_spaces( p + 6 );
1085
if (*p != '"') continue;
1086
include = ++p;
1087
while (*p && (*p != '"')) p++;
1088
if (!*p) fatal_error( "malformed import directive\n" );
1089
*p = 0;
1090
add_dependency( source, include, INCL_IMPORT );
1091
continue;
1092
}
1093
1094
/* check for #include inside cpp_quote */
1095
if (!strncmp( p, "cpp_quote", 9 ))
1096
{
1097
p = skip_spaces( p + 9 );
1098
if (*p++ != '(') continue;
1099
p = skip_spaces( p );
1100
if (*p++ != '"') continue;
1101
if (*p++ != '#') continue;
1102
p = skip_spaces( p );
1103
if (strncmp( p, "include", 7 )) continue;
1104
p = skip_spaces( p + 7 );
1105
if (*p == '\\' && p[1] == '"')
1106
{
1107
p += 2;
1108
quote = '"';
1109
}
1110
else
1111
{
1112
if (*p++ != '<' ) continue;
1113
quote = '>';
1114
}
1115
include = p;
1116
while (*p && (*p != quote)) p++;
1117
if (!*p || (quote == '"' && p[-1] != '\\'))
1118
fatal_error( "malformed #include directive inside cpp_quote\n" );
1119
if (quote == '"') p--; /* remove backslash */
1120
*p = 0;
1121
add_dependency( source, include, (quote == '>') ? INCL_CPP_QUOTE_SYSTEM : INCL_CPP_QUOTE );
1122
continue;
1123
}
1124
1125
parse_cpp_directive( source, p );
1126
}
1127
}
1128
1129
/*******************************************************************
1130
* parse_c_file
1131
*/
1132
static void parse_c_file( struct file *source, FILE *file )
1133
{
1134
char *buffer;
1135
1136
input_line = 0;
1137
while ((buffer = get_line( file )))
1138
{
1139
parse_cpp_directive( source, buffer );
1140
}
1141
}
1142
1143
1144
/*******************************************************************
1145
* parse_rc_file
1146
*/
1147
static void parse_rc_file( struct file *source, FILE *file )
1148
{
1149
char *buffer, *include;
1150
1151
input_line = 0;
1152
while ((buffer = get_line( file )))
1153
{
1154
char quote;
1155
char *p = skip_spaces( buffer );
1156
1157
if (p[0] == '/' && p[1] == '*') /* check for magic makedep comment */
1158
{
1159
p = skip_spaces( p + 2 );
1160
if (strncmp( p, "@makedep:", 9 )) continue;
1161
p = skip_spaces( p + 9 );
1162
quote = '"';
1163
if (*p == quote)
1164
{
1165
include = ++p;
1166
while (*p && *p != quote) p++;
1167
}
1168
else
1169
{
1170
include = p;
1171
while (*p && *p != ' ' && *p != '\t' && *p != '*') p++;
1172
}
1173
if (!*p)
1174
fatal_error( "malformed makedep comment\n" );
1175
*p = 0;
1176
add_dependency( source, include, (quote == '>') ? INCL_SYSTEM : INCL_NORMAL );
1177
continue;
1178
}
1179
1180
parse_cpp_directive( source, buffer );
1181
}
1182
}
1183
1184
1185
/*******************************************************************
1186
* parse_in_file
1187
*/
1188
static void parse_in_file( struct file *source, FILE *file )
1189
{
1190
char *p, *buffer;
1191
1192
if (!strendswith( source->name, ".man.in" )) return; /* not a man page */
1193
1194
input_line = 0;
1195
while ((buffer = get_line( file )))
1196
{
1197
if (strncmp( buffer, ".TH", 3 )) continue;
1198
p = skip_spaces( buffer + 3 );
1199
if (!(p = strtok( p, " \t" ))) continue; /* program name */
1200
if (!(p = strtok( NULL, " \t" ))) continue; /* man section */
1201
source->args = xstrdup( p );
1202
return;
1203
}
1204
}
1205
1206
1207
/*******************************************************************
1208
* parse_sfd_file
1209
*/
1210
static void parse_sfd_file( struct file *source, FILE *file )
1211
{
1212
char *p, *eol, *buffer;
1213
1214
input_line = 0;
1215
while ((buffer = get_line( file )))
1216
{
1217
if (strncmp( buffer, "UComments:", 10 )) continue;
1218
p = buffer + 10;
1219
while (*p == ' ') p++;
1220
if (p[0] == '"' && p[1] && buffer[strlen(buffer) - 1] == '"')
1221
{
1222
p++;
1223
buffer[strlen(buffer) - 1] = 0;
1224
}
1225
while ((eol = strstr( p, "+AAoA" )))
1226
{
1227
*eol = 0;
1228
p = skip_spaces( p );
1229
if (*p++ == '#')
1230
{
1231
p = skip_spaces( p );
1232
if (!strncmp( p, "pragma", 6 )) parse_pragma_directive( source, p + 6 );
1233
}
1234
p = eol + 5;
1235
}
1236
p = skip_spaces( p );
1237
if (*p++ != '#') return;
1238
p = skip_spaces( p );
1239
if (!strncmp( p, "pragma", 6 )) parse_pragma_directive( source, p + 6 );
1240
return;
1241
}
1242
}
1243
1244
1245
static const struct
1246
{
1247
const char *ext;
1248
void (*parse)( struct file *file, FILE *f );
1249
} parse_functions[] =
1250
{
1251
{ ".c", parse_c_file },
1252
{ ".h", parse_c_file },
1253
{ ".inl", parse_c_file },
1254
{ ".l", parse_c_file },
1255
{ ".m", parse_c_file },
1256
{ ".rh", parse_c_file },
1257
{ ".x", parse_c_file },
1258
{ ".y", parse_c_file },
1259
{ ".idl", parse_idl_file },
1260
{ ".rc", parse_rc_file },
1261
{ ".ver", parse_rc_file },
1262
{ ".in", parse_in_file },
1263
{ ".sfd", parse_sfd_file }
1264
};
1265
1266
/*******************************************************************
1267
* load_file
1268
*/
1269
static struct file *load_file( const char *name )
1270
{
1271
struct file *file;
1272
FILE *f;
1273
unsigned int i, hash = hash_filename( name );
1274
1275
LIST_FOR_EACH_ENTRY( file, &files[hash], struct file, entry )
1276
if (!strcmp( name, file->name )) return file;
1277
1278
if (!(f = fopen( name, "r" ))) return NULL;
1279
1280
file = add_file( name );
1281
list_add_tail( &files[hash], &file->entry );
1282
input_file_name = file->name;
1283
input_line = 0;
1284
1285
for (i = 0; i < ARRAY_SIZE(parse_functions); i++)
1286
{
1287
if (!strendswith( name, parse_functions[i].ext )) continue;
1288
parse_functions[i].parse( file, f );
1289
break;
1290
}
1291
1292
fclose( f );
1293
input_file_name = NULL;
1294
1295
return file;
1296
}
1297
1298
1299
/*******************************************************************
1300
* open_include_path_file
1301
*
1302
* Open a file from a directory on the include path.
1303
*/
1304
static struct file *open_include_path_file( const struct makefile *make, const char *dir,
1305
const char *name, char **filename )
1306
{
1307
char *src_path = concat_paths( dir, name );
1308
struct file *ret = load_file( src_path );
1309
1310
if (ret) *filename = src_path;
1311
return ret;
1312
}
1313
1314
1315
/*******************************************************************
1316
* open_file_same_dir
1317
*
1318
* Open a file in the same directory as the parent.
1319
*/
1320
static struct file *open_file_same_dir( const struct incl_file *parent, const char *name, char **filename )
1321
{
1322
char *src_path = replace_filename( parent->file->name, name );
1323
struct file *ret = load_file( src_path );
1324
1325
if (ret) *filename = replace_filename( parent->filename, name );
1326
return ret;
1327
}
1328
1329
1330
/*******************************************************************
1331
* open_same_dir_generated_file
1332
*
1333
* Open a generated_file in the same directory as the parent.
1334
*/
1335
static struct file *open_same_dir_generated_file( const struct makefile *make,
1336
const struct incl_file *parent, struct incl_file *file,
1337
const char *ext, const char *src_ext )
1338
{
1339
char *filename;
1340
struct file *ret = NULL;
1341
1342
if (strendswith( file->name, ext ) &&
1343
(ret = open_file_same_dir( parent, replace_extension( file->name, ext, src_ext ), &filename )))
1344
{
1345
file->sourcename = filename;
1346
file->filename = obj_dir_path( make, replace_filename( parent->name, file->name ));
1347
}
1348
return ret;
1349
}
1350
1351
1352
/*******************************************************************
1353
* open_local_file
1354
*
1355
* Open a file in the source directory of the makefile.
1356
*/
1357
static struct file *open_local_file( const struct makefile *make, const char *path, char **filename )
1358
{
1359
char *src_path = src_dir_path( make, path );
1360
struct file *ret = load_file( src_path );
1361
1362
/* if not found, try parent dir */
1363
if (!ret && make->parent_dir)
1364
{
1365
free( src_path );
1366
path = strmake( "%s/%s", make->parent_dir, path );
1367
src_path = src_dir_path( make, path );
1368
ret = load_file( src_path );
1369
}
1370
1371
if (ret) *filename = src_path;
1372
return ret;
1373
}
1374
1375
1376
/*******************************************************************
1377
* open_local_generated_file
1378
*
1379
* Open a generated file in the directory of the makefile.
1380
*/
1381
static struct file *open_local_generated_file( const struct makefile *make, struct incl_file *file,
1382
const char *ext, const char *src_ext )
1383
{
1384
struct incl_file *include;
1385
1386
if (strendswith( file->name, ext ) &&
1387
(include = find_src_file( make, replace_extension( file->name, ext, src_ext ) )))
1388
{
1389
file->sourcename = include->filename;
1390
file->filename = obj_dir_path( make, file->name );
1391
return include->file;
1392
}
1393
return NULL;
1394
}
1395
1396
1397
/*******************************************************************
1398
* open_local_maintainer_file
1399
*
1400
* Open a maintainer-generated file in the directory of the makefile.
1401
*/
1402
static struct file *open_local_maintainer_file( const struct makefile *make, struct incl_file *file,
1403
const char *ext, const char *src_ext )
1404
{
1405
struct incl_file *include;
1406
1407
if (strendswith( file->name, ext ) &&
1408
(include = find_src_file( make, replace_extension( file->name, ext, src_ext ) )))
1409
{
1410
file->sourcename = include->filename;
1411
file->filename = replace_extension( include->filename, src_ext, ext );
1412
return include->file;
1413
}
1414
return NULL;
1415
}
1416
1417
1418
/*******************************************************************
1419
* open_global_file
1420
*
1421
* Open a file in the top-level source directory.
1422
*/
1423
static struct file *open_global_file( const char *path, char **filename )
1424
{
1425
char *src_path = root_src_dir_path( path );
1426
struct file *ret = load_file( src_path );
1427
1428
if (ret) *filename = src_path;
1429
return ret;
1430
}
1431
1432
1433
/*******************************************************************
1434
* open_global_header
1435
*
1436
* Open a file in the global include source directory.
1437
*/
1438
static struct file *open_global_header( const char *path, char **filename )
1439
{
1440
struct incl_file *include = find_src_file( include_makefile, path );
1441
1442
if (!include) return NULL;
1443
*filename = include->filename;
1444
return include->file;
1445
}
1446
1447
1448
/*******************************************************************
1449
* open_global_generated_file
1450
*
1451
* Open a generated file in the top-level source directory.
1452
*/
1453
static struct file *open_global_generated_file( const struct makefile *make, struct incl_file *file,
1454
const char *ext, const char *src_ext )
1455
{
1456
struct incl_file *include;
1457
1458
if (strendswith( file->name, ext ) &&
1459
(include = find_src_file( include_makefile, replace_extension( file->name, ext, src_ext ) )))
1460
{
1461
file->sourcename = include->filename;
1462
file->filename = strmake( "include/%s", file->name );
1463
return include->file;
1464
}
1465
return NULL;
1466
}
1467
1468
1469
/*******************************************************************
1470
* open_src_file
1471
*/
1472
static struct file *open_src_file( const struct makefile *make, struct incl_file *pFile )
1473
{
1474
struct file *file = open_local_file( make, pFile->name, &pFile->filename );
1475
1476
if (!file) fatal_perror( "open %s", pFile->name );
1477
return file;
1478
}
1479
1480
1481
/*******************************************************************
1482
* find_importlib_module
1483
*/
1484
static struct makefile *find_importlib_module( const char *name )
1485
{
1486
unsigned int i, len;
1487
1488
for (i = 0; i < subdirs.count; i++)
1489
{
1490
if (strncmp( submakes[i]->obj_dir, "dlls/", 5 )) continue;
1491
len = strlen(submakes[i]->obj_dir);
1492
if (strncmp( submakes[i]->obj_dir + 5, name, len - 5 )) continue;
1493
if (!name[len - 5] || !strcmp( name + len - 5, ".dll" )) return submakes[i];
1494
}
1495
return NULL;
1496
}
1497
1498
1499
/*******************************************************************
1500
* open_include_file
1501
*/
1502
static struct file *open_include_file( const struct makefile *make, struct incl_file *pFile )
1503
{
1504
struct file *file = NULL;
1505
struct incl_file *include;
1506
unsigned int len;
1507
1508
errno = ENOENT;
1509
1510
/* check for generated files */
1511
if ((file = open_local_generated_file( make, pFile, ".tab.h", ".y" ))) return file;
1512
if ((file = open_local_generated_file( make, pFile, ".h", ".idl" ))) return file;
1513
if (fontforge && (file = open_local_generated_file( make, pFile, ".ttf", ".sfd" ))) return file;
1514
if (convert && rsvg && icotool)
1515
{
1516
if ((file = open_local_maintainer_file( make, pFile, ".bmp", ".svg" ))) return file;
1517
if ((file = open_local_maintainer_file( make, pFile, ".cur", ".svg" ))) return file;
1518
if ((file = open_local_maintainer_file( make, pFile, ".ico", ".svg" ))) return file;
1519
}
1520
if ((file = open_local_generated_file( make, pFile, "-client-protocol.h", ".xml" ))) return file;
1521
if ((file = open_local_generated_file( make, pFile, ".winmd", ".idl" ))) return file;
1522
1523
/* check for extra targets */
1524
if (strarray_exists( make->extra_targets, pFile->name ))
1525
{
1526
pFile->sourcename = src_dir_path( make, pFile->name );
1527
pFile->filename = obj_dir_path( make, pFile->name );
1528
return NULL;
1529
}
1530
1531
/* check for header explicitly listed in the makefile */
1532
if ((include = find_src_file( make, pFile->name )))
1533
{
1534
pFile->filename = include->filename;
1535
return include->file;
1536
}
1537
1538
/* check for global importlib (module dependency) */
1539
if (pFile->type == INCL_IMPORTLIB && find_importlib_module( pFile->name ))
1540
{
1541
pFile->filename = pFile->name;
1542
return NULL;
1543
}
1544
1545
/* check for generated files in global includes */
1546
if ((file = open_global_generated_file( make, pFile, ".h", ".idl" ))) return file;
1547
if ((file = open_global_generated_file( make, pFile, ".h", ".h.in" ))) return file;
1548
if (strendswith( pFile->name, "tmpl.h" ) &&
1549
(file = open_global_generated_file( make, pFile, ".h", ".x" ))) return file;
1550
1551
/* check in global includes source dir */
1552
if ((file = open_global_header( pFile->name, &pFile->filename ))) return file;
1553
1554
/* check in global msvcrt includes */
1555
if (pFile->use_msvcrt &&
1556
(file = open_global_header( strmake( "msvcrt/%s", pFile->name ), &pFile->filename )))
1557
return file;
1558
1559
/* now try in source dir */
1560
if ((file = open_local_file( make, pFile->name, &pFile->filename ))) return file;
1561
1562
/* now search in include paths */
1563
STRARRAY_FOR_EACH( dir, &make->include_paths )
1564
{
1565
if (root_src_dir)
1566
{
1567
len = strlen( root_src_dir );
1568
if (!strncmp( dir, root_src_dir, len ) && (!dir[len] || dir[len] == '/'))
1569
{
1570
while (dir[len] == '/') len++;
1571
file = open_global_file( concat_paths( dir + len, pFile->name ), &pFile->filename );
1572
}
1573
}
1574
else
1575
{
1576
if (*dir == '/') continue;
1577
file = open_include_path_file( make, dir, pFile->name, &pFile->filename );
1578
}
1579
if (!file) continue;
1580
pFile->is_external = 1;
1581
return file;
1582
}
1583
1584
if (pFile->type == INCL_SYSTEM) return NULL; /* ignore system files we cannot find */
1585
1586
/* try in src file directory */
1587
if ((file = open_same_dir_generated_file( make, pFile->included_by, pFile, ".tab.h", ".y" )) ||
1588
(file = open_same_dir_generated_file( make, pFile->included_by, pFile, ".h", ".idl" )) ||
1589
(file = open_file_same_dir( pFile->included_by, pFile->name, &pFile->filename )))
1590
{
1591
pFile->is_external = pFile->included_by->is_external;
1592
return file;
1593
}
1594
1595
if (make->extlib) return NULL; /* ignore missing files in external libs */
1596
1597
fprintf( stderr, "%s:%d: error: ", pFile->included_by->file->name, pFile->included_line );
1598
perror( pFile->name );
1599
pFile = pFile->included_by;
1600
while (pFile && pFile->included_by)
1601
{
1602
const char *parent = pFile->included_by->sourcename;
1603
if (!parent) parent = pFile->included_by->file->name;
1604
fprintf( stderr, "%s:%d: note: %s was first included here\n",
1605
parent, pFile->included_line, pFile->name );
1606
pFile = pFile->included_by;
1607
}
1608
exit(1);
1609
}
1610
1611
1612
/*******************************************************************
1613
* add_all_includes
1614
*/
1615
static void add_all_includes( struct makefile *make, struct incl_file *parent, struct file *file )
1616
{
1617
ARRAY_FOR_EACH( dep, &file->deps, const struct dependency )
1618
{
1619
switch (dep->type)
1620
{
1621
case INCL_NORMAL:
1622
case INCL_IMPORT:
1623
add_include( make, parent, dep->name, dep->line, INCL_NORMAL );
1624
break;
1625
case INCL_IMPORTLIB:
1626
add_include( make, parent, dep->name, dep->line, INCL_IMPORTLIB );
1627
break;
1628
case INCL_SYSTEM:
1629
add_include( make, parent, dep->name, dep->line, INCL_SYSTEM );
1630
break;
1631
case INCL_CPP_QUOTE:
1632
case INCL_CPP_QUOTE_SYSTEM:
1633
break;
1634
}
1635
}
1636
}
1637
1638
1639
/*******************************************************************
1640
* parse_file
1641
*/
1642
static void parse_file( struct makefile *make, struct incl_file *source, int src )
1643
{
1644
struct file *file = src ? open_src_file( make, source ) : open_include_file( make, source );
1645
1646
if (!file) return;
1647
1648
source->file = file;
1649
1650
if (strendswith( file->name, ".m" )) file->flags |= FLAG_C_UNIX;
1651
if (file->flags & FLAG_C_UNIX) source->use_msvcrt = 0;
1652
else if (file->flags & FLAG_C_IMPLIB) source->use_msvcrt = 1;
1653
1654
if (source->sourcename)
1655
{
1656
if (strendswith( source->sourcename, ".idl" ))
1657
{
1658
/* generated .h file always includes these */
1659
add_include( make, source, "rpc.h", 0, INCL_NORMAL );
1660
add_include( make, source, "rpcndr.h", 0, INCL_NORMAL );
1661
ARRAY_FOR_EACH( dep, &file->deps, const struct dependency )
1662
{
1663
switch (dep->type)
1664
{
1665
case INCL_IMPORT:
1666
if (strendswith( dep->name, ".idl" ))
1667
add_include( make, source, replace_extension( dep->name, ".idl", ".h" ),
1668
dep->line, INCL_NORMAL );
1669
else
1670
add_include( make, source, dep->name, dep->line, INCL_NORMAL );
1671
break;
1672
case INCL_CPP_QUOTE:
1673
add_include( make, source, dep->name, dep->line, INCL_NORMAL );
1674
break;
1675
case INCL_CPP_QUOTE_SYSTEM:
1676
add_include( make, source, dep->name, dep->line, INCL_SYSTEM );
1677
break;
1678
case INCL_NORMAL:
1679
case INCL_SYSTEM:
1680
case INCL_IMPORTLIB:
1681
break;
1682
}
1683
}
1684
return;
1685
}
1686
}
1687
1688
add_all_includes( make, source, file );
1689
}
1690
1691
1692
/*******************************************************************
1693
* add_src_file
1694
*
1695
* Add a source file to the list.
1696
*/
1697
static struct incl_file *add_src_file( struct makefile *make, const char *name )
1698
{
1699
struct incl_file *file = xmalloc( sizeof(*file) );
1700
1701
memset( file, 0, sizeof(*file) );
1702
file->name = xstrdup(name);
1703
file->use_msvcrt = is_using_msvcrt( make );
1704
file->is_external = !!make->extlib;
1705
list_add_tail( &make->sources, &file->entry );
1706
if (make == include_makefile)
1707
{
1708
unsigned int hash = hash_filename( name );
1709
list_add_tail( &global_includes[hash], &file->hash_entry );
1710
}
1711
parse_file( make, file, 1 );
1712
return file;
1713
}
1714
1715
1716
/*******************************************************************
1717
* open_input_makefile
1718
*/
1719
static FILE *open_input_makefile( const struct makefile *make )
1720
{
1721
FILE *ret;
1722
1723
if (make->obj_dir)
1724
input_file_name = root_src_dir_path( obj_dir_path( make, "Makefile.in" ));
1725
else if (input_makefile_name)
1726
input_file_name = input_makefile_name;
1727
else
1728
input_file_name = output_makefile_name; /* always use output name for main Makefile */
1729
1730
input_line = 0;
1731
if (!(ret = fopen( input_file_name, "r" ))) fatal_perror( "open" );
1732
return ret;
1733
}
1734
1735
1736
/*******************************************************************
1737
* get_make_variable
1738
*/
1739
static const char *get_make_variable( const struct makefile *make, const char *name )
1740
{
1741
const char *ret;
1742
1743
if ((ret = strarray_get_value( cmdline_vars, name ))) return ret;
1744
if ((ret = strarray_get_value( make->vars, name ))) return ret;
1745
if (top_makefile && (ret = strarray_get_value( top_makefile->vars, name ))) return ret;
1746
return NULL;
1747
}
1748
1749
1750
/*******************************************************************
1751
* get_expanded_make_variable
1752
*/
1753
static char *get_expanded_make_variable( const struct makefile *make, const char *name )
1754
{
1755
const char *var;
1756
char *p, *end, *expand, *tmp;
1757
1758
var = get_make_variable( make, name );
1759
if (!var) return NULL;
1760
1761
p = expand = xstrdup( var );
1762
while ((p = strchr( p, '$' )))
1763
{
1764
if (p[1] == '(')
1765
{
1766
if (!(end = strchr( p + 2, ')' ))) fatal_error( "syntax error in '%s'\n", expand );
1767
*end++ = 0;
1768
if (strchr( p + 2, ':' )) fatal_error( "pattern replacement not supported for '%s'\n", p + 2 );
1769
var = get_make_variable( make, p + 2 );
1770
tmp = replace_substr( expand, p, end - p, var ? var : "" );
1771
/* switch to the new string */
1772
p = tmp + (p - expand);
1773
free( expand );
1774
expand = tmp;
1775
}
1776
else if (p[1] == '{') /* don't expand ${} variables */
1777
{
1778
if (!(end = strchr( p + 2, '}' ))) fatal_error( "syntax error in '%s'\n", expand );
1779
p = end + 1;
1780
}
1781
else if (p[1] == '$')
1782
{
1783
p += 2;
1784
}
1785
else fatal_error( "syntax error in '%s'\n", expand );
1786
}
1787
1788
/* consider empty variables undefined */
1789
p = skip_spaces( expand );
1790
if (*p) return expand;
1791
free( expand );
1792
return NULL;
1793
}
1794
1795
1796
/*******************************************************************
1797
* get_expanded_make_var_array
1798
*/
1799
static struct strarray get_expanded_make_var_array( const struct makefile *make, const char *name )
1800
{
1801
struct strarray ret = empty_strarray;
1802
char *value, *token;
1803
1804
if ((value = get_expanded_make_variable( make, name )))
1805
for (token = strtok( value, " \t" ); token; token = strtok( NULL, " \t" ))
1806
strarray_add( &ret, token );
1807
return ret;
1808
}
1809
1810
1811
/*******************************************************************
1812
* get_expanded_file_local_var
1813
*/
1814
static struct strarray get_expanded_file_local_var( const struct makefile *make, const char *file,
1815
const char *name )
1816
{
1817
char *p, *var = strmake( "%s_%s", file, name );
1818
1819
for (p = var; *p; p++) if (!isalnum( *p )) *p = '_';
1820
return get_expanded_make_var_array( make, var );
1821
}
1822
1823
1824
/*******************************************************************
1825
* get_expanded_arch_var
1826
*/
1827
static char *get_expanded_arch_var( const struct makefile *make, const char *name, int arch )
1828
{
1829
return get_expanded_make_variable( make, arch ? strmake( "%s_%s", archs.str[arch], name ) : name );
1830
}
1831
1832
1833
/*******************************************************************
1834
* get_expanded_arch_var_array
1835
*/
1836
static struct strarray get_expanded_arch_var_array( const struct makefile *make, const char *name, int arch )
1837
{
1838
return get_expanded_make_var_array( make, arch ? strmake( "%s_%s", archs.str[arch], name ) : name );
1839
}
1840
1841
1842
/*******************************************************************
1843
* set_make_variable
1844
*/
1845
static int set_make_variable( struct strarray *array, const char *assignment )
1846
{
1847
char *p, *name;
1848
1849
p = name = xstrdup( assignment );
1850
while (isalnum(*p) || *p == '_') p++;
1851
if (name == p) return 0; /* not a variable */
1852
if (isspace(*p))
1853
{
1854
*p++ = 0;
1855
p = skip_spaces( p );
1856
}
1857
if (*p != '=') return 0; /* not an assignment */
1858
*p++ = 0;
1859
p = skip_spaces( p );
1860
1861
strarray_set_value( array, name, p );
1862
return 1;
1863
}
1864
1865
1866
/*******************************************************************
1867
* parse_makefile
1868
*/
1869
static struct makefile *parse_makefile( const char *path )
1870
{
1871
char *buffer;
1872
FILE *file;
1873
struct makefile *make = xmalloc( sizeof(*make) );
1874
1875
memset( make, 0, sizeof(*make) );
1876
make->obj_dir = path;
1877
if (root_src_dir) make->src_dir = root_src_dir_path( make->obj_dir );
1878
if (path && !strcmp( path, "include" )) include_makefile = make;
1879
1880
file = open_input_makefile( make );
1881
while ((buffer = get_line( file )))
1882
{
1883
if (!strncmp( buffer, separator, strlen(separator) )) break;
1884
if (*buffer == '\t') continue; /* command */
1885
buffer = skip_spaces( buffer );
1886
if (*buffer == '#') continue; /* comment */
1887
set_make_variable( &make->vars, buffer );
1888
}
1889
fclose( file );
1890
input_file_name = NULL;
1891
return make;
1892
}
1893
1894
1895
/*******************************************************************
1896
* add_generated_version_resource
1897
*
1898
* Add a generated version resource file built from common.ver.
1899
*/
1900
static void add_generated_version_resource( struct makefile *make )
1901
{
1902
struct incl_file *file, *common_ver = find_src_file( include_makefile, "common.ver" );
1903
unsigned int i;
1904
1905
if (!common_ver) return;
1906
1907
for (i = 0; i < ARRAY_SIZE(version_vars); i++) if (get_make_variable( make, version_vars[i] )) break;
1908
if (i == ARRAY_SIZE(version_vars)) return;
1909
1910
file = add_generated_source( make, "version.ver", NULL, 0 );
1911
file->filename = common_ver->filename;
1912
/* copy common.ver dependencies */
1913
ARRAY_FOR_EACH( dep, &common_ver->files, struct incl_file * )
1914
*ARRAY_ADD( &file->files, struct incl_file * ) = *dep;
1915
}
1916
1917
1918
/*******************************************************************
1919
* add_generated_sources
1920
*/
1921
static void add_generated_sources( struct makefile *make )
1922
{
1923
unsigned int arch;
1924
bool has_version_res = false;
1925
struct incl_file *source, *next, *file, *dlldata = NULL;
1926
struct strarray objs = get_expanded_make_var_array( make, "EXTRA_OBJS" );
1927
1928
LIST_FOR_EACH_ENTRY_SAFE( source, next, &make->sources, struct incl_file, entry )
1929
{
1930
for (arch = 0; arch < archs.count; arch++)
1931
{
1932
if (!is_multiarch( arch )) continue;
1933
if (source->file->flags & FLAG_IDL_CLIENT)
1934
{
1935
file = add_generated_source( make, replace_extension( source->name, ".idl", "_c.c" ), NULL, arch );
1936
add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1937
add_all_includes( make, file, file->file );
1938
}
1939
if (source->file->flags & FLAG_IDL_SERVER)
1940
{
1941
file = add_generated_source( make, replace_extension( source->name, ".idl", "_s.c" ), NULL, arch );
1942
add_dependency( file->file, "wine/exception.h", INCL_NORMAL );
1943
add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1944
add_all_includes( make, file, file->file );
1945
}
1946
if (source->file->flags & FLAG_IDL_IDENT)
1947
{
1948
file = add_generated_source( make, replace_extension( source->name, ".idl", "_i.c" ), NULL, arch );
1949
add_dependency( file->file, "rpc.h", INCL_NORMAL );
1950
add_dependency( file->file, "rpcndr.h", INCL_NORMAL );
1951
add_dependency( file->file, "guiddef.h", INCL_NORMAL );
1952
add_all_includes( make, file, file->file );
1953
}
1954
if (source->file->flags & FLAG_IDL_PROXY)
1955
{
1956
file = add_generated_source( make, replace_extension( source->name, ".idl", "_p.c" ), NULL, arch );
1957
add_dependency( file->file, "objbase.h", INCL_NORMAL );
1958
add_dependency( file->file, "rpcproxy.h", INCL_NORMAL );
1959
add_dependency( file->file, "wine/exception.h", INCL_NORMAL );
1960
add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1961
add_all_includes( make, file, file->file );
1962
}
1963
if (source->file->flags & FLAG_IDL_TYPELIB)
1964
{
1965
add_generated_source( make, replace_extension( source->name, ".idl", "_l.res" ), NULL, arch );
1966
}
1967
if (source->file->flags & FLAG_IDL_REGTYPELIB)
1968
{
1969
add_generated_source( make, replace_extension( source->name, ".idl", "_t.res" ), NULL, arch );
1970
}
1971
if (source->file->flags & FLAG_IDL_REGISTER)
1972
{
1973
add_generated_source( make, replace_extension( source->name, ".idl", "_r.res" ), NULL, arch );
1974
}
1975
}
1976
1977
/* now the arch-independent files */
1978
1979
if ((source->file->flags & FLAG_IDL_PROXY) && !dlldata)
1980
{
1981
dlldata = add_generated_source( make, "dlldata.o", "dlldata.c", 0 );
1982
add_dependency( dlldata->file, "objbase.h", INCL_NORMAL );
1983
add_dependency( dlldata->file, "rpcproxy.h", INCL_NORMAL );
1984
add_all_includes( make, dlldata, dlldata->file );
1985
}
1986
if (source->file->flags & FLAG_IDL_HEADER)
1987
{
1988
add_generated_source( make, replace_extension( source->name, ".idl", ".h" ), NULL, 0 );
1989
}
1990
if (source->file->flags & FLAG_IDL_WINMD)
1991
{
1992
file = add_generated_source( make, replace_extension( source->name, ".idl", ".winmd" ), NULL, 0 );
1993
file->file->flags |= source->file->flags & FLAG_INSTALL;
1994
}
1995
if (!source->file->flags && strendswith( source->name, ".idl" ))
1996
{
1997
if (!strncmp( source->name, "wine/", 5 )) continue;
1998
source->file->flags = FLAG_IDL_HEADER | FLAG_INSTALL;
1999
add_generated_source( make, replace_extension( source->name, ".idl", ".h" ), NULL, 0 );
2000
}
2001
else if (strendswith( source->name, ".x" ))
2002
{
2003
add_generated_source( make, replace_extension( source->name, ".x", ".h" ), NULL, 0 );
2004
}
2005
else if (strendswith( source->name, ".y" ))
2006
{
2007
file = add_generated_source( make, replace_extension( source->name, ".y", ".tab.c" ), NULL, 0 );
2008
/* steal the includes list from the source file */
2009
file->files = source->files;
2010
source->files = empty_array;
2011
}
2012
else if (strendswith( source->name, ".l" ))
2013
{
2014
file = add_generated_source( make, replace_extension( source->name, ".l", ".yy.c" ), NULL, 0 );
2015
/* steal the includes list from the source file */
2016
file->files = source->files;
2017
source->files = empty_array;
2018
}
2019
else if (strendswith( source->name, ".rc" ))
2020
{
2021
ARRAY_FOR_EACH( dep, &source->file->deps, const struct dependency )
2022
if (!strcmp( dep->name, "common.ver" )) has_version_res = true;
2023
}
2024
else if (strendswith( source->name, ".po" ))
2025
{
2026
if (!make->disabled[0])
2027
strarray_add_uniq( &linguas, replace_extension( source->name, ".po", "" ));
2028
}
2029
else if (strendswith( source->name, ".spec" ))
2030
{
2031
char *obj = replace_extension( source->name, ".spec", "" );
2032
strarray_addall_uniq( &make->extra_imports,
2033
get_expanded_file_local_var( make, obj, "IMPORTS" ));
2034
}
2035
else if (strendswith( source->name, ".xml" ))
2036
{
2037
char *code_name = replace_extension( source->name , ".xml", "-protocol.c" );
2038
char *header_name = replace_extension( source->name , ".xml", "-client-protocol.h" );
2039
2040
file = add_generated_source( make, code_name, NULL, 0 );
2041
file->file->flags |= FLAG_C_UNIX;
2042
file->use_msvcrt = 0;
2043
file = add_generated_source( make, header_name, NULL, 0 );
2044
file->file->flags |= FLAG_C_UNIX;
2045
file->use_msvcrt = 0;
2046
2047
free( code_name );
2048
free( header_name );
2049
}
2050
}
2051
2052
if (make->module)
2053
{
2054
if (!has_version_res) add_generated_version_resource( make );
2055
}
2056
else if (make->testdll)
2057
{
2058
for (arch = 0; arch < archs.count; arch++)
2059
{
2060
if (!is_multiarch( arch )) continue;
2061
file = add_generated_source( make, "testlist.o", "testlist.c", arch );
2062
add_dependency( file->file, "wine/test.h", INCL_NORMAL );
2063
add_all_includes( make, file, file->file );
2064
}
2065
}
2066
STRARRAY_FOR_EACH( obj, &objs )
2067
{
2068
/* default to .c for unknown extra object files */
2069
if (strendswith( obj, ".o" ))
2070
{
2071
file = add_generated_source( make, obj, replace_extension( obj, ".o", ".c" ), 0);
2072
file->file->flags |= FLAG_C_UNIX;
2073
file->use_msvcrt = 0;
2074
}
2075
else if (strendswith( obj, ".res" ))
2076
add_generated_source( make, replace_extension( obj, ".res", ".rc" ), NULL, 0 );
2077
else
2078
add_generated_source( make, obj, NULL, 0 );
2079
}
2080
}
2081
2082
2083
/*******************************************************************
2084
* create_file_directories
2085
*
2086
* Create the base directories of all the files.
2087
*/
2088
static void create_file_directories( const struct makefile *make, struct strarray files )
2089
{
2090
struct strarray subdirs = empty_strarray;
2091
char *dir;
2092
2093
STRARRAY_FOR_EACH( file, &files )
2094
{
2095
if (!strchr( file, '/' )) continue;
2096
dir = obj_dir_path( make, file );
2097
*strrchr( dir, '/' ) = 0;
2098
strarray_add_uniq( &subdirs, dir );
2099
}
2100
STRARRAY_FOR_EACH( dir, &subdirs ) mkdir_p( dir );
2101
}
2102
2103
2104
/*******************************************************************
2105
* output_filenames_obj_dir
2106
*/
2107
static void output_filenames_obj_dir( const struct makefile *make, struct strarray array )
2108
{
2109
STRARRAY_FOR_EACH( file, &array ) output_filename( obj_dir_path( make, file ));
2110
}
2111
2112
2113
/*******************************************************************
2114
* get_dependencies
2115
*/
2116
static void get_dependencies( struct incl_file *file, struct incl_file *source )
2117
{
2118
if (!file->filename) return;
2119
2120
if (file != source)
2121
{
2122
if (file->owner == source) return; /* already processed */
2123
if (file->type == INCL_IMPORTLIB)
2124
{
2125
if (!(source->file->flags & (FLAG_IDL_TYPELIB | FLAG_IDL_REGTYPELIB)))
2126
return; /* library is imported only when building a typelib */
2127
strarray_add( &source->importlibdeps, file->filename );
2128
}
2129
else strarray_add( &source->dependencies, file->filename );
2130
file->owner = source;
2131
2132
/* sanity checks */
2133
if (!strcmp( file->filename, "include/config.h" ) &&
2134
file != *ARRAY_ENTRY( &source->files, 0, struct incl_file * ) && !source->is_external)
2135
{
2136
input_file_name = source->filename;
2137
input_line = 0;
2138
ARRAY_FOR_EACH( dep, &source->file->deps, const struct dependency )
2139
if (!strcmp( dep->name, file->name )) input_line = dep->line;
2140
2141
fatal_error( "%s must be included before other headers\n", file->name );
2142
}
2143
}
2144
2145
ARRAY_FOR_EACH( ptr, &file->files, struct incl_file * ) get_dependencies( *ptr, source );
2146
}
2147
2148
2149
/*******************************************************************
2150
* get_local_dependencies
2151
*
2152
* Get the local dependencies of a given target.
2153
*/
2154
static struct strarray get_local_dependencies( const struct makefile *make, const char *name,
2155
struct strarray targets )
2156
{
2157
struct strarray deps = get_expanded_file_local_var( make, name, "DEPS" );
2158
struct strarray ret = empty_strarray;
2159
2160
STRARRAY_FOR_EACH( dep, &deps )
2161
{
2162
if (strarray_exists( targets, dep ))
2163
strarray_add( &ret, obj_dir_path( make, dep ));
2164
else
2165
strarray_add( &ret, src_dir_path( make, dep ));
2166
}
2167
return ret;
2168
}
2169
2170
2171
/*******************************************************************
2172
* get_static_lib
2173
*
2174
* Find the makefile that builds the named static library (which may be an import lib).
2175
*/
2176
static struct makefile *get_static_lib( const char *name, unsigned int arch )
2177
{
2178
unsigned int i;
2179
2180
for (i = 0; i < subdirs.count; i++)
2181
{
2182
if (submakes[i]->importlib && !strcmp( submakes[i]->importlib, name )) return submakes[i];
2183
if (!submakes[i]->staticlib) continue;
2184
if (submakes[i]->disabled[arch]) continue;
2185
if (strncmp( submakes[i]->staticlib, "lib", 3 )) continue;
2186
if (strncmp( submakes[i]->staticlib + 3, name, strlen(name) )) continue;
2187
if (strcmp( submakes[i]->staticlib + 3 + strlen(name), ".a" )) continue;
2188
return submakes[i];
2189
}
2190
return NULL;
2191
}
2192
2193
2194
/*******************************************************************
2195
* get_native_unix_lib
2196
*/
2197
static const char *get_native_unix_lib( const struct makefile *make, const char *name )
2198
{
2199
if (!make->unixlib) return NULL;
2200
if (strncmp( make->unixlib, name, strlen(name) )) return NULL;
2201
if (make->unixlib[strlen(name)] != '.') return NULL;
2202
return obj_dir_path( make, make->unixlib );
2203
}
2204
2205
2206
/*******************************************************************
2207
* get_parent_makefile
2208
*/
2209
static struct makefile *get_parent_makefile( struct makefile *make )
2210
{
2211
char *dir, *p;
2212
unsigned int i;
2213
2214
if (!make->obj_dir) return NULL;
2215
dir = xstrdup( make->obj_dir );
2216
if (!(p = strrchr( dir, '/' ))) return NULL;
2217
*p = 0;
2218
for (i = 0; i < subdirs.count; i++)
2219
if (!strcmp( submakes[i]->obj_dir, dir )) return submakes[i];
2220
return NULL;
2221
}
2222
2223
2224
/*******************************************************************
2225
* needs_delay_lib
2226
*/
2227
static int needs_delay_lib( const struct makefile *make, unsigned int arch )
2228
{
2229
if (delay_load_flags[arch]) return 0;
2230
if (!make->importlib) return 0;
2231
return strarray_exists( delay_import_libs, make->importlib );
2232
}
2233
2234
2235
/*******************************************************************
2236
* add_unix_libraries
2237
*/
2238
static struct strarray add_unix_libraries( const struct makefile *make, struct strarray *deps )
2239
{
2240
struct strarray ret = empty_strarray;
2241
struct strarray all_libs = empty_strarray;
2242
2243
if (strcmp( make->unixlib, "ntdll.so" )) strarray_add( &all_libs, "-lntdll" );
2244
strarray_addall( &all_libs, get_expanded_make_var_array( make, "UNIX_LIBS" ));
2245
2246
STRARRAY_FOR_EACH( file, &all_libs )
2247
{
2248
const char *lib = NULL;
2249
2250
if (!strncmp( file, "-l", 2 ))
2251
{
2252
for (unsigned int j = 0; j < subdirs.count; j++)
2253
{
2254
if (make == submakes[j]) continue;
2255
if ((lib = get_native_unix_lib( submakes[j], file + 2 ))) break;
2256
}
2257
}
2258
if (lib)
2259
{
2260
strarray_add( deps, lib );
2261
strarray_add( &ret, lib );
2262
}
2263
else strarray_add( &ret, file );
2264
}
2265
2266
strarray_addall( &ret, libs );
2267
return ret;
2268
}
2269
2270
2271
/*******************************************************************
2272
* is_crt_module
2273
*/
2274
static int is_crt_module( const char *file )
2275
{
2276
return !strncmp( file, "msvcr", 5 ) || !strncmp( file, "ucrt", 4 ) || !strcmp( file, "crtdll.dll" );
2277
}
2278
2279
2280
/*******************************************************************
2281
* get_default_crt
2282
*/
2283
static const char *get_default_crt( const struct makefile *make )
2284
{
2285
if (make->module && is_crt_module( make->module )) return NULL; /* don't add crt import to crt dlls */
2286
return !make->testdll && (!make->staticlib || make->extlib) ? "ucrtbase" : "msvcrt";
2287
}
2288
2289
2290
/*******************************************************************
2291
* get_crt_define
2292
*/
2293
static const char *get_crt_define( const struct makefile *make )
2294
{
2295
const char *crt_dll = NULL;
2296
unsigned int version = 0;
2297
2298
STRARRAY_FOR_EACH( imp, &make->imports )
2299
{
2300
if (!is_crt_module( imp )) continue;
2301
if (crt_dll) fatal_error( "More than one C runtime DLL imported: %s and %s\n", crt_dll, imp );
2302
crt_dll = imp;
2303
}
2304
2305
if (!crt_dll)
2306
{
2307
if (strarray_exists( make->extradllflags, "-nodefaultlibs" )) return "-D_MSVCR_VER=0";
2308
if (!(crt_dll = get_default_crt( make ))) crt_dll = make->module;
2309
}
2310
if (!strncmp( crt_dll, "ucrt", 4 )) return "-D_UCRT";
2311
sscanf( crt_dll, "msvcr%u", &version );
2312
return strmake( "-D_MSVCR_VER=%u", version );
2313
}
2314
2315
2316
/*******************************************************************
2317
* get_default_imports
2318
*/
2319
static struct strarray get_default_imports( const struct makefile *make, struct strarray imports,
2320
int nodefaultlibs )
2321
{
2322
struct strarray ret = empty_strarray;
2323
const char *crt_dll = get_default_crt( make );
2324
2325
if (nodefaultlibs)
2326
{
2327
STRARRAY_FOR_EACH( imp, &imports ) if (!strcmp( imp, "winecrt0" )) return ret;
2328
strarray_add( &ret, "winecrt0" );
2329
if (compiler_rt) strarray_add( &ret, compiler_rt );
2330
return ret;
2331
}
2332
2333
STRARRAY_FOR_EACH( imp, &imports ) if (is_crt_module( imp )) crt_dll = imp;
2334
2335
strarray_add( &ret, "winecrt0" );
2336
if (compiler_rt) strarray_add( &ret, compiler_rt );
2337
if (crt_dll) strarray_add( &ret, crt_dll );
2338
2339
if (make->is_win16 && (!make->importlib || strcmp( make->importlib, "kernel" )))
2340
strarray_add( &ret, "kernel" );
2341
2342
strarray_add( &ret, "kernel32" );
2343
strarray_add( &ret, "ntdll" );
2344
return ret;
2345
}
2346
2347
enum import_type
2348
{
2349
IMPORT_TYPE_DIRECT,
2350
IMPORT_TYPE_DELAYED,
2351
IMPORT_TYPE_DEFAULT,
2352
};
2353
2354
/*******************************************************************
2355
* add_import_libs
2356
*/
2357
static struct strarray add_import_libs( const struct makefile *make, struct strarray *deps,
2358
struct strarray imports, enum import_type type, unsigned int arch )
2359
{
2360
struct strarray ret = empty_strarray;
2361
unsigned int link_arch;
2362
2363
if (!get_link_arch( make, arch, &link_arch )) return ret;
2364
2365
STRARRAY_FOR_EACH( name, &imports )
2366
{
2367
struct makefile *submake;
2368
2369
/* add crt import lib only when adding the default imports libs */
2370
if (is_crt_module( name ) && type != IMPORT_TYPE_DEFAULT) continue;
2371
2372
if (name[0] == '-')
2373
{
2374
switch (name[1])
2375
{
2376
case 'L': strarray_add( &ret, name ); continue;
2377
case 'l': name += 2; break;
2378
default: continue;
2379
}
2380
}
2381
else name = get_base_name( name );
2382
2383
if ((submake = get_static_lib( name, link_arch )))
2384
{
2385
const char *ext = (type == IMPORT_TYPE_DELAYED && !delay_load_flags[arch]) ? ".delay.a" : ".a";
2386
const char *lib = obj_dir_path( submake, strmake( "%slib%s%s", arch_dirs[arch], name, ext ));
2387
strarray_add_uniq( deps, lib );
2388
strarray_add( &ret, lib );
2389
}
2390
else strarray_add( &ret, strmake( "-l%s", name ));
2391
}
2392
return ret;
2393
}
2394
2395
2396
/*******************************************************************
2397
* find_install_command
2398
*/
2399
static struct install_command *find_install_command( enum install_rules rules, struct strarray args,
2400
const char *dir )
2401
{
2402
unsigned int i;
2403
2404
ARRAY_FOR_EACH( cmd, &install_commands[rules], struct install_command )
2405
{
2406
if (strcmp( cmd->dir, dir )) continue;
2407
if (args.count != cmd->args.count) continue;
2408
for (i = 0; i < args.count; i++) if (strcmp( args.str[i], cmd->args.str[i] )) break;
2409
if (i == args.count) return cmd;
2410
}
2411
return NULL;
2412
}
2413
2414
2415
/*******************************************************************
2416
* add_install_command
2417
*/
2418
static struct install_command *add_install_command( struct makefile *make, const char *target,
2419
struct strarray args, const char *dir,
2420
const char *dest )
2421
{
2422
unsigned int i;
2423
struct install_command *cmd = NULL;
2424
2425
if (make->disabled[0]) return NULL;
2426
2427
for (i = 0; i < NB_INSTALL_RULES; i++)
2428
{
2429
if (strarray_exists( make->install[i], target ) ||
2430
strarray_exists( top_install[i], make->obj_dir ) ||
2431
strarray_exists( top_install[i], obj_dir_path( make, target )))
2432
{
2433
if (!dest && (cmd = find_install_command( i, args, dir ))) return cmd;
2434
cmd = ARRAY_ADD( &install_commands[i], struct install_command );
2435
cmd->args = args;
2436
cmd->dir = dir;
2437
cmd->dest = dest;
2438
cmd->files = empty_strarray;
2439
cmd->targets = empty_strarray;
2440
break;
2441
}
2442
}
2443
return cmd;
2444
}
2445
2446
2447
/*******************************************************************
2448
* install_data_file
2449
*/
2450
static void install_data_file( struct makefile *make, const char *target,
2451
const char *obj, const char *dir, const char *dst )
2452
{
2453
struct strarray args = empty_strarray;
2454
struct install_command *cmd;
2455
2456
strarray_add( &args, "-m 644" );
2457
strarray_add( &args, "$(INSTALL_DATA_FLAGS)" );
2458
2459
if ((cmd = add_install_command( make, target, args, dir, dst )))
2460
{
2461
char *file = obj_dir_path( make, obj );
2462
strarray_add( &cmd->files, file );
2463
strarray_add( &cmd->targets, file );
2464
}
2465
}
2466
2467
2468
/*******************************************************************
2469
* install_data_file_src
2470
*/
2471
static void install_data_file_src( struct makefile *make, const char *target,
2472
const char *src, const char *dir )
2473
{
2474
struct strarray args = empty_strarray;
2475
struct install_command *cmd;
2476
2477
strarray_add( &args, "-m 644" );
2478
strarray_add( &args, "$(INSTALL_DATA_FLAGS)" );
2479
2480
if (!(cmd = add_install_command( make, target, args, dir, NULL ))) return;
2481
strarray_add( &cmd->files, src_dir_path( make, src ));
2482
}
2483
2484
2485
/*******************************************************************
2486
* install_header
2487
*/
2488
static void install_header( struct makefile *make, const char *target, const char *obj )
2489
{
2490
const char *dir, *end;
2491
bool is_obj = !!obj;
2492
2493
if (!obj) obj = target;
2494
if (!strncmp( obj, "wine/", 5 )) dir = "$(includedir)";
2495
else if (!strncmp( obj, "msvcrt/", 7 )) dir = "$(includedir)/wine";
2496
else dir = "$(includedir)/wine/windows";
2497
if ((end = strrchr( obj, '/' ))) dir = strmake( "%s/%.*s", dir, (int)(end - obj), obj );
2498
2499
if (is_obj)
2500
install_data_file( make, target, obj, dir, NULL );
2501
else
2502
install_data_file_src( make, target, obj, dir );
2503
}
2504
2505
2506
/*******************************************************************
2507
* install_program
2508
*/
2509
static void install_program( struct makefile *make, const char *target,
2510
unsigned int arch, const char *obj, const char *dir )
2511
{
2512
struct strarray args = empty_strarray;
2513
struct install_command *cmd;
2514
2515
if (arch) strarray_add( &args, "-m 644" );
2516
strarray_add( &args, strip_progs[arch] );
2517
strarray_add( &args, "$(INSTALL_PROGRAM_FLAGS)" );
2518
2519
if ((cmd = add_install_command( make, target, args, dir, NULL )))
2520
{
2521
char *file = obj_dir_path( make, obj );
2522
strarray_add( &cmd->files, file );
2523
strarray_add( &cmd->targets, file );
2524
}
2525
}
2526
2527
2528
/*******************************************************************
2529
* install_script
2530
*/
2531
static void install_script( struct makefile *make, const char *src )
2532
{
2533
struct strarray args = empty_strarray;
2534
struct install_command *cmd;
2535
2536
strarray_add( &args, "$(INSTALL_SCRIPT_FLAGS)" );
2537
2538
if (!(cmd = add_install_command( make, src, args, "$(bindir)", NULL ))) return;
2539
strarray_add( &cmd->files, src_dir_path( make, src ));
2540
}
2541
2542
2543
/*******************************************************************
2544
* install_program_symlink
2545
*/
2546
static void install_program_symlink( struct makefile *make, const char *target,
2547
const char *obj, const char *dst )
2548
{
2549
struct strarray args = empty_strarray;
2550
struct install_command *cmd;
2551
2552
if (symlinks_supported)
2553
{
2554
strarray_add( &args, "-L" );
2555
2556
if (!(cmd = add_install_command( make, target, args, "$(bindir)", dst ))) return;
2557
strarray_add( &cmd->files, get_basename( obj ));
2558
}
2559
else
2560
{
2561
strarray_add( &args, strip_progs[0] );
2562
strarray_add( &args, "$(INSTALL_PROGRAM_FLAGS)" );
2563
2564
if (!(cmd = add_install_command( make, target, args, "$(bindir)", dst ))) return;
2565
strarray_add( &cmd->files, obj );
2566
strarray_add( &cmd->targets, obj );
2567
}
2568
}
2569
2570
2571
/*******************************************************************
2572
* install_data_symlink
2573
*/
2574
static void install_data_symlink( struct makefile *make, const char *target, const char *obj,
2575
const char *link_name, const char *dir, const char *dst )
2576
{
2577
struct strarray args = empty_strarray;
2578
struct install_command *cmd;
2579
2580
if (symlinks_supported)
2581
{
2582
strarray_add( &args, "-L" );
2583
2584
if (!(cmd = add_install_command( make, target, args, dir, dst ))) return;
2585
strarray_add( &cmd->files, link_name );
2586
}
2587
else
2588
{
2589
strarray_add( &args, "-m 644" );
2590
strarray_add( &args, "$(INSTALL_DATA_FLAGS)" );
2591
2592
if ((cmd = add_install_command( make, target, args, dir, dst )))
2593
{
2594
char *file = obj_dir_path( make, obj );
2595
strarray_add( &cmd->files, file );
2596
strarray_add( &cmd->targets, file );
2597
}
2598
}
2599
}
2600
2601
2602
/*******************************************************************
2603
* get_source_defines
2604
*/
2605
static struct strarray get_source_defines( struct makefile *make, struct incl_file *source,
2606
const char *obj )
2607
{
2608
struct strarray ret = empty_strarray;
2609
2610
strarray_addall( &ret, make->include_args );
2611
if (source->use_msvcrt)
2612
{
2613
strarray_add( &ret, strmake( "-I%s", root_src_dir_path( "include/msvcrt" )));
2614
STRARRAY_FOR_EACH( path, &make->include_paths ) strarray_add( &ret, strmake( "-I%s", path ));
2615
strarray_add( &ret, get_crt_define( make ));
2616
}
2617
strarray_addall( &ret, make->define_args );
2618
strarray_addall( &ret, get_expanded_file_local_var( make, obj, "EXTRADEFS" ));
2619
return ret;
2620
}
2621
2622
2623
/*******************************************************************
2624
* defines_from_variables
2625
*
2626
* Build command-line "-Dfoo=bar" arguments for a set of variables.
2627
*/
2628
static struct strarray defines_from_variables( struct strarray vars )
2629
{
2630
struct strarray defs = empty_strarray;
2631
char *p, *escaped;
2632
2633
for (unsigned int i = 0; i < vars.count - 1; i += 2)
2634
{
2635
const char *val = vars.str[i + 1];
2636
2637
if (strpbrk( val, " \t\n*?[]'\"\\`$;&()|<>#" ))
2638
{
2639
escaped = p = xmalloc( 2 * strlen(val) + 1 );
2640
do { if (*val == '"' || *val == '\\') *p++ = '\\'; } while ((*p++ = *val++));
2641
strarray_add( &defs, strmake( "-D%s=\"%s\"", vars.str[i], escaped ));
2642
}
2643
else strarray_add( &defs, strmake( "-D%s=%s", vars.str[i], val ));
2644
}
2645
return defs;
2646
}
2647
2648
2649
/*******************************************************************
2650
* get_version_defines
2651
*/
2652
static struct strarray get_version_defines( struct makefile *make )
2653
{
2654
struct strarray vars = empty_strarray;
2655
const char *name = replace_extension( make->module, "16", "" );
2656
unsigned int i;
2657
2658
if (strendswith( name, ".drv" )) strarray_set_value( &vars, "VER_FILETYPE", "VFT_DRV" );
2659
else if (make->is_exe) strarray_set_value( &vars, "VER_FILETYPE", "VFT_APP" );
2660
strarray_set_value( &vars, "VER_INTERNALNAME_STR", strmake( "\"%s\"", name ));
2661
strarray_set_value( &vars, "VER_FILEDESCRIPTION_STR",
2662
strmake( "\"Wine %s\"", get_basename_noext( name )));
2663
2664
for (i = 0; i < ARRAY_SIZE(version_vars); i++)
2665
{
2666
char *val = get_expanded_make_variable( make, version_vars[i] );
2667
if (val) strarray_set_value( &vars, version_vars[i], val );
2668
}
2669
return defines_from_variables( vars );
2670
}
2671
2672
2673
/*******************************************************************
2674
* remove_warning_flags
2675
*/
2676
static struct strarray remove_warning_flags( struct strarray flags )
2677
{
2678
struct strarray ret = empty_strarray;
2679
2680
STRARRAY_FOR_EACH( flag, &flags )
2681
if (strncmp( flag, "-W", 2 ) || !strncmp( flag, "-Wno-", 5 ))
2682
strarray_add( &ret, flag );
2683
return ret;
2684
}
2685
2686
2687
/*******************************************************************
2688
* get_debug_files
2689
*/
2690
static void output_debug_files( struct makefile *make, const char *name, unsigned int arch )
2691
{
2692
2693
STRARRAY_FOR_EACH( flag, &debug_flags[arch] )
2694
{
2695
const char *debug_file = NULL;
2696
if (!strcmp( flag, "pdb" )) debug_file = strmake( "%s.pdb", get_base_name( name ));
2697
else if (!strncmp( flag, "split", 5 )) debug_file = strmake( "%s.debug", name );
2698
if (!debug_file) continue;
2699
strarray_add( &make->debug_files, debug_file );
2700
output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
2701
}
2702
}
2703
2704
2705
/*******************************************************************
2706
* cmd_prefix
2707
*/
2708
static const char *cmd_prefix( const char *cmd )
2709
{
2710
if (!silent_rules) return "";
2711
return strmake( "$(quiet_%s)", cmd );
2712
}
2713
2714
2715
/*******************************************************************
2716
* output_winegcc_command
2717
*/
2718
static void output_winegcc_command( struct makefile *make, unsigned int arch )
2719
{
2720
output( "\t%s%s -o $@", cmd_prefix( "CCLD" ), winegcc );
2721
output_filename( "--wine-objdir ." );
2722
if (tools_dir)
2723
{
2724
output_filename( "--winebuild" );
2725
output_filename( winebuild );
2726
}
2727
if (cc_cmds[arch]) output_filename( cc_cmds[arch] );
2728
output_filenames( target_flags[arch] );
2729
if (native_archs[arch] && !make->disabled[native_archs[arch]])
2730
output_filenames( hybrid_target_flags[arch] );
2731
if (arch) return;
2732
output_filename( "-mno-cygwin" );
2733
output_filenames( lddll_flags );
2734
}
2735
2736
2737
/*******************************************************************
2738
* output_symlink_rule
2739
*
2740
* Output a rule to create a symlink.
2741
*/
2742
static void output_symlink_rule( const char *src_name, const char *link_name )
2743
{
2744
const char *name = strrchr( link_name, '/' );
2745
char *dir = NULL;
2746
2747
output( "\t%srm -f %s && ", cmd_prefix( "LN" ), link_name );
2748
2749
/* dest path with a directory needs special handling if ln -s isn't supported */
2750
if (name && !symlinks_supported)
2751
{
2752
dir = xstrdup( link_name );
2753
dir[name - link_name] = 0;
2754
output( "cd %s && %s %s %s\n", *dir ? dir : "/", ln_s, src_name, name + 1 );
2755
}
2756
else output( "%s %s %s\n", ln_s, src_name, link_name );
2757
2758
free( dir );
2759
}
2760
2761
2762
/*******************************************************************
2763
* output_srcdir_symlink
2764
*
2765
* Output rule to create a symlink back to the source directory, for source files
2766
* that are needed at run-time.
2767
*/
2768
static void output_srcdir_symlink( struct makefile *make, const char *obj )
2769
{
2770
char *src_file, *dst_file, *src_name;
2771
2772
if (!make->src_dir) return;
2773
src_file = src_dir_path( make, obj );
2774
dst_file = obj_dir_path( make, obj );
2775
output( "%s: %s\n", dst_file, src_file );
2776
2777
src_name = src_file;
2778
if (src_name[0] != '/' && make->obj_dir)
2779
src_name = concat_paths( get_root_relative_path( make ), src_name );
2780
2781
output_symlink_rule( src_name, dst_file );
2782
strarray_add( &make->all_targets[0], obj );
2783
}
2784
2785
2786
/*******************************************************************
2787
* output_install_commands
2788
*/
2789
static void output_install_commands( struct array commands )
2790
{
2791
ARRAY_FOR_EACH( cmd, &commands, const struct install_command )
2792
{
2793
if (cmd->dest)
2794
{
2795
assert( cmd->files.count == 1 );
2796
output( "\t%s", install );
2797
output_filenames( cmd->args );
2798
output_filenames( cmd->files );
2799
output_filename( strmake( "$(DESTDIR)%s/%s", cmd->dir, cmd->dest ));
2800
output( "\n" );
2801
}
2802
else
2803
{
2804
struct strarray args = empty_strarray;
2805
2806
strarray_addall( &args, cmd->args );
2807
strarray_add( &args, strmake( "-t $(DESTDIR)%s", cmd->dir ));
2808
output_multifiles_command( cmd->files, install, args );
2809
}
2810
}
2811
}
2812
2813
2814
/*******************************************************************
2815
* output_install_rules
2816
*/
2817
static void output_install_rules( struct makefile *make )
2818
{
2819
for (int i = 0; i < NB_INSTALL_RULES; i++)
2820
{
2821
struct strarray targets = empty_strarray;
2822
2823
if (!install_commands[i].count) continue;
2824
2825
ARRAY_FOR_EACH( cmd, &install_commands[i], const struct install_command )
2826
strarray_addall_uniq( &targets, cmd->targets );
2827
2828
if (strcmp( install_targets[i], "install-test" )) output( "install " );
2829
if (!strcmp( install_targets[i], "install-unixlib" )) output( "install-lib " );
2830
output( "%s::", install_targets[i] );
2831
output_filenames( targets );
2832
output_filename( install );
2833
output( "\n" );
2834
output_install_commands( install_commands[i] );
2835
strarray_add_uniq( &make->phony_targets, "install" );
2836
strarray_add_uniq( &make->phony_targets, install_targets[i] );
2837
}
2838
}
2839
2840
2841
static int cmp_string_length( const char **a, const char **b )
2842
{
2843
int paths_a = 0, paths_b = 0;
2844
const char *p;
2845
2846
for (p = *a; *p; p++) if (*p == '/') paths_a++;
2847
for (p = *b; *p; p++) if (*p == '/') paths_b++;
2848
if (paths_b != paths_a) return paths_b - paths_a;
2849
return strcmp( *a, *b );
2850
}
2851
2852
/*******************************************************************
2853
* get_removable_dirs
2854
*
2855
* Retrieve a list of directories to try to remove after deleting the files.
2856
*/
2857
static struct strarray get_removable_dirs( struct strarray files )
2858
{
2859
struct strarray dirs = empty_strarray;
2860
2861
STRARRAY_FOR_EACH( file, &files )
2862
{
2863
char *dir = xstrdup( file );
2864
while (strchr( dir, '/' ))
2865
{
2866
*strrchr( dir, '/' ) = 0;
2867
strarray_add_uniq( &dirs, xstrdup(dir) );
2868
}
2869
}
2870
strarray_qsort( &dirs, cmp_string_length );
2871
return dirs;
2872
}
2873
2874
2875
/*******************************************************************
2876
* output_uninstall_rules
2877
*/
2878
static void output_uninstall_rules( struct makefile *make )
2879
{
2880
static const char *dirs_order[] =
2881
{ "$(includedir)", "$(mandir)", "$(datadir)" };
2882
2883
struct strarray uninstall_dirs = empty_strarray, uninstall_files = empty_strarray;
2884
unsigned int i, j;
2885
2886
for (i = 0; i < NB_INSTALL_RULES; i++)
2887
{
2888
ARRAY_FOR_EACH( cmd, &install_commands[i], const struct install_command )
2889
{
2890
strarray_add_uniq( &uninstall_dirs, cmd->dir );
2891
if (cmd->dest)
2892
strarray_add( &uninstall_files, strmake( "$(DESTDIR)%s/%s", cmd->dir, cmd->dest ));
2893
else
2894
STRARRAY_FOR_EACH( file, &cmd->files )
2895
strarray_add( &uninstall_files, strmake( "$(DESTDIR)%s/%s", cmd->dir, get_basename( file )));
2896
}
2897
}
2898
2899
output( "uninstall::\n" );
2900
output_multifiles_command( uninstall_files, "rm -f", empty_strarray );
2901
strarray_add_uniq( &make->phony_targets, "uninstall" );
2902
2903
if (!uninstall_dirs.count) return;
2904
strarray_addall_uniq( &uninstall_dirs, get_removable_dirs( uninstall_dirs ));
2905
strarray_qsort( &uninstall_dirs, cmp_string_length );
2906
output( "\t-rmdir" );
2907
for (i = 0; i < ARRAY_SIZE(dirs_order); i++)
2908
{
2909
for (j = 0; j < uninstall_dirs.count; j++)
2910
{
2911
if (!uninstall_dirs.str[j]) continue;
2912
if (strncmp( uninstall_dirs.str[j], dirs_order[i], strlen(dirs_order[i]) )) continue;
2913
output_filename( strmake( "$(DESTDIR)%s", uninstall_dirs.str[j] ));
2914
uninstall_dirs.str[j] = NULL;
2915
}
2916
}
2917
STRARRAY_FOR_EACH( dir, &uninstall_dirs ) if (dir) output_filename( strmake( "$(DESTDIR)%s", dir ));
2918
output( "\n" );
2919
}
2920
2921
2922
/*******************************************************************
2923
* output_po_files
2924
*/
2925
static void output_po_files( struct makefile *make )
2926
{
2927
const char *po_dir = src_dir_path( make, "po" );
2928
2929
if (linguas.count)
2930
{
2931
STRARRAY_FOR_EACH( lang, &linguas ) output_filename( strmake( "%s/%s.po", po_dir, lang ));
2932
output( ": %s/wine.pot\n", po_dir );
2933
output( "\t%smsgmerge --previous -q $@ %s/wine.pot | msgattrib --no-obsolete -o [email protected] && mv [email protected] $@\n",
2934
cmd_prefix( "MSG" ), po_dir );
2935
output( "po/all:" );
2936
STRARRAY_FOR_EACH( lang, &linguas ) output_filename( strmake( "%s/%s.po", po_dir, lang ));
2937
output( "\n" );
2938
}
2939
output( "%s/wine.pot:", po_dir );
2940
output_filenames( make->pot_files );
2941
output( "\n" );
2942
output( "\t%smsgcat -o $@", cmd_prefix( "MSG" ));
2943
output_filenames( make->pot_files );
2944
output( "\n" );
2945
strarray_add( &make->maintainerclean_files, strmake( "%s/wine.pot", po_dir ));
2946
}
2947
2948
2949
/*******************************************************************
2950
* output_source_y
2951
*/
2952
static void output_source_y( struct makefile *make, struct incl_file *source, const char *obj )
2953
{
2954
char *header = strmake( "%s.tab.h", obj );
2955
2956
if (find_include_file( make, header ))
2957
{
2958
output( "%s: %s\n", obj_dir_path( make, header ), source->filename );
2959
output( "\t%s%s -o %s.tab.$$$$.c --defines=$@ %s && rm -f %s.tab.$$$$.c\n",
2960
cmd_prefix( "BISON" ), bison, obj_dir_path( make, obj ),
2961
source->filename, obj_dir_path( make, obj ));
2962
strarray_add( &make->clean_files, header );
2963
}
2964
output( "%s.tab.c: %s\n", obj_dir_path( make, obj ), source->filename );
2965
output( "\t%s%s -o $@ %s\n", cmd_prefix( "BISON" ), bison, source->filename );
2966
}
2967
2968
2969
/*******************************************************************
2970
* output_source_l
2971
*/
2972
static void output_source_l( struct makefile *make, struct incl_file *source, const char *obj )
2973
{
2974
output( "%s.yy.c: %s\n", obj_dir_path( make, obj ), source->filename );
2975
output( "\t%s%s -o$@ %s\n", cmd_prefix( "FLEX" ), flex, source->filename );
2976
}
2977
2978
2979
/*******************************************************************
2980
* output_source_h
2981
*/
2982
static void output_source_h( struct makefile *make, struct incl_file *source, const char *obj )
2983
{
2984
if (source->file->flags & FLAG_GENERATED)
2985
strarray_add( &make->all_targets[0], source->name );
2986
else if ((source->file->flags & FLAG_INSTALL) || strncmp( source->name, "wine/", 5 ))
2987
install_header( make, source->name, NULL );
2988
}
2989
2990
2991
/*******************************************************************
2992
* output_source_ver
2993
*/
2994
static void output_source_ver( struct makefile *make, struct incl_file *source, const char *obj )
2995
{
2996
const char *res_file = strmake( "%s.res", obj );
2997
2998
if (!(source->file->flags & FLAG_GENERATED))
2999
{
3000
output_source_h( make, source, obj );
3001
return;
3002
}
3003
3004
for (unsigned int arch = 0; arch < archs.count; arch++)
3005
if (!make->disabled[arch]) strarray_add( &make->res_files[arch], res_file );
3006
3007
output( "%s: %s", obj_dir_path( make, res_file ), src_dir_path( make, "Makefile.in" ));
3008
output_filename( wrc );
3009
if (make->src_dir) output_filename( "nls/locale.nls" );
3010
output_filename( source->filename );
3011
output_filenames( source->dependencies );
3012
output( "\n" );
3013
output( "\t%s%s -u -o $@", cmd_prefix( "WRC" ), wrc );
3014
if (make->is_win16) output_filename( "-m16" );
3015
output_filename( "--nostdinc" );
3016
output_filenames( make->include_args );
3017
output_filenames( get_version_defines( make ));
3018
output_filename( source->filename );
3019
output( "\n" );
3020
}
3021
3022
3023
/*******************************************************************
3024
* output_source_rc
3025
*/
3026
static void output_source_rc( struct makefile *make, struct incl_file *source, const char *obj )
3027
{
3028
struct strarray defines = get_source_defines( make, source, obj );
3029
const char *po_dir = NULL, *res_file = strmake( "%s.res", obj );
3030
unsigned int arch;
3031
3032
if (source->file->flags & FLAG_RC_HEADER) return;
3033
if (source->file->flags & FLAG_GENERATED) strarray_add( &make->clean_files, source->name );
3034
if (linguas.count && (source->file->flags & FLAG_RC_PO)) po_dir = "po";
3035
if (!(source->file->flags & FLAG_TESTDLL))
3036
{
3037
for (arch = 0; arch < archs.count; arch++)
3038
if (!make->disabled[arch]) strarray_add( &make->res_files[arch], res_file );
3039
}
3040
else strarray_add( &make->clean_files, res_file );
3041
3042
if (source->file->flags & FLAG_RC_PO)
3043
{
3044
strarray_add( &make->pot_files, strmake( "%s.pot", obj ));
3045
output( "%s.pot ", obj_dir_path( make, obj ) );
3046
}
3047
output( "%s: %s", obj_dir_path( make, res_file ), source->filename );
3048
output_filename( wrc );
3049
if (make->src_dir) output_filename( "nls/locale.nls" );
3050
output_filenames( source->dependencies );
3051
output( "\n" );
3052
output( "\t%s%s -u -o $@", cmd_prefix( "WRC" ), wrc );
3053
if (make->is_win16) output_filename( "-m16" );
3054
output_filename( "--nostdinc" );
3055
if (po_dir) output_filename( strmake( "--po-dir=%s", po_dir ));
3056
output_filenames( defines );
3057
output_filename( source->filename );
3058
output( "\n" );
3059
if (po_dir)
3060
{
3061
output( "%s:", obj_dir_path( make, res_file ));
3062
STRARRAY_FOR_EACH( lang, &linguas ) output_filename( strmake( "%s/%s.mo", po_dir, lang ));
3063
output( "\n" );
3064
}
3065
}
3066
3067
3068
/*******************************************************************
3069
* output_source_mc
3070
*/
3071
static void output_source_mc( struct makefile *make, struct incl_file *source, const char *obj )
3072
{
3073
unsigned int arch;
3074
char *obj_path = obj_dir_path( make, obj );
3075
char *res_file = strmake( "%s.res", obj );
3076
3077
for (arch = 0; arch < archs.count; arch++)
3078
if (!make->disabled[arch]) strarray_add( &make->res_files[arch], res_file );
3079
strarray_add( &make->pot_files, strmake( "%s.pot", obj ));
3080
output( "%s.pot %s.res: %s", obj_path, obj_path, source->filename );
3081
output_filename( wmc );
3082
output_filenames( source->dependencies );
3083
if (make->src_dir) output_filename( "nls/locale.nls" );
3084
output( "\n" );
3085
output( "\t%s%s -u -o $@ %s", cmd_prefix( "WMC" ), wmc, source->filename );
3086
if (linguas.count)
3087
{
3088
output_filename( "--po-dir=po" );
3089
output( "\n" );
3090
output( "%s.res:", obj_dir_path( make, obj ));
3091
STRARRAY_FOR_EACH( lang, &linguas ) output_filename( strmake( "po/%s.mo", lang ));
3092
}
3093
output( "\n" );
3094
}
3095
3096
3097
/*******************************************************************
3098
* output_source_res
3099
*/
3100
static void output_source_res( struct makefile *make, struct incl_file *source, const char *obj )
3101
{
3102
if (make->disabled[source->arch]) return;
3103
strarray_add( &make->res_files[source->arch], source->name );
3104
}
3105
3106
3107
/*******************************************************************
3108
* output_source_idl
3109
*/
3110
static void output_source_idl( struct makefile *make, struct incl_file *source, const char *obj )
3111
{
3112
struct strarray defines = get_source_defines( make, source, obj );
3113
struct strarray headers = empty_strarray;
3114
struct strarray deps = empty_strarray;
3115
struct strarray multiarch_targets[MAX_ARCHS] = { empty_strarray };
3116
const char *dest;
3117
unsigned int i, arch;
3118
3119
if (find_include_file( make, strmake( "%s.h", obj ))) source->file->flags |= FLAG_IDL_HEADER;
3120
if (!source->file->flags) return;
3121
3122
if (source->file->flags & FLAG_IDL_PROXY) strarray_add( &make->dlldata_files, source->name );
3123
if (source->file->flags & FLAG_INSTALL)
3124
{
3125
install_header( make, source->name, NULL );
3126
if (source->file->flags & FLAG_IDL_HEADER)
3127
install_header( make, source->name, strmake( "%s.h", obj ));
3128
}
3129
if (source->file->flags & FLAG_IDL_HEADER)
3130
{
3131
dest = strmake( "%s.h", obj );
3132
strarray_add( &headers, dest );
3133
if (!find_src_file( make, dest )) strarray_add( &make->clean_files, dest );
3134
}
3135
if (source->file->flags & FLAG_IDL_WINMD)
3136
{
3137
dest = strmake( "%s.winmd", obj );
3138
strarray_add( &headers, dest );
3139
strarray_add( &make->clean_files, dest );
3140
}
3141
3142
for (i = 0; i < ARRAY_SIZE(idl_outputs); i++)
3143
{
3144
if (!(source->file->flags & idl_outputs[i].flag)) continue;
3145
for (arch = 0; arch < archs.count; arch++)
3146
{
3147
if (!is_multiarch( arch )) continue;
3148
if (make->disabled[arch]) continue;
3149
dest = strmake( "%s%s%s", arch_dirs[arch], obj, idl_outputs[i].ext );
3150
if (!find_src_file( make, dest )) strarray_add( &make->clean_files, dest );
3151
strarray_add( &multiarch_targets[arch], dest );
3152
}
3153
}
3154
3155
for (arch = 0; arch < archs.count; arch++)
3156
{
3157
struct strarray arch_deps = empty_strarray;
3158
3159
if (!arch) strarray_addall( &arch_deps, headers );
3160
strarray_addall( &arch_deps, multiarch_targets[arch] );
3161
if (!arch_deps.count) continue;
3162
output_filenames_obj_dir( make, arch_deps );
3163
output( ":\n" );
3164
output( "\t%s%s -o $@", cmd_prefix( "WIDL" ), widl );
3165
output_filenames( target_flags[arch] );
3166
output_filename( "--nostdinc" );
3167
output_filename( "-Ldlls/\\*" );
3168
output_filenames( defines );
3169
output_filenames( get_expanded_make_var_array( make, "EXTRAIDLFLAGS" ));
3170
output_filenames( get_expanded_file_local_var( make, obj, "EXTRAIDLFLAGS" ));
3171
if (arch) output_filenames( get_expanded_arch_var_array( make, "EXTRAIDLFLAGS", arch ));
3172
output_filename( source->filename );
3173
output( "\n" );
3174
strarray_addall( &deps, arch_deps );
3175
}
3176
3177
if (deps.count)
3178
{
3179
output_filenames_obj_dir( make, deps );
3180
output( ":" );
3181
output_filename( widl );
3182
output_filename( source->filename );
3183
output_filenames( source->dependencies );
3184
output( "\n" );
3185
}
3186
3187
if (source->importlibdeps.count)
3188
{
3189
for (arch = 0; arch < archs.count; arch++)
3190
{
3191
if (!multiarch_targets[arch].count) continue;
3192
output_filenames_obj_dir( make, multiarch_targets[arch] );
3193
output( ":" );
3194
STRARRAY_FOR_EACH( dep, &source->importlibdeps )
3195
{
3196
int native_arch = native_archs[arch] ? native_archs[arch] : arch;
3197
struct makefile *submake = find_importlib_module( dep );
3198
const char *module = strmake( "%s/%s", arch_pe_dirs[native_arch], submake->module );
3199
output_filename( obj_dir_path( submake, module ));
3200
}
3201
output( "\n" );
3202
}
3203
}
3204
}
3205
3206
3207
/*******************************************************************
3208
* output_source_x
3209
*/
3210
static void output_source_x( struct makefile *make, struct incl_file *source, const char *obj )
3211
{
3212
output( "%s.h: %s %s\n", obj_dir_path( make, obj ), make_xftmpl, source->filename );
3213
output( "\t%s%s -H -o $@ %s\n", cmd_prefix( "GEN" ), make_xftmpl, source->filename );
3214
if (source->file->flags & FLAG_INSTALL)
3215
{
3216
install_header( make, source->name, NULL );
3217
install_header( make, source->name, strmake( "%s.h", obj ));
3218
}
3219
}
3220
3221
3222
/*******************************************************************
3223
* output_source_sfd
3224
*/
3225
static void output_source_sfd( struct makefile *make, struct incl_file *source, const char *obj )
3226
{
3227
char *ttf_obj = strmake( "%s.ttf", obj );
3228
char *ttf_file = src_dir_path( make, ttf_obj );
3229
3230
if (fontforge && !make->src_dir)
3231
{
3232
output( "%s: %s\n", ttf_file, source->filename );
3233
output( "\t%s%s -script %s %s $@\n", cmd_prefix( "GEN" ),
3234
fontforge, root_src_dir_path( "fonts/genttf.ff" ), source->filename );
3235
if (!(source->file->flags & FLAG_SFD_FONTS)) strarray_add( &make->font_files, ttf_obj );
3236
strarray_add( &make->maintainerclean_files, ttf_obj );
3237
}
3238
if (source->file->flags & FLAG_INSTALL)
3239
{
3240
install_data_file_src( make, source->name, ttf_obj, "$(datadir)/wine/fonts" );
3241
output_srcdir_symlink( make, ttf_obj );
3242
}
3243
3244
if (source->file->flags & FLAG_SFD_FONTS)
3245
{
3246
struct strarray *array = source->file->args;
3247
STRARRAY_FOR_EACH( str, array )
3248
{
3249
char *font = strtok( xstrdup(str), " \t" );
3250
char *args = strtok( NULL, "" );
3251
3252
strarray_add( &make->all_targets[0], xstrdup( font ));
3253
output( "%s: %s %s\n", obj_dir_path( make, font ), sfnt2fon, ttf_file );
3254
output( "\t%s%s -q -o $@ %s %s\n", cmd_prefix( "GEN" ), sfnt2fon, ttf_file, args );
3255
install_data_file( make, source->name, font, "$(datadir)/wine/fonts", NULL );
3256
}
3257
}
3258
}
3259
3260
3261
/*******************************************************************
3262
* output_source_svg
3263
*/
3264
static void output_source_svg( struct makefile *make, struct incl_file *source, const char *obj )
3265
{
3266
static const char * const images[] = { "bmp", "cur", "ico", NULL };
3267
unsigned int i;
3268
3269
if (convert && rsvg && icotool)
3270
{
3271
for (i = 0; images[i]; i++)
3272
if (find_include_file( make, strmake( "%s.%s", obj, images[i] ))) break;
3273
3274
if (images[i])
3275
{
3276
output( "%s.%s: %s\n", src_dir_path( make, obj ), images[i], source->filename );
3277
output( "\t%sCONVERT=\"%s\" ICOTOOL=\"%s\" RSVG=\"%s\" %s %s $@\n",
3278
cmd_prefix( "GEN" ), convert, icotool, rsvg, buildimage, source->filename );
3279
strarray_add( &make->maintainerclean_files, strmake( "%s.%s", obj, images[i] ));
3280
}
3281
}
3282
}
3283
3284
3285
/*******************************************************************
3286
* output_source_nls
3287
*/
3288
static void output_source_nls( struct makefile *make, struct incl_file *source, const char *obj )
3289
{
3290
install_data_file_src( make, source->name, source->name, "$(datadir)/wine/nls" );
3291
output_srcdir_symlink( make, strmake( "%s.nls", obj ));
3292
}
3293
3294
3295
/*******************************************************************
3296
* output_source_desktop
3297
*/
3298
static void output_source_desktop( struct makefile *make, struct incl_file *source, const char *obj )
3299
{
3300
install_data_file_src( make, source->name, source->name, "$(datadir)/applications" );
3301
}
3302
3303
3304
/*******************************************************************
3305
* output_source_po
3306
*/
3307
static void output_source_po( struct makefile *make, struct incl_file *source, const char *obj )
3308
{
3309
output( "%s.mo: %s\n", obj_dir_path( make, obj ), source->filename );
3310
output( "\t%s%s -o $@ %s\n", cmd_prefix( "MSG" ), msgfmt, source->filename );
3311
strarray_add( &make->all_targets[0], strmake( "%s.mo", obj ));
3312
}
3313
3314
3315
/*******************************************************************
3316
* output_source_in
3317
*/
3318
static void output_source_in( struct makefile *make, struct incl_file *source, const char *obj )
3319
{
3320
/* ignore generated includes */
3321
if (make == include_makefile && (!strcmp( obj, "config.h" ) || !strcmp( obj, "stamp-h" ))) return;
3322
3323
if (strendswith( obj, ".man" ) && source->file->args)
3324
{
3325
struct strarray symlinks;
3326
char *dir, *dest = replace_extension( obj, ".man", "" );
3327
char *lang = strchr( dest, '.' );
3328
char *section = source->file->args;
3329
if (lang)
3330
{
3331
*lang++ = 0;
3332
dir = strmake( "$(mandir)/%s/man%s", lang, section );
3333
}
3334
else dir = strmake( "$(mandir)/man%s", section );
3335
install_data_file( make, dest, obj, dir, strmake( "%s.%s", dest, section ));
3336
symlinks = get_expanded_file_local_var( make, dest, "SYMLINKS" );
3337
STRARRAY_FOR_EACH( link, &symlinks )
3338
install_data_symlink( make, link, obj, strmake( "%s.%s", dest, section ), dir,
3339
strmake( "%s.%s", link, section ));
3340
}
3341
strarray_add( &make->in_files, obj );
3342
strarray_add( &make->all_targets[0], obj );
3343
output( "%s: %s\n", obj_dir_path( make, obj ), source->filename );
3344
output( "\t%s%s %s >$@ || (rm -f $@ && false)\n", cmd_prefix( "SED" ), sed_cmd, source->filename );
3345
output( "%s: include/config.h", obj_dir_path( make, obj ));
3346
output_filenames( source->dependencies );
3347
output( "\n" );
3348
if (make == include_makefile) install_header( make, source->name, obj );
3349
else install_data_file( make, obj, obj, "$(datadir)/wine", NULL );
3350
}
3351
3352
3353
/*******************************************************************
3354
* output_source_spec
3355
*/
3356
static void output_source_spec( struct makefile *make, struct incl_file *source, const char *obj )
3357
{
3358
/* nothing to do */
3359
}
3360
3361
3362
/*******************************************************************
3363
* output_source_testdll
3364
*/
3365
static void output_source_testdll( struct makefile *make, struct incl_file *source, const char *obj )
3366
{
3367
struct strarray imports = get_expanded_file_local_var( make, obj, "IMPORTS" );
3368
struct strarray dll_flags = empty_strarray;
3369
struct strarray default_imports = empty_strarray;
3370
struct strarray all_libs, dep_libs;
3371
const char *dll_name, *obj_name, *res_name, *output_rsrc, *output_file, *ext = ".dll";
3372
struct incl_file *spec_file = find_src_file( make, strmake( "%s.spec", obj ));
3373
unsigned int arch, link_arch;
3374
3375
if (!imports.count) imports = make->imports;
3376
strarray_addall( &dll_flags, make->extradllflags );
3377
strarray_addall( &dll_flags, get_expanded_file_local_var( make, obj, "EXTRADLLFLAGS" ));
3378
default_imports = get_default_imports( make, imports, strarray_exists( dll_flags, "-nodefaultlibs" ));
3379
if (strarray_exists( dll_flags, "-mconsole" )) ext = ".exe";
3380
3381
for (arch = 0; arch < archs.count; arch++)
3382
{
3383
const char *hybrid_obj_name = NULL;
3384
3385
if (!is_multiarch( arch ) || !get_link_arch( make, arch, &link_arch)) continue;
3386
3387
all_libs = dep_libs = empty_strarray;
3388
strarray_addall( &all_libs, add_import_libs( make, &dep_libs, imports, IMPORT_TYPE_DIRECT, arch ) );
3389
strarray_addall( &all_libs, add_import_libs( make, &dep_libs, default_imports, IMPORT_TYPE_DEFAULT, arch ) );
3390
if (!arch) strarray_addall( &all_libs, libs );
3391
dll_name = arch_module_name( strmake( "%s%s", obj, ext ), arch );
3392
obj_name = obj_dir_path( make, strmake( "%s%s.o", arch_dirs[arch], obj ));
3393
if (link_arch != arch)
3394
hybrid_obj_name = obj_dir_path( make, strmake( "%s%s.o", arch_dirs[link_arch], obj ));
3395
output_file = obj_dir_path( make, dll_name );
3396
output_rsrc = strmake( "%s.res", dll_name );
3397
3398
if (!find_src_file( make, strmake( "%s.rc", obj ) )) res_name = NULL;
3399
else res_name = obj_dir_path( make, strmake( "%s.res", obj ) );
3400
3401
strarray_add( &make->clean_files, dll_name );
3402
strarray_add( &make->res_files[arch], output_rsrc );
3403
output( "%s:", obj_dir_path( make, output_rsrc ));
3404
output_filename( output_file );
3405
output_filename( wrc );
3406
output( "\n" );
3407
output( "\t%secho \"%s%s TESTDLL \\\"%s\\\"\" | %s -u -o $@\n",
3408
cmd_prefix( "WRC" ), obj, ext, output_file, wrc );
3409
3410
output( "%s:", output_file );
3411
if (spec_file) output_filename( spec_file->filename );
3412
output_filename( obj_name );
3413
if (hybrid_obj_name) output_filename( hybrid_obj_name );
3414
if (res_name) output_filename( res_name );
3415
output_filenames( dep_libs );
3416
output_filename( winebuild );
3417
output_filename( winegcc );
3418
output( "\n" );
3419
output_winegcc_command( make, link_arch );
3420
output_filename( "-s" );
3421
output_filenames( dll_flags );
3422
if (link_arch) output_filenames( get_expanded_arch_var_array( make, "EXTRADLLFLAGS", link_arch ));
3423
if (!strcmp( ext, ".dll" )) output_filename( "-shared" );
3424
if (spec_file) output_filename( spec_file->filename );
3425
output_filename( obj_name );
3426
if (hybrid_obj_name) output_filename( hybrid_obj_name );
3427
if (res_name) output_filename( res_name );
3428
output_debug_files( make, dll_name, link_arch );
3429
output_filenames( all_libs );
3430
output_filename( arch_make_variable( "LDFLAGS", link_arch ));
3431
output( "\n" );
3432
}
3433
}
3434
3435
3436
/*******************************************************************
3437
* output_source_xml
3438
*/
3439
static void output_source_xml( struct makefile *make, struct incl_file *source, const char *obj )
3440
{
3441
if (wayland_scanner)
3442
{
3443
output( "%s-protocol.c: %s\n", obj_dir_path( make, obj ), source->filename );
3444
output( "\t%s%s private-code %s $@\n", cmd_prefix( "GEN" ), wayland_scanner, source->filename );
3445
output( "%s-client-protocol.h: %s\n", obj_dir_path( make, obj ), source->filename );
3446
output( "\t%s%s client-header %s $@\n", cmd_prefix( "GEN" ), wayland_scanner, source->filename );
3447
}
3448
}
3449
3450
3451
/*******************************************************************
3452
* output_source_winmd
3453
*/
3454
static void output_source_winmd( struct makefile *make, struct incl_file *source, const char *obj )
3455
{
3456
if (source->file->flags & FLAG_GENERATED) strarray_add( &make->all_targets[0], source->name );
3457
if (source->file->flags & FLAG_INSTALL) install_data_file( make, source->name, source->name,
3458
"$(datadir)/wine/winmd", NULL );
3459
}
3460
3461
3462
/*******************************************************************
3463
* output_source_one_arch
3464
*/
3465
static void output_source_one_arch( struct makefile *make, struct incl_file *source, const char *obj,
3466
struct strarray defines, struct strarray *targets,
3467
unsigned int arch )
3468
{
3469
const char *obj_name, *var_cc, *var_cflags;
3470
struct compile_command *cmd;
3471
struct strarray cflags = empty_strarray;
3472
3473
if (make->disabled[arch] && !(source->file->flags & FLAG_C_IMPLIB)) return;
3474
3475
if (arch)
3476
{
3477
if (source->file->flags & FLAG_C_UNIX) return;
3478
if (!is_multiarch( arch )) return;
3479
if (!is_using_msvcrt( make ) && !make->staticlib && !(source->file->flags & FLAG_C_IMPLIB)) return;
3480
}
3481
else if (source->file->flags & FLAG_C_UNIX)
3482
{
3483
if (!unix_lib_supported) return;
3484
}
3485
else if (archs.count > 1 && is_using_msvcrt( make ))
3486
{
3487
if (!so_dll_supported) return;
3488
if (!(source->file->flags & FLAG_C_IMPLIB) && (!make->staticlib || make->extlib)) return;
3489
}
3490
3491
if (strendswith( source->name, ".S" ) && is_subdir_other_arch( source->name, arch )) return;
3492
3493
obj_name = strmake( "%s%s.o", source->arch ? "" : arch_dirs[arch], obj );
3494
strarray_add( targets, obj_name );
3495
3496
if (source->file->flags & FLAG_C_UNIX)
3497
strarray_add( &make->unixobj_files, obj_name );
3498
else if (source->file->flags & FLAG_C_IMPLIB)
3499
strarray_add( &make->implib_files[arch], obj_name );
3500
else if (!(source->file->flags & FLAG_TESTDLL))
3501
strarray_add( &make->object_files[arch], obj_name );
3502
else
3503
strarray_add( &make->clean_files, obj_name );
3504
3505
if (!source->use_msvcrt) strarray_addall( &cflags, make->unix_cflags );
3506
if ((source->file->flags & FLAG_ARM64EC_X64) && !strcmp( archs.str[arch], "arm64ec" ))
3507
{
3508
var_cc = "$(x86_64_CC)";
3509
var_cflags = "$(x86_64_CFLAGS)";
3510
strarray_add( &cflags, "-D__arm64ec_x64__" );
3511
strarray_addall( &cflags, get_expanded_make_var_array( top_makefile, "x86_64_EXTRACFLAGS" ));
3512
}
3513
else
3514
{
3515
var_cc = arch_make_variable( "CC", arch );
3516
var_cflags = arch_make_variable( "CFLAGS", arch );
3517
strarray_addall( &cflags, make->extlib ? extra_cflags_extlib[arch] : extra_cflags[arch] );
3518
}
3519
3520
if (!arch)
3521
{
3522
if (source->file->flags & FLAG_C_UNIX)
3523
{
3524
strarray_addall( &cflags, unix_dllflags );
3525
}
3526
else if (make->module || make->testdll)
3527
{
3528
strarray_addall( &cflags, dll_flags );
3529
if (source->use_msvcrt) strarray_addall( &cflags, msvcrt_flags );
3530
if (!unix_lib_supported &&
3531
((make->module && is_crt_module( make->module )) ||
3532
(make->testdll && is_crt_module( make->testdll ))))
3533
strarray_add( &cflags, "-fno-builtin" );
3534
}
3535
strarray_addall( &cflags, cpp_flags );
3536
}
3537
else
3538
{
3539
if ((make->module && is_crt_module( make->module )) ||
3540
(make->testdll && is_crt_module( make->testdll )))
3541
strarray_add( &cflags, "-fno-builtin" );
3542
}
3543
3544
output( "%s: %s\n", obj_dir_path( make, obj_name ), source->filename );
3545
output( "\t%s%s -c -o $@ %s", cmd_prefix( "CC" ), var_cc, source->filename );
3546
output_filenames( defines );
3547
output_filenames( cflags );
3548
output_filename( var_cflags );
3549
output( "\n" );
3550
3551
if (make->testdll && strendswith( source->name, ".c" ) &&
3552
!(source->file->flags & (FLAG_GENERATED | FLAG_TESTDLL)))
3553
{
3554
const char *ok_file, *test_exe;
3555
3556
ok_file = strmake( "%s%s.ok", arch_dirs[arch], obj );
3557
test_exe = replace_extension( make->testdll, ".dll", "_test.exe" );
3558
strarray_add( &make->ok_files[arch], ok_file );
3559
output( "%s:\n", obj_dir_path( make, ok_file ));
3560
output( "\t%s%s $(RUNTESTFLAGS) -T . -M %s -p %s %s && touch $@\n",
3561
cmd_prefix( "TEST" ), runtest, make->testdll,
3562
obj_dir_path( make, arch_module_name( test_exe, arch )), obj );
3563
}
3564
3565
if (source->file->flags & FLAG_GENERATED) return;
3566
3567
/* static analysis rules */
3568
3569
if (sarif_converter && make->module && !make->extlib)
3570
{
3571
const char *sast_name = strmake( "%s%s.sarif", source->arch ? "" : arch_dirs[arch], obj );
3572
output( "%s: %s\n", obj_dir_path( make, sast_name ), source->filename );
3573
output( "\t%s%s -o $@ %s", cmd_prefix( "SAST" ), var_cc, source->filename );
3574
output_filenames( defines );
3575
output_filenames( cflags );
3576
output_filename( "--analyze" );
3577
output_filename( "-Xclang" );
3578
output_filename( "-analyzer-output=sarif" );
3579
output_filename( "$(SASTFLAGS)" );
3580
output( "\n" );
3581
strarray_add( &make->sast_files, sast_name );
3582
strarray_add( targets, sast_name );
3583
}
3584
3585
/* compile commands */
3586
3587
cmd = xmalloc( sizeof(*cmd) );
3588
cmd->source = source->filename;
3589
cmd->obj = obj_dir_path( make, obj_name );
3590
cmd->args = empty_strarray;
3591
strarray_addall( &cmd->args, defines );
3592
strarray_addall( &cmd->args, cflags );
3593
3594
if ((source->file->flags & FLAG_ARM64EC_X64) && !strcmp( archs.str[arch], "arm64ec" ))
3595
{
3596
char *cflags = get_expanded_make_variable( make, "x86_64_CFLAGS" );
3597
cmd->cmd = get_expanded_make_variable( make, "x86_64_CC" );
3598
if (cflags) strarray_add( &cmd->args, cflags );
3599
}
3600
else
3601
{
3602
char *cflags = get_expanded_arch_var( make, "CFLAGS", arch );
3603
cmd->cmd = get_expanded_arch_var( make, "CC", arch );
3604
if (cflags) strarray_add( &cmd->args, cflags );
3605
}
3606
list_add_tail( &compile_commands, &cmd->entry );
3607
}
3608
3609
3610
/*******************************************************************
3611
* output_source_default
3612
*/
3613
static void output_source_default( struct makefile *make, struct incl_file *source, const char *obj )
3614
{
3615
struct strarray defines = get_source_defines( make, source, obj );
3616
struct strarray targets = empty_strarray;
3617
unsigned int arch;
3618
3619
for (arch = 0; arch < archs.count; arch++)
3620
if (!source->arch || source->arch == arch)
3621
output_source_one_arch( make, source, obj, defines, &targets, arch );
3622
3623
if (source->file->flags & FLAG_GENERATED)
3624
{
3625
if (!make->testdll || !strendswith( source->filename, "testlist.c" ))
3626
strarray_add( &make->clean_files, source->basename );
3627
}
3628
else if (source->file->flags & FLAG_TESTDLL)
3629
{
3630
output_source_testdll( make, source, obj );
3631
}
3632
else
3633
{
3634
if (make->testdll && strendswith( source->name, ".c" ))
3635
strarray_add( &make->test_files, obj );
3636
}
3637
3638
if (targets.count && source->dependencies.count)
3639
{
3640
output_filenames_obj_dir( make, targets );
3641
output( ":" );
3642
output_filenames( source->dependencies );
3643
output( "\n" );
3644
}
3645
}
3646
3647
3648
/* dispatch table to output rules for a single source file */
3649
static const struct
3650
{
3651
const char *ext;
3652
void (*fn)( struct makefile *make, struct incl_file *source, const char *obj );
3653
} output_source_funcs[] =
3654
{
3655
{ "y", output_source_y },
3656
{ "l", output_source_l },
3657
{ "h", output_source_h },
3658
{ "rh", output_source_h },
3659
{ "inl", output_source_h },
3660
{ "ver", output_source_ver },
3661
{ "rc", output_source_rc },
3662
{ "mc", output_source_mc },
3663
{ "res", output_source_res },
3664
{ "idl", output_source_idl },
3665
{ "sfd", output_source_sfd },
3666
{ "svg", output_source_svg },
3667
{ "nls", output_source_nls },
3668
{ "desktop", output_source_desktop },
3669
{ "po", output_source_po },
3670
{ "in", output_source_in },
3671
{ "x", output_source_x },
3672
{ "spec", output_source_spec },
3673
{ "xml", output_source_xml },
3674
{ "winmd", output_source_winmd },
3675
{ NULL, output_source_default }
3676
};
3677
3678
3679
/*******************************************************************
3680
* output_fake_module
3681
*/
3682
static void output_fake_module( struct makefile *make, const char *spec_file )
3683
{
3684
unsigned int arch = 0; /* fake modules are always native */
3685
const char *name = strmake( "%s/%s", arch_pe_dirs[arch], make->module );
3686
3687
if (make->disabled[arch]) return;
3688
3689
strarray_add( &make->all_targets[arch], name );
3690
install_data_file( make, make->module, name, strmake( "$(libdir)/wine/%s", arch_pe_dirs[arch] ), NULL );
3691
3692
output( "%s:", obj_dir_path( make, name ));
3693
if (spec_file) output_filename( spec_file );
3694
output_filenames_obj_dir( make, make->res_files[arch] );
3695
output_filename( winebuild );
3696
output_filename( winegcc );
3697
output( "\n" );
3698
output_winegcc_command( make, arch );
3699
output_filename( "-Wb,--fake-module" );
3700
if (!make->is_exe) output_filename( "-shared" );
3701
if (spec_file) output_filename( spec_file );
3702
output_filenames( make->extradllflags );
3703
output_filenames_obj_dir( make, make->res_files[arch] );
3704
output( "\n" );
3705
}
3706
3707
3708
/*******************************************************************
3709
* output_module
3710
*/
3711
static void output_module( struct makefile *make, unsigned int arch )
3712
{
3713
struct strarray default_imports = empty_strarray;
3714
struct strarray all_libs = empty_strarray;
3715
struct strarray dep_libs = empty_strarray;
3716
struct strarray imports = make->imports;
3717
const char *module_name;
3718
char *spec_file = NULL;
3719
unsigned int link_arch;
3720
3721
if (!make->is_exe)
3722
{
3723
if (make->data_only || strendswith( make->module, ".drv" ) ||
3724
strarray_exists( make->extradllflags, "-Wl,--subsystem,native" ))
3725
{
3726
/* spec file is optional */
3727
struct incl_file *spec = find_src_file( make, replace_extension( make->module, ".dll", ".spec" ));
3728
if (spec) spec_file = spec->filename;
3729
}
3730
else spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" ));
3731
}
3732
3733
if (!make->data_only)
3734
{
3735
if (!get_link_arch( make, arch, &link_arch )) return;
3736
3737
module_name = arch_module_name( make->module, arch );
3738
default_imports = get_default_imports( make, imports,
3739
strarray_exists( make->extradllflags, "-nodefaultlibs" ));
3740
3741
strarray_addall( &all_libs, add_import_libs( make, &dep_libs, imports, IMPORT_TYPE_DIRECT, arch ));
3742
strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->delayimports, IMPORT_TYPE_DELAYED, arch ));
3743
strarray_addall( &all_libs, add_import_libs( make, &dep_libs, default_imports, IMPORT_TYPE_DEFAULT, arch ) );
3744
if (!arch) strarray_addall( &all_libs, libs );
3745
3746
if (delay_load_flags[arch])
3747
{
3748
STRARRAY_FOR_EACH( imp, &make->delayimports )
3749
{
3750
struct makefile *import = get_static_lib( imp, arch );
3751
if (import) strarray_add( &all_libs, strmake( "%s%s", delay_load_flags[arch], import->module ));
3752
}
3753
}
3754
if (!make->disabled[link_arch]) install_program( make, make->module, arch,
3755
module_name, arch_install_dirs[arch] );
3756
}
3757
else
3758
{
3759
if (native_archs[arch]) return;
3760
if (make->disabled[arch]) return;
3761
link_arch = arch;
3762
3763
module_name = strmake( "%s/%s", arch_pe_dirs[arch], make->module );
3764
install_data_file( make, make->module, module_name,
3765
strmake( "$(libdir)/wine/%s", arch_pe_dirs[arch] ), NULL );
3766
}
3767
3768
strarray_add( &make->all_targets[link_arch], module_name );
3769
output( "%s:", obj_dir_path( make, module_name ));
3770
if (spec_file) output_filename( spec_file );
3771
output_filenames_obj_dir( make, make->object_files[arch] );
3772
if (link_arch != arch) output_filenames_obj_dir( make, make->object_files[link_arch] );
3773
output_filenames_obj_dir( make, make->res_files[arch] );
3774
output_filenames( dep_libs );
3775
output_filename( winebuild );
3776
output_filename( winegcc );
3777
output( "\n" );
3778
output_winegcc_command( make, link_arch );
3779
if (arch) output_filename( "-Wl,--wine-builtin" );
3780
if (!make->is_exe) output_filename( "-shared" );
3781
if (spec_file) output_filename( spec_file );
3782
output_filenames( make->extradllflags );
3783
if (link_arch) output_filenames( get_expanded_arch_var_array( make, "EXTRADLLFLAGS", link_arch ));
3784
output_filenames_obj_dir( make, make->object_files[arch] );
3785
if (link_arch != arch) output_filenames_obj_dir( make, make->object_files[link_arch] );
3786
output_filenames_obj_dir( make, make->res_files[arch] );
3787
output_debug_files( make, module_name, link_arch );
3788
output_filenames( all_libs );
3789
output_filename( arch_make_variable( "LDFLAGS", link_arch ));
3790
output( "\n" );
3791
3792
if (!make->data_only && !arch && unix_lib_supported) output_fake_module( make, spec_file );
3793
}
3794
3795
3796
/*******************************************************************
3797
* output_import_lib
3798
*/
3799
static void output_import_lib( struct makefile *make, unsigned int arch )
3800
{
3801
char *spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" ));
3802
const char *name = strmake( "%slib%s.a", arch_dirs[arch], make->importlib );
3803
unsigned int hybrid_arch = hybrid_archs[arch];
3804
3805
if (native_archs[arch]) return;
3806
3807
strarray_add( &make->clean_files, name );
3808
if (needs_delay_lib( make, arch ))
3809
{
3810
const char *delay_name = replace_extension( name, ".a", ".delay.a" );
3811
strarray_add( &make->clean_files, delay_name );
3812
output( "%s ", obj_dir_path( make, delay_name ));
3813
}
3814
output( "%s: %s %s", obj_dir_path( make, name ), winebuild, spec_file );
3815
output_filenames_obj_dir( make, make->implib_files[arch] );
3816
if (hybrid_arch) output_filenames_obj_dir( make, make->implib_files[hybrid_arch] );
3817
output( "\n" );
3818
output( "\t%s%s -w --implib -o $@", cmd_prefix( "BUILD" ), winebuild );
3819
if (cc_cmds[arch]) output_filename( cc_cmds[arch] );
3820
if (!delay_load_flags[arch]) output_filename( "--without-dlltool" );
3821
output_filenames( target_flags[hybrid_arch ? hybrid_arch : arch] );
3822
if (make->is_win16) output_filename( "-m16" );
3823
if (hybrid_arch) output_filenames( hybrid_target_flags[hybrid_arch] );
3824
output_filename( "--export" );
3825
output_filename( spec_file );
3826
output_filenames_obj_dir( make, make->implib_files[arch] );
3827
if (hybrid_arch) output_filenames_obj_dir( make, make->implib_files[hybrid_arch] );
3828
output( "\n" );
3829
3830
if (make->disabled[arch]) return;
3831
install_data_file( make, make->importlib, name, arch_install_dirs[arch], NULL );
3832
}
3833
3834
3835
/*******************************************************************
3836
* output_unix_lib
3837
*/
3838
static void output_unix_lib( struct makefile *make )
3839
{
3840
struct strarray unix_deps = empty_strarray;
3841
struct strarray unix_libs = add_unix_libraries( make, &unix_deps );
3842
unsigned int arch = 0; /* unix libs are always native */
3843
3844
if (make->disabled[arch]) return;
3845
3846
strarray_add( &make->all_targets[arch], make->unixlib );
3847
install_program( make, make->unixlib, arch, make->unixlib, arch_install_dirs[arch] );
3848
output( "%s:", obj_dir_path( make, make->unixlib ));
3849
output_filenames_obj_dir( make, make->unixobj_files );
3850
output_filenames( unix_deps );
3851
output( "\n" );
3852
output( "\t%s$(CC) -o $@", cmd_prefix( "CCLD" ));
3853
output_filenames( get_expanded_make_var_array( make, "UNIXLDFLAGS" ));
3854
output_filenames_obj_dir( make, make->unixobj_files );
3855
output_filenames( unix_libs );
3856
output_filename( "$(LDFLAGS)" );
3857
output( "\n" );
3858
}
3859
3860
3861
/*******************************************************************
3862
* output_static_lib
3863
*/
3864
static void output_static_lib( struct makefile *make, unsigned int arch )
3865
{
3866
const char *name = strmake( "%s%s", arch_dirs[arch], make->staticlib );
3867
unsigned int hybrid_arch = hybrid_archs[arch];
3868
3869
if (make->disabled[arch]) return;
3870
if (native_archs[arch]) return;
3871
if (arch && !is_multiarch( arch )) return;
3872
3873
strarray_add( &make->clean_files, name );
3874
output( "%s: %s", obj_dir_path( make, name ), winebuild );
3875
output_filenames_obj_dir( make, make->object_files[arch] );
3876
if (hybrid_arch) output_filenames_obj_dir( make, make->object_files[hybrid_arch] );
3877
if (!arch) output_filenames_obj_dir( make, make->unixobj_files );
3878
output( "\n" );
3879
output( "\t%s%s -w --staticlib -o $@", cmd_prefix( "BUILD" ), winebuild );
3880
if (cc_cmds[arch]) output_filename( cc_cmds[arch] );
3881
output_filenames( target_flags[hybrid_arch ? hybrid_arch : arch] );
3882
output_filenames_obj_dir( make, make->object_files[arch] );
3883
if (hybrid_arch) output_filenames_obj_dir( make, make->object_files[hybrid_arch] );
3884
if (!arch) output_filenames_obj_dir( make, make->unixobj_files );
3885
output( "\n" );
3886
install_data_file( make, make->staticlib, name, arch_install_dirs[arch], NULL );
3887
}
3888
3889
3890
/*******************************************************************
3891
* output_test_module
3892
*/
3893
static void output_test_module( struct makefile *make, unsigned int arch )
3894
{
3895
char *basemodule = replace_extension( make->testdll, ".dll", "" );
3896
char *stripped = arch_module_name( strmake( "%s_test-stripped.exe", basemodule ), arch );
3897
char *testmodule = arch_module_name( strmake( "%s_test.exe", basemodule ), arch );
3898
struct strarray default_imports = get_default_imports( make, make->imports, 0 );
3899
struct strarray dep_libs = empty_strarray;
3900
struct strarray all_libs = empty_strarray;
3901
struct makefile *parent = get_parent_makefile( make );
3902
unsigned int link_arch;
3903
3904
if (!get_link_arch( make, arch, &link_arch )) return;
3905
3906
strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->imports, IMPORT_TYPE_DIRECT, arch ) );
3907
strarray_addall( &all_libs, add_import_libs( make, &dep_libs, default_imports, IMPORT_TYPE_DEFAULT, arch ) );
3908
3909
strarray_add( &make->all_targets[arch], testmodule );
3910
strarray_add( &make->clean_files, stripped );
3911
output( "%s:\n", obj_dir_path( make, testmodule ));
3912
output_winegcc_command( make, link_arch );
3913
output_filenames( make->extradllflags );
3914
output_filenames_obj_dir( make, make->object_files[arch] );
3915
if (link_arch != arch) output_filenames_obj_dir( make, make->object_files[link_arch] );
3916
output_filenames_obj_dir( make, make->res_files[arch] );
3917
output_debug_files( make, testmodule, arch );
3918
output_filenames( all_libs );
3919
output_filename( arch_make_variable( "LDFLAGS", link_arch ));
3920
output( "\n" );
3921
output( "%s:\n", obj_dir_path( make, stripped ));
3922
output_winegcc_command( make, link_arch );
3923
output_filename( "-s" );
3924
output_filename( strmake( "-Wb,-F,%s_test.exe", basemodule ));
3925
output_filenames( make->extradllflags );
3926
output_filenames_obj_dir( make, make->object_files[arch] );
3927
if (link_arch != arch) output_filenames_obj_dir( make, make->object_files[link_arch] );
3928
output_filenames_obj_dir( make, make->res_files[arch] );
3929
output_filenames( all_libs );
3930
output_filename( arch_make_variable( "LDFLAGS", link_arch ));
3931
output( "\n" );
3932
output( "%s %s:", obj_dir_path( make, testmodule ), obj_dir_path( make, stripped ));
3933
output_filenames_obj_dir( make, make->object_files[arch] );
3934
if (link_arch != arch) output_filenames_obj_dir( make, make->object_files[link_arch] );
3935
output_filenames_obj_dir( make, make->res_files[arch] );
3936
output_filenames( dep_libs );
3937
output_filename( winebuild );
3938
output_filename( winegcc );
3939
output( "\n" );
3940
3941
output( "programs/winetest/%s%s_test.res: %s\n", arch_dirs[arch], basemodule,
3942
obj_dir_path( make, stripped ));
3943
output( "\t%secho \"%s_test.exe TESTRES \\\"%s\\\"\" | %s -u -o $@\n", cmd_prefix( "WRC" ),
3944
basemodule, obj_dir_path( make, stripped ), wrc );
3945
3946
if (make->disabled[arch] || (parent && parent->disabled[arch]))
3947
{
3948
make->ok_files[arch] = empty_strarray;
3949
return;
3950
}
3951
output_filenames_obj_dir( make, make->ok_files[arch] );
3952
output( ": %s", obj_dir_path( make, testmodule ));
3953
if (parent)
3954
{
3955
char *parent_module = arch_module_name( make->testdll, arch );
3956
output_filename( obj_dir_path( parent, parent_module ));
3957
if (parent->unixlib) output_filename( obj_dir_path( parent, parent->unixlib ));
3958
}
3959
output( "\n" );
3960
output( "%s %s:", obj_dir_path( make, "check" ), obj_dir_path( make, "test" ));
3961
output_filenames_obj_dir( make, make->ok_files[arch] );
3962
output( "\n" );
3963
strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "check" ));
3964
strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "test" ));
3965
output( "%s::\n", obj_dir_path( make, "testclean" ));
3966
output( "\trm -f" );
3967
output_filenames_obj_dir( make, make->ok_files[arch] );
3968
output( "\n" );
3969
strarray_addall( &make->clean_files, make->ok_files[arch] );
3970
strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "testclean" ));
3971
}
3972
3973
3974
/*******************************************************************
3975
* output_programs
3976
*/
3977
static void output_programs( struct makefile *make )
3978
{
3979
unsigned int arch = 0; /* programs are always native */
3980
3981
STRARRAY_FOR_EACH( name, &make->programs )
3982
{
3983
const char *install_dir;
3984
char *program = strmake( "%s%s", name, exe_ext );
3985
struct strarray deps = get_local_dependencies( make, name, make->in_files );
3986
struct strarray ldflags = get_expanded_file_local_var( make, name, "LDFLAGS" );
3987
struct strarray objs = get_expanded_file_local_var( make, name, "OBJS" );
3988
struct strarray symlinks = get_expanded_file_local_var( make, name, "SYMLINKS" );
3989
struct strarray all_libs = get_expanded_make_var_array( make, "UNIX_LIBS" );
3990
3991
if (!objs.count) objs = make->object_files[arch];
3992
if (!strarray_exists( ldflags, "-nodefaultlibs" ))
3993
{
3994
strarray_add( &ldflags, "$(LDFLAGS)" );
3995
strarray_addall( &all_libs, libs );
3996
}
3997
output( "%s:", obj_dir_path( make, program ) );
3998
output_filenames_obj_dir( make, objs );
3999
output_filenames( deps );
4000
output( "\n" );
4001
output( "\t%s$(CC) -o $@", cmd_prefix( "CCLD" ));
4002
output_filenames_obj_dir( make, objs );
4003
output_filenames( all_libs );
4004
output_filenames( ldflags );
4005
output( "\n" );
4006
strarray_add( &make->all_targets[arch], program );
4007
4008
STRARRAY_FOR_EACH( link, &symlinks )
4009
{
4010
output( "%s: %s\n", obj_dir_path( make, link ), obj_dir_path( make, program ));
4011
output_symlink_rule( program, obj_dir_path( make, link ));
4012
}
4013
strarray_addall( &make->all_targets[arch], symlinks );
4014
4015
install_dir = !strcmp( make->obj_dir, "loader" ) ? arch_install_dirs[arch] : "$(bindir)";
4016
install_program( make, name, arch, program, install_dir );
4017
STRARRAY_FOR_EACH( link, &symlinks )
4018
install_program_symlink( make, link, obj_dir_path( make, program ),
4019
strmake( "%s%s", link, exe_ext ));
4020
}
4021
}
4022
4023
4024
/*******************************************************************
4025
* output_subdirs
4026
*/
4027
static void output_subdirs( struct makefile *make )
4028
{
4029
struct strarray all_targets = empty_strarray;
4030
struct strarray makefile_deps = empty_strarray;
4031
struct strarray clean_files = empty_strarray;
4032
struct strarray sast_files = empty_strarray;
4033
struct strarray testclean_files = empty_strarray;
4034
struct strarray distclean_files = empty_strarray;
4035
struct strarray distclean_dirs = empty_strarray;
4036
struct strarray dependencies = empty_strarray;
4037
struct strarray tooldeps_deps = empty_strarray;
4038
struct strarray buildtest_deps = empty_strarray;
4039
unsigned int i, arch;
4040
4041
strarray_addall( &clean_files, make->clean_files );
4042
strarray_addall( &distclean_files, make->distclean_files );
4043
for (arch = 0; arch < archs.count; arch++) strarray_addall( &all_targets, make->all_targets[arch] );
4044
for (i = 0; i < subdirs.count; i++)
4045
{
4046
struct strarray subclean = empty_strarray;
4047
strarray_addall( &subclean, get_removable_dirs( submakes[i]->clean_files ));
4048
strarray_addall( &subclean, get_removable_dirs( submakes[i]->distclean_files ));
4049
strarray_add( &makefile_deps, src_dir_path( submakes[i], "Makefile.in" ));
4050
strarray_addall_uniq( &make->phony_targets, submakes[i]->phony_targets );
4051
strarray_addall_uniq( &dependencies, submakes[i]->dependencies );
4052
strarray_addall_path( &clean_files, submakes[i]->obj_dir, submakes[i]->clean_files );
4053
strarray_addall_path( &sast_files, submakes[i]->obj_dir, submakes[i]->sast_files );
4054
strarray_addall_path( &distclean_files, submakes[i]->obj_dir, submakes[i]->distclean_files );
4055
strarray_addall_path( &distclean_dirs, submakes[i]->obj_dir, subclean );
4056
strarray_addall_path( &make->maintainerclean_files, submakes[i]->obj_dir, submakes[i]->maintainerclean_files );
4057
strarray_addall_path( &make->pot_files, submakes[i]->obj_dir, submakes[i]->pot_files );
4058
4059
for (arch = 0; arch < archs.count; arch++)
4060
{
4061
if (submakes[i]->disabled[arch]) continue;
4062
strarray_addall_path( &all_targets, submakes[i]->obj_dir, submakes[i]->all_targets[arch] );
4063
strarray_addall_path( &testclean_files, submakes[i]->obj_dir, submakes[i]->ok_files[arch] );
4064
}
4065
if (submakes[i]->disabled[0]) continue;
4066
4067
strarray_addall_path( &all_targets, submakes[i]->obj_dir, submakes[i]->font_files );
4068
if (!strcmp( submakes[i]->obj_dir, "tools" ) || !strncmp( submakes[i]->obj_dir, "tools/", 6 ))
4069
strarray_add( &tooldeps_deps, obj_dir_path( submakes[i], "all" ));
4070
if (submakes[i]->testdll)
4071
strarray_add( &buildtest_deps, obj_dir_path( submakes[i], "all" ));
4072
}
4073
strarray_addall( &dependencies, makefile_deps );
4074
output( "all:" );
4075
output_filenames( all_targets );
4076
output( "\n" );
4077
output( "Makefile:" );
4078
output_filenames( makefile_deps );
4079
output( "\n" );
4080
output_filenames( dependencies );
4081
output( ":\n" );
4082
output_install_rules( make );
4083
output_uninstall_rules( make );
4084
if (buildtest_deps.count)
4085
{
4086
output( "buildtests:" );
4087
output_filenames( buildtest_deps );
4088
output( "\n" );
4089
strarray_add_uniq( &make->phony_targets, "buildtests" );
4090
}
4091
output( "check test:" );
4092
output_filenames( testclean_files );
4093
output( "\n" );
4094
strarray_add_uniq( &make->phony_targets, "check" );
4095
strarray_add_uniq( &make->phony_targets, "test" );
4096
4097
if (sarif_converter)
4098
{
4099
if (strcmp( sarif_converter, "false" ))
4100
{
4101
output( "gl-code-quality-report.json:\n" );
4102
output( "\t%s%s -t codequality -r", cmd_prefix( "SAST" ), sarif_converter );
4103
output_filename( root_src_dir_path("") );
4104
output_filenames( sast_files );
4105
output_filename( "$@" );
4106
output( "\n" );
4107
strarray_add( &clean_files, "gl-code-quality-report.json" );
4108
output( "gl-code-quality-report.json " );
4109
}
4110
output( "sast:" );
4111
output_filenames( sast_files );
4112
output( "\n" );
4113
strarray_add_uniq( &make->phony_targets, "sast" );
4114
}
4115
4116
if (get_expanded_make_variable( make, "GETTEXTPO_LIBS" )) output_po_files( make );
4117
4118
output( "clean::\n");
4119
output_multifiles_command( clean_files, "rm -f", empty_strarray );
4120
output( "testclean::\n");
4121
output_multifiles_command( testclean_files, "rm -f", empty_strarray );
4122
output( "distclean:: clean\n");
4123
output_multifiles_command( distclean_files, "rm -f", empty_strarray );
4124
output_multifiles_command( distclean_dirs, "-rmdir 2>/dev/null", empty_strarray );
4125
output( "maintainer-clean::\n");
4126
output_multifiles_command( make->maintainerclean_files, "rm -f", empty_strarray );
4127
strarray_add_uniq( &make->phony_targets, "distclean" );
4128
strarray_add_uniq( &make->phony_targets, "testclean" );
4129
strarray_add_uniq( &make->phony_targets, "maintainer-clean" );
4130
4131
if (tooldeps_deps.count)
4132
{
4133
output( "__tooldeps__:" );
4134
output_filenames( tooldeps_deps );
4135
output( "\n" );
4136
strarray_add_uniq( &make->phony_targets, "__tooldeps__" );
4137
}
4138
4139
if (make->phony_targets.count)
4140
{
4141
output( ".PHONY:" );
4142
output_filenames( make->phony_targets );
4143
output( "\n" );
4144
}
4145
}
4146
4147
4148
/*******************************************************************
4149
* output_sources
4150
*/
4151
static void output_sources( struct makefile *make )
4152
{
4153
struct strarray all_targets = empty_strarray;
4154
struct incl_file *source;
4155
unsigned int i, j, arch;
4156
4157
strarray_add_uniq( &make->phony_targets, "all" );
4158
4159
LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
4160
{
4161
char *obj = xstrdup( source->name );
4162
char *ext = get_extension( obj );
4163
4164
if (!ext) fatal_error( "unsupported file type %s\n", source->name );
4165
*ext++ = 0;
4166
4167
for (j = 0; output_source_funcs[j].ext; j++)
4168
if (!strcmp( ext, output_source_funcs[j].ext )) break;
4169
4170
output_source_funcs[j].fn( make, source, obj );
4171
strarray_addall_uniq( &make->dependencies, source->dependencies );
4172
}
4173
4174
/* special case for winetest: add resource files from other test dirs */
4175
if (make->obj_dir && !strcmp( make->obj_dir, "programs/winetest" ))
4176
{
4177
for (arch = 0; arch < archs.count; arch++)
4178
{
4179
if (!is_multiarch( arch )) continue;
4180
for (i = 0; i < subdirs.count; i++)
4181
{
4182
if (!submakes[i]->testdll) continue;
4183
if (submakes[i]->disabled[arch]) continue;
4184
if (enable_tests.count && !strarray_exists( enable_tests, submakes[i]->testdll )) continue;
4185
strarray_add( &make->res_files[arch],
4186
strmake( "%s%s", arch_dirs[arch],
4187
replace_extension( submakes[i]->testdll, ".dll", "_test.res" )));
4188
}
4189
}
4190
}
4191
4192
if (make->dlldata_files.count)
4193
{
4194
output( "%s: %s %s\n", obj_dir_path( make, "dlldata.c" ),
4195
widl, src_dir_path( make, "Makefile.in" ));
4196
output( "\t%s%s --dlldata-only -o $@", cmd_prefix( "WIDL" ), widl );
4197
output_filenames( make->dlldata_files );
4198
output( "\n" );
4199
}
4200
4201
if (make->staticlib)
4202
{
4203
for (arch = 0; arch < archs.count; arch++)
4204
if (is_multiarch( arch ) || (so_dll_supported && !make->extlib))
4205
output_static_lib( make, arch );
4206
}
4207
else if (make->module)
4208
{
4209
for (arch = 0; arch < archs.count; arch++)
4210
{
4211
if (is_multiarch( arch )) output_module( make, arch );
4212
if (make->importlib && (is_multiarch( arch ) || (!arch && !is_native_arch_disabled( make ))))
4213
output_import_lib( make, arch );
4214
}
4215
if (make->is_exe && !make->is_win16 && unix_lib_supported && strendswith( make->module, ".exe" ))
4216
{
4217
char *binary = replace_extension( make->module, ".exe", "" );
4218
install_program_symlink( make, binary, tools_path("wine"), binary );
4219
}
4220
}
4221
else if (make->testdll)
4222
{
4223
for (arch = 0; arch < archs.count; arch++)
4224
if (is_multiarch( arch )) output_test_module( make, arch );
4225
}
4226
else if (make->programs.count) output_programs( make );
4227
4228
if (make->unixlib) output_unix_lib( make );
4229
4230
STRARRAY_FOR_EACH( script, &make->scripts ) install_script( make, script );
4231
4232
STRARRAY_FOR_EACH( target, &make->extra_targets )
4233
if (strarray_exists( make->dependencies, obj_dir_path( make, target )))
4234
strarray_add( &make->clean_files, target );
4235
else
4236
strarray_add( &make->all_targets[0], target );
4237
4238
if (!make->src_dir) strarray_add( &make->distclean_files, ".gitignore" );
4239
strarray_add( &make->distclean_files, "Makefile" );
4240
if (make->testdll) strarray_add( &make->distclean_files, "testlist.c" );
4241
4242
for (arch = 0; arch < archs.count; arch++)
4243
{
4244
strarray_addall_uniq( &make->clean_files, make->object_files[arch] );
4245
strarray_addall_uniq( &make->clean_files, make->implib_files[arch] );
4246
strarray_addall_uniq( &make->clean_files, make->res_files[arch] );
4247
strarray_addall_uniq( &make->clean_files, make->all_targets[arch] );
4248
}
4249
strarray_addall( &make->clean_files, make->unixobj_files );
4250
strarray_addall( &make->clean_files, make->pot_files );
4251
strarray_addall( &make->clean_files, make->debug_files );
4252
strarray_addall( &make->clean_files, make->sast_files );
4253
4254
if (make == top_makefile)
4255
{
4256
output_subdirs( make );
4257
return;
4258
}
4259
4260
if (!strcmp( make->obj_dir, "po" )) strarray_add( &make->distclean_files, "LINGUAS" );
4261
4262
for (arch = 0; arch < archs.count; arch++) strarray_addall( &all_targets, make->all_targets[arch] );
4263
strarray_addall( &all_targets, make->font_files );
4264
if (all_targets.count)
4265
{
4266
output( "%s:", obj_dir_path( make, "all" ));
4267
output_filenames_obj_dir( make, all_targets );
4268
output( "\n" );
4269
strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "all" ));
4270
}
4271
if (make->clean_files.count)
4272
{
4273
output( "%s::\n", obj_dir_path( make, "clean" ));
4274
output( "\trm -f" );
4275
output_filenames_obj_dir( make, make->clean_files );
4276
output( "\n" );
4277
strarray_add( &make->phony_targets, obj_dir_path( make, "clean" ));
4278
}
4279
}
4280
4281
4282
/*******************************************************************
4283
* create_temp_file
4284
*/
4285
static FILE *create_temp_file( const char *orig )
4286
{
4287
char *name = xmalloc( strlen(orig) + 13 );
4288
unsigned int i, id = getpid();
4289
int fd;
4290
FILE *ret = NULL;
4291
4292
for (i = 0; i < 100; i++)
4293
{
4294
snprintf( name, strlen(orig) + 13, "%s.tmp%08x", orig, id );
4295
if ((fd = open( name, O_RDWR | O_CREAT | O_EXCL, 0666 )) != -1)
4296
{
4297
ret = fdopen( fd, "w" );
4298
break;
4299
}
4300
if (errno != EEXIST) break;
4301
id += 7777;
4302
}
4303
if (!ret) fatal_error( "failed to create output file for '%s'\n", orig );
4304
temp_file_name = name;
4305
return ret;
4306
}
4307
4308
4309
/*******************************************************************
4310
* rename_temp_file
4311
*/
4312
static void rename_temp_file( const char *dest )
4313
{
4314
int ret = rename( temp_file_name, dest );
4315
if (ret == -1 && errno == EEXIST)
4316
{
4317
/* rename doesn't overwrite on windows */
4318
unlink( dest );
4319
ret = rename( temp_file_name, dest );
4320
}
4321
if (ret == -1) fatal_error( "failed to rename output file to '%s'\n", dest );
4322
temp_file_name = NULL;
4323
}
4324
4325
4326
/*******************************************************************
4327
* are_files_identical
4328
*/
4329
static int are_files_identical( FILE *file1, FILE *file2 )
4330
{
4331
for (;;)
4332
{
4333
char buffer1[8192], buffer2[8192];
4334
int size1 = fread( buffer1, 1, sizeof(buffer1), file1 );
4335
int size2 = fread( buffer2, 1, sizeof(buffer2), file2 );
4336
if (size1 != size2) return 0;
4337
if (!size1) return feof( file1 ) && feof( file2 );
4338
if (memcmp( buffer1, buffer2, size1 )) return 0;
4339
}
4340
}
4341
4342
4343
/*******************************************************************
4344
* rename_temp_file_if_changed
4345
*/
4346
static void rename_temp_file_if_changed( const char *dest )
4347
{
4348
FILE *file1, *file2;
4349
int do_rename = 1;
4350
4351
if ((file1 = fopen( dest, "r" )))
4352
{
4353
if ((file2 = fopen( temp_file_name, "r" )))
4354
{
4355
do_rename = !are_files_identical( file1, file2 );
4356
fclose( file2 );
4357
}
4358
fclose( file1 );
4359
}
4360
if (!do_rename)
4361
{
4362
unlink( temp_file_name );
4363
temp_file_name = NULL;
4364
}
4365
else rename_temp_file( dest );
4366
}
4367
4368
4369
/*******************************************************************
4370
* output_linguas
4371
*/
4372
static void output_linguas( const struct makefile *make )
4373
{
4374
const char *dest = obj_dir_path( make, "LINGUAS" );
4375
struct incl_file *source;
4376
4377
output_file = create_temp_file( dest );
4378
4379
output( "# Automatically generated by make depend; DO NOT EDIT!!\n" );
4380
LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
4381
if (strendswith( source->name, ".po" ))
4382
output( "%s\n", replace_extension( source->name, ".po", "" ));
4383
4384
if (fclose( output_file )) fatal_perror( "write" );
4385
output_file = NULL;
4386
rename_temp_file_if_changed( dest );
4387
}
4388
4389
4390
/*******************************************************************
4391
* output_compile_commands
4392
*/
4393
static void output_compile_commands( const char *dest )
4394
{
4395
struct compile_command *cmd;
4396
const char *dir;
4397
4398
output_file = create_temp_file( dest );
4399
dir = escape_cstring( cwd );
4400
4401
output( "[\n" );
4402
LIST_FOR_EACH_ENTRY( cmd, &compile_commands, struct compile_command, entry )
4403
{
4404
output( " {\n" );
4405
output( " \"command\": \"%s -c -o %s %s", cmd->cmd, cmd->obj, cmd->source );
4406
STRARRAY_FOR_EACH( arg, &cmd->args ) output( " %s", escape_cstring( arg ));
4407
output( "\",\n" );
4408
output( " \"file\": \"%s\",\n", cmd->source );
4409
output( " \"output\": \"%s\",\n", cmd->obj );
4410
output( " \"directory\": \"%s\"\n", dir );
4411
output( " }%s\n", list_next( &compile_commands, &cmd->entry ) ? "," : "" );
4412
}
4413
output( "]\n" );
4414
4415
if (fclose( output_file )) fatal_perror( "write" );
4416
output_file = NULL;
4417
rename_temp_file( dest );
4418
}
4419
4420
4421
/*******************************************************************
4422
* output_testlist
4423
*/
4424
static void output_testlist( const struct makefile *make )
4425
{
4426
const char *dest = obj_dir_path( make, "testlist.c" );
4427
4428
output_file = create_temp_file( dest );
4429
4430
output( "/* Automatically generated by make depend; DO NOT EDIT!! */\n\n" );
4431
output( "#define WIN32_LEAN_AND_MEAN\n" );
4432
output( "#include <windows.h>\n\n" );
4433
output( "#define STANDALONE\n" );
4434
output( "#include \"wine/test.h\"\n\n" );
4435
4436
STRARRAY_FOR_EACH( file, &make->test_files ) output( "extern void func_%s(void);\n", file );
4437
output( "\n" );
4438
output( "const struct test winetest_testlist[] =\n" );
4439
output( "{\n" );
4440
STRARRAY_FOR_EACH( file, &make->test_files ) output( " { \"%s\", func_%s },\n", file, file );
4441
output( " { 0, 0 }\n" );
4442
output( "};\n" );
4443
4444
if (fclose( output_file )) fatal_perror( "write" );
4445
output_file = NULL;
4446
rename_temp_file_if_changed( dest );
4447
}
4448
4449
4450
/*******************************************************************
4451
* output_gitignore
4452
*/
4453
static void output_gitignore( const char *dest, struct strarray files )
4454
{
4455
output_file = create_temp_file( dest );
4456
4457
output( "# Automatically generated by make depend; DO NOT EDIT!!\n" );
4458
STRARRAY_FOR_EACH( file, &files )
4459
{
4460
if (!strchr( file, '/' )) output( "/" );
4461
output( "%s\n", file );
4462
}
4463
4464
if (fclose( output_file )) fatal_perror( "write" );
4465
output_file = NULL;
4466
rename_temp_file( dest );
4467
}
4468
4469
4470
/*******************************************************************
4471
* output_stub_makefile
4472
*/
4473
static void output_stub_makefile( struct makefile *make )
4474
{
4475
struct strarray targets = empty_strarray;
4476
const char *make_var = strarray_get_value( top_makefile->vars, "MAKE" );
4477
unsigned int arch;
4478
4479
for (arch = 0; arch < archs.count; arch++)
4480
if (make->all_targets[arch].count) strarray_add_uniq( &targets, "all" );
4481
4482
if (make->clean_files.count) strarray_add( &targets, "clean" );
4483
if (make->test_files.count)
4484
{
4485
strarray_add( &targets, "check" );
4486
strarray_add( &targets, "test" );
4487
strarray_add( &targets, "testclean" );
4488
}
4489
4490
if (!targets.count && !make->clean_files.count) return;
4491
4492
output_file_name = obj_dir_path( make, "Makefile" );
4493
output_file = create_temp_file( output_file_name );
4494
4495
output( "# Auto-generated stub makefile; all rules forward to the top-level makefile\n\n" );
4496
4497
if (make_var) output( "MAKE = %s\n\n", make_var );
4498
4499
output( "all:\n" );
4500
output_filenames( targets );
4501
output_filenames( make->clean_files );
4502
output( ":\n" );
4503
output( "\t@cd %s && $(MAKE) %s/$@\n", get_root_relative_path( make ), make->obj_dir );
4504
output( ".PHONY:" );
4505
output_filenames( targets );
4506
output( "\n" );
4507
4508
fclose( output_file );
4509
output_file = NULL;
4510
rename_temp_file( output_file_name );
4511
}
4512
4513
4514
/*******************************************************************
4515
* output_silent_rules
4516
*/
4517
static void output_silent_rules(void)
4518
{
4519
static const char *cmds[] =
4520
{
4521
"BISON",
4522
"BUILD",
4523
"CC",
4524
"CCLD",
4525
"FLEX",
4526
"GEN",
4527
"LN",
4528
"MSG",
4529
"SAST",
4530
"SED",
4531
"TEST",
4532
"WIDL",
4533
"WMC",
4534
"WRC"
4535
};
4536
unsigned int i;
4537
4538
output( "V = 0\n" );
4539
for (i = 0; i < ARRAY_SIZE(cmds); i++)
4540
{
4541
output( "quiet_%s = $(quiet_%s_$(V))\n", cmds[i], cmds[i] );
4542
output( "quiet_%s_0 = @echo \" %-5s \" $@;\n", cmds[i], cmds[i] );
4543
output( "quiet_%s_1 =\n", cmds[i] );
4544
}
4545
}
4546
4547
4548
/*******************************************************************
4549
* output_top_makefile
4550
*/
4551
static void output_top_makefile( struct makefile *make )
4552
{
4553
char buffer[1024];
4554
FILE *src_file;
4555
unsigned int i;
4556
int found = 0;
4557
4558
output_file_name = obj_dir_path( make, output_makefile_name );
4559
output_file = create_temp_file( output_file_name );
4560
4561
/* copy the contents of the source makefile */
4562
src_file = open_input_makefile( make );
4563
while (fgets( buffer, sizeof(buffer), src_file ) && !found)
4564
{
4565
if (fwrite( buffer, 1, strlen(buffer), output_file ) != strlen(buffer)) fatal_perror( "write" );
4566
found = !strncmp( buffer, separator, strlen(separator) );
4567
}
4568
if (fclose( src_file )) fatal_perror( "close" );
4569
input_file_name = NULL;
4570
4571
if (!found) output( "\n%s (everything below this line is auto-generated; DO NOT EDIT!!)\n", separator );
4572
4573
if (silent_rules) output_silent_rules();
4574
4575
/* add special targets for makefile and dependencies */
4576
4577
output( ".INIT: Makefile\n" );
4578
output( ".PRECIOUS: Makefile\n" );
4579
output( ".MAKEFILEDEPS:\n" );
4580
output( ".SUFFIXES:\n" );
4581
output( "Makefile: config.status %s\n", makedep );
4582
output( "\t@./config.status Makefile\n" );
4583
output( "config.status: %s\n", root_src_dir_path( "configure" ));
4584
output( "\t@./config.status --recheck\n" );
4585
strarray_add( &make->distclean_files, "config.status" );
4586
output( "include/config.h: include/stamp-h\n" );
4587
output( "include/stamp-h: %s config.status\n", root_src_dir_path( "include/config.h.in" ));
4588
output( "\t@./config.status include/config.h include/stamp-h\n" );
4589
strarray_add( &make->distclean_files, "include/config.h" );
4590
strarray_add( &make->distclean_files, "include/stamp-h" );
4591
output( "depend: %s\n", makedep );
4592
output( "\t%s%s%s\n", makedep,
4593
compile_commands_mode ? " -C" : "",
4594
silent_rules ? " -S" : "" );
4595
strarray_add( &make->phony_targets, "depend" );
4596
4597
if (!strarray_exists( disabled_dirs[0], "tools/wine" ))
4598
{
4599
const char *loader = "tools/wine/wine";
4600
if (!strarray_exists( subdirs, "tools/wine" )) loader = tools_path( "wine" );
4601
output( "wine: %s\n", loader );
4602
output( "\t%srm -f $@ && %s %s $@\n", cmd_prefix( "LN" ), ln_s, loader );
4603
strarray_add( &make->all_targets[0], "wine" );
4604
}
4605
4606
if (wine64_dir)
4607
{
4608
output( "loader-wow64:\n" );
4609
output( "\t%srm -f $@ && %s %s/loader $@\n", cmd_prefix( "LN" ), ln_s, wine64_dir );
4610
output( "%s/loader-wow64:\n", wine64_dir );
4611
output( "\t%srm -f $@ && %s %s/loader $@\n", cmd_prefix( "LN" ), ln_s, cwd );
4612
output( "all: %s/loader-wow64\n", wine64_dir );
4613
strarray_add( &make->all_targets[0], "loader-wow64" );
4614
}
4615
else strarray_add( &make->clean_files, "loader-wow64" );
4616
4617
if (compile_commands_mode) strarray_add( &make->distclean_files, "compile_commands.json" );
4618
strarray_addall( &make->distclean_files, get_expanded_make_var_array( make, "CONFIGURE_TARGETS" ));
4619
if (!make->src_dir)
4620
{
4621
strarray_add( &make->maintainerclean_files, "configure" );
4622
strarray_add( &make->maintainerclean_files, "include/config.h.in" );
4623
}
4624
4625
for (i = 0; i < subdirs.count; i++) output_sources( submakes[i] );
4626
output_sources( make );
4627
4628
fclose( output_file );
4629
output_file = NULL;
4630
rename_temp_file( output_file_name );
4631
}
4632
4633
4634
/*******************************************************************
4635
* output_dependencies
4636
*/
4637
static void output_dependencies( struct makefile *make )
4638
{
4639
struct strarray ignore_files = empty_strarray;
4640
4641
if (make->obj_dir) mkdir_p( make->obj_dir );
4642
4643
if (make == top_makefile) output_top_makefile( make );
4644
else output_stub_makefile( make );
4645
4646
strarray_addall( &ignore_files, make->distclean_files );
4647
strarray_addall( &ignore_files, make->clean_files );
4648
if (make->testdll) output_testlist( make );
4649
if (make->obj_dir && !strcmp( make->obj_dir, "po" )) output_linguas( make );
4650
if (!make->src_dir) output_gitignore( obj_dir_path( make, ".gitignore" ), ignore_files );
4651
4652
create_file_directories( make, ignore_files );
4653
4654
output_file_name = NULL;
4655
}
4656
4657
4658
/*******************************************************************
4659
* load_sources
4660
*/
4661
static void load_sources( struct makefile *make )
4662
{
4663
unsigned int i, arch;
4664
struct strarray value;
4665
struct incl_file *file;
4666
4667
strarray_set_value( &make->vars, "top_srcdir", root_src_dir_path( "" ));
4668
strarray_set_value( &make->vars, "srcdir", src_dir_path( make, "" ));
4669
4670
make->parent_dir = get_expanded_make_variable( make, "PARENTSRC" );
4671
make->module = get_expanded_make_variable( make, "MODULE" );
4672
make->testdll = get_expanded_make_variable( make, "TESTDLL" );
4673
make->staticlib = get_expanded_make_variable( make, "STATICLIB" );
4674
make->importlib = get_expanded_make_variable( make, "IMPORTLIB" );
4675
make->extlib = get_expanded_make_variable( make, "EXTLIB" );
4676
if (unix_lib_supported) make->unixlib = get_expanded_make_variable( make, "UNIXLIB" );
4677
4678
make->programs = get_expanded_make_var_array( make, "PROGRAMS" );
4679
make->scripts = get_expanded_make_var_array( make, "SCRIPTS" );
4680
make->imports = get_expanded_make_var_array( make, "IMPORTS" );
4681
make->delayimports = get_expanded_make_var_array( make, "DELAYIMPORTS" );
4682
make->extradllflags = get_expanded_make_var_array( make, "EXTRADLLFLAGS" );
4683
make->extra_targets = get_expanded_make_var_array( make, "EXTRA_TARGETS" );
4684
for (i = 0; i < NB_INSTALL_RULES; i++)
4685
make->install[i] = get_expanded_make_var_array( make, install_variables[i] );
4686
4687
if (make->extlib) make->staticlib = make->extlib;
4688
if (make->staticlib) make->module = make->staticlib;
4689
4690
if (make->obj_dir)
4691
{
4692
make->disabled[0] = strarray_exists( disabled_dirs[0], make->obj_dir );
4693
for (arch = 1; arch < archs.count; arch++)
4694
make->disabled[arch] = make->disabled[0] || strarray_exists( disabled_dirs[arch], make->obj_dir );
4695
}
4696
make->is_win16 = strarray_exists( make->extradllflags, "-m16" );
4697
make->data_only = strarray_exists( make->extradllflags, "-Wb,--data-only" );
4698
make->is_exe = strarray_exists( make->extradllflags, "-mconsole" ) ||
4699
strarray_exists( make->extradllflags, "-mwindows" );
4700
4701
/* add default install rules if nothing was specified */
4702
for (i = 0; i < NB_INSTALL_RULES; i++) if (make->install[i].count) break;
4703
if (i == NB_INSTALL_RULES && !make->extlib)
4704
{
4705
if (make->unixlib) strarray_add( &make->install[INSTALL_UNIXLIB], make->unixlib );
4706
if (make->importlib) strarray_add( &make->install[INSTALL_DEV], make->importlib );
4707
if (make->staticlib) strarray_add( &make->install[INSTALL_DEV], make->staticlib );
4708
else if (make->module) strarray_add( &make->install[INSTALL_LIB], make->module );
4709
}
4710
4711
make->include_paths = empty_strarray;
4712
make->include_args = empty_strarray;
4713
make->define_args = empty_strarray;
4714
make->unix_cflags = empty_strarray;
4715
if (!make->extlib) strarray_add( &make->define_args, "-D__WINESRC__" );
4716
strarray_add( &make->unix_cflags, "-DWINE_UNIX_LIB" );
4717
4718
value = get_expanded_make_var_array( make, "EXTRAINCL" );
4719
STRARRAY_FOR_EACH( arg, &value )
4720
{
4721
if (!strncmp( arg, "-I", 2 ))
4722
{
4723
const char *dir = arg + 2;
4724
if (!strncmp( dir, "./", 2 ))
4725
{
4726
dir += 2;
4727
while (*dir == '/') dir++;
4728
}
4729
strarray_add_uniq( &make->include_paths, dir );
4730
}
4731
else if (!strncmp( arg, "-D", 2 ) || !strncmp( arg, "-U", 2 ))
4732
strarray_add_uniq( &make->define_args, arg );
4733
}
4734
strarray_addall( &make->define_args, get_expanded_make_var_array( make, "EXTRADEFS" ));
4735
strarray_addall_uniq( &make->unix_cflags, get_expanded_make_var_array( make, "UNIX_CFLAGS" ));
4736
4737
strarray_add( &make->include_args, strmake( "-I%s", obj_dir_path( make, "" )));
4738
if (make->src_dir)
4739
strarray_add( &make->include_args, strmake( "-I%s", make->src_dir ));
4740
if (make->parent_dir)
4741
strarray_add( &make->include_args, strmake( "-I%s", src_dir_path( make, make->parent_dir )));
4742
strarray_add( &make->include_args, "-Iinclude" );
4743
if (root_src_dir) strarray_add( &make->include_args, strmake( "-I%s", root_src_dir_path( "include" )));
4744
4745
list_init( &make->sources );
4746
list_init( &make->includes );
4747
4748
value = get_expanded_make_var_array( make, "SOURCES" );
4749
STRARRAY_FOR_EACH( file, &value ) add_src_file( make, file );
4750
4751
add_generated_sources( make );
4752
4753
LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry ) parse_file( make, file, 0 );
4754
LIST_FOR_EACH_ENTRY( file, &make->sources, struct incl_file, entry ) get_dependencies( file, file );
4755
4756
STRARRAY_FOR_EACH( imp, &make->delayimports )
4757
strarray_add_uniq( &delay_import_libs, get_base_name( imp ));
4758
}
4759
4760
4761
/*******************************************************************
4762
* parse_makeflags
4763
*/
4764
static void parse_makeflags( const char *flags )
4765
{
4766
const char *p = flags;
4767
char *var, *buffer = xmalloc( strlen(flags) + 1 );
4768
4769
while (*p)
4770
{
4771
p = skip_spaces( p );
4772
var = buffer;
4773
while (*p && !isspace(*p))
4774
{
4775
if (*p == '\\' && p[1]) p++;
4776
*var++ = *p++;
4777
}
4778
*var = 0;
4779
if (var > buffer) set_make_variable( &cmdline_vars, buffer );
4780
}
4781
}
4782
4783
4784
/*******************************************************************
4785
* parse_option
4786
*/
4787
static int parse_option( const char *opt )
4788
{
4789
if (opt[0] != '-')
4790
{
4791
if (strchr( opt, '=' )) return set_make_variable( &cmdline_vars, opt );
4792
return 0;
4793
}
4794
switch(opt[1])
4795
{
4796
case 'f':
4797
if (opt[2]) output_makefile_name = opt + 2;
4798
break;
4799
case 'i':
4800
if (opt[2]) input_makefile_name = opt + 2;
4801
break;
4802
case 'C':
4803
compile_commands_mode = 1;
4804
break;
4805
case 'S':
4806
silent_rules = 1;
4807
break;
4808
default:
4809
fprintf( stderr, "Unknown option '%s'\n%s", opt, Usage );
4810
exit(1);
4811
}
4812
return 1;
4813
}
4814
4815
4816
/*******************************************************************
4817
* find_pe_arch
4818
*/
4819
static unsigned int find_pe_arch( const char *arch )
4820
{
4821
unsigned int i;
4822
for (i = 1; i < archs.count; i++) if (!strcmp( archs.str[i], arch )) return i;
4823
return 0;
4824
}
4825
4826
4827
/*******************************************************************
4828
* main
4829
*/
4830
int main( int argc, char *argv[] )
4831
{
4832
const char *makeflags = getenv( "MAKEFLAGS" );
4833
const char *target;
4834
unsigned int i, j, arch, ec_arch;
4835
4836
if (makeflags) parse_makeflags( makeflags );
4837
4838
i = 1;
4839
while (i < argc)
4840
{
4841
if (parse_option( argv[i] ))
4842
{
4843
for (j = i; j < argc; j++) argv[j] = argv[j+1];
4844
argc--;
4845
}
4846
else i++;
4847
}
4848
4849
if (argc > 1)
4850
{
4851
fprintf( stderr, "Unknown argument '%s'\n%s", argv[1], Usage );
4852
exit(1);
4853
}
4854
4855
atexit( cleanup_files );
4856
init_signals( exit_on_signal );
4857
getcwd( cwd, sizeof(cwd) );
4858
4859
for (i = 0; i < HASH_SIZE; i++) list_init( &files[i] );
4860
for (i = 0; i < HASH_SIZE; i++) list_init( &global_includes[i] );
4861
4862
top_makefile = parse_makefile( NULL );
4863
4864
target_flags[0] = get_expanded_make_var_array( top_makefile, "TARGETFLAGS" );
4865
msvcrt_flags = get_expanded_make_var_array( top_makefile, "MSVCRTFLAGS" );
4866
dll_flags = get_expanded_make_var_array( top_makefile, "DLLFLAGS" );
4867
unix_dllflags = get_expanded_make_var_array( top_makefile, "UNIXDLLFLAGS" );
4868
cpp_flags = get_expanded_make_var_array( top_makefile, "CPPFLAGS" );
4869
lddll_flags = get_expanded_make_var_array( top_makefile, "LDDLLFLAGS" );
4870
libs = get_expanded_make_var_array( top_makefile, "LIBS" );
4871
enable_tests = get_expanded_make_var_array( top_makefile, "ENABLE_TESTS" );
4872
for (i = 0; i < NB_INSTALL_RULES; i++)
4873
top_install[i] = get_expanded_make_var_array( top_makefile, strmake( "TOP_%s", install_variables[i] ));
4874
4875
root_src_dir = get_expanded_make_variable( top_makefile, "srcdir" );
4876
tools_dir = get_expanded_make_variable( top_makefile, "toolsdir" );
4877
tools_ext = get_expanded_make_variable( top_makefile, "toolsext" );
4878
wine64_dir = get_expanded_make_variable( top_makefile, "wine64dir" );
4879
exe_ext = get_expanded_make_variable( top_makefile, "EXEEXT" );
4880
dll_ext[0] = get_expanded_make_variable( top_makefile, "DLLEXT" );
4881
fontforge = get_expanded_make_variable( top_makefile, "FONTFORGE" );
4882
convert = get_expanded_make_variable( top_makefile, "CONVERT" );
4883
flex = get_expanded_make_variable( top_makefile, "FLEX" );
4884
bison = get_expanded_make_variable( top_makefile, "BISON" );
4885
rsvg = get_expanded_make_variable( top_makefile, "RSVG" );
4886
icotool = get_expanded_make_variable( top_makefile, "ICOTOOL" );
4887
msgfmt = get_expanded_make_variable( top_makefile, "MSGFMT" );
4888
sed_cmd = get_expanded_make_variable( top_makefile, "SED_CMD" );
4889
ln_s = get_expanded_make_variable( top_makefile, "LN_S" );
4890
wayland_scanner = get_expanded_make_variable( top_makefile, "WAYLAND_SCANNER" );
4891
sarif_converter = get_expanded_make_variable( top_makefile, "SARIF_CONVERTER" );
4892
compiler_rt = get_expanded_make_variable( top_makefile, "COMPILER_RT_PE_LIBS" );
4893
4894
if (root_src_dir && !strcmp( root_src_dir, "." )) root_src_dir = NULL;
4895
if (tools_dir && !strcmp( tools_dir, "." )) tools_dir = NULL;
4896
if (!exe_ext) exe_ext = "";
4897
if (!dll_ext[0]) dll_ext[0] = "";
4898
if (!tools_ext) tools_ext = "";
4899
4900
buildimage = root_src_dir_path( "tools/buildimage" );
4901
runtest = root_src_dir_path( "tools/runtest" );
4902
install = tools_base_path( "install" );
4903
makedep = tools_base_path( "makedep" );
4904
make_xftmpl = tools_base_path( "make_xftmpl" );
4905
sfnt2fon = tools_path( "sfnt2fon" );
4906
winebuild = tools_path( "winebuild" );
4907
winegcc = tools_path( "winegcc" );
4908
widl = tools_path( "widl" );
4909
wrc = tools_path( "wrc" );
4910
wmc = tools_path( "wmc" );
4911
4912
symlinks_supported = !strcmp( ln_s, "ln -s" );
4913
unix_lib_supported = !!strcmp( exe_ext, ".exe" );
4914
so_dll_supported = !!dll_ext[0][0]; /* non-empty dll ext means supported */
4915
4916
strarray_add( &archs, get_expanded_make_variable( top_makefile, "HOST_ARCH" ));
4917
strarray_addall( &archs, get_expanded_make_var_array( top_makefile, "PE_ARCHS" ));
4918
4919
/* check for ARM64X setup */
4920
if ((ec_arch = find_pe_arch( "arm64ec" )) && (arch = find_pe_arch( "aarch64" )))
4921
{
4922
native_archs[ec_arch] = arch;
4923
hybrid_archs[arch] = ec_arch;
4924
strarray_add( &hybrid_target_flags[ec_arch], "-marm64x" );
4925
}
4926
4927
arch_dirs[0] = "";
4928
arch_install_dirs[0] = unix_lib_supported ? strmake( "$(libdir)/wine/%s-unix", archs.str[0] ) : "$(libdir)/wine";
4929
strip_progs[0] = "--strip-program=\"$(STRIP)\"";
4930
4931
for (arch = 1; arch < archs.count; arch++)
4932
{
4933
target = get_expanded_arch_var( top_makefile, "TARGET", arch );
4934
strarray_add( &target_flags[arch], "-b" );
4935
strarray_add( &target_flags[arch], target );
4936
arch_dirs[arch] = strmake( "%s-windows/", archs.str[arch] );
4937
arch_install_dirs[arch] = strmake( "$(libdir)/wine/%s-windows", archs.str[arch] );
4938
strip_progs[arch] = strmake( "--strip-program=\"%s --builtin --strip-cmd=%s\"",
4939
winebuild, get_expanded_arch_var( top_makefile, "STRIP", arch ));
4940
dll_ext[arch] = "";
4941
}
4942
4943
for (arch = 0; arch < archs.count; arch++)
4944
{
4945
arch_pe_dirs[arch] = strmake( "%s-windows", archs.str[arch] );
4946
extra_cflags[arch] = get_expanded_arch_var_array( top_makefile, "EXTRACFLAGS", arch );
4947
extra_cflags_extlib[arch] = remove_warning_flags( extra_cflags[arch] );
4948
disabled_dirs[arch] = get_expanded_arch_var_array( top_makefile, "DISABLED_SUBDIRS", arch );
4949
if (!is_multiarch( arch )) continue;
4950
delay_load_flags[arch] = get_expanded_arch_var( top_makefile, "DELAYLOADFLAG", arch );
4951
debug_flags[arch] = get_expanded_arch_var_array( top_makefile, "DEBUG", arch );
4952
cc_cmds[arch] = strmake( "--cc-cmd=\"%s\"", get_expanded_arch_var( top_makefile, "CC", arch ));
4953
}
4954
4955
if (unix_lib_supported)
4956
{
4957
delay_load_flags[0] = "-Wl,-delayload,";
4958
debug_flags[0].count = 0;
4959
}
4960
4961
top_makefile->src_dir = root_src_dir;
4962
subdirs = get_expanded_make_var_array( top_makefile, "SUBDIRS" );
4963
submakes = xmalloc( subdirs.count * sizeof(*submakes) );
4964
4965
for (i = 0; i < subdirs.count; i++) submakes[i] = parse_makefile( subdirs.str[i] );
4966
4967
load_sources( top_makefile );
4968
load_sources( include_makefile );
4969
for (i = 0; i < subdirs.count; i++)
4970
if (submakes[i] != include_makefile) load_sources( submakes[i] );
4971
4972
output_dependencies( top_makefile );
4973
for (i = 0; i < subdirs.count; i++) output_dependencies( submakes[i] );
4974
4975
if (compile_commands_mode) output_compile_commands( "compile_commands.json" );
4976
4977
return 0;
4978
}
4979
4980