msdasql: Add ICommandPrepare interface for ICommandText.
[wine.git] / tools / makedep.c
blobb24acfa3053b1bb91e12f73d1c9574e3a5be9f7f
1 /*
2 * Generate include file dependencies
4 * Copyright 1996, 2013, 2020 Alexandre Julliard
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.
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.
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
21 #include "config.h"
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 <signal.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
35 #include "tools.h"
36 #include "wine/list.h"
38 enum incl_type
40 INCL_NORMAL, /* #include "foo.h" */
41 INCL_SYSTEM, /* #include <foo.h> */
42 INCL_IMPORT, /* idl import "foo.idl" */
43 INCL_IMPORTLIB, /* idl importlib "foo.tlb" */
44 INCL_CPP_QUOTE, /* idl cpp_quote("#include \"foo.h\"") */
45 INCL_CPP_QUOTE_SYSTEM /* idl cpp_quote("#include <foo.h>") */
48 struct dependency
50 int line; /* source line where this header is included */
51 enum incl_type type; /* type of include */
52 char *name; /* header name */
55 struct file
57 struct list entry;
58 char *name; /* full file name relative to cwd */
59 void *args; /* custom arguments for makefile rule */
60 unsigned int flags; /* flags (see below) */
61 unsigned int deps_count; /* files in use */
62 unsigned int deps_size; /* total allocated size */
63 struct dependency *deps; /* all header dependencies */
66 struct incl_file
68 struct list 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 int use_msvcrt:1; /* put msvcrt headers in the search path? */
78 int is_external:1; /* file from external library? */
79 struct incl_file *owner;
80 unsigned int files_count; /* files in use */
81 unsigned int files_size; /* total allocated size */
82 struct incl_file **files;
83 struct strarray dependencies; /* file dependencies */
86 #define FLAG_GENERATED 0x000001 /* generated file */
87 #define FLAG_INSTALL 0x000002 /* file to install */
88 #define FLAG_IDL_PROXY 0x000100 /* generates a proxy (_p.c) file */
89 #define FLAG_IDL_CLIENT 0x000200 /* generates a client (_c.c) file */
90 #define FLAG_IDL_SERVER 0x000400 /* generates a server (_s.c) file */
91 #define FLAG_IDL_IDENT 0x000800 /* generates an ident (_i.c) file */
92 #define FLAG_IDL_REGISTER 0x001000 /* generates a registration (_r.res) file */
93 #define FLAG_IDL_TYPELIB 0x002000 /* generates a typelib (.tlb) file */
94 #define FLAG_IDL_REGTYPELIB 0x004000 /* generates a registered typelib (_t.res) file */
95 #define FLAG_IDL_HEADER 0x008000 /* generates a header (.h) file */
96 #define FLAG_RC_PO 0x010000 /* rc file contains translations */
97 #define FLAG_C_IMPLIB 0x020000 /* file is part of an import library */
98 #define FLAG_C_UNIX 0x040000 /* file is part of a Unix library */
99 #define FLAG_SFD_FONTS 0x080000 /* sfd file generated bitmap fonts */
101 static const struct
103 unsigned int flag;
104 const char *ext;
105 } idl_outputs[] =
107 { FLAG_IDL_TYPELIB, ".tlb" },
108 { FLAG_IDL_REGTYPELIB, "_t.res" },
109 { FLAG_IDL_CLIENT, "_c.c" },
110 { FLAG_IDL_IDENT, "_i.c" },
111 { FLAG_IDL_PROXY, "_p.c" },
112 { FLAG_IDL_SERVER, "_s.c" },
113 { FLAG_IDL_REGISTER, "_r.res" },
114 { FLAG_IDL_HEADER, ".h" }
117 #define HASH_SIZE 997
119 static struct list files[HASH_SIZE];
121 enum install_rules { INSTALL_LIB, INSTALL_DEV, NB_INSTALL_RULES };
123 /* variables common to all makefiles */
124 static struct strarray linguas;
125 static struct strarray dll_flags;
126 static struct strarray unix_dllflags;
127 static struct strarray target_flags;
128 static struct strarray msvcrt_flags;
129 static struct strarray extra_cflags;
130 static struct strarray extra_cross_cflags;
131 static struct strarray extra_cflags_extlib;
132 static struct strarray extra_cross_cflags_extlib;
133 static struct strarray cpp_flags;
134 static struct strarray lddll_flags;
135 static struct strarray libs;
136 static struct strarray enable_tests;
137 static struct strarray cmdline_vars;
138 static struct strarray subdirs;
139 static struct strarray disabled_dirs;
140 static struct strarray delay_import_libs;
141 static struct strarray top_install_lib;
142 static struct strarray top_install_dev;
143 static const char *root_src_dir;
144 static const char *tools_dir;
145 static const char *tools_ext;
146 static const char *exe_ext;
147 static const char *dll_ext;
148 static const char *man_ext;
149 static const char *host_cpu;
150 static const char *pe_dir;
151 static const char *so_dir;
152 static const char *crosstarget;
153 static const char *crossdebug;
154 static const char *fontforge;
155 static const char *convert;
156 static const char *flex;
157 static const char *bison;
158 static const char *ar;
159 static const char *ranlib;
160 static const char *rsvg;
161 static const char *icotool;
162 static const char *dlltool;
163 static const char *msgfmt;
164 static const char *ln_s;
165 static const char *sed_cmd;
166 static const char *delay_load_flag;
168 struct makefile
170 /* values determined from input makefile */
171 struct strarray vars;
172 struct strarray include_paths;
173 struct strarray include_args;
174 struct strarray define_args;
175 struct strarray programs;
176 struct strarray scripts;
177 struct strarray imports;
178 struct strarray delayimports;
179 struct strarray extradllflags;
180 struct strarray install_lib;
181 struct strarray install_dev;
182 struct strarray extra_targets;
183 struct strarray extra_imports;
184 struct list sources;
185 struct list includes;
186 const char *src_dir;
187 const char *obj_dir;
188 const char *parent_dir;
189 const char *module;
190 const char *testdll;
191 const char *extlib;
192 const char *sharedlib;
193 const char *staticlib;
194 const char *staticimplib;
195 const char *importlib;
196 const char *unixlib;
197 int native_unix_lib;
198 int disabled;
199 int use_msvcrt;
200 int is_cross;
201 int is_win16;
202 int is_exe;
204 /* values generated at output time */
205 struct strarray in_files;
206 struct strarray ok_files;
207 struct strarray pot_files;
208 struct strarray clean_files;
209 struct strarray distclean_files;
210 struct strarray uninstall_files;
211 struct strarray object_files;
212 struct strarray crossobj_files;
213 struct strarray unixobj_files;
214 struct strarray res_files;
215 struct strarray font_files;
216 struct strarray c2man_files;
217 struct strarray debug_files;
218 struct strarray dlldata_files;
219 struct strarray implib_objs;
220 struct strarray all_targets;
221 struct strarray phony_targets;
222 struct strarray dependencies;
223 struct strarray install_rules[NB_INSTALL_RULES];
226 static struct makefile *top_makefile;
227 static struct makefile **submakes;
229 static const char separator[] = "### Dependencies";
230 static const char *output_makefile_name = "Makefile";
231 static const char *input_file_name;
232 static const char *output_file_name;
233 static const char *temp_file_name;
234 static int relative_dir_mode;
235 static int silent_rules;
236 static int input_line;
237 static int output_column;
238 static FILE *output_file;
240 static const char Usage[] =
241 "Usage: makedep [options] [directories]\n"
242 "Options:\n"
243 " -R from to Compute the relative path between two directories\n"
244 " -S Generate Automake-style silent rules\n"
245 " -fxxx Store output in file 'xxx' (default: Makefile)\n";
248 static void fatal_error( const char *msg, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
249 static void fatal_perror( const char *msg, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
250 static void output( const char *format, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
251 static char *strmake( const char* fmt, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
253 /*******************************************************************
254 * fatal_error
256 static void fatal_error( const char *msg, ... )
258 va_list valist;
259 va_start( valist, msg );
260 if (input_file_name)
262 fprintf( stderr, "%s:", input_file_name );
263 if (input_line) fprintf( stderr, "%d:", input_line );
264 fprintf( stderr, " error: " );
266 else fprintf( stderr, "makedep: error: " );
267 vfprintf( stderr, msg, valist );
268 va_end( valist );
269 exit(1);
273 /*******************************************************************
274 * fatal_perror
276 static void fatal_perror( const char *msg, ... )
278 va_list valist;
279 va_start( valist, msg );
280 if (input_file_name)
282 fprintf( stderr, "%s:", input_file_name );
283 if (input_line) fprintf( stderr, "%d:", input_line );
284 fprintf( stderr, " error: " );
286 else fprintf( stderr, "makedep: error: " );
287 vfprintf( stderr, msg, valist );
288 perror( " " );
289 va_end( valist );
290 exit(1);
294 /*******************************************************************
295 * cleanup_files
297 static void cleanup_files(void)
299 if (temp_file_name) unlink( temp_file_name );
300 if (output_file_name) unlink( output_file_name );
304 /*******************************************************************
305 * exit_on_signal
307 static void exit_on_signal( int sig )
309 exit( 1 ); /* this will call the atexit functions */
313 /*******************************************************************
314 * output
316 static void output( const char *format, ... )
318 int ret;
319 va_list valist;
321 va_start( valist, format );
322 ret = vfprintf( output_file, format, valist );
323 va_end( valist );
324 if (ret < 0) fatal_perror( "output" );
325 if (format[0] && format[strlen(format) - 1] == '\n') output_column = 0;
326 else output_column += ret;
330 /*******************************************************************
331 * strarray_get_value
333 * Find a value in a name/value pair string array.
335 static const char *strarray_get_value( const struct strarray *array, const char *name )
337 int pos, res, min = 0, max = array->count / 2 - 1;
339 while (min <= max)
341 pos = (min + max) / 2;
342 if (!(res = strcmp( array->str[pos * 2], name ))) return array->str[pos * 2 + 1];
343 if (res < 0) min = pos + 1;
344 else max = pos - 1;
346 return NULL;
350 /*******************************************************************
351 * strarray_set_value
353 * Define a value in a name/value pair string array.
355 static void strarray_set_value( struct strarray *array, const char *name, const char *value )
357 int i, pos, res, min = 0, max = array->count / 2 - 1;
359 while (min <= max)
361 pos = (min + max) / 2;
362 if (!(res = strcmp( array->str[pos * 2], name )))
364 /* redefining a variable replaces the previous value */
365 array->str[pos * 2 + 1] = value;
366 return;
368 if (res < 0) min = pos + 1;
369 else max = pos - 1;
371 strarray_add( array, NULL );
372 strarray_add( array, NULL );
373 for (i = array->count - 1; i > min * 2 + 1; i--) array->str[i] = array->str[i - 2];
374 array->str[min * 2] = name;
375 array->str[min * 2 + 1] = value;
379 /*******************************************************************
380 * normalize_arch
382 static const char *normalize_arch( const char *arch )
384 unsigned int i, j;
386 static const char *map[][8] =
388 /* normalized aliases */
389 { "i386", "i486", "i586", "i686", "ia32" },
390 { "x86_64", "amd64", "x86-64", "x86_amd64", "x64" },
391 { "aarch64", "arm64" },
392 { "arm" },
395 for (i = 0; i < sizeof(map) / sizeof(map[0]); i++)
396 for (j = 0; map[i][j]; j++)
397 if (!strncmp( arch, map[i][j], strlen(map[i][j]) ))
398 return map[i][0];
399 return NULL;
403 /*******************************************************************
404 * output_filename
406 static void output_filename( const char *name )
408 if (output_column + strlen(name) + 1 > 100)
410 output( " \\\n" );
411 output( " " );
413 else if (output_column) output( " " );
414 output( "%s", name );
418 /*******************************************************************
419 * output_filenames
421 static void output_filenames( struct strarray array )
423 unsigned int i;
425 for (i = 0; i < array.count; i++) output_filename( array.str[i] );
429 /*******************************************************************
430 * output_rm_filenames
432 static void output_rm_filenames( struct strarray array )
434 static const unsigned int max_cmdline = 30000; /* to be on the safe side */
435 unsigned int i, len;
437 if (!array.count) return;
438 output( "\trm -f" );
439 for (i = len = 0; i < array.count; i++)
441 if (len > max_cmdline)
443 output( "\n" );
444 output( "\trm -f" );
445 len = 0;
447 output_filename( array.str[i] );
448 len += strlen( array.str[i] ) + 1;
450 output( "\n" );
454 /*******************************************************************
455 * get_extension
457 static char *get_extension( char *filename )
459 char *ext = strrchr( filename, '.' );
460 if (ext && strchr( ext, '/' )) ext = NULL;
461 return ext;
465 /*******************************************************************
466 * get_base_name
468 static const char *get_base_name( const char *name )
470 char *base;
471 if (!strchr( name, '.' )) return name;
472 base = xstrdup( name );
473 *strrchr( base, '.' ) = 0;
474 return base;
478 /*******************************************************************
479 * replace_filename
481 static char *replace_filename( const char *path, const char *name )
483 const char *p;
484 char *ret;
485 size_t len;
487 if (!path) return xstrdup( name );
488 if (!(p = strrchr( path, '/' ))) return xstrdup( name );
489 len = p - path + 1;
490 ret = xmalloc( len + strlen( name ) + 1 );
491 memcpy( ret, path, len );
492 strcpy( ret + len, name );
493 return ret;
497 /*******************************************************************
498 * strarray_replace_extension
500 static struct strarray strarray_replace_extension( const struct strarray *array,
501 const char *old_ext, const char *new_ext )
503 unsigned int i;
504 struct strarray ret;
506 ret.count = ret.size = array->count;
507 ret.str = xmalloc( sizeof(ret.str[0]) * ret.size );
508 for (i = 0; i < array->count; i++) ret.str[i] = replace_extension( array->str[i], old_ext, new_ext );
509 return ret;
513 /*******************************************************************
514 * replace_substr
516 static char *replace_substr( const char *str, const char *start, size_t len, const char *replace )
518 size_t pos = start - str;
519 char *ret = xmalloc( pos + strlen(replace) + strlen(start + len) + 1 );
520 memcpy( ret, str, pos );
521 strcpy( ret + pos, replace );
522 strcat( ret + pos, start + len );
523 return ret;
527 /*******************************************************************
528 * get_relative_path
530 * Determine where the destination path is located relative to the 'from' path.
532 static char *get_relative_path( const char *from, const char *dest )
534 const char *start;
535 char *ret, *p;
536 unsigned int dotdots = 0;
538 /* a path of "." is equivalent to an empty path */
539 if (!strcmp( from, "." )) from = "";
541 for (;;)
543 while (*from == '/') from++;
544 while (*dest == '/') dest++;
545 start = dest; /* save start of next path element */
546 if (!*from) break;
548 while (*from && *from != '/' && *from == *dest) { from++; dest++; }
549 if ((!*from || *from == '/') && (!*dest || *dest == '/')) continue;
551 /* count remaining elements in 'from' */
554 dotdots++;
555 while (*from && *from != '/') from++;
556 while (*from == '/') from++;
558 while (*from);
559 break;
562 if (!start[0] && !dotdots) return NULL; /* empty path */
564 ret = xmalloc( 3 * dotdots + strlen( start ) + 1 );
565 for (p = ret; dotdots; dotdots--, p += 3) memcpy( p, "../", 3 );
567 if (start[0]) strcpy( p, start );
568 else p[-1] = 0; /* remove trailing slash */
569 return ret;
573 /*******************************************************************
574 * concat_paths
576 static char *concat_paths( const char *base, const char *path )
578 int i, len;
579 char *ret;
581 if (!base || !base[0]) return xstrdup( path && path[0] ? path : "." );
582 if (!path || !path[0]) return xstrdup( base );
583 if (path[0] == '/') return xstrdup( path );
585 len = strlen( base );
586 while (len && base[len - 1] == '/') len--;
587 while (len && !strncmp( path, "..", 2 ) && (!path[2] || path[2] == '/'))
589 for (i = len; i > 0; i--) if (base[i - 1] == '/') break;
590 if (i == len - 2 && !memcmp( base + i, "..", 2 )) break; /* we can't go up if we already have ".." */
591 if (i != len - 1 || base[i] != '.')
593 path += 2;
594 while (*path == '/') path++;
596 /* else ignore "." element */
597 while (i > 0 && base[i - 1] == '/') i--;
598 len = i;
600 if (!len && base[0] != '/') return xstrdup( path[0] ? path : "." );
601 ret = xmalloc( len + strlen( path ) + 2 );
602 memcpy( ret, base, len );
603 ret[len++] = '/';
604 strcpy( ret + len, path );
605 return ret;
609 /*******************************************************************
610 * obj_dir_path
612 static char *obj_dir_path( const struct makefile *make, const char *path )
614 return concat_paths( make->obj_dir, path );
618 /*******************************************************************
619 * src_dir_path
621 static char *src_dir_path( const struct makefile *make, const char *path )
623 if (make->src_dir) return concat_paths( make->src_dir, path );
624 return obj_dir_path( make, path );
628 /*******************************************************************
629 * root_src_dir_path
631 static char *root_src_dir_path( const char *path )
633 return concat_paths( root_src_dir, path );
637 /*******************************************************************
638 * tools_dir_path
640 static char *tools_dir_path( const struct makefile *make, const char *path )
642 if (tools_dir) return strmake( "%s/tools/%s", tools_dir, path );
643 return strmake( "tools/%s", path );
647 /*******************************************************************
648 * tools_path
650 static char *tools_path( const struct makefile *make, const char *name )
652 return strmake( "%s/%s%s", tools_dir_path( make, name ), name, tools_ext );
656 /*******************************************************************
657 * strarray_addall_path
659 static void strarray_addall_path( struct strarray *array, const char *dir, struct strarray added )
661 unsigned int i;
663 for (i = 0; i < added.count; i++) strarray_add( array, concat_paths( dir, added.str[i] ));
667 /*******************************************************************
668 * get_line
670 static char *get_line( FILE *file )
672 static char *buffer;
673 static size_t size;
675 if (!size)
677 size = 1024;
678 buffer = xmalloc( size );
680 if (!fgets( buffer, size, file )) return NULL;
681 input_line++;
683 for (;;)
685 char *p = buffer + strlen(buffer);
686 /* if line is larger than buffer, resize buffer */
687 while (p == buffer + size - 1 && p[-1] != '\n')
689 buffer = xrealloc( buffer, size * 2 );
690 if (!fgets( buffer + size - 1, size + 1, file )) break;
691 p = buffer + strlen(buffer);
692 size *= 2;
694 if (p > buffer && p[-1] == '\n')
696 *(--p) = 0;
697 if (p > buffer && p[-1] == '\r') *(--p) = 0;
698 if (p > buffer && p[-1] == '\\')
700 *(--p) = 0;
701 /* line ends in backslash, read continuation line */
702 if (!fgets( p, size - (p - buffer), file )) return buffer;
703 input_line++;
704 continue;
707 return buffer;
712 /*******************************************************************
713 * hash_filename
715 static unsigned int hash_filename( const char *name )
717 /* FNV-1 hash */
718 unsigned int ret = 2166136261u;
719 while (*name) ret = (ret * 16777619) ^ *name++;
720 return ret % HASH_SIZE;
724 /*******************************************************************
725 * add_file
727 static struct file *add_file( const char *name )
729 struct file *file = xmalloc( sizeof(*file) );
730 memset( file, 0, sizeof(*file) );
731 file->name = xstrdup( name );
732 return file;
736 /*******************************************************************
737 * add_dependency
739 static void add_dependency( struct file *file, const char *name, enum incl_type type )
741 if (file->deps_count >= file->deps_size)
743 file->deps_size *= 2;
744 if (file->deps_size < 16) file->deps_size = 16;
745 file->deps = xrealloc( file->deps, file->deps_size * sizeof(*file->deps) );
747 file->deps[file->deps_count].line = input_line;
748 file->deps[file->deps_count].type = type;
749 file->deps[file->deps_count].name = xstrdup( name );
750 file->deps_count++;
754 /*******************************************************************
755 * find_src_file
757 static struct incl_file *find_src_file( const struct makefile *make, const char *name )
759 struct incl_file *file;
761 LIST_FOR_EACH_ENTRY( file, &make->sources, struct incl_file, entry )
762 if (!strcmp( name, file->name )) return file;
763 return NULL;
766 /*******************************************************************
767 * find_include_file
769 static struct incl_file *find_include_file( const struct makefile *make, const char *name )
771 struct incl_file *file;
773 LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry )
774 if (!strcmp( name, file->name )) return file;
775 return NULL;
778 /*******************************************************************
779 * add_include
781 * Add an include file if it doesn't already exists.
783 static struct incl_file *add_include( struct makefile *make, struct incl_file *parent,
784 const char *name, int line, enum incl_type type )
786 struct incl_file *include;
788 if (parent->files_count >= parent->files_size)
790 parent->files_size *= 2;
791 if (parent->files_size < 16) parent->files_size = 16;
792 parent->files = xrealloc( parent->files, parent->files_size * sizeof(*parent->files) );
795 LIST_FOR_EACH_ENTRY( include, &make->includes, struct incl_file, entry )
796 if (!parent->use_msvcrt == !include->use_msvcrt && !strcmp( name, include->name ))
797 goto found;
799 include = xmalloc( sizeof(*include) );
800 memset( include, 0, sizeof(*include) );
801 include->name = xstrdup(name);
802 include->included_by = parent;
803 include->included_line = line;
804 include->type = type;
805 include->use_msvcrt = parent->use_msvcrt;
806 list_add_tail( &make->includes, &include->entry );
807 found:
808 parent->files[parent->files_count++] = include;
809 return include;
813 /*******************************************************************
814 * add_generated_source
816 * Add a generated source file to the list.
818 static struct incl_file *add_generated_source( struct makefile *make,
819 const char *name, const char *filename )
821 struct incl_file *file;
823 if ((file = find_src_file( make, name ))) return file; /* we already have it */
824 file = xmalloc( sizeof(*file) );
825 memset( file, 0, sizeof(*file) );
826 file->file = add_file( name );
827 file->name = xstrdup( name );
828 file->basename = xstrdup( filename ? filename : name );
829 file->filename = obj_dir_path( make, file->basename );
830 file->file->flags = FLAG_GENERATED;
831 file->use_msvcrt = make->use_msvcrt;
832 list_add_tail( &make->sources, &file->entry );
833 return file;
837 /*******************************************************************
838 * parse_include_directive
840 static void parse_include_directive( struct file *source, char *str )
842 char quote, *include, *p = str;
844 while (*p && isspace(*p)) p++;
845 if (*p != '\"' && *p != '<' ) return;
846 quote = *p++;
847 if (quote == '<') quote = '>';
848 include = p;
849 while (*p && (*p != quote)) p++;
850 if (!*p) fatal_error( "malformed include directive '%s'\n", str );
851 *p = 0;
852 add_dependency( source, include, (quote == '>') ? INCL_SYSTEM : INCL_NORMAL );
856 /*******************************************************************
857 * parse_pragma_directive
859 static void parse_pragma_directive( struct file *source, char *str )
861 char *flag, *p = str;
863 if (!isspace( *p )) return;
864 while (*p && isspace(*p)) p++;
865 p = strtok( p, " \t" );
866 if (strcmp( p, "makedep" )) return;
868 while ((flag = strtok( NULL, " \t" )))
870 if (!strcmp( flag, "depend" ))
872 while ((p = strtok( NULL, " \t" ))) add_dependency( source, p, INCL_NORMAL );
873 return;
875 else if (!strcmp( flag, "install" )) source->flags |= FLAG_INSTALL;
877 if (strendswith( source->name, ".idl" ))
879 if (!strcmp( flag, "header" )) source->flags |= FLAG_IDL_HEADER;
880 else if (!strcmp( flag, "proxy" )) source->flags |= FLAG_IDL_PROXY;
881 else if (!strcmp( flag, "client" )) source->flags |= FLAG_IDL_CLIENT;
882 else if (!strcmp( flag, "server" )) source->flags |= FLAG_IDL_SERVER;
883 else if (!strcmp( flag, "ident" )) source->flags |= FLAG_IDL_IDENT;
884 else if (!strcmp( flag, "typelib" )) source->flags |= FLAG_IDL_TYPELIB;
885 else if (!strcmp( flag, "register" )) source->flags |= FLAG_IDL_REGISTER;
886 else if (!strcmp( flag, "regtypelib" )) source->flags |= FLAG_IDL_REGTYPELIB;
888 else if (strendswith( source->name, ".rc" ))
890 if (!strcmp( flag, "po" )) source->flags |= FLAG_RC_PO;
892 else if (strendswith( source->name, ".sfd" ))
894 if (!strcmp( flag, "font" ))
896 struct strarray *array = source->args;
898 if (!array)
900 source->args = array = xmalloc( sizeof(*array) );
901 *array = empty_strarray;
902 source->flags |= FLAG_SFD_FONTS;
904 strarray_add( array, xstrdup( strtok( NULL, "" )));
905 return;
908 else
910 if (!strcmp( flag, "implib" )) source->flags |= FLAG_C_IMPLIB;
911 if (!strcmp( flag, "unix" )) source->flags |= FLAG_C_UNIX;
917 /*******************************************************************
918 * parse_cpp_directive
920 static void parse_cpp_directive( struct file *source, char *str )
922 while (*str && isspace(*str)) str++;
923 if (*str++ != '#') return;
924 while (*str && isspace(*str)) str++;
926 if (!strncmp( str, "include", 7 ))
927 parse_include_directive( source, str + 7 );
928 else if (!strncmp( str, "import", 6 ) && strendswith( source->name, ".m" ))
929 parse_include_directive( source, str + 6 );
930 else if (!strncmp( str, "pragma", 6 ))
931 parse_pragma_directive( source, str + 6 );
935 /*******************************************************************
936 * parse_idl_file
938 static void parse_idl_file( struct file *source, FILE *file )
940 char *buffer, *include;
942 input_line = 0;
944 while ((buffer = get_line( file )))
946 char quote;
947 char *p = buffer;
948 while (*p && isspace(*p)) p++;
950 if (!strncmp( p, "importlib", 9 ))
952 p += 9;
953 while (*p && isspace(*p)) p++;
954 if (*p++ != '(') continue;
955 while (*p && isspace(*p)) p++;
956 if (*p++ != '"') continue;
957 include = p;
958 while (*p && (*p != '"')) p++;
959 if (!*p) fatal_error( "malformed importlib directive\n" );
960 *p = 0;
961 add_dependency( source, include, INCL_IMPORTLIB );
962 continue;
965 if (!strncmp( p, "import", 6 ))
967 p += 6;
968 while (*p && isspace(*p)) p++;
969 if (*p != '"') continue;
970 include = ++p;
971 while (*p && (*p != '"')) p++;
972 if (!*p) fatal_error( "malformed import directive\n" );
973 *p = 0;
974 add_dependency( source, include, INCL_IMPORT );
975 continue;
978 /* check for #include inside cpp_quote */
979 if (!strncmp( p, "cpp_quote", 9 ))
981 p += 9;
982 while (*p && isspace(*p)) p++;
983 if (*p++ != '(') continue;
984 while (*p && isspace(*p)) p++;
985 if (*p++ != '"') continue;
986 if (*p++ != '#') continue;
987 while (*p && isspace(*p)) p++;
988 if (strncmp( p, "include", 7 )) continue;
989 p += 7;
990 while (*p && isspace(*p)) p++;
991 if (*p == '\\' && p[1] == '"')
993 p += 2;
994 quote = '"';
996 else
998 if (*p++ != '<' ) continue;
999 quote = '>';
1001 include = p;
1002 while (*p && (*p != quote)) p++;
1003 if (!*p || (quote == '"' && p[-1] != '\\'))
1004 fatal_error( "malformed #include directive inside cpp_quote\n" );
1005 if (quote == '"') p--; /* remove backslash */
1006 *p = 0;
1007 add_dependency( source, include, (quote == '>') ? INCL_CPP_QUOTE_SYSTEM : INCL_CPP_QUOTE );
1008 continue;
1011 parse_cpp_directive( source, p );
1015 /*******************************************************************
1016 * parse_c_file
1018 static void parse_c_file( struct file *source, FILE *file )
1020 char *buffer;
1022 input_line = 0;
1023 while ((buffer = get_line( file )))
1025 parse_cpp_directive( source, buffer );
1030 /*******************************************************************
1031 * parse_rc_file
1033 static void parse_rc_file( struct file *source, FILE *file )
1035 char *buffer, *include;
1037 input_line = 0;
1038 while ((buffer = get_line( file )))
1040 char quote;
1041 char *p = buffer;
1042 while (*p && isspace(*p)) p++;
1044 if (p[0] == '/' && p[1] == '*') /* check for magic makedep comment */
1046 p += 2;
1047 while (*p && isspace(*p)) p++;
1048 if (strncmp( p, "@makedep:", 9 )) continue;
1049 p += 9;
1050 while (*p && isspace(*p)) p++;
1051 quote = '"';
1052 if (*p == quote)
1054 include = ++p;
1055 while (*p && *p != quote) p++;
1057 else
1059 include = p;
1060 while (*p && !isspace(*p) && *p != '*') p++;
1062 if (!*p)
1063 fatal_error( "malformed makedep comment\n" );
1064 *p = 0;
1065 add_dependency( source, include, (quote == '>') ? INCL_SYSTEM : INCL_NORMAL );
1066 continue;
1069 parse_cpp_directive( source, buffer );
1074 /*******************************************************************
1075 * parse_in_file
1077 static void parse_in_file( struct file *source, FILE *file )
1079 char *p, *buffer;
1081 /* make sure it gets rebuilt when the version changes */
1082 add_dependency( source, "config.h", INCL_SYSTEM );
1084 if (!strendswith( source->name, ".man.in" )) return; /* not a man page */
1086 input_line = 0;
1087 while ((buffer = get_line( file )))
1089 if (strncmp( buffer, ".TH", 3 )) continue;
1090 if (!(p = strtok( buffer, " \t" ))) continue; /* .TH */
1091 if (!(p = strtok( NULL, " \t" ))) continue; /* program name */
1092 if (!(p = strtok( NULL, " \t" ))) continue; /* man section */
1093 source->args = xstrdup( p );
1094 return;
1099 /*******************************************************************
1100 * parse_sfd_file
1102 static void parse_sfd_file( struct file *source, FILE *file )
1104 char *p, *eol, *buffer;
1106 input_line = 0;
1107 while ((buffer = get_line( file )))
1109 if (strncmp( buffer, "UComments:", 10 )) continue;
1110 p = buffer + 10;
1111 while (*p == ' ') p++;
1112 if (p[0] == '"' && p[1] && buffer[strlen(buffer) - 1] == '"')
1114 p++;
1115 buffer[strlen(buffer) - 1] = 0;
1117 while ((eol = strstr( p, "+AAoA" )))
1119 *eol = 0;
1120 while (*p && isspace(*p)) p++;
1121 if (*p++ == '#')
1123 while (*p && isspace(*p)) p++;
1124 if (!strncmp( p, "pragma", 6 )) parse_pragma_directive( source, p + 6 );
1126 p = eol + 5;
1128 while (*p && isspace(*p)) p++;
1129 if (*p++ != '#') return;
1130 while (*p && isspace(*p)) p++;
1131 if (!strncmp( p, "pragma", 6 )) parse_pragma_directive( source, p + 6 );
1132 return;
1137 static const struct
1139 const char *ext;
1140 void (*parse)( struct file *file, FILE *f );
1141 } parse_functions[] =
1143 { ".c", parse_c_file },
1144 { ".h", parse_c_file },
1145 { ".inl", parse_c_file },
1146 { ".l", parse_c_file },
1147 { ".m", parse_c_file },
1148 { ".rh", parse_c_file },
1149 { ".x", parse_c_file },
1150 { ".y", parse_c_file },
1151 { ".idl", parse_idl_file },
1152 { ".rc", parse_rc_file },
1153 { ".in", parse_in_file },
1154 { ".sfd", parse_sfd_file }
1157 /*******************************************************************
1158 * load_file
1160 static struct file *load_file( const char *name )
1162 struct file *file;
1163 FILE *f;
1164 unsigned int i, hash = hash_filename( name );
1166 LIST_FOR_EACH_ENTRY( file, &files[hash], struct file, entry )
1167 if (!strcmp( name, file->name )) return file;
1169 if (!(f = fopen( name, "r" ))) return NULL;
1171 file = add_file( name );
1172 list_add_tail( &files[hash], &file->entry );
1173 input_file_name = file->name;
1174 input_line = 0;
1176 for (i = 0; i < sizeof(parse_functions) / sizeof(parse_functions[0]); i++)
1178 if (!strendswith( name, parse_functions[i].ext )) continue;
1179 parse_functions[i].parse( file, f );
1180 break;
1183 fclose( f );
1184 input_file_name = NULL;
1186 return file;
1190 /*******************************************************************
1191 * open_include_path_file
1193 * Open a file from a directory on the include path.
1195 static struct file *open_include_path_file( const struct makefile *make, const char *dir,
1196 const char *name, char **filename )
1198 char *src_path = concat_paths( dir, name );
1199 struct file *ret = load_file( src_path );
1201 if (ret) *filename = src_path;
1202 return ret;
1206 /*******************************************************************
1207 * open_file_same_dir
1209 * Open a file in the same directory as the parent.
1211 static struct file *open_file_same_dir( const struct incl_file *parent, const char *name, char **filename )
1213 char *src_path = replace_filename( parent->file->name, name );
1214 struct file *ret = load_file( src_path );
1216 if (ret) *filename = replace_filename( parent->filename, name );
1217 return ret;
1221 /*******************************************************************
1222 * open_local_file
1224 * Open a file in the source directory of the makefile.
1226 static struct file *open_local_file( const struct makefile *make, const char *path, char **filename )
1228 char *src_path = src_dir_path( make, path );
1229 struct file *ret = load_file( src_path );
1231 /* if not found, try parent dir */
1232 if (!ret && make->parent_dir)
1234 free( src_path );
1235 path = strmake( "%s/%s", make->parent_dir, path );
1236 src_path = src_dir_path( make, path );
1237 ret = load_file( src_path );
1240 if (ret) *filename = src_path;
1241 return ret;
1245 /*******************************************************************
1246 * open_global_file
1248 * Open a file in the top-level source directory.
1250 static struct file *open_global_file( const struct makefile *make, const char *path, char **filename )
1252 char *src_path = root_src_dir_path( path );
1253 struct file *ret = load_file( src_path );
1255 if (ret) *filename = src_path;
1256 return ret;
1260 /*******************************************************************
1261 * open_global_header
1263 * Open a file in the global include source directory.
1265 static struct file *open_global_header( const struct makefile *make, const char *path, char **filename )
1267 if (!strncmp( path, "../", 3 )) return NULL;
1268 return open_global_file( make, strmake( "include/%s", path ), filename );
1272 /*******************************************************************
1273 * open_src_file
1275 static struct file *open_src_file( const struct makefile *make, struct incl_file *pFile )
1277 struct file *file = open_local_file( make, pFile->name, &pFile->filename );
1279 if (!file) fatal_perror( "open %s", pFile->name );
1280 return file;
1284 /*******************************************************************
1285 * open_include_file
1287 static struct file *open_include_file( const struct makefile *make, struct incl_file *pFile )
1289 struct file *file = NULL;
1290 char *filename;
1291 unsigned int i, len;
1293 errno = ENOENT;
1295 /* check for generated bison header */
1297 if (strendswith( pFile->name, ".tab.h" ) &&
1298 (file = open_local_file( make, replace_extension( pFile->name, ".tab.h", ".y" ), &filename )))
1300 pFile->sourcename = filename;
1301 pFile->filename = obj_dir_path( make, pFile->name );
1302 return file;
1305 /* check for corresponding idl file in source dir */
1307 if (strendswith( pFile->name, ".h" ) &&
1308 (file = open_local_file( make, replace_extension( pFile->name, ".h", ".idl" ), &filename )))
1310 pFile->sourcename = filename;
1311 pFile->filename = obj_dir_path( make, pFile->name );
1312 return file;
1315 /* check for corresponding tlb file in source dir */
1317 if (strendswith( pFile->name, ".tlb" ) &&
1318 (file = open_local_file( make, replace_extension( pFile->name, ".tlb", ".idl" ), &filename )))
1320 pFile->sourcename = filename;
1321 pFile->filename = obj_dir_path( make, pFile->name );
1322 return file;
1325 /* check for extra targets */
1326 if (strarray_exists( &make->extra_targets, pFile->name ))
1328 pFile->sourcename = src_dir_path( make, pFile->name );
1329 pFile->filename = obj_dir_path( make, pFile->name );
1330 return NULL;
1333 /* now try in source dir */
1334 if ((file = open_local_file( make, pFile->name, &pFile->filename ))) return file;
1336 /* check for corresponding idl file in global includes */
1338 if (strendswith( pFile->name, ".h" ) &&
1339 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".idl" ), &filename )))
1341 pFile->sourcename = filename;
1342 pFile->filename = strmake( "include/%s", pFile->name );
1343 return file;
1346 /* check for corresponding .in file in global includes (for config.h.in) */
1348 if (strendswith( pFile->name, ".h" ) &&
1349 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".h.in" ), &filename )))
1351 pFile->sourcename = filename;
1352 pFile->filename = strmake( "include/%s", pFile->name );
1353 return file;
1356 /* check for corresponding .x file in global includes */
1358 if (strendswith( pFile->name, "tmpl.h" ) &&
1359 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".x" ), &filename )))
1361 pFile->sourcename = filename;
1362 pFile->filename = strmake( "include/%s", pFile->name );
1363 return file;
1366 /* check for corresponding .tlb file in global includes */
1368 if (strendswith( pFile->name, ".tlb" ) &&
1369 (file = open_global_header( make, replace_extension( pFile->name, ".tlb", ".idl" ), &filename )))
1371 pFile->sourcename = filename;
1372 pFile->filename = strmake( "include/%s", pFile->name );
1373 return file;
1376 /* check in global includes source dir */
1378 if ((file = open_global_header( make, pFile->name, &pFile->filename ))) return file;
1380 /* check in global msvcrt includes */
1381 if (pFile->use_msvcrt &&
1382 (file = open_global_header( make, strmake( "msvcrt/%s", pFile->name ), &pFile->filename )))
1383 return file;
1385 /* now search in include paths */
1386 for (i = 0; i < make->include_paths.count; i++)
1388 const char *dir = make->include_paths.str[i];
1390 if (root_src_dir)
1392 len = strlen( root_src_dir );
1393 if (!strncmp( dir, root_src_dir, len ) && (!dir[len] || dir[len] == '/'))
1395 while (dir[len] == '/') len++;
1396 file = open_global_file( make, concat_paths( dir + len, pFile->name ), &pFile->filename );
1399 else
1401 if (*dir == '/') continue;
1402 file = open_include_path_file( make, dir, pFile->name, &pFile->filename );
1404 if (!file) continue;
1405 pFile->is_external = 1;
1406 return file;
1409 if (pFile->type == INCL_SYSTEM && pFile->use_msvcrt &&
1410 !make->extlib && !pFile->included_by->is_external)
1412 if (!strcmp( pFile->name, "stdarg.h" )) return NULL;
1413 if (!strcmp( pFile->name, "x86intrin.h" )) return NULL;
1414 if (make->include_paths.count) return NULL;
1415 fprintf( stderr, "%s:%d: error: system header %s cannot be used with msvcrt\n",
1416 pFile->included_by->file->name, pFile->included_line, pFile->name );
1417 exit(1);
1420 if (pFile->type == INCL_SYSTEM) return NULL; /* ignore system files we cannot find */
1422 /* try in src file directory */
1423 if ((file = open_file_same_dir( pFile->included_by, pFile->name, &pFile->filename )))
1425 pFile->is_external = pFile->included_by->is_external;
1426 return file;
1429 if (make->extlib) return NULL; /* ignore missing files in external libs */
1431 fprintf( stderr, "%s:%d: error: ", pFile->included_by->file->name, pFile->included_line );
1432 perror( pFile->name );
1433 pFile = pFile->included_by;
1434 while (pFile && pFile->included_by)
1436 const char *parent = pFile->included_by->sourcename;
1437 if (!parent) parent = pFile->included_by->file->name;
1438 fprintf( stderr, "%s:%d: note: %s was first included here\n",
1439 parent, pFile->included_line, pFile->name );
1440 pFile = pFile->included_by;
1442 exit(1);
1446 /*******************************************************************
1447 * add_all_includes
1449 static void add_all_includes( struct makefile *make, struct incl_file *parent, struct file *file )
1451 unsigned int i;
1453 for (i = 0; i < file->deps_count; i++)
1455 switch (file->deps[i].type)
1457 case INCL_NORMAL:
1458 case INCL_IMPORT:
1459 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1460 break;
1461 case INCL_IMPORTLIB:
1462 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_IMPORTLIB );
1463 break;
1464 case INCL_SYSTEM:
1465 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_SYSTEM );
1466 break;
1467 case INCL_CPP_QUOTE:
1468 case INCL_CPP_QUOTE_SYSTEM:
1469 break;
1475 /*******************************************************************
1476 * parse_file
1478 static void parse_file( struct makefile *make, struct incl_file *source, int src )
1480 struct file *file = src ? open_src_file( make, source ) : open_include_file( make, source );
1482 if (!file) return;
1484 source->file = file;
1485 source->files_count = 0;
1486 source->files_size = file->deps_count;
1487 source->files = xmalloc( source->files_size * sizeof(*source->files) );
1488 if (file->flags & FLAG_C_UNIX) source->use_msvcrt = 0;
1489 else if (file->flags & FLAG_C_IMPLIB) source->use_msvcrt = 1;
1491 if (source->sourcename)
1493 if (strendswith( source->sourcename, ".idl" ))
1495 unsigned int i;
1497 if (strendswith( source->name, ".tlb" )) return; /* typelibs don't include anything */
1499 /* generated .h file always includes these */
1500 add_include( make, source, "rpc.h", 0, INCL_NORMAL );
1501 add_include( make, source, "rpcndr.h", 0, INCL_NORMAL );
1502 for (i = 0; i < file->deps_count; i++)
1504 switch (file->deps[i].type)
1506 case INCL_IMPORT:
1507 if (strendswith( file->deps[i].name, ".idl" ))
1508 add_include( make, source, replace_extension( file->deps[i].name, ".idl", ".h" ),
1509 file->deps[i].line, INCL_NORMAL );
1510 else
1511 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1512 break;
1513 case INCL_CPP_QUOTE:
1514 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1515 break;
1516 case INCL_CPP_QUOTE_SYSTEM:
1517 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_SYSTEM );
1518 break;
1519 case INCL_NORMAL:
1520 case INCL_SYSTEM:
1521 case INCL_IMPORTLIB:
1522 break;
1525 return;
1527 if (strendswith( source->sourcename, ".y" ))
1528 return; /* generated .tab.h doesn't include anything */
1531 add_all_includes( make, source, file );
1535 /*******************************************************************
1536 * add_src_file
1538 * Add a source file to the list.
1540 static struct incl_file *add_src_file( struct makefile *make, const char *name )
1542 struct incl_file *file;
1544 if ((file = find_src_file( make, name ))) return file; /* we already have it */
1545 file = xmalloc( sizeof(*file) );
1546 memset( file, 0, sizeof(*file) );
1547 file->name = xstrdup(name);
1548 file->use_msvcrt = make->use_msvcrt;
1549 file->is_external = !!make->extlib;
1550 list_add_tail( &make->sources, &file->entry );
1551 parse_file( make, file, 1 );
1552 return file;
1556 /*******************************************************************
1557 * open_input_makefile
1559 static FILE *open_input_makefile( const struct makefile *make )
1561 FILE *ret;
1563 if (make->obj_dir)
1564 input_file_name = root_src_dir_path( obj_dir_path( make, strmake( "%s.in", output_makefile_name )));
1565 else
1566 input_file_name = output_makefile_name; /* always use output name for main Makefile */
1568 input_line = 0;
1569 if (!(ret = fopen( input_file_name, "r" ))) fatal_perror( "open" );
1570 return ret;
1574 /*******************************************************************
1575 * get_make_variable
1577 static const char *get_make_variable( const struct makefile *make, const char *name )
1579 const char *ret;
1581 if ((ret = strarray_get_value( &cmdline_vars, name ))) return ret;
1582 if ((ret = strarray_get_value( &make->vars, name ))) return ret;
1583 if (top_makefile && (ret = strarray_get_value( &top_makefile->vars, name ))) return ret;
1584 return NULL;
1588 /*******************************************************************
1589 * get_expanded_make_variable
1591 static char *get_expanded_make_variable( const struct makefile *make, const char *name )
1593 const char *var;
1594 char *p, *end, *expand, *tmp;
1596 var = get_make_variable( make, name );
1597 if (!var) return NULL;
1599 p = expand = xstrdup( var );
1600 while ((p = strchr( p, '$' )))
1602 if (p[1] == '(')
1604 if (!(end = strchr( p + 2, ')' ))) fatal_error( "syntax error in '%s'\n", expand );
1605 *end++ = 0;
1606 if (strchr( p + 2, ':' )) fatal_error( "pattern replacement not supported for '%s'\n", p + 2 );
1607 var = get_make_variable( make, p + 2 );
1608 tmp = replace_substr( expand, p, end - p, var ? var : "" );
1609 /* switch to the new string */
1610 p = tmp + (p - expand);
1611 free( expand );
1612 expand = tmp;
1614 else if (p[1] == '{') /* don't expand ${} variables */
1616 if (!(end = strchr( p + 2, '}' ))) fatal_error( "syntax error in '%s'\n", expand );
1617 p = end + 1;
1619 else if (p[1] == '$')
1621 p += 2;
1623 else fatal_error( "syntax error in '%s'\n", expand );
1626 /* consider empty variables undefined */
1627 p = expand;
1628 while (*p && isspace(*p)) p++;
1629 if (*p) return expand;
1630 free( expand );
1631 return NULL;
1635 /*******************************************************************
1636 * get_expanded_make_var_array
1638 static struct strarray get_expanded_make_var_array( const struct makefile *make, const char *name )
1640 struct strarray ret = empty_strarray;
1641 char *value, *token;
1643 if ((value = get_expanded_make_variable( make, name )))
1644 for (token = strtok( value, " \t" ); token; token = strtok( NULL, " \t" ))
1645 strarray_add( &ret, token );
1646 return ret;
1650 /*******************************************************************
1651 * get_expanded_file_local_var
1653 static struct strarray get_expanded_file_local_var( const struct makefile *make, const char *file,
1654 const char *name )
1656 char *p, *var = strmake( "%s_%s", file, name );
1658 for (p = var; *p; p++) if (!isalnum( *p )) *p = '_';
1659 return get_expanded_make_var_array( make, var );
1663 /*******************************************************************
1664 * set_make_variable
1666 static int set_make_variable( struct strarray *array, const char *assignment )
1668 char *p, *name;
1670 p = name = xstrdup( assignment );
1671 while (isalnum(*p) || *p == '_') p++;
1672 if (name == p) return 0; /* not a variable */
1673 if (isspace(*p))
1675 *p++ = 0;
1676 while (isspace(*p)) p++;
1678 if (*p != '=') return 0; /* not an assignment */
1679 *p++ = 0;
1680 while (isspace(*p)) p++;
1682 strarray_set_value( array, name, p );
1683 return 1;
1687 /*******************************************************************
1688 * parse_makefile
1690 static struct makefile *parse_makefile( const char *path )
1692 char *buffer;
1693 FILE *file;
1694 struct makefile *make = xmalloc( sizeof(*make) );
1696 memset( make, 0, sizeof(*make) );
1697 make->obj_dir = path;
1698 if (root_src_dir) make->src_dir = root_src_dir_path( make->obj_dir );
1700 file = open_input_makefile( make );
1701 while ((buffer = get_line( file )))
1703 if (!strncmp( buffer, separator, strlen(separator) )) break;
1704 if (*buffer == '\t') continue; /* command */
1705 while (isspace( *buffer )) buffer++;
1706 if (*buffer == '#') continue; /* comment */
1707 set_make_variable( &make->vars, buffer );
1709 fclose( file );
1710 input_file_name = NULL;
1711 return make;
1715 /*******************************************************************
1716 * add_generated_sources
1718 static void add_generated_sources( struct makefile *make )
1720 unsigned int i;
1721 struct incl_file *source, *next, *file;
1722 struct strarray objs = get_expanded_make_var_array( make, "EXTRA_OBJS" );
1724 LIST_FOR_EACH_ENTRY_SAFE( source, next, &make->sources, struct incl_file, entry )
1726 if (source->file->flags & FLAG_IDL_CLIENT)
1728 file = add_generated_source( make, replace_extension( source->name, ".idl", "_c.c" ), NULL );
1729 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1730 add_all_includes( make, file, file->file );
1732 if (source->file->flags & FLAG_IDL_SERVER)
1734 file = add_generated_source( make, replace_extension( source->name, ".idl", "_s.c" ), NULL );
1735 add_dependency( file->file, "wine/exception.h", INCL_NORMAL );
1736 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1737 add_all_includes( make, file, file->file );
1739 if (source->file->flags & FLAG_IDL_IDENT)
1741 file = add_generated_source( make, replace_extension( source->name, ".idl", "_i.c" ), NULL );
1742 add_dependency( file->file, "rpc.h", INCL_NORMAL );
1743 add_dependency( file->file, "rpcndr.h", INCL_NORMAL );
1744 add_dependency( file->file, "guiddef.h", INCL_NORMAL );
1745 add_all_includes( make, file, file->file );
1747 if (source->file->flags & FLAG_IDL_PROXY)
1749 file = add_generated_source( make, "dlldata.o", "dlldata.c" );
1750 add_dependency( file->file, "objbase.h", INCL_NORMAL );
1751 add_dependency( file->file, "rpcproxy.h", INCL_NORMAL );
1752 add_all_includes( make, file, file->file );
1753 file = add_generated_source( make, replace_extension( source->name, ".idl", "_p.c" ), NULL );
1754 add_dependency( file->file, "objbase.h", INCL_NORMAL );
1755 add_dependency( file->file, "rpcproxy.h", INCL_NORMAL );
1756 add_dependency( file->file, "wine/exception.h", INCL_NORMAL );
1757 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1758 add_all_includes( make, file, file->file );
1760 if (source->file->flags & FLAG_IDL_TYPELIB)
1762 add_generated_source( make, replace_extension( source->name, ".idl", ".tlb" ), NULL );
1764 if (source->file->flags & FLAG_IDL_REGTYPELIB)
1766 add_generated_source( make, replace_extension( source->name, ".idl", "_t.res" ), NULL );
1768 if (source->file->flags & FLAG_IDL_REGISTER)
1770 add_generated_source( make, replace_extension( source->name, ".idl", "_r.res" ), NULL );
1772 if (source->file->flags & FLAG_IDL_HEADER)
1774 add_generated_source( make, replace_extension( source->name, ".idl", ".h" ), NULL );
1776 if (!source->file->flags && strendswith( source->name, ".idl" ))
1778 add_generated_source( make, replace_extension( source->name, ".idl", ".h" ), NULL );
1780 if (strendswith( source->name, ".x" ))
1782 add_generated_source( make, replace_extension( source->name, ".x", ".h" ), NULL );
1784 if (strendswith( source->name, ".y" ))
1786 file = add_generated_source( make, replace_extension( source->name, ".y", ".tab.c" ), NULL );
1787 /* steal the includes list from the source file */
1788 file->files_count = source->files_count;
1789 file->files_size = source->files_size;
1790 file->files = source->files;
1791 source->files_count = source->files_size = 0;
1792 source->files = NULL;
1794 if (strendswith( source->name, ".l" ))
1796 file = add_generated_source( make, replace_extension( source->name, ".l", ".yy.c" ), NULL );
1797 /* steal the includes list from the source file */
1798 file->files_count = source->files_count;
1799 file->files_size = source->files_size;
1800 file->files = source->files;
1801 source->files_count = source->files_size = 0;
1802 source->files = NULL;
1804 if (source->file->flags & FLAG_C_IMPLIB)
1806 if (!make->staticimplib && make->importlib && *dll_ext)
1807 make->staticimplib = strmake( "lib%s.a", make->importlib );
1809 if (strendswith( source->name, ".po" ))
1811 if (!make->disabled)
1812 strarray_add_uniq( &linguas, replace_extension( source->name, ".po", "" ));
1814 if (strendswith( source->name, ".spec" ))
1816 char *obj = replace_extension( source->name, ".spec", "" );
1817 strarray_addall_uniq( &make->extra_imports,
1818 get_expanded_file_local_var( make, obj, "IMPORTS" ));
1821 if (make->testdll)
1823 file = add_generated_source( make, "testlist.o", "testlist.c" );
1824 add_dependency( file->file, "wine/test.h", INCL_NORMAL );
1825 add_all_includes( make, file, file->file );
1827 for (i = 0; i < objs.count; i++)
1829 /* default to .c for unknown extra object files */
1830 if (strendswith( objs.str[i], ".o" ))
1832 file = add_generated_source( make, objs.str[i], replace_extension( objs.str[i], ".o", ".c" ));
1833 file->file->flags |= FLAG_C_UNIX;
1834 file->use_msvcrt = 0;
1836 else if (strendswith( objs.str[i], ".res" ))
1837 add_generated_source( make, replace_extension( objs.str[i], ".res", ".rc" ), NULL );
1838 else
1839 add_generated_source( make, objs.str[i], NULL );
1844 /*******************************************************************
1845 * create_dir
1847 static void create_dir( const char *dir )
1849 char *p, *path;
1851 p = path = xstrdup( dir );
1852 while ((p = strchr( p, '/' )))
1854 *p = 0;
1855 if (mkdir( path, 0755 ) == -1 && errno != EEXIST) fatal_perror( "mkdir %s", path );
1856 *p++ = '/';
1857 while (*p == '/') p++;
1859 if (mkdir( path, 0755 ) == -1 && errno != EEXIST) fatal_perror( "mkdir %s", path );
1860 free( path );
1864 /*******************************************************************
1865 * create_file_directories
1867 * Create the base directories of all the files.
1869 static void create_file_directories( const struct makefile *make, struct strarray files )
1871 struct strarray subdirs = empty_strarray;
1872 unsigned int i;
1873 char *dir;
1875 for (i = 0; i < files.count; i++)
1877 if (!strchr( files.str[i], '/' )) continue;
1878 dir = obj_dir_path( make, files.str[i] );
1879 *strrchr( dir, '/' ) = 0;
1880 strarray_add_uniq( &subdirs, dir );
1883 for (i = 0; i < subdirs.count; i++) create_dir( subdirs.str[i] );
1887 /*******************************************************************
1888 * output_filenames_obj_dir
1890 static void output_filenames_obj_dir( const struct makefile *make, struct strarray array )
1892 unsigned int i;
1894 for (i = 0; i < array.count; i++) output_filename( obj_dir_path( make, array.str[i] ));
1898 /*******************************************************************
1899 * get_dependencies
1901 static void get_dependencies( struct incl_file *file, struct incl_file *source )
1903 unsigned int i;
1905 if (!file->filename) return;
1907 if (file != source)
1909 if (file->owner == source) return; /* already processed */
1910 if (file->type == INCL_IMPORTLIB &&
1911 !(source->file->flags & (FLAG_IDL_TYPELIB | FLAG_IDL_REGTYPELIB)))
1912 return; /* library is imported only when building a typelib */
1913 file->owner = source;
1914 strarray_add( &source->dependencies, file->filename );
1916 /* sanity checks */
1917 if (!strcmp( file->filename, "include/config.h" ) &&
1918 file != source->files[0] && !source->is_external)
1920 input_file_name = source->filename;
1921 input_line = 0;
1922 for (i = 0; i < source->file->deps_count; i++)
1924 if (!strcmp( source->file->deps[i].name, file->name ))
1925 input_line = source->file->deps[i].line;
1927 fatal_error( "%s must be included before other headers\n", file->name );
1931 for (i = 0; i < file->files_count; i++) get_dependencies( file->files[i], source );
1935 /*******************************************************************
1936 * get_local_dependencies
1938 * Get the local dependencies of a given target.
1940 static struct strarray get_local_dependencies( const struct makefile *make, const char *name,
1941 struct strarray targets )
1943 unsigned int i;
1944 struct strarray deps = get_expanded_file_local_var( make, name, "DEPS" );
1946 for (i = 0; i < deps.count; i++)
1948 if (strarray_exists( &targets, deps.str[i] ))
1949 deps.str[i] = obj_dir_path( make, deps.str[i] );
1950 else
1951 deps.str[i] = src_dir_path( make, deps.str[i] );
1953 return deps;
1957 /*******************************************************************
1958 * get_static_lib
1960 * Check if makefile builds the named static library and return the full lib path.
1962 static const char *get_static_lib( const struct makefile *make, const char *name )
1964 if (!make->staticlib) return NULL;
1965 if (make->disabled) return NULL;
1966 if (strncmp( make->staticlib, "lib", 3 )) return NULL;
1967 if (strncmp( make->staticlib + 3, name, strlen(name) )) return NULL;
1968 if (strcmp( make->staticlib + 3 + strlen(name), ".a" )) return NULL;
1969 return obj_dir_path( make, make->staticlib );
1973 /*******************************************************************
1974 * get_native_unix_lib
1976 static const char *get_native_unix_lib( const struct makefile *make, const char *name )
1978 if (!make->native_unix_lib) return NULL;
1979 if (strncmp( make->unixlib, name, strlen(name) )) return NULL;
1980 if (make->unixlib[strlen(name)] != '.') return NULL;
1981 return obj_dir_path( make, make->unixlib );
1985 /*******************************************************************
1986 * get_parent_makefile
1988 static struct makefile *get_parent_makefile( struct makefile *make )
1990 char *dir, *p;
1991 int i;
1993 if (!make->obj_dir) return NULL;
1994 dir = xstrdup( make->obj_dir );
1995 if (!(p = strrchr( dir, '/' ))) return NULL;
1996 *p = 0;
1997 for (i = 0; i < subdirs.count; i++)
1998 if (!strcmp( submakes[i]->obj_dir, dir )) return submakes[i];
1999 return NULL;
2003 /*******************************************************************
2004 * needs_delay_lib
2006 static int needs_delay_lib( const struct makefile *make )
2008 if (delay_load_flag) return 0;
2009 if (*dll_ext && !crosstarget) return 0;
2010 if (!make->importlib) return 0;
2011 return strarray_exists( &delay_import_libs, make->importlib );
2015 /*******************************************************************
2016 * needs_implib_symlink
2018 static int needs_implib_symlink( const struct makefile *make )
2020 if (!make->module) return 0;
2021 if (!make->importlib) return 0;
2022 if (make->is_win16 && make->disabled) return 0;
2023 if (strncmp( make->obj_dir, "dlls/", 5 )) return 0;
2024 if (!strcmp( make->module, make->importlib )) return 0;
2025 if (!strchr( make->importlib, '.' ) &&
2026 !strncmp( make->module, make->importlib, strlen( make->importlib )) &&
2027 !strcmp( make->module + strlen( make->importlib ), ".dll" ))
2028 return 0;
2029 return 1;
2033 /*******************************************************************
2034 * add_unix_libraries
2036 static struct strarray add_unix_libraries( const struct makefile *make, struct strarray *deps )
2038 struct strarray ret = empty_strarray;
2039 struct strarray all_libs = empty_strarray;
2040 unsigned int i, j;
2042 if (make->native_unix_lib && strcmp( make->unixlib, "ntdll.so" )) strarray_add( &all_libs, "-lntdll" );
2043 strarray_addall( &all_libs, get_expanded_make_var_array( make, "EXTRALIBS" ));
2044 strarray_addall( &all_libs, libs );
2046 for (i = 0; i < all_libs.count; i++)
2048 const char *lib = NULL;
2050 if (!strncmp( all_libs.str[i], "-l", 2 ))
2052 const char *name = all_libs.str[i] + 2;
2054 for (j = 0; j < subdirs.count; j++)
2056 if (make == submakes[j]) continue;
2057 if ((lib = get_static_lib( submakes[j], name ))) break;
2059 if (!lib && make->native_unix_lib)
2060 for (j = 0; j < subdirs.count; j++)
2062 if (make == submakes[j]) continue;
2063 if ((lib = get_native_unix_lib( submakes[j], name ))) break;
2067 if (lib)
2069 strarray_add( deps, lib );
2070 strarray_add( &ret, lib );
2072 else strarray_add( &ret, all_libs.str[i] );
2074 return ret;
2078 /*******************************************************************
2079 * add_import_libs
2081 static struct strarray add_import_libs( const struct makefile *make, struct strarray *deps,
2082 struct strarray imports, int delay, int is_unix )
2084 struct strarray ret = empty_strarray;
2085 unsigned int i, j;
2086 int is_cross = make->is_cross && !is_unix;
2088 for (i = 0; i < imports.count; i++)
2090 const char *name = imports.str[i];
2091 const char *lib = NULL;
2093 if (name[0] == '-')
2095 switch (name[1])
2097 case 'L': strarray_add( &ret, name ); continue;
2098 case 'l': name += 2; break;
2099 default: continue;
2102 else name = get_base_name( name );
2104 for (j = 0; j < subdirs.count; j++)
2106 if (submakes[j]->importlib && !strcmp( submakes[j]->importlib, name ))
2108 if (is_cross || !*dll_ext || submakes[j]->staticimplib)
2109 lib = obj_dir_path( submakes[j], strmake( "lib%s.a", name ));
2110 else
2112 strarray_add( deps, strmake( "%s/lib%s.def", submakes[j]->obj_dir, name ));
2113 if (needs_implib_symlink( submakes[j] ))
2114 strarray_add( deps, strmake( "dlls/lib%s.def", name ));
2116 break;
2119 if ((lib = get_static_lib( submakes[j], name ))) break;
2122 if (lib)
2124 const char *ext = NULL;
2126 if (delay && !delay_load_flag && (is_cross || !*dll_ext)) ext = ".delay.a";
2127 else if (is_cross) ext = ".cross.a";
2128 if (ext) lib = replace_extension( lib, ".a", ext );
2129 strarray_add( deps, lib );
2130 strarray_add( &ret, lib );
2131 if (needs_implib_symlink( submakes[j] ))
2132 strarray_add( deps, strmake( "dlls/lib%s%s", name, ext ? ext : ".a" ));
2134 else strarray_add( &ret, strmake( "-l%s", name ));
2136 return ret;
2140 /*******************************************************************
2141 * get_default_imports
2143 static struct strarray get_default_imports( const struct makefile *make )
2145 struct strarray ret = empty_strarray;
2147 if (strarray_exists( &make->extradllflags, "-nodefaultlibs" )) return ret;
2148 strarray_add( &ret, "winecrt0" );
2149 if (make->is_win16) strarray_add( &ret, "kernel" );
2150 strarray_add( &ret, "kernel32" );
2151 strarray_add( &ret, "ntdll" );
2152 return ret;
2156 /*******************************************************************
2157 * is_crt_module
2159 static int is_crt_module( const char *file )
2161 return !strncmp( file, "msvcr", 5 ) || !strncmp( file, "ucrt", 4 ) || !strcmp( file, "crtdll.dll" );
2165 /*******************************************************************
2166 * add_crt_import
2168 static void add_crt_import( const struct makefile *make, struct strarray *imports, struct strarray *defs )
2170 unsigned int i;
2171 const char *crt_dll = NULL;
2173 for (i = 0; i < imports->count; i++)
2175 if (!is_crt_module( imports->str[i])) continue;
2176 if (crt_dll) fatal_error( "More than one C runtime DLL imported: %s and %s\n", crt_dll, imports->str[i] );
2177 crt_dll = imports->str[i];
2179 if (!crt_dll && !strarray_exists( &make->extradllflags, "-nodefaultlibs" ))
2181 if (make->module && is_crt_module( make->module ))
2183 crt_dll = make->module;
2185 else
2187 crt_dll = !make->testdll && (!make->staticlib || make->extlib) ? "ucrtbase" : "msvcrt";
2188 strarray_add( imports, crt_dll );
2192 if (!defs) return;
2193 if (crt_dll && !strncmp( crt_dll, "ucrt", 4 )) strarray_add( defs, "-D_UCRT" );
2194 else
2196 unsigned int version = 0;
2197 if (crt_dll) sscanf( crt_dll, "msvcr%u", &version );
2198 strarray_add( defs, strmake( "-D_MSVCR_VER=%u", version ));
2203 /*******************************************************************
2204 * add_install_rule
2206 static void add_install_rule( struct makefile *make, const char *target,
2207 const char *file, const char *dest )
2209 if (strarray_exists( &make->install_lib, target ) ||
2210 strarray_exists( &top_install_lib, make->obj_dir ) ||
2211 strarray_exists( &top_install_lib, obj_dir_path( make, target )))
2213 strarray_add( &make->install_rules[INSTALL_LIB], file );
2214 strarray_add( &make->install_rules[INSTALL_LIB], dest );
2216 else if (strarray_exists( &make->install_dev, target ) ||
2217 strarray_exists( &top_install_dev, make->obj_dir ) ||
2218 strarray_exists( &top_install_dev, obj_dir_path( make, target )))
2220 strarray_add( &make->install_rules[INSTALL_DEV], file );
2221 strarray_add( &make->install_rules[INSTALL_DEV], dest );
2226 /*******************************************************************
2227 * get_include_install_path
2229 * Determine the installation path for a given include file.
2231 static const char *get_include_install_path( const char *name )
2233 if (!strncmp( name, "wine/", 5 )) return name + 5;
2234 if (!strncmp( name, "msvcrt/", 7 )) return name;
2235 return strmake( "windows/%s", name );
2239 /*******************************************************************
2240 * get_shared_library_name
2242 * Determine possible names for a shared library with a version number.
2244 static struct strarray get_shared_lib_names( const char *libname )
2246 struct strarray ret = empty_strarray;
2247 const char *ext, *p;
2248 char *name, *first, *second;
2249 size_t len = 0;
2251 strarray_add( &ret, libname );
2253 for (p = libname; (p = strchr( p, '.' )); p++)
2254 if ((len = strspn( p + 1, "0123456789." ))) break;
2256 if (!len) return ret;
2257 ext = p + 1 + len;
2258 if (*ext && ext[-1] == '.') ext--;
2260 /* keep only the first group of digits */
2261 name = xstrdup( libname );
2262 first = name + (p - libname);
2263 if ((second = strchr( first + 1, '.' )))
2265 strcpy( second, ext );
2266 strarray_add( &ret, xstrdup( name ));
2268 return ret;
2272 /*******************************************************************
2273 * get_source_defines
2275 static struct strarray get_source_defines( struct makefile *make, struct incl_file *source,
2276 const char *obj )
2278 unsigned int i;
2279 struct strarray ret = empty_strarray;
2281 strarray_addall( &ret, make->include_args );
2282 if (source->use_msvcrt)
2283 strarray_add( &ret, strmake( "-I%s", root_src_dir_path( "include/msvcrt" )));
2284 for (i = 0; i < make->include_paths.count; i++)
2285 strarray_add( &ret, strmake( "-I%s", make->include_paths.str[i] ));
2286 strarray_addall( &ret, make->define_args );
2287 strarray_addall( &ret, get_expanded_file_local_var( make, obj, "EXTRADEFS" ));
2288 if ((source->file->flags & FLAG_C_UNIX) && *dll_ext) strarray_add( &ret, "-DWINE_UNIX_LIB" );
2289 return ret;
2293 /*******************************************************************
2294 * remove_warning_flags
2296 static struct strarray remove_warning_flags( struct strarray flags )
2298 unsigned int i;
2299 struct strarray ret = empty_strarray;
2301 for (i = 0; i < flags.count; i++)
2302 if (strncmp( flags.str[i], "-W", 2 ) || !strncmp( flags.str[i], "-Wno-", 5 ))
2303 strarray_add( &ret, flags.str[i] );
2304 return ret;
2308 /*******************************************************************
2309 * get_debug_file
2311 static const char *get_debug_file( struct makefile *make, const char *name )
2313 const char *debug_file = NULL;
2314 if (!make->is_cross || !crossdebug) return NULL;
2315 if (!strcmp( crossdebug, "pdb" )) debug_file = strmake( "%s.pdb", get_base_name( name ));
2316 else if(!strncmp( crossdebug, "split", 5 )) debug_file = strmake( "%s.debug", name );
2317 if (debug_file) strarray_add( &make->debug_files, debug_file );
2318 return debug_file;
2322 /*******************************************************************
2323 * cmd_prefix
2325 static const char *cmd_prefix( const char *cmd )
2327 if (!silent_rules) return "";
2328 return strmake( "$(quiet_%s)", cmd );
2332 /*******************************************************************
2333 * output_winegcc_command
2335 static void output_winegcc_command( struct makefile *make, int is_cross )
2337 output( "\t%s%s -o $@", cmd_prefix( "CCLD" ), tools_path( make, "winegcc" ));
2338 output_filename( "--wine-objdir ." );
2339 if (tools_dir)
2341 output_filename( "--winebuild" );
2342 output_filename( tools_path( make, "winebuild" ));
2344 if (is_cross)
2346 output_filename( "-b" );
2347 output_filename( crosstarget );
2348 output_filename( "--lib-suffix=.cross.a" );
2350 else
2352 output_filenames( target_flags );
2353 output_filenames( lddll_flags );
2358 /*******************************************************************
2359 * output_symlink_rule
2361 * Output a rule to create a symlink.
2363 static void output_symlink_rule( const char *src_name, const char *link_name, int create_dir )
2365 const char *name = strrchr( link_name, '/' );
2366 char *dir = NULL;
2368 if (name)
2370 dir = xstrdup( link_name );
2371 dir[name - link_name] = 0;
2374 output( "\t%s", cmd_prefix( "LN" ));
2375 if (create_dir && dir && *dir) output( "%s -d %s && ", root_src_dir_path( "tools/install-sh" ), dir );
2376 output( "rm -f %s && ", link_name );
2378 /* dest path with a directory needs special handling if ln -s isn't supported */
2379 if (dir && strcmp( ln_s, "ln -s" ))
2380 output( "cd %s && %s %s %s\n", *dir ? dir : "/", ln_s, src_name, name + 1 );
2381 else
2382 output( "%s %s %s\n", ln_s, src_name, link_name );
2384 free( dir );
2388 /*******************************************************************
2389 * output_srcdir_symlink
2391 * Output rule to create a symlink back to the source directory, for source files
2392 * that are needed at run-time.
2394 static void output_srcdir_symlink( struct makefile *make, const char *obj )
2396 char *src_file, *dst_file, *src_name;
2398 if (!make->src_dir) return;
2399 src_file = src_dir_path( make, obj );
2400 dst_file = obj_dir_path( make, obj );
2401 output( "%s: %s\n", dst_file, src_file );
2403 src_name = src_file;
2404 if (src_name[0] != '/' && make->obj_dir)
2405 src_name = concat_paths( get_relative_path( make->obj_dir, "" ), src_name );
2407 output_symlink_rule( src_name, dst_file, 0 );
2408 strarray_add( &make->all_targets, obj );
2412 /*******************************************************************
2413 * output_install_commands
2415 static void output_install_commands( struct makefile *make, struct strarray files )
2417 unsigned int i;
2418 char *install_sh = root_src_dir_path( "tools/install-sh" );
2420 for (i = 0; i < files.count; i += 2)
2422 const char *file = files.str[i];
2423 const char *dest = strmake( "$(DESTDIR)%s", files.str[i + 1] + 1 );
2425 switch (*files.str[i + 1])
2427 case 'c': /* cross-compiled program */
2428 output( "\tSTRIPPROG=%s-strip %s -m 644 $(INSTALL_PROGRAM_FLAGS) %s %s\n",
2429 crosstarget, install_sh, obj_dir_path( make, file ), dest );
2430 output( "\t%s --builtin %s\n", tools_path( make, "winebuild" ), dest );
2431 break;
2432 case 'd': /* data file */
2433 output( "\t%s -m 644 $(INSTALL_DATA_FLAGS) %s %s\n",
2434 install_sh, obj_dir_path( make, file ), dest );
2435 break;
2436 case 'D': /* data file in source dir */
2437 output( "\t%s -m 644 $(INSTALL_DATA_FLAGS) %s %s\n",
2438 install_sh, src_dir_path( make, file ), dest );
2439 break;
2440 case 'p': /* program file */
2441 output( "\tSTRIPPROG=\"$(STRIP)\" %s $(INSTALL_PROGRAM_FLAGS) %s %s\n",
2442 install_sh, obj_dir_path( make, file ), dest );
2443 break;
2444 case 's': /* script */
2445 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2446 install_sh, obj_dir_path( make, file ), dest );
2447 break;
2448 case 'S': /* script in source dir */
2449 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2450 install_sh, src_dir_path( make, file ), dest );
2451 break;
2452 case 't': /* script in tools dir */
2453 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2454 install_sh, tools_dir_path( make, files.str[i] ), dest );
2455 break;
2456 case 'y': /* symlink */
2457 output_symlink_rule( files.str[i], dest, 1 );
2458 break;
2459 default:
2460 assert(0);
2462 strarray_add( &make->uninstall_files, dest );
2467 /*******************************************************************
2468 * output_install_rules
2470 * Rules are stored as a (file,dest) pair of values.
2471 * The first char of dest indicates the type of install.
2473 static void output_install_rules( struct makefile *make, enum install_rules rules, const char *target )
2475 unsigned int i;
2476 struct strarray files = make->install_rules[rules];
2477 struct strarray targets = empty_strarray;
2479 if (!files.count) return;
2481 for (i = 0; i < files.count; i += 2)
2483 const char *file = files.str[i];
2484 switch (*files.str[i + 1])
2486 case 'c': /* cross-compiled program */
2487 case 'd': /* data file */
2488 case 'p': /* program file */
2489 case 's': /* script */
2490 strarray_add_uniq( &targets, obj_dir_path( make, file ));
2491 break;
2492 case 't': /* script in tools dir */
2493 strarray_add_uniq( &targets, tools_dir_path( make, file ));
2494 break;
2498 output( "%s %s::", obj_dir_path( make, "install" ), obj_dir_path( make, target ));
2499 output_filenames( targets );
2500 output( "\n" );
2501 output_install_commands( make, files );
2502 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "install" ));
2503 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, target ));
2507 static int cmp_string_length( const char **a, const char **b )
2509 int paths_a = 0, paths_b = 0;
2510 const char *p;
2512 for (p = *a; *p; p++) if (*p == '/') paths_a++;
2513 for (p = *b; *p; p++) if (*p == '/') paths_b++;
2514 if (paths_b != paths_a) return paths_b - paths_a;
2515 return strcmp( *a, *b );
2518 /*******************************************************************
2519 * output_uninstall_rules
2521 static void output_uninstall_rules( struct makefile *make )
2523 static const char *dirs_order[] =
2524 { "$(includedir)", "$(mandir)", "$(fontdir)", "$(nlsdir)", "$(datadir)", "$(dlldir)" };
2526 struct strarray uninstall_dirs = empty_strarray;
2527 unsigned int i, j;
2529 if (!make->uninstall_files.count) return;
2530 output( "uninstall::\n" );
2531 output_rm_filenames( make->uninstall_files );
2532 strarray_add_uniq( &make->phony_targets, "uninstall" );
2534 if (!subdirs.count) return;
2535 for (i = 0; i < make->uninstall_files.count; i++)
2537 char *dir = xstrdup( make->uninstall_files.str[i] );
2538 while (strchr( dir, '/' ))
2540 *strrchr( dir, '/' ) = 0;
2541 strarray_add_uniq( &uninstall_dirs, xstrdup(dir) );
2544 strarray_qsort( &uninstall_dirs, cmp_string_length );
2545 output( "\t-rmdir" );
2546 for (i = 0; i < sizeof(dirs_order)/sizeof(dirs_order[0]); i++)
2548 for (j = 0; j < uninstall_dirs.count; j++)
2550 if (!uninstall_dirs.str[j]) continue;
2551 if (strncmp( uninstall_dirs.str[j] + strlen("$(DESTDIR)"), dirs_order[i], strlen(dirs_order[i]) ))
2552 continue;
2553 output_filename( uninstall_dirs.str[j] );
2554 uninstall_dirs.str[j] = NULL;
2557 for (j = 0; j < uninstall_dirs.count; j++)
2558 if (uninstall_dirs.str[j]) output_filename( uninstall_dirs.str[j] );
2559 output( "\n" );
2563 /*******************************************************************
2564 * output_importlib_symlinks
2566 static struct strarray output_importlib_symlinks( const struct makefile *make )
2568 struct strarray ret = empty_strarray;
2569 const char *lib, *dst, *ext[4];
2570 int i, count = 0;
2572 ext[count++] = (*dll_ext && !make->implib_objs.count) ? "def" : "a";
2573 if (crosstarget) ext[count++] = "cross.a";
2574 if (needs_delay_lib( make )) ext[count++] = "delay.a";
2576 for (i = 0; i < count; i++)
2578 lib = strmake( "lib%s.%s", make->importlib, ext[i] );
2579 dst = strmake( "dlls/%s", lib );
2580 output( "%s: %s\n", dst, obj_dir_path( make, lib ));
2581 output_symlink_rule( concat_paths( make->obj_dir + strlen("dlls/"), lib ), dst, 0 );
2582 strarray_add( &ret, dst );
2584 return ret;
2588 /*******************************************************************
2589 * output_po_files
2591 static void output_po_files( const struct makefile *make )
2593 const char *po_dir = src_dir_path( make, "po" );
2594 unsigned int i;
2596 if (linguas.count)
2598 for (i = 0; i < linguas.count; i++)
2599 output_filename( strmake( "%s/%s.po", po_dir, linguas.str[i] ));
2600 output( ": %s/wine.pot\n", po_dir );
2601 output( "\t%smsgmerge --previous -q $@ %s/wine.pot | msgattrib --no-obsolete -o $@.new && mv $@.new $@\n",
2602 cmd_prefix( "MSG" ), po_dir );
2603 output( "po:" );
2604 for (i = 0; i < linguas.count; i++)
2605 output_filename( strmake( "%s/%s.po", po_dir, linguas.str[i] ));
2606 output( "\n" );
2608 output( "%s/wine.pot:", po_dir );
2609 output_filenames( make->pot_files );
2610 output( "\n" );
2611 output( "\t%smsgcat -o $@", cmd_prefix( "MSG" ));
2612 output_filenames( make->pot_files );
2613 output( "\n" );
2617 /*******************************************************************
2618 * output_source_y
2620 static void output_source_y( struct makefile *make, struct incl_file *source, const char *obj )
2622 /* add source file dependency for parallel makes */
2623 char *header = strmake( "%s.tab.h", obj );
2625 if (find_include_file( make, header ))
2627 output( "%s: %s\n", obj_dir_path( make, header ), source->filename );
2628 output( "\t%s%s -p %s_ -o %s.tab.c -d %s\n",
2629 cmd_prefix( "BISON" ), bison, obj, obj_dir_path( make, obj ), source->filename );
2630 output( "%s.tab.c: %s %s\n", obj_dir_path( make, obj ),
2631 source->filename, obj_dir_path( make, header ));
2632 strarray_add( &make->clean_files, header );
2634 else output( "%s.tab.c: %s\n", obj_dir_path( make, obj ), source->filename );
2636 output( "\t%s%s -p %s_ -o $@ %s\n", cmd_prefix( "BISON" ), bison, obj, source->filename );
2640 /*******************************************************************
2641 * output_source_l
2643 static void output_source_l( struct makefile *make, struct incl_file *source, const char *obj )
2645 output( "%s.yy.c: %s\n", obj_dir_path( make, obj ), source->filename );
2646 output( "\t%s%s -o$@ %s\n", cmd_prefix( "FLEX" ), flex, source->filename );
2650 /*******************************************************************
2651 * output_source_h
2653 static void output_source_h( struct makefile *make, struct incl_file *source, const char *obj )
2655 if (source->file->flags & FLAG_GENERATED)
2656 strarray_add( &make->all_targets, source->name );
2657 else
2658 add_install_rule( make, source->name, source->name,
2659 strmake( "D$(includedir)/wine/%s", get_include_install_path( source->name ) ));
2663 /*******************************************************************
2664 * output_source_rc
2666 static void output_source_rc( struct makefile *make, struct incl_file *source, const char *obj )
2668 struct strarray defines = get_source_defines( make, source, obj );
2669 const char *po_dir = NULL;
2670 unsigned int i;
2672 if (source->file->flags & FLAG_GENERATED) strarray_add( &make->clean_files, source->name );
2673 if (linguas.count && (source->file->flags & FLAG_RC_PO)) po_dir = "po";
2674 strarray_add( &make->res_files, strmake( "%s.res", obj ));
2675 if (source->file->flags & FLAG_RC_PO)
2677 strarray_add( &make->pot_files, strmake( "%s.pot", obj ));
2678 output( "%s.pot ", obj_dir_path( make, obj ) );
2680 output( "%s.res: %s", obj_dir_path( make, obj ), source->filename );
2681 output_filename( tools_path( make, "wrc" ));
2682 output_filenames( source->dependencies );
2683 output( "\n" );
2684 output( "\t%s%s -u -o $@", cmd_prefix( "WRC" ), tools_path( make, "wrc" ) );
2685 if (make->is_win16) output_filename( "-m16" );
2686 else output_filenames( target_flags );
2687 output_filename( "--nostdinc" );
2688 if (po_dir) output_filename( strmake( "--po-dir=%s", po_dir ));
2689 output_filenames( defines );
2690 output_filename( source->filename );
2691 output( "\n" );
2692 if (po_dir)
2694 output( "%s.res:", obj_dir_path( make, obj ));
2695 for (i = 0; i < linguas.count; i++)
2696 output_filename( strmake( "%s/%s.mo", po_dir, linguas.str[i] ));
2697 output( "\n" );
2702 /*******************************************************************
2703 * output_source_mc
2705 static void output_source_mc( struct makefile *make, struct incl_file *source, const char *obj )
2707 unsigned int i;
2708 char *obj_path = obj_dir_path( make, obj );
2710 strarray_add( &make->res_files, strmake( "%s.res", obj ));
2711 strarray_add( &make->pot_files, strmake( "%s.pot", obj ));
2712 output( "%s.pot %s.res: %s", obj_path, obj_path, source->filename );
2713 output_filename( tools_path( make, "wmc" ));
2714 output_filenames( source->dependencies );
2715 output( "\n" );
2716 output( "\t%s%s -u -o $@ %s", cmd_prefix( "WMC" ), tools_path( make, "wmc" ), source->filename );
2717 if (linguas.count)
2719 output_filename( "--po-dir=po" );
2720 output( "\n" );
2721 output( "%s.res:", obj_dir_path( make, obj ));
2722 for (i = 0; i < linguas.count; i++)
2723 output_filename( strmake( "po/%s.mo", linguas.str[i] ));
2725 output( "\n" );
2729 /*******************************************************************
2730 * output_source_res
2732 static void output_source_res( struct makefile *make, struct incl_file *source, const char *obj )
2734 strarray_add( &make->res_files, source->name );
2738 /*******************************************************************
2739 * output_source_idl
2741 static void output_source_idl( struct makefile *make, struct incl_file *source, const char *obj )
2743 struct strarray defines = get_source_defines( make, source, obj );
2744 struct strarray targets = empty_strarray;
2745 char *dest;
2746 unsigned int i;
2748 if (!source->file->flags) source->file->flags |= FLAG_IDL_HEADER | FLAG_INSTALL;
2749 if (find_include_file( make, strmake( "%s.h", obj ))) source->file->flags |= FLAG_IDL_HEADER;
2751 for (i = 0; i < sizeof(idl_outputs) / sizeof(idl_outputs[0]); i++)
2753 if (!(source->file->flags & idl_outputs[i].flag)) continue;
2754 dest = strmake( "%s%s", obj, idl_outputs[i].ext );
2755 if (!find_src_file( make, dest )) strarray_add( &make->clean_files, dest );
2756 strarray_add( &targets, dest );
2758 if (source->file->flags & FLAG_IDL_PROXY) strarray_add( &make->dlldata_files, source->name );
2759 if (source->file->flags & FLAG_INSTALL)
2761 add_install_rule( make, source->name, xstrdup( source->name ),
2762 strmake( "D$(includedir)/wine/%s.idl", get_include_install_path( obj ) ));
2763 if (source->file->flags & FLAG_IDL_HEADER)
2764 add_install_rule( make, source->name, strmake( "%s.h", obj ),
2765 strmake( "d$(includedir)/wine/%s.h", get_include_install_path( obj ) ));
2766 if (source->file->flags & FLAG_IDL_TYPELIB)
2767 add_install_rule( make, source->name, strmake( "%s.tlb", obj ),
2768 strmake( "d$(includedir)/wine/%s.tlb", get_include_install_path( obj ) ));
2770 if (!targets.count) return;
2772 output_filenames_obj_dir( make, targets );
2773 output( ": %s\n", tools_path( make, "widl" ));
2774 output( "\t%s%s -o $@", cmd_prefix( "WIDL" ), tools_path( make, "widl" ) );
2775 output_filenames( target_flags );
2776 output_filename( "--nostdinc" );
2777 output_filenames( defines );
2778 output_filenames( get_expanded_make_var_array( make, "EXTRAIDLFLAGS" ));
2779 output_filenames( get_expanded_file_local_var( make, obj, "EXTRAIDLFLAGS" ));
2780 output_filename( source->filename );
2781 output( "\n" );
2782 output_filenames_obj_dir( make, targets );
2783 output( ": %s", source->filename );
2784 output_filenames( source->dependencies );
2785 output( "\n" );
2789 /*******************************************************************
2790 * output_source_tlb
2792 static void output_source_tlb( struct makefile *make, struct incl_file *source, const char *obj )
2794 strarray_add( &make->all_targets, source->name );
2798 /*******************************************************************
2799 * output_source_x
2801 static void output_source_x( struct makefile *make, struct incl_file *source, const char *obj )
2803 output( "%s.h: %s%s %s\n", obj_dir_path( make, obj ),
2804 tools_dir_path( make, "make_xftmpl" ), tools_ext, source->filename );
2805 output( "\t%s%s%s -H -o $@ %s\n", cmd_prefix( "GEN" ),
2806 tools_dir_path( make, "make_xftmpl" ), tools_ext, source->filename );
2807 if (source->file->flags & FLAG_INSTALL)
2809 add_install_rule( make, source->name, source->name,
2810 strmake( "D$(includedir)/wine/%s", get_include_install_path( source->name ) ));
2811 add_install_rule( make, source->name, strmake( "%s.h", obj ),
2812 strmake( "d$(includedir)/wine/%s.h", get_include_install_path( obj ) ));
2817 /*******************************************************************
2818 * output_source_sfd
2820 static void output_source_sfd( struct makefile *make, struct incl_file *source, const char *obj )
2822 unsigned int i;
2823 char *ttf_obj = strmake( "%s.ttf", obj );
2824 char *ttf_file = src_dir_path( make, ttf_obj );
2826 if (fontforge && !make->src_dir)
2828 output( "%s: %s\n", ttf_file, source->filename );
2829 output( "\t%s%s -script %s %s $@\n", cmd_prefix( "GEN" ),
2830 fontforge, root_src_dir_path( "fonts/genttf.ff" ), source->filename );
2831 if (!(source->file->flags & FLAG_SFD_FONTS)) strarray_add( &make->font_files, ttf_obj );
2833 if (source->file->flags & FLAG_INSTALL)
2835 add_install_rule( make, source->name, ttf_obj, strmake( "D$(fontdir)/%s", ttf_obj ));
2836 output_srcdir_symlink( make, ttf_obj );
2839 if (source->file->flags & FLAG_SFD_FONTS)
2841 struct strarray *array = source->file->args;
2843 for (i = 0; i < array->count; i++)
2845 char *font = strtok( xstrdup(array->str[i]), " \t" );
2846 char *args = strtok( NULL, "" );
2848 strarray_add( &make->all_targets, xstrdup( font ));
2849 output( "%s: %s %s\n", obj_dir_path( make, font ),
2850 tools_path( make, "sfnt2fon" ), ttf_file );
2851 output( "\t%s%s -q -o $@ %s %s\n", cmd_prefix( "GEN" ),
2852 tools_path( make, "sfnt2fon" ), ttf_file, args );
2853 add_install_rule( make, source->name, xstrdup(font), strmake( "d$(fontdir)/%s", font ));
2859 /*******************************************************************
2860 * output_source_svg
2862 static void output_source_svg( struct makefile *make, struct incl_file *source, const char *obj )
2864 static const char * const images[] = { "bmp", "cur", "ico", NULL };
2865 unsigned int i;
2867 if (convert && rsvg && icotool && !make->src_dir)
2869 for (i = 0; images[i]; i++)
2870 if (find_include_file( make, strmake( "%s.%s", obj, images[i] ))) break;
2872 if (images[i])
2874 output( "%s.%s: %s\n", src_dir_path( make, obj ), images[i], source->filename );
2875 output( "\t%sCONVERT=\"%s\" ICOTOOL=\"%s\" RSVG=\"%s\" %s %s $@\n",
2876 cmd_prefix( "GEN" ), convert, icotool, rsvg,
2877 root_src_dir_path( "tools/buildimage" ), source->filename );
2883 /*******************************************************************
2884 * output_source_nls
2886 static void output_source_nls( struct makefile *make, struct incl_file *source, const char *obj )
2888 add_install_rule( make, source->name, source->name,
2889 strmake( "D$(nlsdir)/%s", source->name ));
2890 output_srcdir_symlink( make, strmake( "%s.nls", obj ));
2894 /*******************************************************************
2895 * output_source_desktop
2897 static void output_source_desktop( struct makefile *make, struct incl_file *source, const char *obj )
2899 add_install_rule( make, source->name, source->name,
2900 strmake( "D$(datadir)/applications/%s", source->name ));
2904 /*******************************************************************
2905 * output_source_po
2907 static void output_source_po( struct makefile *make, struct incl_file *source, const char *obj )
2909 output( "%s.mo: %s\n", obj_dir_path( make, obj ), source->filename );
2910 output( "\t%s%s -o $@ %s\n", cmd_prefix( "MSG" ), msgfmt, source->filename );
2911 strarray_add( &make->all_targets, strmake( "%s.mo", obj ));
2915 /*******************************************************************
2916 * output_source_in
2918 static void output_source_in( struct makefile *make, struct incl_file *source, const char *obj )
2920 unsigned int i;
2922 if (strendswith( obj, ".man" ) && source->file->args)
2924 struct strarray symlinks;
2925 char *dir, *dest = replace_extension( obj, ".man", "" );
2926 char *lang = strchr( dest, '.' );
2927 char *section = source->file->args;
2928 if (lang)
2930 *lang++ = 0;
2931 dir = strmake( "$(mandir)/%s/man%s", lang, section );
2933 else dir = strmake( "$(mandir)/man%s", section );
2934 add_install_rule( make, dest, xstrdup(obj), strmake( "d%s/%s.%s", dir, dest, section ));
2935 symlinks = get_expanded_file_local_var( make, dest, "SYMLINKS" );
2936 for (i = 0; i < symlinks.count; i++)
2937 add_install_rule( make, symlinks.str[i], strmake( "%s.%s", dest, section ),
2938 strmake( "y%s/%s.%s", dir, symlinks.str[i], section ));
2939 free( dest );
2940 free( dir );
2942 strarray_add( &make->in_files, xstrdup(obj) );
2943 strarray_add( &make->all_targets, xstrdup(obj) );
2944 output( "%s: %s\n", obj_dir_path( make, obj ), source->filename );
2945 output( "\t%s%s %s >$@ || (rm -f $@ && false)\n", cmd_prefix( "SED" ), sed_cmd, source->filename );
2946 output( "%s:", obj_dir_path( make, obj ));
2947 output_filenames( source->dependencies );
2948 output( "\n" );
2949 add_install_rule( make, obj, xstrdup( obj ), strmake( "d$(datadir)/wine/%s", obj ));
2953 /*******************************************************************
2954 * output_source_spec
2956 static void output_source_spec( struct makefile *make, struct incl_file *source, const char *obj )
2958 struct strarray imports = get_expanded_file_local_var( make, obj, "IMPORTS" );
2959 struct strarray dll_flags = get_expanded_file_local_var( make, obj, "EXTRADLLFLAGS" );
2960 struct strarray all_libs, dep_libs = empty_strarray;
2961 char *dll_name, *obj_name, *output_file;
2962 const char *debug_file;
2964 if (!imports.count) imports = make->imports;
2965 else if (make->use_msvcrt) add_crt_import( make, &imports, NULL );
2967 if (!dll_flags.count) dll_flags = make->extradllflags;
2968 all_libs = add_import_libs( make, &dep_libs, imports, 0, 0 );
2969 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
2970 dll_name = strmake( "%s.dll%s", obj, make->is_cross ? "" : dll_ext );
2971 obj_name = strmake( "%s%s", obj_dir_path( make, obj ), make->is_cross ? ".cross.o" : ".o" );
2972 output_file = obj_dir_path( make, dll_name );
2974 strarray_add( &make->clean_files, dll_name );
2975 strarray_add( &make->res_files, strmake( "%s.res", obj ));
2976 output( "%s.res:", obj_dir_path( make, obj ));
2977 output_filename( obj_dir_path( make, dll_name ));
2978 output_filename( tools_path( make, "wrc" ));
2979 output( "\n" );
2980 output( "\t%secho \"%s.dll TESTDLL \\\"%s\\\"\" | %s -u -o $@\n", cmd_prefix( "WRC" ), obj, output_file,
2981 tools_path( make, "wrc" ));
2983 output( "%s:", output_file);
2984 output_filename( source->filename );
2985 output_filename( obj_name );
2986 output_filenames( dep_libs );
2987 output_filename( tools_path( make, "winebuild" ));
2988 output_filename( tools_path( make, "winegcc" ));
2989 output( "\n" );
2990 output_winegcc_command( make, make->is_cross );
2991 output_filename( "-s" );
2992 output_filenames( dll_flags );
2993 output_filename( "-shared" );
2994 output_filename( source->filename );
2995 output_filename( obj_name );
2996 if ((debug_file = get_debug_file( make, dll_name )))
2997 output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
2998 output_filenames( all_libs );
2999 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3000 output( "\n" );
3004 /*******************************************************************
3005 * output_source_default
3007 static void output_source_default( struct makefile *make, struct incl_file *source, const char *obj )
3009 struct strarray defines = get_source_defines( make, source, obj );
3010 int is_dll_src = (make->testdll &&
3011 strendswith( source->name, ".c" ) &&
3012 find_src_file( make, replace_extension( source->name, ".c", ".spec" )));
3013 int need_cross = (crosstarget &&
3014 !(source->file->flags & FLAG_C_UNIX) &&
3015 (make->is_cross || make->staticlib ||
3016 (source->file->flags & FLAG_C_IMPLIB)));
3017 int need_obj = ((*dll_ext || !(source->file->flags & FLAG_C_UNIX)) &&
3018 (!need_cross ||
3019 (source->file->flags & FLAG_C_IMPLIB) ||
3020 make->staticlib));
3022 if ((source->file->flags & FLAG_GENERATED) &&
3023 (!make->testdll || !strendswith( source->filename, "testlist.c" )))
3024 strarray_add( &make->clean_files, source->basename );
3025 if (source->file->flags & FLAG_C_IMPLIB) strarray_add( &make->implib_objs, strmake( "%s.o", obj ));
3027 if (need_obj)
3029 if ((source->file->flags & FLAG_C_UNIX) && *dll_ext)
3030 strarray_add( &make->unixobj_files, strmake( "%s.o", obj ));
3031 else if (!is_dll_src && !(source->file->flags & FLAG_C_IMPLIB))
3032 strarray_add( &make->object_files, strmake( "%s.o", obj ));
3033 else
3034 strarray_add( &make->clean_files, strmake( "%s.o", obj ));
3035 output( "%s.o: %s\n", obj_dir_path( make, obj ), source->filename );
3036 output( "\t%s$(CC) -c -o $@ %s", cmd_prefix( "CC" ), source->filename );
3037 output_filenames( defines );
3038 if (make->sharedlib || (source->file->flags & FLAG_C_UNIX))
3040 output_filenames( unix_dllflags );
3042 else if (make->module || make->testdll)
3044 output_filenames( dll_flags );
3045 if (source->use_msvcrt) output_filenames( msvcrt_flags );
3046 if (!*dll_ext && make->module && is_crt_module( make->module ))
3047 output_filename( "-fno-builtin" );
3049 output_filenames( make->extlib ? extra_cflags_extlib : extra_cflags );
3050 output_filenames( cpp_flags );
3051 output_filename( "$(CFLAGS)" );
3052 output( "\n" );
3054 if (need_cross)
3056 if (!is_dll_src && !(source->file->flags & FLAG_C_IMPLIB))
3057 strarray_add( &make->crossobj_files, strmake( "%s.cross.o", obj ));
3058 else
3059 strarray_add( &make->clean_files, strmake( "%s.cross.o", obj ));
3060 output( "%s.cross.o: %s\n", obj_dir_path( make, obj ), source->filename );
3061 output( "\t%s$(CROSSCC) -c -o $@ %s", cmd_prefix( "CC" ), source->filename );
3062 output_filenames( defines );
3063 output_filenames( make->extlib ? extra_cross_cflags_extlib : extra_cross_cflags );
3064 if (make->module && is_crt_module( make->module ))
3065 output_filename( "-fno-builtin" );
3066 output_filenames( cpp_flags );
3067 output_filename( "$(CROSSCFLAGS)" );
3068 output( "\n" );
3070 if (strendswith( source->name, ".c" ) && !(source->file->flags & FLAG_GENERATED))
3072 strarray_add( &make->c2man_files, source->filename );
3073 if (make->testdll && !is_dll_src)
3075 strarray_add( &make->ok_files, strmake( "%s.ok", obj ));
3076 output( "%s.ok:\n", obj_dir_path( make, obj ));
3077 output( "\t%s%s $(RUNTESTFLAGS) -T . -M %s -p %s%s %s && touch $@\n",
3078 cmd_prefix( "TEST" ),
3079 root_src_dir_path( "tools/runtest" ), make->testdll,
3080 obj_dir_path( make, replace_extension( make->testdll, ".dll", "_test.exe" )),
3081 make->is_cross ? "" : dll_ext, obj );
3084 if (need_obj) output_filename( strmake( "%s.o", obj_dir_path( make, obj )));
3085 if (need_cross) output_filename( strmake( "%s.cross.o", obj_dir_path( make, obj )));
3086 output( ":" );
3087 output_filenames( source->dependencies );
3088 output( "\n" );
3092 /* dispatch table to output rules for a single source file */
3093 static const struct
3095 const char *ext;
3096 void (*fn)( struct makefile *make, struct incl_file *source, const char *obj );
3097 } output_source_funcs[] =
3099 { "y", output_source_y },
3100 { "l", output_source_l },
3101 { "h", output_source_h },
3102 { "rh", output_source_h },
3103 { "inl", output_source_h },
3104 { "rc", output_source_rc },
3105 { "mc", output_source_mc },
3106 { "res", output_source_res },
3107 { "idl", output_source_idl },
3108 { "tlb", output_source_tlb },
3109 { "sfd", output_source_sfd },
3110 { "svg", output_source_svg },
3111 { "nls", output_source_nls },
3112 { "desktop", output_source_desktop },
3113 { "po", output_source_po },
3114 { "in", output_source_in },
3115 { "x", output_source_x },
3116 { "spec", output_source_spec },
3117 { NULL, output_source_default }
3121 /*******************************************************************
3122 * get_unix_lib_name
3124 static char *get_unix_lib_name( struct makefile *make )
3126 struct incl_file *source;
3128 if (!*dll_ext) return NULL;
3129 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
3131 if (!(source->file->flags & FLAG_C_UNIX)) continue;
3132 return strmake( "%s%s", get_base_name( make->module ), dll_ext );
3134 return NULL;
3138 /*******************************************************************
3139 * output_man_pages
3141 static void output_man_pages( struct makefile *make )
3143 if (make->c2man_files.count)
3145 char *spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" ));
3147 output( "manpages::\n" );
3148 output( "\t%s -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3149 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3150 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3151 output_filename( strmake( "-o documentation/man%s", man_ext ));
3152 output_filenames( make->c2man_files );
3153 output( "\n" );
3154 output( "htmlpages::\n" );
3155 output( "\t%s -Th -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3156 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3157 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3158 output_filename( "-o documentation/html" );
3159 output_filenames( make->c2man_files );
3160 output( "\n" );
3161 output( "sgmlpages::\n" );
3162 output( "\t%s -Ts -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3163 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3164 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3165 output_filename( "-o documentation/api-guide" );
3166 output_filenames( make->c2man_files );
3167 output( "\n" );
3168 output( "xmlpages::\n" );
3169 output( "\t%s -Tx -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3170 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3171 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3172 output_filename( "-o documentation/api-guide-xml" );
3173 output_filenames( make->c2man_files );
3174 output( "\n" );
3175 strarray_add( &make->phony_targets, "manpages" );
3176 strarray_add( &make->phony_targets, "htmlpages" );
3177 strarray_add( &make->phony_targets, "sgmlpages" );
3178 strarray_add( &make->phony_targets, "xmlpages" );
3183 /*******************************************************************
3184 * output_module
3186 static void output_module( struct makefile *make )
3188 struct strarray all_libs = empty_strarray;
3189 struct strarray dep_libs = empty_strarray;
3190 char *module_path = obj_dir_path( make, make->module );
3191 const char *debug_file = NULL;
3192 char *spec_file = NULL;
3193 unsigned int i;
3195 if (!make->is_exe) spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" ));
3196 strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->delayimports, 1, 0 ));
3197 strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->imports, 0, 0 ));
3198 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
3200 if (make->is_cross)
3202 if (delay_load_flag)
3204 for (i = 0; i < make->delayimports.count; i++)
3205 strarray_add( &all_libs, strmake( "%s%s%s", delay_load_flag, make->delayimports.str[i],
3206 strchr( make->delayimports.str[i], '.' ) ? "" : ".dll" ));
3208 strarray_add( &make->all_targets, strmake( "%s", make->module ));
3209 add_install_rule( make, make->module, strmake( "%s", make->module ),
3210 strmake( "c%s/%s", pe_dir, make->module ));
3211 debug_file = get_debug_file( make, make->module );
3212 output( "%s:", module_path );
3214 else if (*dll_ext)
3216 if (!make->use_msvcrt) strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3217 for (i = 0; i < make->delayimports.count; i++)
3218 strarray_add( &all_libs, strmake( "-Wl,-delayload,%s%s", make->delayimports.str[i],
3219 strchr( make->delayimports.str[i], '.' ) ? "" : ".dll" ));
3220 strarray_add( &make->all_targets, strmake( "%s%s", make->module, dll_ext ));
3221 strarray_add( &make->all_targets, strmake( "%s.fake", make->module ));
3222 add_install_rule( make, make->module, strmake( "%s%s", make->module, dll_ext ),
3223 strmake( "p%s/%s%s", so_dir, make->module, dll_ext ));
3224 add_install_rule( make, make->module, strmake( "%s.fake", make->module ),
3225 strmake( "d%s/%s", pe_dir, make->module ));
3226 output( "%s%s %s.fake:", module_path, dll_ext, module_path );
3228 else
3230 strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3231 strarray_add( &make->all_targets, make->module );
3232 add_install_rule( make, make->module, make->module,
3233 strmake( "p$(%s)/%s", spec_file ? "dlldir" : "bindir", make->module ));
3234 debug_file = get_debug_file( make, make->module );
3235 output( "%s:", module_path );
3238 if (spec_file) output_filename( spec_file );
3239 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3240 output_filenames_obj_dir( make, make->res_files );
3241 output_filenames( dep_libs );
3242 output_filename( tools_path( make, "winebuild" ));
3243 output_filename( tools_path( make, "winegcc" ));
3244 output( "\n" );
3245 output_winegcc_command( make, make->is_cross );
3246 if (make->is_cross) output_filename( "-Wl,--wine-builtin" );
3247 if (spec_file)
3249 output_filename( "-shared" );
3250 output_filename( spec_file );
3252 output_filenames( make->extradllflags );
3253 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3254 output_filenames_obj_dir( make, make->res_files );
3255 if (debug_file) output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
3256 output_filenames( all_libs );
3257 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3258 output( "\n" );
3260 if (make->unixlib)
3262 struct strarray unix_libs = empty_strarray;
3263 struct strarray unix_deps = empty_strarray;
3265 if (!make->native_unix_lib)
3267 struct strarray unix_imports = empty_strarray;
3269 if (!strarray_exists( &make->extradllflags, "-nodefaultlibs" ))
3271 strarray_add( &unix_imports, "ntdll" );
3272 strarray_add( &unix_deps, obj_dir_path( top_makefile, "dlls/ntdll/ntdll.so" ));
3274 strarray_add( &unix_imports, "winecrt0" );
3275 if (spec_file) strarray_add( &unix_deps, spec_file );
3277 strarray_addall( &unix_libs, add_import_libs( make, &unix_deps, unix_imports, 0, 1 ));
3280 strarray_addall( &unix_libs, add_unix_libraries( make, &unix_deps ));
3282 strarray_add( &make->all_targets, make->unixlib );
3283 add_install_rule( make, make->module, make->unixlib, strmake( "p%s/%s", so_dir, make->unixlib ));
3284 output( "%s:", obj_dir_path( make, make->unixlib ));
3285 output_filenames_obj_dir( make, make->unixobj_files );
3286 output_filenames( unix_deps );
3288 if (make->native_unix_lib)
3290 output( "\n" );
3291 output( "\t%s$(CC) -o $@", cmd_prefix( "CCLD" ));
3292 output_filenames( get_expanded_make_var_array( make, "UNIXLDFLAGS" ));
3294 else
3296 output_filename( tools_path( make, "winebuild" ));
3297 output_filename( tools_path( make, "winegcc" ));
3298 output( "\n" );
3299 output_winegcc_command( make, 0 );
3300 output_filename( "-munix" );
3301 output_filename( "-shared" );
3302 if (spec_file) output_filename( spec_file );
3303 if (strarray_exists( &make->extradllflags, "-nodefaultlibs" )) output_filename( "-nodefaultlibs" );
3305 output_filenames_obj_dir( make, make->unixobj_files );
3306 output_filenames( unix_libs );
3307 output_filename( "$(LDFLAGS)" );
3308 output( "\n" );
3311 if (spec_file && make->importlib)
3313 char *importlib_path = obj_dir_path( make, strmake( "lib%s", make->importlib ));
3314 if (*dll_ext && !make->implib_objs.count)
3316 strarray_add( &make->clean_files, strmake( "lib%s.def", make->importlib ));
3317 output( "%s.def: %s %s\n", importlib_path, tools_path( make, "winebuild" ), spec_file );
3318 output( "\t%s%s -w --def -o $@", cmd_prefix( "BUILD" ), tools_path( make, "winebuild" ) );
3319 output_filenames( target_flags );
3320 if (make->is_win16) output_filename( "-m16" );
3321 output_filename( "--export" );
3322 output_filename( spec_file );
3323 output( "\n" );
3324 add_install_rule( make, make->importlib,
3325 strmake( "lib%s.def", make->importlib ),
3326 strmake( "d%s/lib%s.def", so_dir, make->importlib ));
3328 else
3330 strarray_add( &make->clean_files, strmake( "lib%s.a", make->importlib ));
3331 if (!*dll_ext && needs_delay_lib( make ))
3333 strarray_add( &make->clean_files, strmake( "lib%s.delay.a", make->importlib ));
3334 output( "%s.delay.a ", importlib_path );
3336 output( "%s.a: %s %s", importlib_path, tools_path( make, "winebuild" ), spec_file );
3337 output_filenames_obj_dir( make, make->implib_objs );
3338 output( "\n" );
3339 output( "\t%s%s -w --implib -o $@", cmd_prefix( "BUILD" ), tools_path( make, "winebuild" ) );
3340 output_filenames( target_flags );
3341 if (make->is_win16) output_filename( "-m16" );
3342 output_filename( "--export" );
3343 output_filename( spec_file );
3344 output_filenames_obj_dir( make, make->implib_objs );
3345 output( "\n" );
3346 add_install_rule( make, make->importlib,
3347 strmake( "lib%s.a", make->importlib ),
3348 strmake( "d%s/lib%s.a", so_dir, make->importlib ));
3350 if (crosstarget)
3352 struct strarray cross_files = strarray_replace_extension( &make->implib_objs, ".o", ".cross.o" );
3354 strarray_add( &make->clean_files, strmake( "lib%s.cross.a", make->importlib ));
3355 output_filename( strmake( "%s.cross.a", importlib_path ));
3356 if (needs_delay_lib( make ))
3358 strarray_add( &make->clean_files, strmake( "lib%s.delay.a", make->importlib ));
3359 output_filename( strmake( "%s.delay.a", importlib_path ));
3361 output( ": %s %s", tools_path( make, "winebuild" ), spec_file );
3362 output_filenames_obj_dir( make, cross_files );
3363 output( "\n" );
3364 output( "\t%s%s -b %s -w --implib -o $@", cmd_prefix( "BUILD" ),
3365 tools_path( make, "winebuild" ), crosstarget );
3366 if (make->is_win16) output_filename( "-m16" );
3367 output_filename( "--export" );
3368 output_filename( spec_file );
3369 output_filenames_obj_dir( make, cross_files );
3370 output( "\n" );
3371 add_install_rule( make, make->importlib,
3372 strmake( "lib%s.cross.a", make->importlib ),
3373 strmake( "d%s/lib%s.a", pe_dir, make->importlib ));
3375 if (needs_implib_symlink( make ))
3376 strarray_addall( &top_makefile->clean_files, output_importlib_symlinks( make ));
3379 if (spec_file)
3380 output_man_pages( make );
3381 else if (*dll_ext && !make->is_win16 && strendswith( make->module, ".exe" ))
3383 char *binary = replace_extension( make->module, ".exe", "" );
3384 add_install_rule( make, binary, "wineapploader", strmake( "t$(bindir)/%s", binary ));
3389 /*******************************************************************
3390 * output_static_lib
3392 static void output_static_lib( struct makefile *make )
3394 strarray_add( &make->clean_files, make->staticlib );
3395 output( "%s:", obj_dir_path( make, make->staticlib ));
3396 output_filenames_obj_dir( make, make->object_files );
3397 output_filenames_obj_dir( make, make->unixobj_files );
3398 output( "\n\t%srm -f $@ && %s rc $@", cmd_prefix( "AR" ), ar );
3399 output_filenames_obj_dir( make, make->object_files );
3400 output_filenames_obj_dir( make, make->unixobj_files );
3401 output( " && %s $@\n", ranlib );
3402 add_install_rule( make, make->staticlib, make->staticlib, strmake( "d%s/%s", so_dir, make->staticlib ));
3403 if (crosstarget)
3405 char *name = replace_extension( make->staticlib, ".a", ".cross.a" );
3407 strarray_add( &make->clean_files, name );
3408 output( "%s: %s", obj_dir_path( make, name ), tools_path( make, "winebuild" ));
3409 output_filenames_obj_dir( make, make->crossobj_files );
3410 output( "\n" );
3411 output( "\t%s%s -b %s -w --staticlib -o $@", cmd_prefix( "BUILD" ),
3412 tools_path( make, "winebuild" ), crosstarget );
3413 output_filenames_obj_dir( make, make->crossobj_files );
3414 output( "\n" );
3415 add_install_rule( make, make->staticlib, name,
3416 strmake( "d%s/%s", pe_dir, make->staticlib ));
3421 /*******************************************************************
3422 * output_shared_lib
3424 static void output_shared_lib( struct makefile *make )
3426 unsigned int i;
3427 char *basename, *p;
3428 struct strarray names = get_shared_lib_names( make->sharedlib );
3429 struct strarray all_libs = empty_strarray;
3430 struct strarray dep_libs = empty_strarray;
3432 basename = xstrdup( make->sharedlib );
3433 if ((p = strchr( basename, '.' ))) *p = 0;
3435 strarray_addall( &dep_libs, get_local_dependencies( make, basename, make->in_files ));
3436 strarray_addall( &all_libs, get_expanded_file_local_var( make, basename, "LDFLAGS" ));
3437 strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3439 output( "%s:", obj_dir_path( make, make->sharedlib ));
3440 output_filenames_obj_dir( make, make->object_files );
3441 output_filenames( dep_libs );
3442 output( "\n" );
3443 output( "\t%s$(CC) -o $@", cmd_prefix( "CCLD" ));
3444 output_filenames_obj_dir( make, make->object_files );
3445 output_filenames( all_libs );
3446 output_filename( "$(LDFLAGS)" );
3447 output( "\n" );
3448 add_install_rule( make, make->sharedlib, make->sharedlib, strmake( "p%s/%s", so_dir, make->sharedlib ));
3449 for (i = 1; i < names.count; i++)
3451 output( "%s: %s\n", obj_dir_path( make, names.str[i] ), obj_dir_path( make, names.str[i-1] ));
3452 output_symlink_rule( names.str[i-1], obj_dir_path( make, names.str[i] ), 0 );
3453 add_install_rule( make, names.str[i], names.str[i-1], strmake( "y%s/%s", so_dir, names.str[i] ));
3455 strarray_addall( &make->all_targets, names );
3459 /*******************************************************************
3460 * output_test_module
3462 static void output_test_module( struct makefile *make )
3464 char *testmodule = replace_extension( make->testdll, ".dll", "_test.exe" );
3465 char *stripped = replace_extension( make->testdll, ".dll", "_test-stripped.exe" );
3466 char *testres = replace_extension( make->testdll, ".dll", "_test.res" );
3467 struct strarray dep_libs = empty_strarray;
3468 struct strarray all_libs = add_import_libs( make, &dep_libs, make->imports, 0, 0 );
3469 struct makefile *parent = get_parent_makefile( make );
3470 const char *ext = make->is_cross ? "" : dll_ext;
3471 const char *debug_file;
3472 char *output_file;
3474 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
3475 strarray_add( &make->all_targets, strmake( "%s%s", testmodule, ext ));
3476 strarray_add( &make->clean_files, strmake( "%s%s", stripped, ext ));
3477 output_file = strmake( "%s%s", obj_dir_path( make, testmodule ), ext );
3478 output( "%s:\n", output_file );
3479 output_winegcc_command( make, make->is_cross );
3480 output_filenames( make->extradllflags );
3481 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3482 output_filenames_obj_dir( make, make->res_files );
3483 if ((debug_file = get_debug_file( make, testmodule )))
3484 output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
3485 output_filenames( all_libs );
3486 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3487 output( "\n" );
3488 output( "%s%s:\n", obj_dir_path( make, stripped ), ext );
3489 output_winegcc_command( make, make->is_cross );
3490 output_filename( "-s" );
3491 output_filename( strmake( "-Wb,-F,%s", testmodule ));
3492 output_filenames( make->extradllflags );
3493 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3494 output_filenames_obj_dir( make, make->res_files );
3495 output_filenames( all_libs );
3496 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3497 output( "\n" );
3498 output( "%s%s %s%s:", obj_dir_path( make, testmodule ), ext, obj_dir_path( make, stripped ), ext );
3499 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3500 output_filenames_obj_dir( make, make->res_files );
3501 output_filenames( dep_libs );
3502 output_filename( tools_path( make, "winebuild" ));
3503 output_filename( tools_path( make, "winegcc" ));
3504 output( "\n" );
3506 output( "programs/winetest/%s: %s%s\n", testres, obj_dir_path( make, stripped ), ext );
3507 output( "\t%secho \"%s TESTRES \\\"%s%s\\\"\" | %s -u -o $@\n", cmd_prefix( "WRC" ),
3508 testmodule, obj_dir_path( make, stripped ), ext, tools_path( make, "wrc" ));
3510 output_filenames_obj_dir( make, make->ok_files );
3511 output( ": %s%s", obj_dir_path( make, testmodule ), ext );
3512 if (parent)
3514 output_filename( parent->is_cross ? obj_dir_path( parent, make->testdll )
3515 : strmake( "%s%s", obj_dir_path( parent, make->testdll ), dll_ext ));
3516 if (parent->unixlib) output_filename( obj_dir_path( parent, parent->unixlib ));
3518 output( "\n" );
3519 output( "%s %s:", obj_dir_path( make, "check" ), obj_dir_path( make, "test" ));
3520 if (!make->disabled && parent && !parent->disabled) output_filenames_obj_dir( make, make->ok_files );
3521 output( "\n" );
3522 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "check" ));
3523 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "test" ));
3524 output( "%s::\n", obj_dir_path( make, "testclean" ));
3525 output( "\trm -f" );
3526 output_filenames_obj_dir( make, make->ok_files );
3527 output( "\n" );
3528 strarray_addall( &make->clean_files, make->ok_files );
3529 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "testclean" ));
3533 /*******************************************************************
3534 * output_programs
3536 static void output_programs( struct makefile *make )
3538 unsigned int i, j;
3540 for (i = 0; i < make->programs.count; i++)
3542 char *program_installed = NULL;
3543 char *program = strmake( "%s%s", make->programs.str[i], exe_ext );
3544 struct strarray deps = get_local_dependencies( make, make->programs.str[i], make->in_files );
3545 struct strarray all_libs = get_expanded_file_local_var( make, make->programs.str[i], "LDFLAGS" );
3546 struct strarray objs = get_expanded_file_local_var( make, make->programs.str[i], "OBJS" );
3547 struct strarray symlinks = get_expanded_file_local_var( make, make->programs.str[i], "SYMLINKS" );
3549 if (!objs.count) objs = make->object_files;
3550 if (!strarray_exists( &all_libs, "-nodefaultlibs" ))
3551 strarray_addall( &all_libs, add_unix_libraries( make, &deps ));
3553 output( "%s:", obj_dir_path( make, program ) );
3554 output_filenames_obj_dir( make, objs );
3555 output_filenames( deps );
3556 output( "\n" );
3557 output( "\t%s$(CC) -o $@", cmd_prefix( "CC" ));
3558 output_filenames_obj_dir( make, objs );
3559 output_filenames( all_libs );
3560 output_filename( "$(LDFLAGS)" );
3561 output( "\n" );
3562 strarray_add( &make->all_targets, program );
3564 for (j = 0; j < symlinks.count; j++)
3566 output( "%s: %s\n", obj_dir_path( make, symlinks.str[j] ), obj_dir_path( make, program ));
3567 output_symlink_rule( program, obj_dir_path( make, symlinks.str[j] ), 0 );
3569 strarray_addall( &make->all_targets, symlinks );
3571 add_install_rule( make, program, program_installed ? program_installed : program,
3572 strmake( "p$(bindir)/%s", program ));
3573 for (j = 0; j < symlinks.count; j++)
3574 add_install_rule( make, symlinks.str[j], program,
3575 strmake( "y$(bindir)/%s%s", symlinks.str[j], exe_ext ));
3580 /*******************************************************************
3581 * output_subdirs
3583 static void output_subdirs( struct makefile *make )
3585 struct strarray all_targets = empty_strarray;
3586 struct strarray makefile_deps = empty_strarray;
3587 struct strarray clean_files = empty_strarray;
3588 struct strarray testclean_files = empty_strarray;
3589 struct strarray distclean_files = empty_strarray;
3590 struct strarray dependencies = empty_strarray;
3591 struct strarray install_lib_deps = empty_strarray;
3592 struct strarray install_dev_deps = empty_strarray;
3593 struct strarray tooldeps_deps = empty_strarray;
3594 struct strarray buildtest_deps = empty_strarray;
3595 unsigned int i;
3597 strarray_addall( &clean_files, make->clean_files );
3598 strarray_addall( &distclean_files, make->distclean_files );
3599 strarray_addall( &all_targets, make->all_targets );
3600 for (i = 0; i < subdirs.count; i++)
3602 strarray_add( &makefile_deps, src_dir_path( submakes[i], strmake ( "%s.in", output_makefile_name )));
3603 strarray_addall_uniq( &make->phony_targets, submakes[i]->phony_targets );
3604 strarray_addall_uniq( &make->uninstall_files, submakes[i]->uninstall_files );
3605 strarray_addall_uniq( &dependencies, submakes[i]->dependencies );
3606 strarray_addall_path( &clean_files, submakes[i]->obj_dir, submakes[i]->clean_files );
3607 strarray_addall_path( &distclean_files, submakes[i]->obj_dir, submakes[i]->distclean_files );
3608 strarray_addall_path( &testclean_files, submakes[i]->obj_dir, submakes[i]->ok_files );
3609 strarray_addall_path( &make->pot_files, submakes[i]->obj_dir, submakes[i]->pot_files );
3611 if (submakes[i]->disabled) continue;
3613 strarray_addall_path( &all_targets, submakes[i]->obj_dir, submakes[i]->all_targets );
3614 if (!strcmp( submakes[i]->obj_dir, "tools" ) || !strncmp( submakes[i]->obj_dir, "tools/", 6 ))
3615 strarray_add( &tooldeps_deps, obj_dir_path( submakes[i], "all" ));
3616 if (submakes[i]->testdll)
3617 strarray_add( &buildtest_deps, obj_dir_path( submakes[i], "all" ));
3618 if (submakes[i]->install_rules[INSTALL_LIB].count)
3619 strarray_add( &install_lib_deps, obj_dir_path( submakes[i], "install-lib" ));
3620 if (submakes[i]->install_rules[INSTALL_DEV].count)
3621 strarray_add( &install_dev_deps, obj_dir_path( submakes[i], "install-dev" ));
3623 strarray_addall( &dependencies, makefile_deps );
3624 output( "all:" );
3625 output_filenames( all_targets );
3626 output( "\n" );
3627 output( "Makefile:" );
3628 output_filenames( makefile_deps );
3629 output( "\n" );
3630 output_filenames( dependencies );
3631 output( ":\n" );
3632 if (install_lib_deps.count)
3634 output( "install install-lib::" );
3635 output_filenames( install_lib_deps );
3636 output( "\n" );
3637 strarray_add_uniq( &make->phony_targets, "install" );
3638 strarray_add_uniq( &make->phony_targets, "install-lib" );
3640 if (install_dev_deps.count)
3642 output( "install install-dev::" );
3643 output_filenames( install_dev_deps );
3644 output( "\n" );
3645 strarray_add_uniq( &make->phony_targets, "install" );
3646 strarray_add_uniq( &make->phony_targets, "install-dev" );
3648 output_uninstall_rules( make );
3649 if (buildtest_deps.count)
3651 output( "buildtests:" );
3652 output_filenames( buildtest_deps );
3653 output( "\n" );
3654 strarray_add_uniq( &make->phony_targets, "buildtests" );
3656 output( "check test:" );
3657 output_filenames( testclean_files );
3658 output( "\n" );
3659 strarray_add_uniq( &make->phony_targets, "check" );
3660 strarray_add_uniq( &make->phony_targets, "test" );
3662 output( "clean::\n");
3663 output_rm_filenames( clean_files );
3664 output( "testclean::\n");
3665 output_rm_filenames( testclean_files );
3666 output( "distclean::\n");
3667 output_rm_filenames( distclean_files );
3668 strarray_add_uniq( &make->phony_targets, "distclean" );
3669 strarray_add_uniq( &make->phony_targets, "testclean" );
3671 if (tooldeps_deps.count)
3673 output( "__tooldeps__:" );
3674 output_filenames( tooldeps_deps );
3675 output( "\n" );
3676 strarray_add_uniq( &make->phony_targets, "__tooldeps__" );
3679 if (get_expanded_make_variable( make, "GETTEXTPO_LIBS" )) output_po_files( make );
3681 if (make->phony_targets.count)
3683 output( ".PHONY:" );
3684 output_filenames( make->phony_targets );
3685 output( "\n" );
3690 /*******************************************************************
3691 * output_sources
3693 static void output_sources( struct makefile *make )
3695 struct strarray all_targets = empty_strarray;
3696 struct incl_file *source;
3697 unsigned int i, j;
3699 strarray_add_uniq( &make->phony_targets, "all" );
3701 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
3703 char *obj = xstrdup( source->name );
3704 char *ext = get_extension( obj );
3706 if (!ext) fatal_error( "unsupported file type %s\n", source->name );
3707 *ext++ = 0;
3709 for (j = 0; output_source_funcs[j].ext; j++)
3710 if (!strcmp( ext, output_source_funcs[j].ext )) break;
3712 output_source_funcs[j].fn( make, source, obj );
3713 strarray_addall_uniq( &make->dependencies, source->dependencies );
3716 /* special case for winetest: add resource files from other test dirs */
3717 if (make->obj_dir && !strcmp( make->obj_dir, "programs/winetest" ))
3719 struct strarray tests = enable_tests;
3720 if (!tests.count)
3721 for (i = 0; i < subdirs.count; i++)
3722 if (submakes[i]->testdll && !submakes[i]->disabled)
3723 strarray_add( &tests, submakes[i]->testdll );
3724 for (i = 0; i < tests.count; i++)
3725 strarray_add( &make->res_files, replace_extension( tests.str[i], ".dll", "_test.res" ));
3728 if (make->dlldata_files.count)
3730 output( "%s: %s %s\n", obj_dir_path( make, "dlldata.c" ),
3731 tools_path( make, "widl" ), src_dir_path( make, "Makefile.in" ));
3732 output( "\t%s%s --dlldata-only -o $@", cmd_prefix( "WIDL" ), tools_path( make, "widl" ));
3733 output_filenames( make->dlldata_files );
3734 output( "\n" );
3737 if (make->staticlib) output_static_lib( make );
3738 else if (make->module) output_module( make );
3739 else if (make->testdll) output_test_module( make );
3740 else if (make->sharedlib) output_shared_lib( make );
3741 else if (make->programs.count) output_programs( make );
3743 for (i = 0; i < make->scripts.count; i++)
3744 add_install_rule( make, make->scripts.str[i], make->scripts.str[i],
3745 strmake( "S$(bindir)/%s", make->scripts.str[i] ));
3747 for (i = 0; i < make->extra_targets.count; i++)
3748 if (strarray_exists( &make->dependencies, obj_dir_path( make, make->extra_targets.str[i] )))
3749 strarray_add( &make->clean_files, make->extra_targets.str[i] );
3750 else
3751 strarray_add( &make->all_targets, make->extra_targets.str[i] );
3753 if (!make->src_dir) strarray_add( &make->distclean_files, ".gitignore" );
3754 strarray_add( &make->distclean_files, "Makefile" );
3755 if (make->testdll) strarray_add( &make->distclean_files, "testlist.c" );
3757 if (!make->obj_dir)
3758 strarray_addall( &make->distclean_files, get_expanded_make_var_array( make, "CONFIGURE_TARGETS" ));
3759 else if (!strcmp( make->obj_dir, "po" ))
3760 strarray_add( &make->distclean_files, "LINGUAS" );
3762 strarray_addall( &make->clean_files, make->object_files );
3763 strarray_addall( &make->clean_files, make->crossobj_files );
3764 strarray_addall( &make->clean_files, make->unixobj_files );
3765 strarray_addall( &make->clean_files, make->res_files );
3766 strarray_addall( &make->clean_files, make->pot_files );
3767 strarray_addall( &make->clean_files, make->debug_files );
3768 strarray_addall( &make->clean_files, make->all_targets );
3770 if (make == top_makefile)
3772 output_subdirs( make );
3773 return;
3776 strarray_addall( &all_targets, make->all_targets );
3777 strarray_addall( &all_targets, make->font_files );
3778 if (all_targets.count)
3780 output( "%s:", obj_dir_path( make, "all" ));
3781 output_filenames_obj_dir( make, all_targets );
3782 output( "\n" );
3783 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "all" ));
3785 output_install_rules( make, INSTALL_LIB, "install-lib" );
3786 output_install_rules( make, INSTALL_DEV, "install-dev" );
3788 if (make->clean_files.count)
3790 output( "%s::\n", obj_dir_path( make, "clean" ));
3791 output( "\trm -f" );
3792 output_filenames_obj_dir( make, make->clean_files );
3793 output( "\n" );
3794 strarray_add( &make->phony_targets, obj_dir_path( make, "clean" ));
3799 /*******************************************************************
3800 * create_temp_file
3802 static FILE *create_temp_file( const char *orig )
3804 char *name = xmalloc( strlen(orig) + 13 );
3805 unsigned int i, id = getpid();
3806 int fd;
3807 FILE *ret = NULL;
3809 for (i = 0; i < 100; i++)
3811 sprintf( name, "%s.tmp%08x", orig, id );
3812 if ((fd = open( name, O_RDWR | O_CREAT | O_EXCL, 0666 )) != -1)
3814 ret = fdopen( fd, "w" );
3815 break;
3817 if (errno != EEXIST) break;
3818 id += 7777;
3820 if (!ret) fatal_error( "failed to create output file for '%s'\n", orig );
3821 temp_file_name = name;
3822 return ret;
3826 /*******************************************************************
3827 * rename_temp_file
3829 static void rename_temp_file( const char *dest )
3831 int ret = rename( temp_file_name, dest );
3832 if (ret == -1 && errno == EEXIST)
3834 /* rename doesn't overwrite on windows */
3835 unlink( dest );
3836 ret = rename( temp_file_name, dest );
3838 if (ret == -1) fatal_error( "failed to rename output file to '%s'\n", dest );
3839 temp_file_name = NULL;
3843 /*******************************************************************
3844 * are_files_identical
3846 static int are_files_identical( FILE *file1, FILE *file2 )
3848 for (;;)
3850 char buffer1[8192], buffer2[8192];
3851 int size1 = fread( buffer1, 1, sizeof(buffer1), file1 );
3852 int size2 = fread( buffer2, 1, sizeof(buffer2), file2 );
3853 if (size1 != size2) return 0;
3854 if (!size1) return feof( file1 ) && feof( file2 );
3855 if (memcmp( buffer1, buffer2, size1 )) return 0;
3860 /*******************************************************************
3861 * rename_temp_file_if_changed
3863 static void rename_temp_file_if_changed( const char *dest )
3865 FILE *file1, *file2;
3866 int do_rename = 1;
3868 if ((file1 = fopen( dest, "r" )))
3870 if ((file2 = fopen( temp_file_name, "r" )))
3872 do_rename = !are_files_identical( file1, file2 );
3873 fclose( file2 );
3875 fclose( file1 );
3877 if (!do_rename)
3879 unlink( temp_file_name );
3880 temp_file_name = NULL;
3882 else rename_temp_file( dest );
3886 /*******************************************************************
3887 * output_linguas
3889 static void output_linguas( const struct makefile *make )
3891 const char *dest = obj_dir_path( make, "LINGUAS" );
3892 struct incl_file *source;
3894 output_file = create_temp_file( dest );
3896 output( "# Automatically generated by make depend; DO NOT EDIT!!\n" );
3897 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
3898 if (strendswith( source->name, ".po" ))
3899 output( "%s\n", replace_extension( source->name, ".po", "" ));
3901 if (fclose( output_file )) fatal_perror( "write" );
3902 output_file = NULL;
3903 rename_temp_file_if_changed( dest );
3907 /*******************************************************************
3908 * output_testlist
3910 static void output_testlist( const struct makefile *make )
3912 const char *dest = obj_dir_path( make, "testlist.c" );
3913 struct strarray files = empty_strarray;
3914 unsigned int i;
3916 for (i = 0; i < make->ok_files.count; i++)
3917 strarray_add( &files, replace_extension( make->ok_files.str[i], ".ok", "" ));
3919 output_file = create_temp_file( dest );
3921 output( "/* Automatically generated by make depend; DO NOT EDIT!! */\n\n" );
3922 output( "#define WIN32_LEAN_AND_MEAN\n" );
3923 output( "#include <windows.h>\n\n" );
3924 output( "#define STANDALONE\n" );
3925 output( "#include \"wine/test.h\"\n\n" );
3927 for (i = 0; i < files.count; i++) output( "extern void func_%s(void);\n", files.str[i] );
3928 output( "\n" );
3929 output( "const struct test winetest_testlist[] =\n" );
3930 output( "{\n" );
3931 for (i = 0; i < files.count; i++) output( " { \"%s\", func_%s },\n", files.str[i], files.str[i] );
3932 output( " { 0, 0 }\n" );
3933 output( "};\n" );
3935 if (fclose( output_file )) fatal_perror( "write" );
3936 output_file = NULL;
3937 rename_temp_file_if_changed( dest );
3941 /*******************************************************************
3942 * output_gitignore
3944 static void output_gitignore( const char *dest, struct strarray files )
3946 int i;
3948 output_file = create_temp_file( dest );
3950 output( "# Automatically generated by make depend; DO NOT EDIT!!\n" );
3951 for (i = 0; i < files.count; i++)
3953 if (!strchr( files.str[i], '/' )) output( "/" );
3954 output( "%s\n", files.str[i] );
3957 if (fclose( output_file )) fatal_perror( "write" );
3958 output_file = NULL;
3959 rename_temp_file( dest );
3963 /*******************************************************************
3964 * output_stub_makefile
3966 static void output_stub_makefile( struct makefile *make )
3968 struct strarray targets = empty_strarray;
3969 const char *make_var = strarray_get_value( &top_makefile->vars, "MAKE" );
3971 if (make_var) output( "MAKE = %s\n\n", make_var );
3972 output( "all:\n" );
3974 if (make->all_targets.count) strarray_add( &targets, "all" );
3975 if (make->install_rules[INSTALL_LIB].count || make->install_rules[INSTALL_DEV].count)
3976 strarray_add( &targets, "install" );
3977 if (make->install_rules[INSTALL_LIB].count) strarray_add( &targets, "install-lib" );
3978 if (make->install_rules[INSTALL_DEV].count) strarray_add( &targets, "install-dev" );
3979 if (make->clean_files.count) strarray_add( &targets, "clean" );
3980 if (make->ok_files.count)
3982 strarray_add( &targets, "check" );
3983 strarray_add( &targets, "test" );
3984 strarray_add( &targets, "testclean" );
3987 output_filenames( targets );
3988 output_filenames( make->clean_files );
3989 output( ":\n" );
3990 output( "\t@cd %s && $(MAKE) %s/$@\n", get_relative_path( make->obj_dir, "" ), make->obj_dir );
3991 output( ".PHONY:" );
3992 output_filenames( targets );
3993 output( "\n" );
3997 /*******************************************************************
3998 * output_silent_rules
4000 static void output_silent_rules(void)
4002 static const char *cmds[] =
4004 "AR",
4005 "BISON",
4006 "BUILD",
4007 "CC",
4008 "CCLD",
4009 "FLEX",
4010 "GEN",
4011 "LN",
4012 "MSG",
4013 "SED",
4014 "TEST",
4015 "WIDL",
4016 "WMC",
4017 "WRC"
4019 unsigned int i;
4021 output( "V = 0\n" );
4022 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++)
4024 output( "quiet_%s = $(quiet_%s_$(V))\n", cmds[i], cmds[i] );
4025 output( "quiet_%s_0 = @echo \" %-5s \" $@;\n", cmds[i], cmds[i] );
4026 output( "quiet_%s_1 =\n", cmds[i] );
4031 /*******************************************************************
4032 * output_dependencies
4034 static void output_dependencies( struct makefile *make )
4036 struct strarray ignore_files = empty_strarray;
4037 char buffer[1024];
4038 FILE *src_file;
4039 int i, found = 0;
4041 if (make->obj_dir) create_dir( make->obj_dir );
4043 output_file_name = obj_dir_path( make, output_makefile_name );
4044 output_file = create_temp_file( output_file_name );
4046 /* copy the contents of the source makefile */
4047 src_file = open_input_makefile( make );
4048 while (fgets( buffer, sizeof(buffer), src_file ) && !found)
4050 if (fwrite( buffer, 1, strlen(buffer), output_file ) != strlen(buffer)) fatal_perror( "write" );
4051 found = !strncmp( buffer, separator, strlen(separator) );
4053 if (fclose( src_file )) fatal_perror( "close" );
4054 input_file_name = NULL;
4056 if (!found) output( "\n%s (everything below this line is auto-generated; DO NOT EDIT!!)\n", separator );
4058 if (make == top_makefile)
4060 if (silent_rules) output_silent_rules();
4061 for (i = 0; i < subdirs.count; i++) output_sources( submakes[i] );
4062 output_sources( make );
4064 else output_stub_makefile( make );
4066 /* disable implicit rules */
4067 output( ".SUFFIXES:\n" );
4069 fclose( output_file );
4070 output_file = NULL;
4071 rename_temp_file( output_file_name );
4073 strarray_addall( &ignore_files, make->distclean_files );
4074 strarray_addall( &ignore_files, make->clean_files );
4075 if (make->testdll) output_testlist( make );
4076 if (make->obj_dir && !strcmp( make->obj_dir, "po" )) output_linguas( make );
4077 if (!make->src_dir) output_gitignore( obj_dir_path( make, ".gitignore" ), ignore_files );
4079 create_file_directories( make, ignore_files );
4081 output_file_name = NULL;
4085 /*******************************************************************
4086 * load_sources
4088 static void load_sources( struct makefile *make )
4090 static const char *source_vars[] =
4092 "SOURCES",
4093 "C_SRCS",
4094 "OBJC_SRCS",
4095 "RC_SRCS",
4096 "MC_SRCS",
4097 "IDL_SRCS",
4098 "BISON_SRCS",
4099 "LEX_SRCS",
4100 "HEADER_SRCS",
4101 "XTEMPLATE_SRCS",
4102 "SVG_SRCS",
4103 "FONT_SRCS",
4104 "IN_SRCS",
4105 "PO_SRCS",
4106 "MANPAGES",
4107 NULL
4109 const char **var;
4110 unsigned int i;
4111 struct strarray value;
4112 struct incl_file *file;
4114 strarray_set_value( &make->vars, "top_srcdir", root_src_dir_path( "" ));
4115 strarray_set_value( &make->vars, "srcdir", src_dir_path( make, "" ));
4117 make->parent_dir = get_expanded_make_variable( make, "PARENTSRC" );
4118 make->module = get_expanded_make_variable( make, "MODULE" );
4119 make->testdll = get_expanded_make_variable( make, "TESTDLL" );
4120 make->sharedlib = get_expanded_make_variable( make, "SHAREDLIB" );
4121 make->staticlib = get_expanded_make_variable( make, "STATICLIB" );
4122 make->importlib = get_expanded_make_variable( make, "IMPORTLIB" );
4123 make->extlib = get_expanded_make_variable( make, "EXTLIB" );
4124 if (*dll_ext) make->unixlib = get_expanded_make_variable( make, "UNIXLIB" );
4126 make->programs = get_expanded_make_var_array( make, "PROGRAMS" );
4127 make->scripts = get_expanded_make_var_array( make, "SCRIPTS" );
4128 make->imports = get_expanded_make_var_array( make, "IMPORTS" );
4129 make->delayimports = get_expanded_make_var_array( make, "DELAYIMPORTS" );
4130 make->extradllflags = get_expanded_make_var_array( make, "EXTRADLLFLAGS" );
4131 make->install_lib = get_expanded_make_var_array( make, "INSTALL_LIB" );
4132 make->install_dev = get_expanded_make_var_array( make, "INSTALL_DEV" );
4133 make->extra_targets = get_expanded_make_var_array( make, "EXTRA_TARGETS" );
4135 if (make->extlib) make->staticlib = make->extlib;
4136 if (make->staticlib) make->module = make->staticlib;
4138 make->disabled = make->obj_dir && strarray_exists( &disabled_dirs, make->obj_dir );
4139 make->is_win16 = strarray_exists( &make->extradllflags, "-m16" );
4140 make->use_msvcrt = (make->module || make->testdll || make->is_win16) &&
4141 !strarray_exists( &make->extradllflags, "-mcygwin" );
4142 make->is_exe = strarray_exists( &make->extradllflags, "-mconsole" ) ||
4143 strarray_exists( &make->extradllflags, "-mwindows" );
4144 make->native_unix_lib = !!make->unixlib;
4146 if (make->use_msvcrt) strarray_add_uniq( &make->extradllflags, "-mno-cygwin" );
4148 if (make->module && !make->install_lib.count && !make->install_dev.count)
4150 if (make->importlib) strarray_add( &make->install_dev, make->importlib );
4151 if (make->staticlib) strarray_add( &make->install_dev, make->staticlib );
4152 else strarray_add( &make->install_lib, make->module );
4155 make->include_paths = empty_strarray;
4156 make->include_args = empty_strarray;
4157 make->define_args = empty_strarray;
4158 if (!make->extlib) strarray_add( &make->define_args, "-D__WINESRC__" );
4160 value = get_expanded_make_var_array( make, "EXTRAINCL" );
4161 for (i = 0; i < value.count; i++)
4162 if (!strncmp( value.str[i], "-I", 2 ))
4163 strarray_add_uniq( &make->include_paths, value.str[i] + 2 );
4164 else if (!strncmp( value.str[i], "-D", 2 ) || !strncmp( value.str[i], "-U", 2 ))
4165 strarray_add_uniq( &make->define_args, value.str[i] );
4166 strarray_addall( &make->define_args, get_expanded_make_var_array( make, "EXTRADEFS" ));
4168 strarray_add( &make->include_args, strmake( "-I%s", obj_dir_path( make, "" )));
4169 if (make->src_dir)
4170 strarray_add( &make->include_args, strmake( "-I%s", make->src_dir ));
4171 if (make->parent_dir)
4172 strarray_add( &make->include_args, strmake( "-I%s", src_dir_path( make, make->parent_dir )));
4173 strarray_add( &make->include_args, "-Iinclude" );
4174 if (root_src_dir) strarray_add( &make->include_args, strmake( "-I%s", root_src_dir_path( "include" )));
4176 list_init( &make->sources );
4177 list_init( &make->includes );
4179 for (var = source_vars; *var; var++)
4181 value = get_expanded_make_var_array( make, *var );
4182 for (i = 0; i < value.count; i++) add_src_file( make, value.str[i] );
4185 add_generated_sources( make );
4186 if (!make->unixlib) make->unixlib = get_unix_lib_name( make );
4188 if (make->use_msvcrt) add_crt_import( make, &make->imports, &make->define_args );
4190 LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry ) parse_file( make, file, 0 );
4191 LIST_FOR_EACH_ENTRY( file, &make->sources, struct incl_file, entry ) get_dependencies( file, file );
4193 make->is_cross = crosstarget && make->use_msvcrt;
4195 if (!*dll_ext || make->is_cross)
4196 for (i = 0; i < make->delayimports.count; i++)
4197 strarray_add_uniq( &delay_import_libs, get_base_name( make->delayimports.str[i] ));
4201 /*******************************************************************
4202 * parse_makeflags
4204 static void parse_makeflags( const char *flags )
4206 const char *p = flags;
4207 char *var, *buffer = xmalloc( strlen(flags) + 1 );
4209 while (*p)
4211 while (isspace(*p)) p++;
4212 var = buffer;
4213 while (*p && !isspace(*p))
4215 if (*p == '\\' && p[1]) p++;
4216 *var++ = *p++;
4218 *var = 0;
4219 if (var > buffer) set_make_variable( &cmdline_vars, buffer );
4224 /*******************************************************************
4225 * parse_option
4227 static int parse_option( const char *opt )
4229 if (opt[0] != '-')
4231 if (strchr( opt, '=' )) return set_make_variable( &cmdline_vars, opt );
4232 return 0;
4234 switch(opt[1])
4236 case 'f':
4237 if (opt[2]) output_makefile_name = opt + 2;
4238 break;
4239 case 'R':
4240 relative_dir_mode = 1;
4241 break;
4242 case 'S':
4243 silent_rules = 1;
4244 break;
4245 default:
4246 fprintf( stderr, "Unknown option '%s'\n%s", opt, Usage );
4247 exit(1);
4249 return 1;
4253 /*******************************************************************
4254 * main
4256 int main( int argc, char *argv[] )
4258 const char *makeflags = getenv( "MAKEFLAGS" );
4259 int i, j;
4261 if (makeflags) parse_makeflags( makeflags );
4263 i = 1;
4264 while (i < argc)
4266 if (parse_option( argv[i] ))
4268 for (j = i; j < argc; j++) argv[j] = argv[j+1];
4269 argc--;
4271 else i++;
4274 if (relative_dir_mode)
4276 char *relpath;
4278 if (argc != 3)
4280 fprintf( stderr, "Option -R needs two directories\n%s", Usage );
4281 exit( 1 );
4283 relpath = get_relative_path( argv[1], argv[2] );
4284 printf( "%s\n", relpath ? relpath : "." );
4285 exit( 0 );
4288 if (argc > 1) fatal_error( "Directory arguments not supported in this mode\n" );
4290 atexit( cleanup_files );
4291 signal( SIGTERM, exit_on_signal );
4292 signal( SIGINT, exit_on_signal );
4293 #ifdef SIGHUP
4294 signal( SIGHUP, exit_on_signal );
4295 #endif
4297 for (i = 0; i < HASH_SIZE; i++) list_init( &files[i] );
4299 top_makefile = parse_makefile( NULL );
4301 target_flags = get_expanded_make_var_array( top_makefile, "TARGETFLAGS" );
4302 msvcrt_flags = get_expanded_make_var_array( top_makefile, "MSVCRTFLAGS" );
4303 dll_flags = get_expanded_make_var_array( top_makefile, "DLLFLAGS" );
4304 extra_cflags = get_expanded_make_var_array( top_makefile, "EXTRACFLAGS" );
4305 extra_cross_cflags = get_expanded_make_var_array( top_makefile, "EXTRACROSSCFLAGS" );
4306 unix_dllflags = get_expanded_make_var_array( top_makefile, "UNIXDLLFLAGS" );
4307 cpp_flags = get_expanded_make_var_array( top_makefile, "CPPFLAGS" );
4308 lddll_flags = get_expanded_make_var_array( top_makefile, "LDDLLFLAGS" );
4309 libs = get_expanded_make_var_array( top_makefile, "LIBS" );
4310 enable_tests = get_expanded_make_var_array( top_makefile, "ENABLE_TESTS" );
4311 top_install_lib = get_expanded_make_var_array( top_makefile, "TOP_INSTALL_LIB" );
4312 top_install_dev = get_expanded_make_var_array( top_makefile, "TOP_INSTALL_DEV" );
4314 delay_load_flag = get_expanded_make_variable( top_makefile, "DELAYLOADFLAG" );
4315 root_src_dir = get_expanded_make_variable( top_makefile, "srcdir" );
4316 tools_dir = get_expanded_make_variable( top_makefile, "TOOLSDIR" );
4317 tools_ext = get_expanded_make_variable( top_makefile, "TOOLSEXT" );
4318 exe_ext = get_expanded_make_variable( top_makefile, "EXEEXT" );
4319 man_ext = get_expanded_make_variable( top_makefile, "api_manext" );
4320 dll_ext = (exe_ext && !strcmp( exe_ext, ".exe" )) ? "" : ".so";
4321 host_cpu = get_expanded_make_variable( top_makefile, "host_cpu" );
4322 crosstarget = get_expanded_make_variable( top_makefile, "CROSSTARGET" );
4323 crossdebug = get_expanded_make_variable( top_makefile, "CROSSDEBUG" );
4324 fontforge = get_expanded_make_variable( top_makefile, "FONTFORGE" );
4325 convert = get_expanded_make_variable( top_makefile, "CONVERT" );
4326 flex = get_expanded_make_variable( top_makefile, "FLEX" );
4327 bison = get_expanded_make_variable( top_makefile, "BISON" );
4328 ar = get_expanded_make_variable( top_makefile, "AR" );
4329 ranlib = get_expanded_make_variable( top_makefile, "RANLIB" );
4330 rsvg = get_expanded_make_variable( top_makefile, "RSVG" );
4331 icotool = get_expanded_make_variable( top_makefile, "ICOTOOL" );
4332 dlltool = get_expanded_make_variable( top_makefile, "DLLTOOL" );
4333 msgfmt = get_expanded_make_variable( top_makefile, "MSGFMT" );
4334 sed_cmd = get_expanded_make_variable( top_makefile, "SED_CMD" );
4335 ln_s = get_expanded_make_variable( top_makefile, "LN_S" );
4337 if (root_src_dir && !strcmp( root_src_dir, "." )) root_src_dir = NULL;
4338 if (tools_dir && !strcmp( tools_dir, "." )) tools_dir = NULL;
4339 if (!exe_ext) exe_ext = "";
4340 if (!tools_ext) tools_ext = "";
4341 if (!man_ext) man_ext = "3w";
4342 if (host_cpu && (host_cpu = normalize_arch( host_cpu )))
4344 so_dir = strmake( "$(dlldir)/%s-unix", host_cpu );
4345 pe_dir = strmake( "$(dlldir)/%s-windows", host_cpu );
4347 else
4348 so_dir = pe_dir = "$(dlldir)";
4350 extra_cflags_extlib = remove_warning_flags( extra_cflags );
4351 extra_cross_cflags_extlib = remove_warning_flags( extra_cross_cflags );
4353 top_makefile->src_dir = root_src_dir;
4354 subdirs = get_expanded_make_var_array( top_makefile, "SUBDIRS" );
4355 disabled_dirs = get_expanded_make_var_array( top_makefile, "DISABLED_SUBDIRS" );
4356 submakes = xmalloc( subdirs.count * sizeof(*submakes) );
4358 for (i = 0; i < subdirs.count; i++) submakes[i] = parse_makefile( subdirs.str[i] );
4360 load_sources( top_makefile );
4361 for (i = 0; i < subdirs.count; i++) load_sources( submakes[i] );
4363 output_dependencies( top_makefile );
4364 for (i = 0; i < subdirs.count; i++) output_dependencies( submakes[i] );
4366 return 0;