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