ntdll: Simplify the platform-specific dispatcher interface.
[wine.git] / tools / makedep.c
blobdb076d0c05771a3c66869dfe0490727a910f8377
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>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #if defined(_WIN32) && !defined(__CYGWIN__)
38 #include <direct.h>
39 #include <io.h>
40 #define mkdir(path,mode) mkdir(path)
41 #endif
42 #include "wine/list.h"
44 struct strarray
46 unsigned int count; /* strings in use */
47 unsigned int size; /* total allocated size */
48 const char **str;
51 enum incl_type
53 INCL_NORMAL, /* #include "foo.h" */
54 INCL_SYSTEM, /* #include <foo.h> */
55 INCL_IMPORT, /* idl import "foo.idl" */
56 INCL_IMPORTLIB, /* idl importlib "foo.tlb" */
57 INCL_CPP_QUOTE, /* idl cpp_quote("#include \"foo.h\"") */
58 INCL_CPP_QUOTE_SYSTEM /* idl cpp_quote("#include <foo.h>") */
61 struct dependency
63 int line; /* source line where this header is included */
64 enum incl_type type; /* type of include */
65 char *name; /* header name */
68 struct file
70 struct list entry;
71 char *name; /* full file name relative to cwd */
72 void *args; /* custom arguments for makefile rule */
73 unsigned int flags; /* flags (see below) */
74 unsigned int deps_count; /* files in use */
75 unsigned int deps_size; /* total allocated size */
76 struct dependency *deps; /* all header dependencies */
79 struct incl_file
81 struct list entry;
82 struct file *file;
83 char *name;
84 char *filename;
85 char *basename; /* base target name for generated files */
86 char *sourcename; /* source file name for generated headers */
87 struct incl_file *included_by; /* file that included this one */
88 int included_line; /* line where this file was included */
89 enum incl_type type; /* type of include */
90 int use_msvcrt; /* put msvcrt headers in the search path? */
91 struct incl_file *owner;
92 unsigned int files_count; /* files in use */
93 unsigned int files_size; /* total allocated size */
94 struct incl_file **files;
95 struct strarray dependencies; /* file dependencies */
98 #define FLAG_GENERATED 0x000001 /* generated file */
99 #define FLAG_INSTALL 0x000002 /* file to install */
100 #define FLAG_IDL_PROXY 0x000100 /* generates a proxy (_p.c) file */
101 #define FLAG_IDL_CLIENT 0x000200 /* generates a client (_c.c) file */
102 #define FLAG_IDL_SERVER 0x000400 /* generates a server (_s.c) file */
103 #define FLAG_IDL_IDENT 0x000800 /* generates an ident (_i.c) file */
104 #define FLAG_IDL_REGISTER 0x001000 /* generates a registration (_r.res) file */
105 #define FLAG_IDL_TYPELIB 0x002000 /* generates a typelib (.tlb) file */
106 #define FLAG_IDL_REGTYPELIB 0x004000 /* generates a registered typelib (_t.res) file */
107 #define FLAG_IDL_HEADER 0x008000 /* generates a header (.h) file */
108 #define FLAG_RC_PO 0x010000 /* rc file contains translations */
109 #define FLAG_C_IMPLIB 0x020000 /* file is part of an import library */
110 #define FLAG_C_UNIX 0x040000 /* file is part of a Unix library */
111 #define FLAG_SFD_FONTS 0x080000 /* sfd file generated bitmap fonts */
113 static const struct
115 unsigned int flag;
116 const char *ext;
117 } idl_outputs[] =
119 { FLAG_IDL_TYPELIB, ".tlb" },
120 { FLAG_IDL_REGTYPELIB, "_t.res" },
121 { FLAG_IDL_CLIENT, "_c.c" },
122 { FLAG_IDL_IDENT, "_i.c" },
123 { FLAG_IDL_PROXY, "_p.c" },
124 { FLAG_IDL_SERVER, "_s.c" },
125 { FLAG_IDL_REGISTER, "_r.res" },
126 { FLAG_IDL_HEADER, ".h" }
129 #define HASH_SIZE 997
131 static struct list files[HASH_SIZE];
133 static const struct strarray empty_strarray;
135 enum install_rules { INSTALL_LIB, INSTALL_DEV, NB_INSTALL_RULES };
137 /* variables common to all makefiles */
138 static struct strarray linguas;
139 static struct strarray dll_flags;
140 static struct strarray target_flags;
141 static struct strarray msvcrt_flags;
142 static struct strarray extra_cflags;
143 static struct strarray extra_cross_cflags;
144 static struct strarray cpp_flags;
145 static struct strarray lddll_flags;
146 static struct strarray libs;
147 static struct strarray enable_tests;
148 static struct strarray cmdline_vars;
149 static struct strarray subdirs;
150 static struct strarray disabled_dirs;
151 static struct strarray delay_import_libs;
152 static struct strarray top_install_lib;
153 static struct strarray top_install_dev;
154 static const char *root_src_dir;
155 static const char *tools_dir;
156 static const char *tools_ext;
157 static const char *exe_ext;
158 static const char *dll_ext;
159 static const char *man_ext;
160 static const char *arch;
161 static const char *pe_dir;
162 static const char *so_dir;
163 static const char *crosstarget;
164 static const char *crossdebug;
165 static const char *fontforge;
166 static const char *convert;
167 static const char *flex;
168 static const char *bison;
169 static const char *ar;
170 static const char *ranlib;
171 static const char *rsvg;
172 static const char *icotool;
173 static const char *dlltool;
174 static const char *msgfmt;
175 static const char *ln_s;
176 static const char *sed_cmd;
177 static const char *delay_load_flag;
179 struct makefile
181 /* values determined from input makefile */
182 struct strarray vars;
183 struct strarray include_paths;
184 struct strarray include_args;
185 struct strarray define_args;
186 struct strarray programs;
187 struct strarray scripts;
188 struct strarray imports;
189 struct strarray delayimports;
190 struct strarray extradllflags;
191 struct strarray install_lib;
192 struct strarray install_dev;
193 struct strarray extra_targets;
194 struct strarray extra_imports;
195 struct list sources;
196 struct list includes;
197 const char *src_dir;
198 const char *obj_dir;
199 const char *parent_dir;
200 const char *module;
201 const char *testdll;
202 const char *sharedlib;
203 const char *staticlib;
204 const char *staticimplib;
205 const char *importlib;
206 int disabled;
207 int use_msvcrt;
208 int is_cross;
209 int is_win16;
210 int is_exe;
212 /* values generated at output time */
213 struct strarray in_files;
214 struct strarray ok_files;
215 struct strarray pot_files;
216 struct strarray clean_files;
217 struct strarray distclean_files;
218 struct strarray uninstall_files;
219 struct strarray object_files;
220 struct strarray crossobj_files;
221 struct strarray unixobj_files;
222 struct strarray res_files;
223 struct strarray font_files;
224 struct strarray c2man_files;
225 struct strarray debug_files;
226 struct strarray dlldata_files;
227 struct strarray implib_objs;
228 struct strarray all_targets;
229 struct strarray phony_targets;
230 struct strarray dependencies;
231 struct strarray install_rules[NB_INSTALL_RULES];
234 static struct makefile *top_makefile;
235 static struct makefile **submakes;
237 static const char separator[] = "### Dependencies";
238 static const char *output_makefile_name = "Makefile";
239 static const char *input_file_name;
240 static const char *output_file_name;
241 static const char *temp_file_name;
242 static int relative_dir_mode;
243 static int silent_rules;
244 static int input_line;
245 static int output_column;
246 static FILE *output_file;
248 static const char Usage[] =
249 "Usage: makedep [options] [directories]\n"
250 "Options:\n"
251 " -R from to Compute the relative path between two directories\n"
252 " -S Generate Automake-style silent rules\n"
253 " -fxxx Store output in file 'xxx' (default: Makefile)\n";
256 #ifndef __GNUC__
257 #define __attribute__(x)
258 #endif
260 static void fatal_error( const char *msg, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
261 static void fatal_perror( const char *msg, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
262 static void output( const char *format, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
263 static char *strmake( const char* fmt, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
265 /*******************************************************************
266 * fatal_error
268 static void fatal_error( const char *msg, ... )
270 va_list valist;
271 va_start( valist, msg );
272 if (input_file_name)
274 fprintf( stderr, "%s:", input_file_name );
275 if (input_line) fprintf( stderr, "%d:", input_line );
276 fprintf( stderr, " error: " );
278 else fprintf( stderr, "makedep: error: " );
279 vfprintf( stderr, msg, valist );
280 va_end( valist );
281 exit(1);
285 /*******************************************************************
286 * fatal_perror
288 static void fatal_perror( const char *msg, ... )
290 va_list valist;
291 va_start( valist, msg );
292 if (input_file_name)
294 fprintf( stderr, "%s:", input_file_name );
295 if (input_line) fprintf( stderr, "%d:", input_line );
296 fprintf( stderr, " error: " );
298 else fprintf( stderr, "makedep: error: " );
299 vfprintf( stderr, msg, valist );
300 perror( " " );
301 va_end( valist );
302 exit(1);
306 /*******************************************************************
307 * cleanup_files
309 static void cleanup_files(void)
311 if (temp_file_name) unlink( temp_file_name );
312 if (output_file_name) unlink( output_file_name );
316 /*******************************************************************
317 * exit_on_signal
319 static void exit_on_signal( int sig )
321 exit( 1 ); /* this will call the atexit functions */
325 /*******************************************************************
326 * xmalloc
328 static void *xmalloc( size_t size )
330 void *res;
331 if (!(res = malloc (size ? size : 1)))
332 fatal_error( "Virtual memory exhausted.\n" );
333 return res;
337 /*******************************************************************
338 * xrealloc
340 static void *xrealloc (void *ptr, size_t size)
342 void *res;
343 assert( size );
344 if (!(res = realloc( ptr, size )))
345 fatal_error( "Virtual memory exhausted.\n" );
346 return res;
349 /*******************************************************************
350 * xstrdup
352 static char *xstrdup( const char *str )
354 char *res = strdup( str );
355 if (!res) fatal_error( "Virtual memory exhausted.\n" );
356 return res;
360 /*******************************************************************
361 * strmake
363 static char *strmake( const char* fmt, ... )
365 int n;
366 size_t size = 100;
367 va_list ap;
369 for (;;)
371 char *p = xmalloc (size);
372 va_start(ap, fmt);
373 n = vsnprintf (p, size, fmt, ap);
374 va_end(ap);
375 if (n == -1) size *= 2;
376 else if ((size_t)n >= size) size = n + 1;
377 else return xrealloc( p, n + 1 );
378 free(p);
383 /*******************************************************************
384 * strendswith
386 static int strendswith( const char* str, const char* end )
388 size_t l = strlen( str );
389 size_t m = strlen( end );
391 return l >= m && strcmp(str + l - m, end) == 0;
395 /*******************************************************************
396 * output
398 static void output( const char *format, ... )
400 int ret;
401 va_list valist;
403 va_start( valist, format );
404 ret = vfprintf( output_file, format, valist );
405 va_end( valist );
406 if (ret < 0) fatal_perror( "output" );
407 if (format[0] && format[strlen(format) - 1] == '\n') output_column = 0;
408 else output_column += ret;
412 /*******************************************************************
413 * strarray_add
415 static void strarray_add( struct strarray *array, const char *str )
417 if (array->count == array->size)
419 if (array->size) array->size *= 2;
420 else array->size = 16;
421 array->str = xrealloc( array->str, sizeof(array->str[0]) * array->size );
423 array->str[array->count++] = str;
427 /*******************************************************************
428 * strarray_addall
430 static void strarray_addall( struct strarray *array, struct strarray added )
432 unsigned int i;
434 for (i = 0; i < added.count; i++) strarray_add( array, added.str[i] );
438 /*******************************************************************
439 * strarray_exists
441 static int strarray_exists( const struct strarray *array, const char *str )
443 unsigned int i;
445 for (i = 0; i < array->count; i++) if (!strcmp( array->str[i], str )) return 1;
446 return 0;
450 /*******************************************************************
451 * strarray_add_uniq
453 static void strarray_add_uniq( struct strarray *array, const char *str )
455 if (!strarray_exists( array, str )) strarray_add( array, str );
459 /*******************************************************************
460 * strarray_addall_uniq
462 static void strarray_addall_uniq( struct strarray *array, struct strarray added )
464 unsigned int i;
466 for (i = 0; i < added.count; i++) strarray_add_uniq( array, added.str[i] );
470 /*******************************************************************
471 * strarray_get_value
473 * Find a value in a name/value pair string array.
475 static const char *strarray_get_value( const struct strarray *array, const char *name )
477 int pos, res, min = 0, max = array->count / 2 - 1;
479 while (min <= max)
481 pos = (min + max) / 2;
482 if (!(res = strcmp( array->str[pos * 2], name ))) return array->str[pos * 2 + 1];
483 if (res < 0) min = pos + 1;
484 else max = pos - 1;
486 return NULL;
490 /*******************************************************************
491 * strarray_set_value
493 * Define a value in a name/value pair string array.
495 static void strarray_set_value( struct strarray *array, const char *name, const char *value )
497 int i, pos, res, min = 0, max = array->count / 2 - 1;
499 while (min <= max)
501 pos = (min + max) / 2;
502 if (!(res = strcmp( array->str[pos * 2], name )))
504 /* redefining a variable replaces the previous value */
505 array->str[pos * 2 + 1] = value;
506 return;
508 if (res < 0) min = pos + 1;
509 else max = pos - 1;
511 strarray_add( array, NULL );
512 strarray_add( array, NULL );
513 for (i = array->count - 1; i > min * 2 + 1; i--) array->str[i] = array->str[i - 2];
514 array->str[min * 2] = name;
515 array->str[min * 2 + 1] = value;
519 /*******************************************************************
520 * strarray_set_qsort
522 static void strarray_qsort( struct strarray *array, int (*func)(const char **, const char **) )
524 if (array->count) qsort( array->str, array->count, sizeof(*array->str), (void *)func );
528 /*******************************************************************
529 * output_filename
531 static void output_filename( const char *name )
533 if (output_column + strlen(name) + 1 > 100)
535 output( " \\\n" );
536 output( " " );
538 else if (output_column) output( " " );
539 output( "%s", name );
543 /*******************************************************************
544 * output_filenames
546 static void output_filenames( struct strarray array )
548 unsigned int i;
550 for (i = 0; i < array.count; i++) output_filename( array.str[i] );
554 /*******************************************************************
555 * output_rm_filenames
557 static void output_rm_filenames( struct strarray array )
559 static const unsigned int max_cmdline = 30000; /* to be on the safe side */
560 unsigned int i, len;
562 if (!array.count) return;
563 output( "\trm -f" );
564 for (i = len = 0; i < array.count; i++)
566 if (len > max_cmdline)
568 output( "\n" );
569 output( "\trm -f" );
570 len = 0;
572 output_filename( array.str[i] );
573 len += strlen( array.str[i] ) + 1;
575 output( "\n" );
579 /*******************************************************************
580 * get_extension
582 static char *get_extension( char *filename )
584 char *ext = strrchr( filename, '.' );
585 if (ext && strchr( ext, '/' )) ext = NULL;
586 return ext;
590 /*******************************************************************
591 * get_base_name
593 static const char *get_base_name( const char *name )
595 char *base;
596 if (!strchr( name, '.' )) return name;
597 base = strdup( name );
598 *strrchr( base, '.' ) = 0;
599 return base;
603 /*******************************************************************
604 * replace_extension
606 static char *replace_extension( const char *name, const char *old_ext, const char *new_ext )
608 char *ret;
609 size_t name_len = strlen( name );
610 size_t ext_len = strlen( old_ext );
612 if (name_len >= ext_len && !strcmp( name + name_len - ext_len, old_ext )) name_len -= ext_len;
613 ret = xmalloc( name_len + strlen( new_ext ) + 1 );
614 memcpy( ret, name, name_len );
615 strcpy( ret + name_len, new_ext );
616 return ret;
620 /*******************************************************************
621 * replace_filename
623 static char *replace_filename( const char *path, const char *name )
625 const char *p;
626 char *ret;
627 size_t len;
629 if (!path) return xstrdup( name );
630 if (!(p = strrchr( path, '/' ))) return xstrdup( name );
631 len = p - path + 1;
632 ret = xmalloc( len + strlen( name ) + 1 );
633 memcpy( ret, path, len );
634 strcpy( ret + len, name );
635 return ret;
639 /*******************************************************************
640 * strarray_replace_extension
642 static struct strarray strarray_replace_extension( const struct strarray *array,
643 const char *old_ext, const char *new_ext )
645 unsigned int i;
646 struct strarray ret;
648 ret.count = ret.size = array->count;
649 ret.str = xmalloc( sizeof(ret.str[0]) * ret.size );
650 for (i = 0; i < array->count; i++) ret.str[i] = replace_extension( array->str[i], old_ext, new_ext );
651 return ret;
655 /*******************************************************************
656 * replace_substr
658 static char *replace_substr( const char *str, const char *start, size_t len, const char *replace )
660 size_t pos = start - str;
661 char *ret = xmalloc( pos + strlen(replace) + strlen(start + len) + 1 );
662 memcpy( ret, str, pos );
663 strcpy( ret + pos, replace );
664 strcat( ret + pos, start + len );
665 return ret;
669 /*******************************************************************
670 * get_relative_path
672 * Determine where the destination path is located relative to the 'from' path.
674 static char *get_relative_path( const char *from, const char *dest )
676 const char *start;
677 char *ret, *p;
678 unsigned int dotdots = 0;
680 /* a path of "." is equivalent to an empty path */
681 if (!strcmp( from, "." )) from = "";
683 for (;;)
685 while (*from == '/') from++;
686 while (*dest == '/') dest++;
687 start = dest; /* save start of next path element */
688 if (!*from) break;
690 while (*from && *from != '/' && *from == *dest) { from++; dest++; }
691 if ((!*from || *from == '/') && (!*dest || *dest == '/')) continue;
693 /* count remaining elements in 'from' */
696 dotdots++;
697 while (*from && *from != '/') from++;
698 while (*from == '/') from++;
700 while (*from);
701 break;
704 if (!start[0] && !dotdots) return NULL; /* empty path */
706 ret = xmalloc( 3 * dotdots + strlen( start ) + 1 );
707 for (p = ret; dotdots; dotdots--, p += 3) memcpy( p, "../", 3 );
709 if (start[0]) strcpy( p, start );
710 else p[-1] = 0; /* remove trailing slash */
711 return ret;
715 /*******************************************************************
716 * concat_paths
718 static char *concat_paths( const char *base, const char *path )
720 int i, len;
721 char *ret;
723 if (!base || !base[0]) return xstrdup( path && path[0] ? path : "." );
724 if (!path || !path[0]) return xstrdup( base );
725 if (path[0] == '/') return xstrdup( path );
727 len = strlen( base );
728 while (len && base[len - 1] == '/') len--;
729 while (len && !strncmp( path, "..", 2 ) && (!path[2] || path[2] == '/'))
731 for (i = len; i > 0; i--) if (base[i - 1] == '/') break;
732 if (i == len - 2 && !memcmp( base + i, "..", 2 )) break; /* we can't go up if we already have ".." */
733 if (i != len - 1 || base[i] != '.')
735 path += 2;
736 while (*path == '/') path++;
738 /* else ignore "." element */
739 while (i > 0 && base[i - 1] == '/') i--;
740 len = i;
742 if (!len && base[0] != '/') return xstrdup( path[0] ? path : "." );
743 ret = xmalloc( len + strlen( path ) + 2 );
744 memcpy( ret, base, len );
745 ret[len++] = '/';
746 strcpy( ret + len, path );
747 return ret;
751 /*******************************************************************
752 * obj_dir_path
754 static char *obj_dir_path( const struct makefile *make, const char *path )
756 return concat_paths( make->obj_dir, path );
760 /*******************************************************************
761 * src_dir_path
763 static char *src_dir_path( const struct makefile *make, const char *path )
765 if (make->src_dir) return concat_paths( make->src_dir, path );
766 return obj_dir_path( make, path );
770 /*******************************************************************
771 * root_src_dir_path
773 static char *root_src_dir_path( const char *path )
775 return concat_paths( root_src_dir, path );
779 /*******************************************************************
780 * tools_dir_path
782 static char *tools_dir_path( const struct makefile *make, const char *path )
784 if (tools_dir) return strmake( "%s/tools/%s", tools_dir, path );
785 return strmake( "tools/%s", path );
789 /*******************************************************************
790 * tools_path
792 static char *tools_path( const struct makefile *make, const char *name )
794 return strmake( "%s/%s%s", tools_dir_path( make, name ), name, tools_ext );
798 /*******************************************************************
799 * strarray_addall_path
801 static void strarray_addall_path( struct strarray *array, const char *dir, struct strarray added )
803 unsigned int i;
805 for (i = 0; i < added.count; i++) strarray_add( array, concat_paths( dir, added.str[i] ));
809 /*******************************************************************
810 * get_line
812 static char *get_line( FILE *file )
814 static char *buffer;
815 static size_t size;
817 if (!size)
819 size = 1024;
820 buffer = xmalloc( size );
822 if (!fgets( buffer, size, file )) return NULL;
823 input_line++;
825 for (;;)
827 char *p = buffer + strlen(buffer);
828 /* if line is larger than buffer, resize buffer */
829 while (p == buffer + size - 1 && p[-1] != '\n')
831 buffer = xrealloc( buffer, size * 2 );
832 if (!fgets( buffer + size - 1, size + 1, file )) break;
833 p = buffer + strlen(buffer);
834 size *= 2;
836 if (p > buffer && p[-1] == '\n')
838 *(--p) = 0;
839 if (p > buffer && p[-1] == '\r') *(--p) = 0;
840 if (p > buffer && p[-1] == '\\')
842 *(--p) = 0;
843 /* line ends in backslash, read continuation line */
844 if (!fgets( p, size - (p - buffer), file )) return buffer;
845 input_line++;
846 continue;
849 return buffer;
854 /*******************************************************************
855 * hash_filename
857 static unsigned int hash_filename( const char *name )
859 /* FNV-1 hash */
860 unsigned int ret = 2166136261u;
861 while (*name) ret = (ret * 16777619) ^ *name++;
862 return ret % HASH_SIZE;
866 /*******************************************************************
867 * add_file
869 static struct file *add_file( const char *name )
871 struct file *file = xmalloc( sizeof(*file) );
872 memset( file, 0, sizeof(*file) );
873 file->name = xstrdup( name );
874 return file;
878 /*******************************************************************
879 * add_dependency
881 static void add_dependency( struct file *file, const char *name, enum incl_type type )
883 /* enforce some rules for the Wine tree */
885 if (!memcmp( name, "../", 3 ))
886 fatal_error( "#include directive with relative path not allowed\n" );
888 if (!strcmp( name, "config.h" ))
890 if (strendswith( file->name, ".h" ))
891 fatal_error( "config.h must not be included by a header file\n" );
892 if (file->deps_count)
893 fatal_error( "config.h must be included before anything else\n" );
895 else if (!strcmp( name, "wine/port.h" ))
897 if (strendswith( file->name, ".h" ))
898 fatal_error( "wine/port.h must not be included by a header file\n" );
899 if (!file->deps_count) fatal_error( "config.h must be included before wine/port.h\n" );
900 if (file->deps_count > 1)
901 fatal_error( "wine/port.h must be included before everything except config.h\n" );
902 if (strcmp( file->deps[0].name, "config.h" ))
903 fatal_error( "config.h must be included before wine/port.h\n" );
906 if (file->deps_count >= file->deps_size)
908 file->deps_size *= 2;
909 if (file->deps_size < 16) file->deps_size = 16;
910 file->deps = xrealloc( file->deps, file->deps_size * sizeof(*file->deps) );
912 file->deps[file->deps_count].line = input_line;
913 file->deps[file->deps_count].type = type;
914 file->deps[file->deps_count].name = xstrdup( name );
915 file->deps_count++;
919 /*******************************************************************
920 * find_src_file
922 static struct incl_file *find_src_file( const struct makefile *make, const char *name )
924 struct incl_file *file;
926 LIST_FOR_EACH_ENTRY( file, &make->sources, struct incl_file, entry )
927 if (!strcmp( name, file->name )) return file;
928 return NULL;
931 /*******************************************************************
932 * find_include_file
934 static struct incl_file *find_include_file( const struct makefile *make, const char *name )
936 struct incl_file *file;
938 LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry )
939 if (!strcmp( name, file->name )) return file;
940 return NULL;
943 /*******************************************************************
944 * add_include
946 * Add an include file if it doesn't already exists.
948 static struct incl_file *add_include( struct makefile *make, struct incl_file *parent,
949 const char *name, int line, enum incl_type type )
951 struct incl_file *include;
953 if (parent->files_count >= parent->files_size)
955 parent->files_size *= 2;
956 if (parent->files_size < 16) parent->files_size = 16;
957 parent->files = xrealloc( parent->files, parent->files_size * sizeof(*parent->files) );
960 LIST_FOR_EACH_ENTRY( include, &make->includes, struct incl_file, entry )
961 if (!parent->use_msvcrt == !include->use_msvcrt && !strcmp( name, include->name ))
962 goto found;
964 include = xmalloc( sizeof(*include) );
965 memset( include, 0, sizeof(*include) );
966 include->name = xstrdup(name);
967 include->included_by = parent;
968 include->included_line = line;
969 include->type = type;
970 include->use_msvcrt = parent->use_msvcrt;
971 list_add_tail( &make->includes, &include->entry );
972 found:
973 parent->files[parent->files_count++] = include;
974 return include;
978 /*******************************************************************
979 * add_generated_source
981 * Add a generated source file to the list.
983 static struct incl_file *add_generated_source( struct makefile *make,
984 const char *name, const char *filename )
986 struct incl_file *file;
988 if ((file = find_src_file( make, name ))) return file; /* we already have it */
989 file = xmalloc( sizeof(*file) );
990 memset( file, 0, sizeof(*file) );
991 file->file = add_file( name );
992 file->name = xstrdup( name );
993 file->basename = xstrdup( filename ? filename : name );
994 file->filename = obj_dir_path( make, file->basename );
995 file->file->flags = FLAG_GENERATED;
996 file->use_msvcrt = make->use_msvcrt;
997 list_add_tail( &make->sources, &file->entry );
998 return file;
1002 /*******************************************************************
1003 * parse_include_directive
1005 static void parse_include_directive( struct file *source, char *str )
1007 char quote, *include, *p = str;
1009 while (*p && isspace(*p)) p++;
1010 if (*p != '\"' && *p != '<' ) return;
1011 quote = *p++;
1012 if (quote == '<') quote = '>';
1013 include = p;
1014 while (*p && (*p != quote)) p++;
1015 if (!*p) fatal_error( "malformed include directive '%s'\n", str );
1016 *p = 0;
1017 add_dependency( source, include, (quote == '>') ? INCL_SYSTEM : INCL_NORMAL );
1021 /*******************************************************************
1022 * parse_pragma_directive
1024 static void parse_pragma_directive( struct file *source, char *str )
1026 char *flag, *p = str;
1028 if (!isspace( *p )) return;
1029 while (*p && isspace(*p)) p++;
1030 p = strtok( p, " \t" );
1031 if (strcmp( p, "makedep" )) return;
1033 while ((flag = strtok( NULL, " \t" )))
1035 if (!strcmp( flag, "depend" ))
1037 while ((p = strtok( NULL, " \t" ))) add_dependency( source, p, INCL_NORMAL );
1038 return;
1040 else if (!strcmp( flag, "install" )) source->flags |= FLAG_INSTALL;
1042 if (strendswith( source->name, ".idl" ))
1044 if (!strcmp( flag, "header" )) source->flags |= FLAG_IDL_HEADER;
1045 else if (!strcmp( flag, "proxy" )) source->flags |= FLAG_IDL_PROXY;
1046 else if (!strcmp( flag, "client" )) source->flags |= FLAG_IDL_CLIENT;
1047 else if (!strcmp( flag, "server" )) source->flags |= FLAG_IDL_SERVER;
1048 else if (!strcmp( flag, "ident" )) source->flags |= FLAG_IDL_IDENT;
1049 else if (!strcmp( flag, "typelib" )) source->flags |= FLAG_IDL_TYPELIB;
1050 else if (!strcmp( flag, "register" )) source->flags |= FLAG_IDL_REGISTER;
1051 else if (!strcmp( flag, "regtypelib" )) source->flags |= FLAG_IDL_REGTYPELIB;
1053 else if (strendswith( source->name, ".rc" ))
1055 if (!strcmp( flag, "po" )) source->flags |= FLAG_RC_PO;
1057 else if (strendswith( source->name, ".sfd" ))
1059 if (!strcmp( flag, "font" ))
1061 struct strarray *array = source->args;
1063 if (!array)
1065 source->args = array = xmalloc( sizeof(*array) );
1066 *array = empty_strarray;
1067 source->flags |= FLAG_SFD_FONTS;
1069 strarray_add( array, xstrdup( strtok( NULL, "" )));
1070 return;
1073 else
1075 if (!strcmp( flag, "implib" )) source->flags |= FLAG_C_IMPLIB;
1076 if (!strcmp( flag, "unix" )) source->flags |= FLAG_C_UNIX;
1082 /*******************************************************************
1083 * parse_cpp_directive
1085 static void parse_cpp_directive( struct file *source, char *str )
1087 while (*str && isspace(*str)) str++;
1088 if (*str++ != '#') return;
1089 while (*str && isspace(*str)) str++;
1091 if (!strncmp( str, "include", 7 ))
1092 parse_include_directive( source, str + 7 );
1093 else if (!strncmp( str, "import", 6 ) && strendswith( source->name, ".m" ))
1094 parse_include_directive( source, str + 6 );
1095 else if (!strncmp( str, "pragma", 6 ))
1096 parse_pragma_directive( source, str + 6 );
1100 /*******************************************************************
1101 * parse_idl_file
1103 static void parse_idl_file( struct file *source, FILE *file )
1105 char *buffer, *include;
1107 input_line = 0;
1109 while ((buffer = get_line( file )))
1111 char quote;
1112 char *p = buffer;
1113 while (*p && isspace(*p)) p++;
1115 if (!strncmp( p, "importlib", 9 ))
1117 p += 9;
1118 while (*p && isspace(*p)) p++;
1119 if (*p++ != '(') continue;
1120 while (*p && isspace(*p)) p++;
1121 if (*p++ != '"') continue;
1122 include = p;
1123 while (*p && (*p != '"')) p++;
1124 if (!*p) fatal_error( "malformed importlib directive\n" );
1125 *p = 0;
1126 add_dependency( source, include, INCL_IMPORTLIB );
1127 continue;
1130 if (!strncmp( p, "import", 6 ))
1132 p += 6;
1133 while (*p && isspace(*p)) p++;
1134 if (*p != '"') continue;
1135 include = ++p;
1136 while (*p && (*p != '"')) p++;
1137 if (!*p) fatal_error( "malformed import directive\n" );
1138 *p = 0;
1139 add_dependency( source, include, INCL_IMPORT );
1140 continue;
1143 /* check for #include inside cpp_quote */
1144 if (!strncmp( p, "cpp_quote", 9 ))
1146 p += 9;
1147 while (*p && isspace(*p)) p++;
1148 if (*p++ != '(') continue;
1149 while (*p && isspace(*p)) p++;
1150 if (*p++ != '"') continue;
1151 if (*p++ != '#') continue;
1152 while (*p && isspace(*p)) p++;
1153 if (strncmp( p, "include", 7 )) continue;
1154 p += 7;
1155 while (*p && isspace(*p)) p++;
1156 if (*p == '\\' && p[1] == '"')
1158 p += 2;
1159 quote = '"';
1161 else
1163 if (*p++ != '<' ) continue;
1164 quote = '>';
1166 include = p;
1167 while (*p && (*p != quote)) p++;
1168 if (!*p || (quote == '"' && p[-1] != '\\'))
1169 fatal_error( "malformed #include directive inside cpp_quote\n" );
1170 if (quote == '"') p--; /* remove backslash */
1171 *p = 0;
1172 add_dependency( source, include, (quote == '>') ? INCL_CPP_QUOTE_SYSTEM : INCL_CPP_QUOTE );
1173 continue;
1176 parse_cpp_directive( source, p );
1180 /*******************************************************************
1181 * parse_c_file
1183 static void parse_c_file( struct file *source, FILE *file )
1185 char *buffer;
1187 input_line = 0;
1188 while ((buffer = get_line( file )))
1190 parse_cpp_directive( source, buffer );
1195 /*******************************************************************
1196 * parse_rc_file
1198 static void parse_rc_file( struct file *source, FILE *file )
1200 char *buffer, *include;
1202 input_line = 0;
1203 while ((buffer = get_line( file )))
1205 char quote;
1206 char *p = buffer;
1207 while (*p && isspace(*p)) p++;
1209 if (p[0] == '/' && p[1] == '*') /* check for magic makedep comment */
1211 p += 2;
1212 while (*p && isspace(*p)) p++;
1213 if (strncmp( p, "@makedep:", 9 )) continue;
1214 p += 9;
1215 while (*p && isspace(*p)) p++;
1216 quote = '"';
1217 if (*p == quote)
1219 include = ++p;
1220 while (*p && *p != quote) p++;
1222 else
1224 include = p;
1225 while (*p && !isspace(*p) && *p != '*') p++;
1227 if (!*p)
1228 fatal_error( "malformed makedep comment\n" );
1229 *p = 0;
1230 add_dependency( source, include, (quote == '>') ? INCL_SYSTEM : INCL_NORMAL );
1231 continue;
1234 parse_cpp_directive( source, buffer );
1239 /*******************************************************************
1240 * parse_in_file
1242 static void parse_in_file( struct file *source, FILE *file )
1244 char *p, *buffer;
1246 /* make sure it gets rebuilt when the version changes */
1247 add_dependency( source, "config.h", INCL_SYSTEM );
1249 if (!strendswith( source->name, ".man.in" )) return; /* not a man page */
1251 input_line = 0;
1252 while ((buffer = get_line( file )))
1254 if (strncmp( buffer, ".TH", 3 )) continue;
1255 if (!(p = strtok( buffer, " \t" ))) continue; /* .TH */
1256 if (!(p = strtok( NULL, " \t" ))) continue; /* program name */
1257 if (!(p = strtok( NULL, " \t" ))) continue; /* man section */
1258 source->args = xstrdup( p );
1259 return;
1264 /*******************************************************************
1265 * parse_sfd_file
1267 static void parse_sfd_file( struct file *source, FILE *file )
1269 char *p, *eol, *buffer;
1271 input_line = 0;
1272 while ((buffer = get_line( file )))
1274 if (strncmp( buffer, "UComments:", 10 )) continue;
1275 p = buffer + 10;
1276 while (*p == ' ') p++;
1277 if (p[0] == '"' && p[1] && buffer[strlen(buffer) - 1] == '"')
1279 p++;
1280 buffer[strlen(buffer) - 1] = 0;
1282 while ((eol = strstr( p, "+AAoA" )))
1284 *eol = 0;
1285 while (*p && isspace(*p)) p++;
1286 if (*p++ == '#')
1288 while (*p && isspace(*p)) p++;
1289 if (!strncmp( p, "pragma", 6 )) parse_pragma_directive( source, p + 6 );
1291 p = eol + 5;
1293 while (*p && isspace(*p)) p++;
1294 if (*p++ != '#') return;
1295 while (*p && isspace(*p)) p++;
1296 if (!strncmp( p, "pragma", 6 )) parse_pragma_directive( source, p + 6 );
1297 return;
1302 static const struct
1304 const char *ext;
1305 void (*parse)( struct file *file, FILE *f );
1306 } parse_functions[] =
1308 { ".c", parse_c_file },
1309 { ".h", parse_c_file },
1310 { ".inl", parse_c_file },
1311 { ".l", parse_c_file },
1312 { ".m", parse_c_file },
1313 { ".rh", parse_c_file },
1314 { ".x", parse_c_file },
1315 { ".y", parse_c_file },
1316 { ".idl", parse_idl_file },
1317 { ".rc", parse_rc_file },
1318 { ".in", parse_in_file },
1319 { ".sfd", parse_sfd_file }
1322 /*******************************************************************
1323 * load_file
1325 static struct file *load_file( const char *name )
1327 struct file *file;
1328 FILE *f;
1329 unsigned int i, hash = hash_filename( name );
1331 LIST_FOR_EACH_ENTRY( file, &files[hash], struct file, entry )
1332 if (!strcmp( name, file->name )) return file;
1334 if (!(f = fopen( name, "r" ))) return NULL;
1336 file = add_file( name );
1337 list_add_tail( &files[hash], &file->entry );
1338 input_file_name = file->name;
1339 input_line = 0;
1341 for (i = 0; i < sizeof(parse_functions) / sizeof(parse_functions[0]); i++)
1343 if (!strendswith( name, parse_functions[i].ext )) continue;
1344 parse_functions[i].parse( file, f );
1345 break;
1348 fclose( f );
1349 input_file_name = NULL;
1351 return file;
1355 /*******************************************************************
1356 * open_include_path_file
1358 * Open a file from a directory on the include path.
1360 static struct file *open_include_path_file( const struct makefile *make, const char *dir,
1361 const char *name, char **filename )
1363 char *src_path = concat_paths( dir, name );
1364 struct file *ret = load_file( src_path );
1366 if (ret) *filename = src_path;
1367 return ret;
1371 /*******************************************************************
1372 * open_file_same_dir
1374 * Open a file in the same directory as the parent.
1376 static struct file *open_file_same_dir( const struct incl_file *parent, const char *name, char **filename )
1378 char *src_path = replace_filename( parent->file->name, name );
1379 struct file *ret = load_file( src_path );
1381 if (ret) *filename = replace_filename( parent->filename, name );
1382 return ret;
1386 /*******************************************************************
1387 * open_local_file
1389 * Open a file in the source directory of the makefile.
1391 static struct file *open_local_file( const struct makefile *make, const char *path, char **filename )
1393 char *src_path = src_dir_path( make, path );
1394 struct file *ret = load_file( src_path );
1396 /* if not found, try parent dir */
1397 if (!ret && make->parent_dir)
1399 free( src_path );
1400 path = strmake( "%s/%s", make->parent_dir, path );
1401 src_path = src_dir_path( make, path );
1402 ret = load_file( src_path );
1405 if (ret) *filename = src_path;
1406 return ret;
1410 /*******************************************************************
1411 * open_global_file
1413 * Open a file in the top-level source directory.
1415 static struct file *open_global_file( const struct makefile *make, const char *path, char **filename )
1417 char *src_path = root_src_dir_path( path );
1418 struct file *ret = load_file( src_path );
1420 if (ret) *filename = src_path;
1421 return ret;
1425 /*******************************************************************
1426 * open_global_header
1428 * Open a file in the global include source directory.
1430 static struct file *open_global_header( const struct makefile *make, const char *path, char **filename )
1432 return open_global_file( make, strmake( "include/%s", path ), filename );
1436 /*******************************************************************
1437 * open_src_file
1439 static struct file *open_src_file( const struct makefile *make, struct incl_file *pFile )
1441 struct file *file = open_local_file( make, pFile->name, &pFile->filename );
1443 if (!file) fatal_perror( "open %s", pFile->name );
1444 return file;
1448 /*******************************************************************
1449 * open_include_file
1451 static struct file *open_include_file( const struct makefile *make, struct incl_file *pFile )
1453 struct file *file = NULL;
1454 char *filename;
1455 unsigned int i, len;
1457 errno = ENOENT;
1459 /* check for generated bison header */
1461 if (strendswith( pFile->name, ".tab.h" ) &&
1462 (file = open_local_file( make, replace_extension( pFile->name, ".tab.h", ".y" ), &filename )))
1464 pFile->sourcename = filename;
1465 pFile->filename = obj_dir_path( make, pFile->name );
1466 return file;
1469 /* check for corresponding idl file in source dir */
1471 if (strendswith( pFile->name, ".h" ) &&
1472 (file = open_local_file( make, replace_extension( pFile->name, ".h", ".idl" ), &filename )))
1474 pFile->sourcename = filename;
1475 pFile->filename = obj_dir_path( make, pFile->name );
1476 return file;
1479 /* check for corresponding tlb file in source dir */
1481 if (strendswith( pFile->name, ".tlb" ) &&
1482 (file = open_local_file( make, replace_extension( pFile->name, ".tlb", ".idl" ), &filename )))
1484 pFile->sourcename = filename;
1485 pFile->filename = obj_dir_path( make, pFile->name );
1486 return file;
1489 /* check for extra targets */
1490 if (strarray_exists( &make->extra_targets, pFile->name ))
1492 pFile->sourcename = src_dir_path( make, pFile->name );
1493 pFile->filename = obj_dir_path( make, pFile->name );
1494 return NULL;
1497 /* now try in source dir */
1498 if ((file = open_local_file( make, pFile->name, &pFile->filename ))) return file;
1500 /* check for corresponding idl file in global includes */
1502 if (strendswith( pFile->name, ".h" ) &&
1503 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".idl" ), &filename )))
1505 pFile->sourcename = filename;
1506 pFile->filename = strmake( "include/%s", pFile->name );
1507 return file;
1510 /* check for corresponding .in file in global includes (for config.h.in) */
1512 if (strendswith( pFile->name, ".h" ) &&
1513 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".h.in" ), &filename )))
1515 pFile->sourcename = filename;
1516 pFile->filename = strmake( "include/%s", pFile->name );
1517 return file;
1520 /* check for corresponding .x file in global includes */
1522 if (strendswith( pFile->name, "tmpl.h" ) &&
1523 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".x" ), &filename )))
1525 pFile->sourcename = filename;
1526 pFile->filename = strmake( "include/%s", pFile->name );
1527 return file;
1530 /* check for corresponding .tlb file in global includes */
1532 if (strendswith( pFile->name, ".tlb" ) &&
1533 (file = open_global_header( make, replace_extension( pFile->name, ".tlb", ".idl" ), &filename )))
1535 pFile->sourcename = filename;
1536 pFile->filename = strmake( "include/%s", pFile->name );
1537 return file;
1540 /* check in global includes source dir */
1542 if ((file = open_global_header( make, pFile->name, &pFile->filename ))) return file;
1544 /* check in global msvcrt includes */
1545 if (pFile->use_msvcrt &&
1546 (file = open_global_header( make, strmake( "msvcrt/%s", pFile->name ), &pFile->filename )))
1547 return file;
1549 /* now search in include paths */
1550 for (i = 0; i < make->include_paths.count; i++)
1552 const char *dir = make->include_paths.str[i];
1554 if (root_src_dir)
1556 len = strlen( root_src_dir );
1557 if (!strncmp( dir, root_src_dir, len ) && (!dir[len] || dir[len] == '/'))
1559 while (dir[len] == '/') len++;
1560 file = open_global_file( make, concat_paths( dir + len, pFile->name ), &pFile->filename );
1561 if (file) return file;
1563 continue; /* ignore paths that don't point to the top source dir */
1565 if (*dir != '/')
1567 if ((file = open_include_path_file( make, dir, pFile->name, &pFile->filename )))
1568 return file;
1572 if (pFile->type == INCL_SYSTEM && pFile->use_msvcrt)
1574 if (!strcmp( pFile->name, "stdarg.h" )) return NULL;
1575 if (!strcmp( pFile->name, "x86intrin.h" )) return NULL;
1576 fprintf( stderr, "%s:%d: error: system header %s cannot be used with msvcrt\n",
1577 pFile->included_by->file->name, pFile->included_line, pFile->name );
1578 exit(1);
1581 if (pFile->type == INCL_SYSTEM) return NULL; /* ignore system files we cannot find */
1583 /* try in src file directory */
1584 if ((file = open_file_same_dir( pFile->included_by, pFile->name, &pFile->filename ))) return file;
1586 fprintf( stderr, "%s:%d: error: ", pFile->included_by->file->name, pFile->included_line );
1587 perror( pFile->name );
1588 pFile = pFile->included_by;
1589 while (pFile && pFile->included_by)
1591 const char *parent = pFile->included_by->sourcename;
1592 if (!parent) parent = pFile->included_by->file->name;
1593 fprintf( stderr, "%s:%d: note: %s was first included here\n",
1594 parent, pFile->included_line, pFile->name );
1595 pFile = pFile->included_by;
1597 exit(1);
1601 /*******************************************************************
1602 * add_all_includes
1604 static void add_all_includes( struct makefile *make, struct incl_file *parent, struct file *file )
1606 unsigned int i;
1608 parent->files_count = 0;
1609 parent->files_size = file->deps_count;
1610 parent->files = xmalloc( parent->files_size * sizeof(*parent->files) );
1611 for (i = 0; i < file->deps_count; i++)
1613 switch (file->deps[i].type)
1615 case INCL_NORMAL:
1616 case INCL_IMPORT:
1617 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1618 break;
1619 case INCL_IMPORTLIB:
1620 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_IMPORTLIB );
1621 break;
1622 case INCL_SYSTEM:
1623 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_SYSTEM );
1624 break;
1625 case INCL_CPP_QUOTE:
1626 case INCL_CPP_QUOTE_SYSTEM:
1627 break;
1633 /*******************************************************************
1634 * parse_file
1636 static void parse_file( struct makefile *make, struct incl_file *source, int src )
1638 struct file *file = src ? open_src_file( make, source ) : open_include_file( make, source );
1640 if (!file) return;
1642 source->file = file;
1643 source->files_count = 0;
1644 source->files_size = file->deps_count;
1645 source->files = xmalloc( source->files_size * sizeof(*source->files) );
1646 if (file->flags & FLAG_C_UNIX) source->use_msvcrt = 0;
1647 else if (file->flags & FLAG_C_IMPLIB) source->use_msvcrt = 1;
1649 if (source->sourcename)
1651 if (strendswith( source->sourcename, ".idl" ))
1653 unsigned int i;
1655 if (strendswith( source->name, ".tlb" )) return; /* typelibs don't include anything */
1657 /* generated .h file always includes these */
1658 add_include( make, source, "rpc.h", 0, INCL_NORMAL );
1659 add_include( make, source, "rpcndr.h", 0, INCL_NORMAL );
1660 for (i = 0; i < file->deps_count; i++)
1662 switch (file->deps[i].type)
1664 case INCL_IMPORT:
1665 if (strendswith( file->deps[i].name, ".idl" ))
1666 add_include( make, source, replace_extension( file->deps[i].name, ".idl", ".h" ),
1667 file->deps[i].line, INCL_NORMAL );
1668 else
1669 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1670 break;
1671 case INCL_CPP_QUOTE:
1672 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1673 break;
1674 case INCL_CPP_QUOTE_SYSTEM:
1675 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_SYSTEM );
1676 break;
1677 case INCL_NORMAL:
1678 case INCL_SYSTEM:
1679 case INCL_IMPORTLIB:
1680 break;
1683 return;
1685 if (strendswith( source->sourcename, ".y" ))
1686 return; /* generated .tab.h doesn't include anything */
1689 add_all_includes( make, source, file );
1693 /*******************************************************************
1694 * add_src_file
1696 * Add a source file to the list.
1698 static struct incl_file *add_src_file( struct makefile *make, const char *name )
1700 struct incl_file *file;
1702 if ((file = find_src_file( make, name ))) return file; /* we already have it */
1703 file = xmalloc( sizeof(*file) );
1704 memset( file, 0, sizeof(*file) );
1705 file->name = xstrdup(name);
1706 file->use_msvcrt = make->use_msvcrt;
1707 list_add_tail( &make->sources, &file->entry );
1708 parse_file( make, file, 1 );
1709 return file;
1713 /*******************************************************************
1714 * open_input_makefile
1716 static FILE *open_input_makefile( const struct makefile *make )
1718 FILE *ret;
1720 if (make->obj_dir)
1721 input_file_name = root_src_dir_path( obj_dir_path( make, strmake( "%s.in", output_makefile_name )));
1722 else
1723 input_file_name = output_makefile_name; /* always use output name for main Makefile */
1725 input_line = 0;
1726 if (!(ret = fopen( input_file_name, "r" ))) fatal_perror( "open" );
1727 return ret;
1731 /*******************************************************************
1732 * get_make_variable
1734 static const char *get_make_variable( const struct makefile *make, const char *name )
1736 const char *ret;
1738 if ((ret = strarray_get_value( &cmdline_vars, name ))) return ret;
1739 if ((ret = strarray_get_value( &make->vars, name ))) return ret;
1740 if (top_makefile && (ret = strarray_get_value( &top_makefile->vars, name ))) return ret;
1741 return NULL;
1745 /*******************************************************************
1746 * get_expanded_make_variable
1748 static char *get_expanded_make_variable( const struct makefile *make, const char *name )
1750 const char *var;
1751 char *p, *end, *expand, *tmp;
1753 var = get_make_variable( make, name );
1754 if (!var) return NULL;
1756 p = expand = xstrdup( var );
1757 while ((p = strchr( p, '$' )))
1759 if (p[1] == '(')
1761 if (!(end = strchr( p + 2, ')' ))) fatal_error( "syntax error in '%s'\n", expand );
1762 *end++ = 0;
1763 if (strchr( p + 2, ':' )) fatal_error( "pattern replacement not supported for '%s'\n", p + 2 );
1764 var = get_make_variable( make, p + 2 );
1765 tmp = replace_substr( expand, p, end - p, var ? var : "" );
1766 /* switch to the new string */
1767 p = tmp + (p - expand);
1768 free( expand );
1769 expand = tmp;
1771 else if (p[1] == '{') /* don't expand ${} variables */
1773 if (!(end = strchr( p + 2, '}' ))) fatal_error( "syntax error in '%s'\n", expand );
1774 p = end + 1;
1776 else if (p[1] == '$')
1778 p += 2;
1780 else fatal_error( "syntax error in '%s'\n", expand );
1783 /* consider empty variables undefined */
1784 p = expand;
1785 while (*p && isspace(*p)) p++;
1786 if (*p) return expand;
1787 free( expand );
1788 return NULL;
1792 /*******************************************************************
1793 * get_expanded_make_var_array
1795 static struct strarray get_expanded_make_var_array( const struct makefile *make, const char *name )
1797 struct strarray ret = empty_strarray;
1798 char *value, *token;
1800 if ((value = get_expanded_make_variable( make, name )))
1801 for (token = strtok( value, " \t" ); token; token = strtok( NULL, " \t" ))
1802 strarray_add( &ret, token );
1803 return ret;
1807 /*******************************************************************
1808 * get_expanded_file_local_var
1810 static struct strarray get_expanded_file_local_var( const struct makefile *make, const char *file,
1811 const char *name )
1813 char *p, *var = strmake( "%s_%s", file, name );
1815 for (p = var; *p; p++) if (!isalnum( *p )) *p = '_';
1816 return get_expanded_make_var_array( make, var );
1820 /*******************************************************************
1821 * set_make_variable
1823 static int set_make_variable( struct strarray *array, const char *assignment )
1825 char *p, *name;
1827 p = name = xstrdup( assignment );
1828 while (isalnum(*p) || *p == '_') p++;
1829 if (name == p) return 0; /* not a variable */
1830 if (isspace(*p))
1832 *p++ = 0;
1833 while (isspace(*p)) p++;
1835 if (*p != '=') return 0; /* not an assignment */
1836 *p++ = 0;
1837 while (isspace(*p)) p++;
1839 strarray_set_value( array, name, p );
1840 return 1;
1844 /*******************************************************************
1845 * parse_makefile
1847 static struct makefile *parse_makefile( const char *path )
1849 char *buffer;
1850 FILE *file;
1851 struct makefile *make = xmalloc( sizeof(*make) );
1853 memset( make, 0, sizeof(*make) );
1854 make->obj_dir = path;
1855 if (root_src_dir) make->src_dir = root_src_dir_path( make->obj_dir );
1857 file = open_input_makefile( make );
1858 while ((buffer = get_line( file )))
1860 if (!strncmp( buffer, separator, strlen(separator) )) break;
1861 if (*buffer == '\t') continue; /* command */
1862 while (isspace( *buffer )) buffer++;
1863 if (*buffer == '#') continue; /* comment */
1864 set_make_variable( &make->vars, buffer );
1866 fclose( file );
1867 input_file_name = NULL;
1868 return make;
1872 /*******************************************************************
1873 * add_generated_sources
1875 static void add_generated_sources( struct makefile *make )
1877 unsigned int i;
1878 struct incl_file *source, *next, *file;
1879 struct strarray objs = get_expanded_make_var_array( make, "EXTRA_OBJS" );
1881 LIST_FOR_EACH_ENTRY_SAFE( source, next, &make->sources, struct incl_file, entry )
1883 if (source->file->flags & FLAG_IDL_CLIENT)
1885 file = add_generated_source( make, replace_extension( source->name, ".idl", "_c.c" ), NULL );
1886 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1887 add_all_includes( make, file, file->file );
1889 if (source->file->flags & FLAG_IDL_SERVER)
1891 file = add_generated_source( make, replace_extension( source->name, ".idl", "_s.c" ), NULL );
1892 add_dependency( file->file, "wine/exception.h", INCL_NORMAL );
1893 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1894 add_all_includes( make, file, file->file );
1896 if (source->file->flags & FLAG_IDL_IDENT)
1898 file = add_generated_source( make, replace_extension( source->name, ".idl", "_i.c" ), NULL );
1899 add_dependency( file->file, "rpc.h", INCL_NORMAL );
1900 add_dependency( file->file, "rpcndr.h", INCL_NORMAL );
1901 add_dependency( file->file, "guiddef.h", INCL_NORMAL );
1902 add_all_includes( make, file, file->file );
1904 if (source->file->flags & FLAG_IDL_PROXY)
1906 file = add_generated_source( make, "dlldata.o", "dlldata.c" );
1907 add_dependency( file->file, "objbase.h", INCL_NORMAL );
1908 add_dependency( file->file, "rpcproxy.h", INCL_NORMAL );
1909 add_all_includes( make, file, file->file );
1910 file = add_generated_source( make, replace_extension( source->name, ".idl", "_p.c" ), NULL );
1911 add_dependency( file->file, "objbase.h", INCL_NORMAL );
1912 add_dependency( file->file, "rpcproxy.h", INCL_NORMAL );
1913 add_dependency( file->file, "wine/exception.h", INCL_NORMAL );
1914 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1915 add_all_includes( make, file, file->file );
1917 if (source->file->flags & FLAG_IDL_TYPELIB)
1919 add_generated_source( make, replace_extension( source->name, ".idl", ".tlb" ), NULL );
1921 if (source->file->flags & FLAG_IDL_REGTYPELIB)
1923 add_generated_source( make, replace_extension( source->name, ".idl", "_t.res" ), NULL );
1925 if (source->file->flags & FLAG_IDL_REGISTER)
1927 add_generated_source( make, replace_extension( source->name, ".idl", "_r.res" ), NULL );
1929 if (source->file->flags & FLAG_IDL_HEADER)
1931 add_generated_source( make, replace_extension( source->name, ".idl", ".h" ), NULL );
1933 if (!source->file->flags && strendswith( source->name, ".idl" ))
1935 add_generated_source( make, replace_extension( source->name, ".idl", ".h" ), NULL );
1937 if (strendswith( source->name, ".x" ))
1939 add_generated_source( make, replace_extension( source->name, ".x", ".h" ), NULL );
1941 if (strendswith( source->name, ".y" ))
1943 file = add_generated_source( make, replace_extension( source->name, ".y", ".tab.c" ), NULL );
1944 /* steal the includes list from the source file */
1945 file->files_count = source->files_count;
1946 file->files_size = source->files_size;
1947 file->files = source->files;
1948 source->files_count = source->files_size = 0;
1949 source->files = NULL;
1951 if (strendswith( source->name, ".l" ))
1953 file = add_generated_source( make, replace_extension( source->name, ".l", ".yy.c" ), NULL );
1954 /* steal the includes list from the source file */
1955 file->files_count = source->files_count;
1956 file->files_size = source->files_size;
1957 file->files = source->files;
1958 source->files_count = source->files_size = 0;
1959 source->files = NULL;
1961 if (source->file->flags & FLAG_C_IMPLIB)
1963 if (!make->staticimplib && make->importlib && *dll_ext)
1964 make->staticimplib = strmake( "lib%s.a", make->importlib );
1966 if (strendswith( source->name, ".po" ))
1968 if (!make->disabled)
1969 strarray_add_uniq( &linguas, replace_extension( source->name, ".po", "" ));
1971 if (strendswith( source->name, ".spec" ))
1973 char *obj = replace_extension( source->name, ".spec", "" );
1974 strarray_addall_uniq( &make->extra_imports,
1975 get_expanded_file_local_var( make, obj, "IMPORTS" ));
1978 if (make->testdll)
1980 file = add_generated_source( make, "testlist.o", "testlist.c" );
1981 add_dependency( file->file, "wine/test.h", INCL_NORMAL );
1982 add_all_includes( make, file, file->file );
1984 for (i = 0; i < objs.count; i++)
1986 /* default to .c for unknown extra object files */
1987 if (strendswith( objs.str[i], ".o" ))
1989 file = add_generated_source( make, objs.str[i], replace_extension( objs.str[i], ".o", ".c" ));
1990 if (make->module || make->staticlib) file->file->flags |= FLAG_C_UNIX;
1992 else if (strendswith( objs.str[i], ".res" ))
1993 add_generated_source( make, replace_extension( objs.str[i], ".res", ".rc" ), NULL );
1994 else
1995 add_generated_source( make, objs.str[i], NULL );
2000 /*******************************************************************
2001 * create_dir
2003 static void create_dir( const char *dir )
2005 char *p, *path;
2007 p = path = xstrdup( dir );
2008 while ((p = strchr( p, '/' )))
2010 *p = 0;
2011 if (mkdir( path, 0755 ) == -1 && errno != EEXIST) fatal_perror( "mkdir %s", path );
2012 *p++ = '/';
2013 while (*p == '/') p++;
2015 if (mkdir( path, 0755 ) == -1 && errno != EEXIST) fatal_perror( "mkdir %s", path );
2016 free( path );
2020 /*******************************************************************
2021 * create_file_directories
2023 * Create the base directories of all the files.
2025 static void create_file_directories( const struct makefile *make, struct strarray files )
2027 struct strarray subdirs = empty_strarray;
2028 unsigned int i;
2029 char *dir;
2031 for (i = 0; i < files.count; i++)
2033 if (!strchr( files.str[i], '/' )) continue;
2034 dir = obj_dir_path( make, files.str[i] );
2035 *strrchr( dir, '/' ) = 0;
2036 strarray_add_uniq( &subdirs, dir );
2039 for (i = 0; i < subdirs.count; i++) create_dir( subdirs.str[i] );
2043 /*******************************************************************
2044 * output_filenames_obj_dir
2046 static void output_filenames_obj_dir( const struct makefile *make, struct strarray array )
2048 unsigned int i;
2050 for (i = 0; i < array.count; i++) output_filename( obj_dir_path( make, array.str[i] ));
2054 /*******************************************************************
2055 * get_dependencies
2057 static void get_dependencies( struct incl_file *file, struct incl_file *source )
2059 unsigned int i;
2061 if (!file->filename) return;
2063 if (file != source)
2065 if (file->owner == source) return; /* already processed */
2066 if (file->type == INCL_IMPORTLIB &&
2067 !(source->file->flags & (FLAG_IDL_TYPELIB | FLAG_IDL_REGTYPELIB)))
2068 return; /* library is imported only when building a typelib */
2069 file->owner = source;
2070 strarray_add( &source->dependencies, file->filename );
2072 for (i = 0; i < file->files_count; i++) get_dependencies( file->files[i], source );
2076 /*******************************************************************
2077 * get_local_dependencies
2079 * Get the local dependencies of a given target.
2081 static struct strarray get_local_dependencies( const struct makefile *make, const char *name,
2082 struct strarray targets )
2084 unsigned int i;
2085 struct strarray deps = get_expanded_file_local_var( make, name, "DEPS" );
2087 for (i = 0; i < deps.count; i++)
2089 if (strarray_exists( &targets, deps.str[i] ))
2090 deps.str[i] = obj_dir_path( make, deps.str[i] );
2091 else
2092 deps.str[i] = src_dir_path( make, deps.str[i] );
2094 return deps;
2098 /*******************************************************************
2099 * get_static_lib
2101 * Check if makefile builds the named static library and return the full lib path.
2103 static const char *get_static_lib( const struct makefile *make, const char *name )
2105 if (!make->staticlib) return NULL;
2106 if (strncmp( make->staticlib, "lib", 3 )) return NULL;
2107 if (strncmp( make->staticlib + 3, name, strlen(name) )) return NULL;
2108 if (strcmp( make->staticlib + 3 + strlen(name), ".a" )) return NULL;
2109 return obj_dir_path( make, make->staticlib );
2113 /*******************************************************************
2114 * get_parent_makefile
2116 static struct makefile *get_parent_makefile( struct makefile *make )
2118 char *dir, *p;
2119 int i;
2121 if (!make->obj_dir) return NULL;
2122 dir = xstrdup( make->obj_dir );
2123 if (!(p = strrchr( dir, '/' ))) return NULL;
2124 *p = 0;
2125 for (i = 0; i < subdirs.count; i++)
2126 if (!strcmp( submakes[i]->obj_dir, dir )) return submakes[i];
2127 return NULL;
2131 /*******************************************************************
2132 * needs_delay_lib
2134 static int needs_delay_lib( const struct makefile *make )
2136 if (delay_load_flag) return 0;
2137 if (*dll_ext && !crosstarget) return 0;
2138 if (!make->importlib) return 0;
2139 return strarray_exists( &delay_import_libs, make->importlib );
2143 /*******************************************************************
2144 * needs_implib_symlink
2146 static int needs_implib_symlink( const struct makefile *make )
2148 if (!make->module) return 0;
2149 if (!make->importlib) return 0;
2150 if (make->is_win16 && make->disabled) return 0;
2151 if (strncmp( make->obj_dir, "dlls/", 5 )) return 0;
2152 if (!strcmp( make->module, make->importlib )) return 0;
2153 if (!strchr( make->importlib, '.' ) &&
2154 !strncmp( make->module, make->importlib, strlen( make->importlib )) &&
2155 !strcmp( make->module + strlen( make->importlib ), ".dll" ))
2156 return 0;
2157 return 1;
2161 /*******************************************************************
2162 * add_unix_libraries
2164 static struct strarray add_unix_libraries( const struct makefile *make, struct strarray *deps )
2166 struct strarray ret = empty_strarray;
2167 struct strarray all_libs = empty_strarray;
2168 unsigned int i, j;
2170 strarray_add( &all_libs, "-lwine_port" );
2171 strarray_addall( &all_libs, get_expanded_make_var_array( make, "EXTRALIBS" ));
2172 strarray_addall( &all_libs, libs );
2174 for (i = 0; i < all_libs.count; i++)
2176 const char *lib = NULL;
2178 if (!strncmp( all_libs.str[i], "-l", 2 ))
2180 const char *name = all_libs.str[i] + 2;
2182 for (j = 0; j < subdirs.count; j++)
2183 if ((lib = get_static_lib( submakes[j], name ))) break;
2186 if (lib)
2188 strarray_add( deps, lib );
2189 strarray_add( &ret, lib );
2191 else strarray_add( &ret, all_libs.str[i] );
2193 return ret;
2197 /*******************************************************************
2198 * add_import_libs
2200 static struct strarray add_import_libs( const struct makefile *make, struct strarray *deps,
2201 struct strarray imports, int delay, int is_unix )
2203 struct strarray ret = empty_strarray;
2204 unsigned int i, j;
2205 int is_cross = make->is_cross && !is_unix;
2207 for (i = 0; i < imports.count; i++)
2209 const char *name = get_base_name( imports.str[i] );
2210 const char *lib = NULL;
2212 for (j = 0; j < subdirs.count; j++)
2214 if (submakes[j]->importlib && !strcmp( submakes[j]->importlib, name ))
2216 if (is_cross || !*dll_ext || submakes[j]->staticimplib)
2217 lib = obj_dir_path( submakes[j], strmake( "lib%s.a", name ));
2218 else
2220 strarray_add( deps, strmake( "%s/lib%s.def", submakes[j]->obj_dir, name ));
2221 if (needs_implib_symlink( submakes[j] ))
2222 strarray_add( deps, strmake( "dlls/lib%s.def", name ));
2224 break;
2227 if ((lib = get_static_lib( submakes[j], name ))) break;
2230 if (lib)
2232 const char *ext = NULL;
2234 if (delay && !delay_load_flag && (is_cross || !*dll_ext)) ext = ".delay.a";
2235 else if (is_cross) ext = ".cross.a";
2236 if (ext) lib = replace_extension( lib, ".a", ext );
2237 strarray_add( deps, lib );
2238 strarray_add( &ret, lib );
2239 if (needs_implib_symlink( submakes[j] ))
2240 strarray_add( deps, strmake( "dlls/lib%s%s", name, ext ? ext : ".a" ));
2242 else strarray_add( &ret, strmake( "-l%s", name ));
2244 return ret;
2248 /*******************************************************************
2249 * get_default_imports
2251 static struct strarray get_default_imports( const struct makefile *make )
2253 struct strarray ret = empty_strarray;
2255 if (strarray_exists( &make->extradllflags, "-nodefaultlibs" )) return ret;
2256 strarray_add( &ret, "winecrt0" );
2257 if (make->is_win16) strarray_add( &ret, "kernel" );
2258 strarray_add( &ret, "kernel32" );
2259 strarray_add( &ret, "ntdll" );
2260 return ret;
2264 /*******************************************************************
2265 * is_crt_module
2267 static int is_crt_module( const char *file )
2269 return !strncmp( file, "msvcr", 5 ) || !strncmp( file, "ucrt", 4 ) || !strcmp( file, "crtdll.dll" );
2273 /*******************************************************************
2274 * add_crt_import
2276 static void add_crt_import( const struct makefile *make, struct strarray *imports, struct strarray *defs )
2278 unsigned int i;
2279 const char *crt_dll = NULL;
2281 for (i = 0; i < imports->count; i++)
2283 if (!is_crt_module( imports->str[i])) continue;
2284 if (crt_dll) fatal_error( "More than one C runtime DLL imported: %s and %s\n", crt_dll, imports->str[i] );
2285 crt_dll = imports->str[i];
2287 if (!crt_dll && !strarray_exists( &make->extradllflags, "-nodefaultlibs" ))
2289 if (make->module && is_crt_module( make->module ))
2291 crt_dll = make->module;
2293 else
2295 crt_dll = !make->testdll && !make->staticlib ? "ucrtbase" : "msvcrt";
2296 strarray_add( imports, crt_dll );
2300 if (!defs) return;
2301 if (crt_dll && !strncmp( crt_dll, "ucrt", 4 )) strarray_add( defs, "-D_UCRT" );
2302 else
2304 unsigned int version = 0;
2305 if (crt_dll) sscanf( crt_dll, "msvcr%u", &version );
2306 strarray_add( defs, strmake( "-D_MSVCR_VER=%u", version ));
2311 /*******************************************************************
2312 * add_install_rule
2314 static void add_install_rule( struct makefile *make, const char *target,
2315 const char *file, const char *dest )
2317 if (strarray_exists( &make->install_lib, target ) ||
2318 strarray_exists( &top_install_lib, make->obj_dir ) ||
2319 strarray_exists( &top_install_lib, obj_dir_path( make, target )))
2321 strarray_add( &make->install_rules[INSTALL_LIB], file );
2322 strarray_add( &make->install_rules[INSTALL_LIB], dest );
2324 else if (strarray_exists( &make->install_dev, target ) ||
2325 strarray_exists( &top_install_dev, make->obj_dir ) ||
2326 strarray_exists( &top_install_dev, obj_dir_path( make, target )))
2328 strarray_add( &make->install_rules[INSTALL_DEV], file );
2329 strarray_add( &make->install_rules[INSTALL_DEV], dest );
2334 /*******************************************************************
2335 * get_include_install_path
2337 * Determine the installation path for a given include file.
2339 static const char *get_include_install_path( const char *name )
2341 if (!strncmp( name, "wine/", 5 )) return name + 5;
2342 if (!strncmp( name, "msvcrt/", 7 )) return name;
2343 return strmake( "windows/%s", name );
2347 /*******************************************************************
2348 * get_shared_library_name
2350 * Determine possible names for a shared library with a version number.
2352 static struct strarray get_shared_lib_names( const char *libname )
2354 struct strarray ret = empty_strarray;
2355 const char *ext, *p;
2356 char *name, *first, *second;
2357 size_t len = 0;
2359 strarray_add( &ret, libname );
2361 for (p = libname; (p = strchr( p, '.' )); p++)
2362 if ((len = strspn( p + 1, "0123456789." ))) break;
2364 if (!len) return ret;
2365 ext = p + 1 + len;
2366 if (*ext && ext[-1] == '.') ext--;
2368 /* keep only the first group of digits */
2369 name = xstrdup( libname );
2370 first = name + (p - libname);
2371 if ((second = strchr( first + 1, '.' )))
2373 strcpy( second, ext );
2374 strarray_add( &ret, xstrdup( name ));
2376 return ret;
2380 /*******************************************************************
2381 * get_source_defines
2383 static struct strarray get_source_defines( struct makefile *make, struct incl_file *source,
2384 const char *obj )
2386 unsigned int i;
2387 struct strarray ret = empty_strarray;
2389 strarray_addall( &ret, make->include_args );
2390 if (source->use_msvcrt)
2391 strarray_add( &ret, strmake( "-I%s", root_src_dir_path( "include/msvcrt" )));
2392 for (i = 0; i < make->include_paths.count; i++)
2393 strarray_add( &ret, strmake( "-I%s", make->include_paths.str[i] ));
2394 strarray_addall( &ret, make->define_args );
2395 strarray_addall( &ret, get_expanded_file_local_var( make, obj, "EXTRADEFS" ));
2396 if ((source->file->flags & FLAG_C_UNIX) && *dll_ext) strarray_add( &ret, "-DWINE_UNIX_LIB" );
2397 return ret;
2401 /*******************************************************************
2402 * get_debug_file
2404 static const char *get_debug_file( struct makefile *make, const char *name )
2406 const char *debug_file = NULL;
2407 if (!make->is_cross || !crossdebug) return NULL;
2408 if (!strcmp( crossdebug, "pdb" )) debug_file = strmake( "%s.pdb", get_base_name( name ));
2409 else if(!strncmp( crossdebug, "split", 5 )) debug_file = strmake( "%s.debug", name );
2410 if (debug_file) strarray_add( &make->debug_files, debug_file );
2411 return debug_file;
2415 /*******************************************************************
2416 * cmd_prefix
2418 static const char *cmd_prefix( const char *cmd )
2420 if (!silent_rules) return "";
2421 return strmake( "$(quiet_%s)", cmd );
2425 /*******************************************************************
2426 * output_winegcc_command
2428 static void output_winegcc_command( struct makefile *make, int is_cross )
2430 output( "\t%s%s -o $@", cmd_prefix( "CCLD" ), tools_path( make, "winegcc" ));
2431 output_filename( "--wine-objdir ." );
2432 if (tools_dir)
2434 output_filename( "--winebuild" );
2435 output_filename( tools_path( make, "winebuild" ));
2437 if (is_cross)
2439 output_filename( "-b" );
2440 output_filename( crosstarget );
2441 output_filename( "--lib-suffix=.cross.a" );
2443 else
2445 output_filenames( target_flags );
2446 output_filenames( lddll_flags );
2451 /*******************************************************************
2452 * output_symlink_rule
2454 * Output a rule to create a symlink.
2456 static void output_symlink_rule( const char *src_name, const char *link_name, int create_dir )
2458 const char *name = strrchr( link_name, '/' );
2459 char *dir = NULL;
2461 if (name)
2463 dir = xstrdup( link_name );
2464 dir[name - link_name] = 0;
2467 output( "\t%s", cmd_prefix( "LN" ));
2468 if (create_dir && dir && *dir) output( "%s -d %s && ", root_src_dir_path( "tools/install-sh" ), dir );
2469 output( "rm -f %s && ", link_name );
2471 /* dest path with a directory needs special handling if ln -s isn't supported */
2472 if (dir && strcmp( ln_s, "ln -s" ))
2473 output( "cd %s && %s %s %s\n", *dir ? dir : "/", ln_s, src_name, name + 1 );
2474 else
2475 output( "%s %s %s\n", ln_s, src_name, link_name );
2477 free( dir );
2481 /*******************************************************************
2482 * output_srcdir_symlink
2484 * Output rule to create a symlink back to the source directory, for source files
2485 * that are needed at run-time.
2487 static void output_srcdir_symlink( struct makefile *make, const char *obj )
2489 char *src_file, *dst_file, *src_name;
2491 if (!make->src_dir) return;
2492 src_file = src_dir_path( make, obj );
2493 dst_file = obj_dir_path( make, obj );
2494 output( "%s: %s\n", dst_file, src_file );
2496 src_name = src_file;
2497 if (src_name[0] != '/' && make->obj_dir)
2498 src_name = concat_paths( get_relative_path( make->obj_dir, "" ), src_name );
2500 output_symlink_rule( src_name, dst_file, 0 );
2501 strarray_add( &make->all_targets, obj );
2505 /*******************************************************************
2506 * output_install_commands
2508 static void output_install_commands( struct makefile *make, struct strarray files )
2510 unsigned int i;
2511 char *install_sh = root_src_dir_path( "tools/install-sh" );
2513 for (i = 0; i < files.count; i += 2)
2515 const char *file = files.str[i];
2516 const char *dest = strmake( "$(DESTDIR)%s", files.str[i + 1] + 1 );
2518 switch (*files.str[i + 1])
2520 case 'c': /* cross-compiled program */
2521 output( "\tSTRIPPROG=%s-strip %s -m 644 $(INSTALL_PROGRAM_FLAGS) %s %s\n",
2522 crosstarget, install_sh, obj_dir_path( make, file ), dest );
2523 output( "\t%s --builtin %s\n", tools_path( make, "winebuild" ), dest );
2524 break;
2525 case 'd': /* data file */
2526 output( "\t%s -m 644 $(INSTALL_DATA_FLAGS) %s %s\n",
2527 install_sh, obj_dir_path( make, file ), dest );
2528 break;
2529 case 'D': /* data file in source dir */
2530 output( "\t%s -m 644 $(INSTALL_DATA_FLAGS) %s %s\n",
2531 install_sh, src_dir_path( make, file ), dest );
2532 break;
2533 case 'p': /* program file */
2534 output( "\tSTRIPPROG=\"$(STRIP)\" %s $(INSTALL_PROGRAM_FLAGS) %s %s\n",
2535 install_sh, obj_dir_path( make, file ), dest );
2536 break;
2537 case 's': /* script */
2538 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2539 install_sh, obj_dir_path( make, file ), dest );
2540 break;
2541 case 'S': /* script in source dir */
2542 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2543 install_sh, src_dir_path( make, file ), dest );
2544 break;
2545 case 't': /* script in tools dir */
2546 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2547 install_sh, tools_dir_path( make, files.str[i] ), dest );
2548 break;
2549 case 'y': /* symlink */
2550 output_symlink_rule( files.str[i], dest, 1 );
2551 break;
2552 default:
2553 assert(0);
2555 strarray_add( &make->uninstall_files, dest );
2560 /*******************************************************************
2561 * output_install_rules
2563 * Rules are stored as a (file,dest) pair of values.
2564 * The first char of dest indicates the type of install.
2566 static void output_install_rules( struct makefile *make, enum install_rules rules, const char *target )
2568 unsigned int i;
2569 struct strarray files = make->install_rules[rules];
2570 struct strarray targets = empty_strarray;
2572 if (!files.count) return;
2574 for (i = 0; i < files.count; i += 2)
2576 const char *file = files.str[i];
2577 switch (*files.str[i + 1])
2579 case 'c': /* cross-compiled program */
2580 case 'd': /* data file */
2581 case 'p': /* program file */
2582 case 's': /* script */
2583 strarray_add_uniq( &targets, obj_dir_path( make, file ));
2584 break;
2585 case 't': /* script in tools dir */
2586 strarray_add_uniq( &targets, tools_dir_path( make, file ));
2587 break;
2591 output( "%s %s::", obj_dir_path( make, "install" ), obj_dir_path( make, target ));
2592 output_filenames( targets );
2593 output( "\n" );
2594 output_install_commands( make, files );
2595 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "install" ));
2596 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, target ));
2600 static int cmp_string_length( const char **a, const char **b )
2602 int paths_a = 0, paths_b = 0;
2603 const char *p;
2605 for (p = *a; *p; p++) if (*p == '/') paths_a++;
2606 for (p = *b; *p; p++) if (*p == '/') paths_b++;
2607 if (paths_b != paths_a) return paths_b - paths_a;
2608 return strcmp( *a, *b );
2611 /*******************************************************************
2612 * output_uninstall_rules
2614 static void output_uninstall_rules( struct makefile *make )
2616 static const char *dirs_order[] =
2617 { "$(includedir)", "$(mandir)", "$(fontdir)", "$(nlsdir)", "$(datadir)", "$(dlldir)" };
2619 struct strarray uninstall_dirs = empty_strarray;
2620 unsigned int i, j;
2622 if (!make->uninstall_files.count) return;
2623 output( "uninstall::\n" );
2624 output_rm_filenames( make->uninstall_files );
2625 strarray_add_uniq( &make->phony_targets, "uninstall" );
2627 if (!subdirs.count) return;
2628 for (i = 0; i < make->uninstall_files.count; i++)
2630 char *dir = xstrdup( make->uninstall_files.str[i] );
2631 while (strchr( dir, '/' ))
2633 *strrchr( dir, '/' ) = 0;
2634 strarray_add_uniq( &uninstall_dirs, xstrdup(dir) );
2637 strarray_qsort( &uninstall_dirs, cmp_string_length );
2638 output( "\t-rmdir" );
2639 for (i = 0; i < sizeof(dirs_order)/sizeof(dirs_order[0]); i++)
2641 for (j = 0; j < uninstall_dirs.count; j++)
2643 if (!uninstall_dirs.str[j]) continue;
2644 if (strncmp( uninstall_dirs.str[j] + strlen("$(DESTDIR)"), dirs_order[i], strlen(dirs_order[i]) ))
2645 continue;
2646 output_filename( uninstall_dirs.str[j] );
2647 uninstall_dirs.str[j] = NULL;
2650 for (j = 0; j < uninstall_dirs.count; j++)
2651 if (uninstall_dirs.str[j]) output_filename( uninstall_dirs.str[j] );
2652 output( "\n" );
2656 /*******************************************************************
2657 * output_importlib_symlinks
2659 static struct strarray output_importlib_symlinks( const struct makefile *make )
2661 struct strarray ret = empty_strarray;
2662 const char *lib, *dst, *ext[4];
2663 int i, count = 0;
2665 ext[count++] = (*dll_ext && !make->implib_objs.count) ? "def" : "a";
2666 if (crosstarget) ext[count++] = "cross.a";
2667 if (needs_delay_lib( make )) ext[count++] = "delay.a";
2669 for (i = 0; i < count; i++)
2671 lib = strmake( "lib%s.%s", make->importlib, ext[i] );
2672 dst = strmake( "dlls/%s", lib );
2673 output( "%s: %s\n", dst, obj_dir_path( make, lib ));
2674 output_symlink_rule( concat_paths( make->obj_dir + strlen("dlls/"), lib ), dst, 0 );
2675 strarray_add( &ret, dst );
2677 return ret;
2681 /*******************************************************************
2682 * output_po_files
2684 static void output_po_files( const struct makefile *make )
2686 const char *po_dir = src_dir_path( make, "po" );
2687 unsigned int i;
2689 if (linguas.count)
2691 for (i = 0; i < linguas.count; i++)
2692 output_filename( strmake( "%s/%s.po", po_dir, linguas.str[i] ));
2693 output( ": %s/wine.pot\n", po_dir );
2694 output( "\t%smsgmerge --previous -q $@ %s/wine.pot | msgattrib --no-obsolete -o $@.new && mv $@.new $@\n",
2695 cmd_prefix( "MSG" ), po_dir );
2696 output( "po:" );
2697 for (i = 0; i < linguas.count; i++)
2698 output_filename( strmake( "%s/%s.po", po_dir, linguas.str[i] ));
2699 output( "\n" );
2701 output( "%s/wine.pot:", po_dir );
2702 output_filenames( make->pot_files );
2703 output( "\n" );
2704 output( "\t%smsgcat -o $@", cmd_prefix( "MSG" ));
2705 output_filenames( make->pot_files );
2706 output( "\n" );
2710 /*******************************************************************
2711 * output_source_y
2713 static void output_source_y( struct makefile *make, struct incl_file *source, const char *obj )
2715 /* add source file dependency for parallel makes */
2716 char *header = strmake( "%s.tab.h", obj );
2718 if (find_include_file( make, header ))
2720 output( "%s: %s\n", obj_dir_path( make, header ), source->filename );
2721 output( "\t%s%s -p %s_ -o %s.tab.c -d %s\n",
2722 cmd_prefix( "BISON" ), bison, obj, obj_dir_path( make, obj ), source->filename );
2723 output( "%s.tab.c: %s %s\n", obj_dir_path( make, obj ),
2724 source->filename, obj_dir_path( make, header ));
2725 strarray_add( &make->clean_files, header );
2727 else output( "%s.tab.c: %s\n", obj_dir_path( make, obj ), source->filename );
2729 output( "\t%s%s -p %s_ -o $@ %s\n", cmd_prefix( "BISON" ), bison, obj, source->filename );
2733 /*******************************************************************
2734 * output_source_l
2736 static void output_source_l( struct makefile *make, struct incl_file *source, const char *obj )
2738 output( "%s.yy.c: %s\n", obj_dir_path( make, obj ), source->filename );
2739 output( "\t%s%s -o$@ %s\n", cmd_prefix( "FLEX" ), flex, source->filename );
2743 /*******************************************************************
2744 * output_source_h
2746 static void output_source_h( struct makefile *make, struct incl_file *source, const char *obj )
2748 if (source->file->flags & FLAG_GENERATED)
2749 strarray_add( &make->all_targets, source->name );
2750 else
2751 add_install_rule( make, source->name, source->name,
2752 strmake( "D$(includedir)/wine/%s", get_include_install_path( source->name ) ));
2756 /*******************************************************************
2757 * output_source_rc
2759 static void output_source_rc( struct makefile *make, struct incl_file *source, const char *obj )
2761 struct strarray defines = get_source_defines( make, source, obj );
2762 const char *po_dir = NULL;
2763 unsigned int i;
2765 if (source->file->flags & FLAG_GENERATED) strarray_add( &make->clean_files, source->name );
2766 if (linguas.count && (source->file->flags & FLAG_RC_PO)) po_dir = "po";
2767 strarray_add( &make->res_files, strmake( "%s.res", obj ));
2768 if (source->file->flags & FLAG_RC_PO)
2770 strarray_add( &make->pot_files, strmake( "%s.pot", obj ));
2771 output( "%s.pot ", obj_dir_path( make, obj ) );
2773 output( "%s.res: %s", obj_dir_path( make, obj ), source->filename );
2774 output_filename( tools_path( make, "wrc" ));
2775 output_filenames( source->dependencies );
2776 output( "\n" );
2777 output( "\t%s%s -u -o $@", cmd_prefix( "WRC" ), tools_path( make, "wrc" ) );
2778 if (make->is_win16) output_filename( "-m16" );
2779 else output_filenames( target_flags );
2780 output_filename( "--nostdinc" );
2781 if (po_dir) output_filename( strmake( "--po-dir=%s", po_dir ));
2782 output_filenames( defines );
2783 output_filename( source->filename );
2784 output( "\n" );
2785 if (po_dir)
2787 output( "%s.res:", obj_dir_path( make, obj ));
2788 for (i = 0; i < linguas.count; i++)
2789 output_filename( strmake( "%s/%s.mo", po_dir, linguas.str[i] ));
2790 output( "\n" );
2795 /*******************************************************************
2796 * output_source_mc
2798 static void output_source_mc( struct makefile *make, struct incl_file *source, const char *obj )
2800 unsigned int i;
2801 char *obj_path = obj_dir_path( make, obj );
2803 strarray_add( &make->res_files, strmake( "%s.res", obj ));
2804 strarray_add( &make->pot_files, strmake( "%s.pot", obj ));
2805 output( "%s.pot %s.res: %s", obj_path, obj_path, source->filename );
2806 output_filename( tools_path( make, "wmc" ));
2807 output_filenames( source->dependencies );
2808 output( "\n" );
2809 output( "\t%s%s -u -o $@ %s", cmd_prefix( "WMC" ), tools_path( make, "wmc" ), source->filename );
2810 if (linguas.count)
2812 output_filename( "--po-dir=po" );
2813 output( "\n" );
2814 output( "%s.res:", obj_dir_path( make, obj ));
2815 for (i = 0; i < linguas.count; i++)
2816 output_filename( strmake( "po/%s.mo", linguas.str[i] ));
2818 output( "\n" );
2822 /*******************************************************************
2823 * output_source_res
2825 static void output_source_res( struct makefile *make, struct incl_file *source, const char *obj )
2827 strarray_add( &make->res_files, source->name );
2831 /*******************************************************************
2832 * output_source_idl
2834 static void output_source_idl( struct makefile *make, struct incl_file *source, const char *obj )
2836 struct strarray defines = get_source_defines( make, source, obj );
2837 struct strarray targets = empty_strarray;
2838 char *dest;
2839 unsigned int i;
2841 if (!source->file->flags) source->file->flags |= FLAG_IDL_HEADER | FLAG_INSTALL;
2842 if (find_include_file( make, strmake( "%s.h", obj ))) source->file->flags |= FLAG_IDL_HEADER;
2844 for (i = 0; i < sizeof(idl_outputs) / sizeof(idl_outputs[0]); i++)
2846 if (!(source->file->flags & idl_outputs[i].flag)) continue;
2847 dest = strmake( "%s%s", obj, idl_outputs[i].ext );
2848 if (!find_src_file( make, dest )) strarray_add( &make->clean_files, dest );
2849 strarray_add( &targets, dest );
2851 if (source->file->flags & FLAG_IDL_PROXY) strarray_add( &make->dlldata_files, source->name );
2852 if (source->file->flags & FLAG_INSTALL)
2854 add_install_rule( make, source->name, xstrdup( source->name ),
2855 strmake( "D$(includedir)/wine/%s.idl", get_include_install_path( obj ) ));
2856 if (source->file->flags & FLAG_IDL_HEADER)
2857 add_install_rule( make, source->name, strmake( "%s.h", obj ),
2858 strmake( "d$(includedir)/wine/%s.h", get_include_install_path( obj ) ));
2859 if (source->file->flags & FLAG_IDL_TYPELIB)
2860 add_install_rule( make, source->name, strmake( "%s.tlb", obj ),
2861 strmake( "d$(includedir)/wine/%s.tlb", get_include_install_path( obj ) ));
2863 if (!targets.count) return;
2865 output_filenames_obj_dir( make, targets );
2866 output( ": %s\n", tools_path( make, "widl" ));
2867 output( "\t%s%s -o $@", cmd_prefix( "WIDL" ), tools_path( make, "widl" ) );
2868 output_filenames( target_flags );
2869 output_filename( "--nostdinc" );
2870 output_filenames( defines );
2871 output_filenames( get_expanded_make_var_array( make, "EXTRAIDLFLAGS" ));
2872 output_filenames( get_expanded_file_local_var( make, obj, "EXTRAIDLFLAGS" ));
2873 output_filename( source->filename );
2874 output( "\n" );
2875 output_filenames_obj_dir( make, targets );
2876 output( ": %s", source->filename );
2877 output_filenames( source->dependencies );
2878 output( "\n" );
2882 /*******************************************************************
2883 * output_source_tlb
2885 static void output_source_tlb( struct makefile *make, struct incl_file *source, const char *obj )
2887 strarray_add( &make->all_targets, source->name );
2891 /*******************************************************************
2892 * output_source_x
2894 static void output_source_x( struct makefile *make, struct incl_file *source, const char *obj )
2896 output( "%s.h: %s%s %s\n", obj_dir_path( make, obj ),
2897 tools_dir_path( make, "make_xftmpl" ), tools_ext, source->filename );
2898 output( "\t%s%s%s -H -o $@ %s\n", cmd_prefix( "GEN" ),
2899 tools_dir_path( make, "make_xftmpl" ), tools_ext, source->filename );
2900 if (source->file->flags & FLAG_INSTALL)
2902 add_install_rule( make, source->name, source->name,
2903 strmake( "D$(includedir)/wine/%s", get_include_install_path( source->name ) ));
2904 add_install_rule( make, source->name, strmake( "%s.h", obj ),
2905 strmake( "d$(includedir)/wine/%s.h", get_include_install_path( obj ) ));
2910 /*******************************************************************
2911 * output_source_sfd
2913 static void output_source_sfd( struct makefile *make, struct incl_file *source, const char *obj )
2915 unsigned int i;
2916 char *ttf_obj = strmake( "%s.ttf", obj );
2917 char *ttf_file = src_dir_path( make, ttf_obj );
2919 if (fontforge && !make->src_dir)
2921 output( "%s: %s\n", ttf_file, source->filename );
2922 output( "\t%s%s -script %s %s $@\n", cmd_prefix( "GEN" ),
2923 fontforge, root_src_dir_path( "fonts/genttf.ff" ), source->filename );
2924 if (!(source->file->flags & FLAG_SFD_FONTS)) strarray_add( &make->font_files, ttf_obj );
2926 if (source->file->flags & FLAG_INSTALL)
2928 add_install_rule( make, source->name, ttf_obj, strmake( "D$(fontdir)/%s", ttf_obj ));
2929 output_srcdir_symlink( make, ttf_obj );
2932 if (source->file->flags & FLAG_SFD_FONTS)
2934 struct strarray *array = source->file->args;
2936 for (i = 0; i < array->count; i++)
2938 char *font = strtok( xstrdup(array->str[i]), " \t" );
2939 char *args = strtok( NULL, "" );
2941 strarray_add( &make->all_targets, xstrdup( font ));
2942 output( "%s: %s %s\n", obj_dir_path( make, font ),
2943 tools_path( make, "sfnt2fon" ), ttf_file );
2944 output( "\t%s%s -q -o $@ %s %s\n", cmd_prefix( "GEN" ),
2945 tools_path( make, "sfnt2fon" ), ttf_file, args );
2946 add_install_rule( make, source->name, xstrdup(font), strmake( "d$(fontdir)/%s", font ));
2952 /*******************************************************************
2953 * output_source_svg
2955 static void output_source_svg( struct makefile *make, struct incl_file *source, const char *obj )
2957 static const char * const images[] = { "bmp", "cur", "ico", NULL };
2958 unsigned int i;
2960 if (convert && rsvg && icotool && !make->src_dir)
2962 for (i = 0; images[i]; i++)
2963 if (find_include_file( make, strmake( "%s.%s", obj, images[i] ))) break;
2965 if (images[i])
2967 output( "%s.%s: %s\n", src_dir_path( make, obj ), images[i], source->filename );
2968 output( "\t%sCONVERT=\"%s\" ICOTOOL=\"%s\" RSVG=\"%s\" %s %s $@\n",
2969 cmd_prefix( "GEN" ), convert, icotool, rsvg,
2970 root_src_dir_path( "tools/buildimage" ), source->filename );
2976 /*******************************************************************
2977 * output_source_nls
2979 static void output_source_nls( struct makefile *make, struct incl_file *source, const char *obj )
2981 add_install_rule( make, source->name, source->name,
2982 strmake( "D$(nlsdir)/%s", source->name ));
2983 output_srcdir_symlink( make, strmake( "%s.nls", obj ));
2987 /*******************************************************************
2988 * output_source_desktop
2990 static void output_source_desktop( struct makefile *make, struct incl_file *source, const char *obj )
2992 add_install_rule( make, source->name, source->name,
2993 strmake( "D$(datadir)/applications/%s", source->name ));
2997 /*******************************************************************
2998 * output_source_po
3000 static void output_source_po( struct makefile *make, struct incl_file *source, const char *obj )
3002 output( "%s.mo: %s\n", obj_dir_path( make, obj ), source->filename );
3003 output( "\t%s%s -o $@ %s\n", cmd_prefix( "MSG" ), msgfmt, source->filename );
3004 strarray_add( &make->all_targets, strmake( "%s.mo", obj ));
3008 /*******************************************************************
3009 * output_source_in
3011 static void output_source_in( struct makefile *make, struct incl_file *source, const char *obj )
3013 unsigned int i;
3015 if (strendswith( obj, ".man" ) && source->file->args)
3017 struct strarray symlinks;
3018 char *dir, *dest = replace_extension( obj, ".man", "" );
3019 char *lang = strchr( dest, '.' );
3020 char *section = source->file->args;
3021 if (lang)
3023 *lang++ = 0;
3024 dir = strmake( "$(mandir)/%s/man%s", lang, section );
3026 else dir = strmake( "$(mandir)/man%s", section );
3027 add_install_rule( make, dest, xstrdup(obj), strmake( "d%s/%s.%s", dir, dest, section ));
3028 symlinks = get_expanded_file_local_var( make, dest, "SYMLINKS" );
3029 for (i = 0; i < symlinks.count; i++)
3030 add_install_rule( make, symlinks.str[i], strmake( "%s.%s", dest, section ),
3031 strmake( "y%s/%s.%s", dir, symlinks.str[i], section ));
3032 free( dest );
3033 free( dir );
3035 strarray_add( &make->in_files, xstrdup(obj) );
3036 strarray_add( &make->all_targets, xstrdup(obj) );
3037 output( "%s: %s\n", obj_dir_path( make, obj ), source->filename );
3038 output( "\t%s%s %s >$@ || (rm -f $@ && false)\n", cmd_prefix( "SED" ), sed_cmd, source->filename );
3039 output( "%s:", obj_dir_path( make, obj ));
3040 output_filenames( source->dependencies );
3041 output( "\n" );
3042 add_install_rule( make, obj, xstrdup( obj ), strmake( "d$(datadir)/wine/%s", obj ));
3046 /*******************************************************************
3047 * output_source_spec
3049 static void output_source_spec( struct makefile *make, struct incl_file *source, const char *obj )
3051 struct strarray imports = get_expanded_file_local_var( make, obj, "IMPORTS" );
3052 struct strarray dll_flags = get_expanded_file_local_var( make, obj, "EXTRADLLFLAGS" );
3053 struct strarray all_libs, dep_libs = empty_strarray;
3054 char *dll_name, *obj_name, *output_file;
3055 const char *debug_file;
3057 if (!imports.count) imports = make->imports;
3058 else if (make->use_msvcrt) add_crt_import( make, &imports, NULL );
3060 if (!dll_flags.count) dll_flags = make->extradllflags;
3061 all_libs = add_import_libs( make, &dep_libs, imports, 0, 0 );
3062 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
3063 dll_name = strmake( "%s.dll%s", obj, make->is_cross ? "" : dll_ext );
3064 obj_name = strmake( "%s%s", obj_dir_path( make, obj ), make->is_cross ? ".cross.o" : ".o" );
3065 output_file = obj_dir_path( make, dll_name );
3067 strarray_add( &make->clean_files, dll_name );
3068 strarray_add( &make->res_files, strmake( "%s.res", obj ));
3069 output( "%s.res:", obj_dir_path( make, obj ));
3070 output_filename( obj_dir_path( make, dll_name ));
3071 output_filename( tools_path( make, "wrc" ));
3072 output( "\n" );
3073 output( "\t%secho \"%s.dll TESTDLL \\\"%s\\\"\" | %s -u -o $@\n", cmd_prefix( "WRC" ), obj, output_file,
3074 tools_path( make, "wrc" ));
3076 output( "%s:", output_file);
3077 output_filename( source->filename );
3078 output_filename( obj_name );
3079 output_filenames( dep_libs );
3080 output_filename( tools_path( make, "winebuild" ));
3081 output_filename( tools_path( make, "winegcc" ));
3082 output( "\n" );
3083 output_winegcc_command( make, make->is_cross );
3084 output_filename( "-s" );
3085 output_filenames( dll_flags );
3086 output_filename( "-shared" );
3087 output_filename( source->filename );
3088 output_filename( obj_name );
3089 if ((debug_file = get_debug_file( make, dll_name )))
3090 output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
3091 output_filenames( all_libs );
3092 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3093 output( "\n" );
3097 /*******************************************************************
3098 * output_source_default
3100 static void output_source_default( struct makefile *make, struct incl_file *source, const char *obj )
3102 struct strarray defines = get_source_defines( make, source, obj );
3103 int is_dll_src = (make->testdll &&
3104 strendswith( source->name, ".c" ) &&
3105 find_src_file( make, replace_extension( source->name, ".c", ".spec" )));
3106 int need_cross = (crosstarget &&
3107 !(source->file->flags & FLAG_C_UNIX) &&
3108 (make->is_cross || (make->module && make->staticlib) ||
3109 (source->file->flags & FLAG_C_IMPLIB)));
3110 int need_obj = ((*dll_ext || !(source->file->flags & FLAG_C_UNIX)) &&
3111 (!need_cross ||
3112 (source->file->flags & FLAG_C_IMPLIB) ||
3113 (make->module && make->staticlib)));
3115 if ((source->file->flags & FLAG_GENERATED) &&
3116 (!make->testdll || !strendswith( source->filename, "testlist.c" )))
3117 strarray_add( &make->clean_files, source->basename );
3118 if (source->file->flags & FLAG_C_IMPLIB) strarray_add( &make->implib_objs, strmake( "%s.o", obj ));
3120 if (need_obj)
3122 if ((source->file->flags & FLAG_C_UNIX) && *dll_ext)
3123 strarray_add( &make->unixobj_files, strmake( "%s.o", obj ));
3124 else if (!is_dll_src && !(source->file->flags & FLAG_C_IMPLIB))
3125 strarray_add( &make->object_files, strmake( "%s.o", obj ));
3126 else
3127 strarray_add( &make->clean_files, strmake( "%s.o", obj ));
3128 output( "%s.o: %s\n", obj_dir_path( make, obj ), source->filename );
3129 output( "\t%s$(CC) -c -o $@ %s", cmd_prefix( "CC" ), source->filename );
3130 output_filenames( defines );
3131 if (make->module || make->staticlib || make->sharedlib || make->testdll)
3133 output_filenames( dll_flags );
3134 if (source->use_msvcrt) output_filenames( msvcrt_flags );
3136 output_filenames( extra_cflags );
3137 output_filenames( cpp_flags );
3138 output_filename( "$(CFLAGS)" );
3139 output( "\n" );
3141 if (need_cross)
3143 if (!is_dll_src && !(source->file->flags & FLAG_C_IMPLIB))
3144 strarray_add( &make->crossobj_files, strmake( "%s.cross.o", obj ));
3145 else
3146 strarray_add( &make->clean_files, strmake( "%s.cross.o", obj ));
3147 output( "%s.cross.o: %s\n", obj_dir_path( make, obj ), source->filename );
3148 output( "\t%s$(CROSSCC) -c -o $@ %s", cmd_prefix( "CC" ), source->filename );
3149 output_filenames( defines );
3150 output_filenames( extra_cross_cflags );
3151 if (source->file->flags & FLAG_C_IMPLIB || (make->module && is_crt_module( make->module )))
3152 output_filename( "-fno-builtin" );
3153 output_filenames( cpp_flags );
3154 output_filename( "$(CROSSCFLAGS)" );
3155 output( "\n" );
3157 if (strendswith( source->name, ".c" ) && !(source->file->flags & FLAG_GENERATED))
3159 strarray_add( &make->c2man_files, source->filename );
3160 if (make->testdll && !is_dll_src)
3162 strarray_add( &make->ok_files, strmake( "%s.ok", obj ));
3163 output( "%s.ok:\n", obj_dir_path( make, obj ));
3164 output( "\t%s%s $(RUNTESTFLAGS) -T . -M %s -p %s%s %s && touch $@\n",
3165 cmd_prefix( "TEST" ),
3166 root_src_dir_path( "tools/runtest" ), make->testdll,
3167 obj_dir_path( make, replace_extension( make->testdll, ".dll", "_test.exe" )),
3168 make->is_cross ? "" : dll_ext, obj );
3171 if (need_obj) output_filename( strmake( "%s.o", obj_dir_path( make, obj )));
3172 if (need_cross) output_filename( strmake( "%s.cross.o", obj_dir_path( make, obj )));
3173 output( ":" );
3174 output_filenames( source->dependencies );
3175 output( "\n" );
3179 /* dispatch table to output rules for a single source file */
3180 static const struct
3182 const char *ext;
3183 void (*fn)( struct makefile *make, struct incl_file *source, const char *obj );
3184 } output_source_funcs[] =
3186 { "y", output_source_y },
3187 { "l", output_source_l },
3188 { "h", output_source_h },
3189 { "rh", output_source_h },
3190 { "inl", output_source_h },
3191 { "rc", output_source_rc },
3192 { "mc", output_source_mc },
3193 { "res", output_source_res },
3194 { "idl", output_source_idl },
3195 { "tlb", output_source_tlb },
3196 { "sfd", output_source_sfd },
3197 { "svg", output_source_svg },
3198 { "nls", output_source_nls },
3199 { "desktop", output_source_desktop },
3200 { "po", output_source_po },
3201 { "in", output_source_in },
3202 { "x", output_source_x },
3203 { "spec", output_source_spec },
3204 { NULL, output_source_default }
3208 /*******************************************************************
3209 * has_object_file
3211 static int has_object_file( struct makefile *make )
3213 struct incl_file *source;
3214 int i;
3216 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
3218 char *ext = get_extension( source->name );
3220 if (!ext) fatal_error( "unsupported file type %s\n", source->name );
3221 ext++;
3223 for (i = 0; output_source_funcs[i].ext; i++)
3224 if (!strcmp( ext, output_source_funcs[i].ext )) break;
3226 if (!output_source_funcs[i].ext) return 1; /* default extension builds to an object file */
3228 return 0;
3232 /*******************************************************************
3233 * output_man_pages
3235 static void output_man_pages( struct makefile *make )
3237 if (make->c2man_files.count)
3239 char *spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" ));
3241 output( "manpages::\n" );
3242 output( "\t%s -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3243 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3244 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3245 output_filename( strmake( "-o documentation/man%s", man_ext ));
3246 output_filenames( make->c2man_files );
3247 output( "\n" );
3248 output( "htmlpages::\n" );
3249 output( "\t%s -Th -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3250 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3251 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3252 output_filename( "-o documentation/html" );
3253 output_filenames( make->c2man_files );
3254 output( "\n" );
3255 output( "sgmlpages::\n" );
3256 output( "\t%s -Ts -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3257 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3258 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3259 output_filename( "-o documentation/api-guide" );
3260 output_filenames( make->c2man_files );
3261 output( "\n" );
3262 output( "xmlpages::\n" );
3263 output( "\t%s -Tx -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3264 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3265 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3266 output_filename( "-o documentation/api-guide-xml" );
3267 output_filenames( make->c2man_files );
3268 output( "\n" );
3269 strarray_add( &make->phony_targets, "manpages" );
3270 strarray_add( &make->phony_targets, "htmlpages" );
3271 strarray_add( &make->phony_targets, "sgmlpages" );
3272 strarray_add( &make->phony_targets, "xmlpages" );
3277 /*******************************************************************
3278 * output_module
3280 static void output_module( struct makefile *make )
3282 struct strarray all_libs = empty_strarray;
3283 struct strarray dep_libs = empty_strarray;
3284 char *module_path = obj_dir_path( make, make->module );
3285 const char *debug_file = NULL;
3286 char *spec_file = NULL;
3287 unsigned int i;
3289 if (!make->is_exe) spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" ));
3290 strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->delayimports, 1, 0 ));
3291 strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->imports, 0, 0 ));
3292 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
3294 if (make->is_cross)
3296 if (delay_load_flag)
3298 for (i = 0; i < make->delayimports.count; i++)
3299 strarray_add( &all_libs, strmake( "%s%s%s", delay_load_flag, make->delayimports.str[i],
3300 strchr( make->delayimports.str[i], '.' ) ? "" : ".dll" ));
3302 strarray_add( &make->all_targets, strmake( "%s", make->module ));
3303 add_install_rule( make, make->module, strmake( "%s", make->module ),
3304 strmake( "c%s/%s", pe_dir, make->module ));
3305 debug_file = get_debug_file( make, make->module );
3306 output( "%s:", module_path );
3308 else if (*dll_ext)
3310 if (!make->use_msvcrt) strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3311 for (i = 0; i < make->delayimports.count; i++)
3312 strarray_add( &all_libs, strmake( "-Wl,-delayload,%s%s", make->delayimports.str[i],
3313 strchr( make->delayimports.str[i], '.' ) ? "" : ".dll" ));
3314 strarray_add( &make->all_targets, strmake( "%s%s", make->module, dll_ext ));
3315 strarray_add( &make->all_targets, strmake( "%s.fake", make->module ));
3316 add_install_rule( make, make->module, strmake( "%s%s", make->module, dll_ext ),
3317 strmake( "p%s/%s%s", so_dir, make->module, dll_ext ));
3318 add_install_rule( make, make->module, strmake( "%s.fake", make->module ),
3319 strmake( "d%s/%s", pe_dir, make->module ));
3320 output( "%s%s %s.fake:", module_path, dll_ext, module_path );
3322 else
3324 strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3325 strarray_add( &make->all_targets, make->module );
3326 add_install_rule( make, make->module, make->module,
3327 strmake( "p$(%s)/%s", spec_file ? "dlldir" : "bindir", make->module ));
3328 debug_file = get_debug_file( make, make->module );
3329 output( "%s:", module_path );
3332 if (spec_file) output_filename( spec_file );
3333 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3334 output_filenames_obj_dir( make, make->res_files );
3335 output_filenames( dep_libs );
3336 output_filename( tools_path( make, "winebuild" ));
3337 output_filename( tools_path( make, "winegcc" ));
3338 output( "\n" );
3339 output_winegcc_command( make, make->is_cross );
3340 if (make->is_cross) output_filename( "-Wl,--wine-builtin" );
3341 if (spec_file)
3343 output_filename( "-shared" );
3344 output_filename( spec_file );
3346 output_filenames( make->extradllflags );
3347 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3348 output_filenames_obj_dir( make, make->res_files );
3349 if (debug_file) output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
3350 output_filenames( all_libs );
3351 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3352 output( "\n" );
3354 if (make->unixobj_files.count)
3356 struct strarray unix_imports = empty_strarray;
3357 struct strarray unix_libs = empty_strarray;
3358 struct strarray unix_deps = empty_strarray;
3359 char *ext, *unix_lib = xmalloc( strlen( make->module ) + strlen( dll_ext ) + 1 );
3360 strcpy( unix_lib, make->module );
3361 if ((ext = get_extension( unix_lib ))) *ext = 0;
3362 strcat( unix_lib, dll_ext );
3364 if (!strarray_exists( &make->extradllflags, "-nodefaultlibs" ))
3366 strarray_add( &unix_imports, "ntdll" );
3367 strarray_add( &unix_deps, obj_dir_path( top_makefile, "dlls/ntdll/ntdll.so" ));
3369 strarray_add( &unix_imports, "winecrt0" );
3371 strarray_addall( &unix_libs, add_import_libs( make, &unix_deps, unix_imports, 0, 1 ));
3372 strarray_addall( &unix_libs, add_unix_libraries( make, &unix_deps ));
3374 strarray_add( &make->all_targets, unix_lib );
3375 add_install_rule( make, make->module, unix_lib, strmake( "p%s/%s", so_dir, unix_lib ));
3376 output( "%s:", obj_dir_path( make, unix_lib ));
3377 if (spec_file) output_filename( spec_file );
3378 output_filenames_obj_dir( make, make->unixobj_files );
3379 output_filenames( unix_deps );
3380 output_filename( tools_path( make, "winebuild" ));
3381 output_filename( tools_path( make, "winegcc" ));
3382 output( "\n" );
3383 output_winegcc_command( make, 0 );
3384 output_filename( "-munix" );
3385 output_filename( "-shared" );
3386 if (spec_file) output_filename( spec_file );
3387 if (strarray_exists( &make->extradllflags, "-nodefaultlibs" )) output_filename( "-nodefaultlibs" );
3388 output_filenames_obj_dir( make, make->unixobj_files );
3389 output_filenames( unix_libs );
3390 output_filename( "$(LDFLAGS)" );
3391 output( "\n" );
3394 if (spec_file && make->importlib)
3396 char *importlib_path = obj_dir_path( make, strmake( "lib%s", make->importlib ));
3397 if (*dll_ext && !make->implib_objs.count)
3399 strarray_add( &make->clean_files, strmake( "lib%s.def", make->importlib ));
3400 output( "%s.def: %s %s\n", importlib_path, tools_path( make, "winebuild" ), spec_file );
3401 output( "\t%s%s -w --def -o $@", cmd_prefix( "BUILD" ), tools_path( make, "winebuild" ) );
3402 output_filenames( target_flags );
3403 if (make->is_win16) output_filename( "-m16" );
3404 output_filename( "--export" );
3405 output_filename( spec_file );
3406 output( "\n" );
3407 add_install_rule( make, make->importlib,
3408 strmake( "lib%s.def", make->importlib ),
3409 strmake( "d%s/lib%s.def", so_dir, make->importlib ));
3411 else
3413 strarray_add( &make->clean_files, strmake( "lib%s.a", make->importlib ));
3414 if (!*dll_ext && needs_delay_lib( make ))
3416 strarray_add( &make->clean_files, strmake( "lib%s.delay.a", make->importlib ));
3417 output( "%s.delay.a ", importlib_path );
3419 output( "%s.a: %s %s", importlib_path, tools_path( make, "winebuild" ), spec_file );
3420 output_filenames_obj_dir( make, make->implib_objs );
3421 output( "\n" );
3422 output( "\t%s%s -w --implib -o $@", cmd_prefix( "BUILD" ), tools_path( make, "winebuild" ) );
3423 output_filenames( target_flags );
3424 if (make->is_win16) output_filename( "-m16" );
3425 output_filename( "--export" );
3426 output_filename( spec_file );
3427 output_filenames_obj_dir( make, make->implib_objs );
3428 output( "\n" );
3429 add_install_rule( make, make->importlib,
3430 strmake( "lib%s.a", make->importlib ),
3431 strmake( "d%s/lib%s.a", so_dir, make->importlib ));
3433 if (crosstarget)
3435 struct strarray cross_files = strarray_replace_extension( &make->implib_objs, ".o", ".cross.o" );
3437 strarray_add( &make->clean_files, strmake( "lib%s.cross.a", make->importlib ));
3438 output_filename( strmake( "%s.cross.a", importlib_path ));
3439 if (needs_delay_lib( make ))
3441 strarray_add( &make->clean_files, strmake( "lib%s.delay.a", make->importlib ));
3442 output_filename( strmake( "%s.delay.a", importlib_path ));
3444 output( ": %s %s", tools_path( make, "winebuild" ), spec_file );
3445 output_filenames_obj_dir( make, cross_files );
3446 output( "\n" );
3447 output( "\t%s%s -b %s -w --implib -o $@", cmd_prefix( "BUILD" ),
3448 tools_path( make, "winebuild" ), crosstarget );
3449 if (make->is_win16) output_filename( "-m16" );
3450 output_filename( "--export" );
3451 output_filename( spec_file );
3452 output_filenames_obj_dir( make, cross_files );
3453 output( "\n" );
3454 add_install_rule( make, make->importlib,
3455 strmake( "lib%s.cross.a", make->importlib ),
3456 strmake( "d%s/lib%s.a", pe_dir, make->importlib ));
3458 if (needs_implib_symlink( make ))
3459 strarray_addall( &top_makefile->clean_files, output_importlib_symlinks( make ));
3462 if (spec_file)
3463 output_man_pages( make );
3464 else if (*dll_ext && !make->is_win16 && strendswith( make->module, ".exe" ))
3466 char *binary = replace_extension( make->module, ".exe", "" );
3467 add_install_rule( make, binary, "wineapploader", strmake( "t$(bindir)/%s", binary ));
3472 /*******************************************************************
3473 * output_static_lib
3475 static void output_static_lib( struct makefile *make )
3477 strarray_add( &make->all_targets, make->staticlib );
3478 output( "%s:", obj_dir_path( make, make->staticlib ));
3479 output_filenames_obj_dir( make, make->object_files );
3480 output_filenames_obj_dir( make, make->unixobj_files );
3481 output( "\n\t%srm -f $@ && %s rc $@", cmd_prefix( "AR" ), ar );
3482 output_filenames_obj_dir( make, make->object_files );
3483 output_filenames_obj_dir( make, make->unixobj_files );
3484 output( " && %s $@\n", ranlib );
3485 add_install_rule( make, make->staticlib, make->staticlib, strmake( "d%s/%s", so_dir, make->staticlib ));
3486 if (crosstarget && make->module)
3488 char *name = replace_extension( make->staticlib, ".a", ".cross.a" );
3490 strarray_add( &make->all_targets, name );
3491 output( "%s: %s", obj_dir_path( make, name ), tools_path( make, "winebuild" ));
3492 output_filenames_obj_dir( make, make->crossobj_files );
3493 output( "\n" );
3494 output( "\t%s%s -b %s -w --staticlib -o $@", cmd_prefix( "BUILD" ),
3495 tools_path( make, "winebuild" ), crosstarget );
3496 output_filenames_obj_dir( make, make->crossobj_files );
3497 output( "\n" );
3498 add_install_rule( make, make->staticlib, name,
3499 strmake( "d%s/%s", pe_dir, make->staticlib ));
3504 /*******************************************************************
3505 * output_shared_lib
3507 static void output_shared_lib( struct makefile *make )
3509 unsigned int i;
3510 char *basename, *p;
3511 struct strarray names = get_shared_lib_names( make->sharedlib );
3512 struct strarray all_libs = empty_strarray;
3513 struct strarray dep_libs = empty_strarray;
3515 basename = xstrdup( make->sharedlib );
3516 if ((p = strchr( basename, '.' ))) *p = 0;
3518 strarray_addall( &dep_libs, get_local_dependencies( make, basename, make->in_files ));
3519 strarray_addall( &all_libs, get_expanded_file_local_var( make, basename, "LDFLAGS" ));
3520 strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3522 output( "%s:", obj_dir_path( make, make->sharedlib ));
3523 output_filenames_obj_dir( make, make->object_files );
3524 output_filenames( dep_libs );
3525 output( "\n" );
3526 output( "\t%s$(CC) -o $@", cmd_prefix( "CC" ));
3527 output_filenames_obj_dir( make, make->object_files );
3528 output_filenames( all_libs );
3529 output_filename( "$(LDFLAGS)" );
3530 output( "\n" );
3531 add_install_rule( make, make->sharedlib, make->sharedlib, strmake( "p%s/%s", so_dir, make->sharedlib ));
3532 for (i = 1; i < names.count; i++)
3534 output( "%s: %s\n", obj_dir_path( make, names.str[i] ), obj_dir_path( make, names.str[i-1] ));
3535 output_symlink_rule( names.str[i-1], obj_dir_path( make, names.str[i] ), 0 );
3536 add_install_rule( make, names.str[i], names.str[i-1], strmake( "y%s/%s", so_dir, names.str[i] ));
3538 strarray_addall( &make->all_targets, names );
3542 /*******************************************************************
3543 * output_test_module
3545 static void output_test_module( struct makefile *make )
3547 char *testmodule = replace_extension( make->testdll, ".dll", "_test.exe" );
3548 char *stripped = replace_extension( make->testdll, ".dll", "_test-stripped.exe" );
3549 char *testres = replace_extension( make->testdll, ".dll", "_test.res" );
3550 struct strarray dep_libs = empty_strarray;
3551 struct strarray all_libs = add_import_libs( make, &dep_libs, make->imports, 0, 0 );
3552 struct makefile *parent = get_parent_makefile( make );
3553 const char *ext = make->is_cross ? "" : dll_ext;
3554 const char *debug_file;
3555 char *output_file;
3557 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
3558 strarray_add( &make->all_targets, strmake( "%s%s", testmodule, ext ));
3559 strarray_add( &make->clean_files, strmake( "%s%s", stripped, ext ));
3560 output_file = strmake( "%s%s", obj_dir_path( make, testmodule ), ext );
3561 output( "%s:\n", output_file );
3562 output_winegcc_command( make, make->is_cross );
3563 output_filenames( make->extradllflags );
3564 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3565 output_filenames_obj_dir( make, make->res_files );
3566 if ((debug_file = get_debug_file( make, testmodule )))
3567 output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
3568 output_filenames( all_libs );
3569 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3570 output( "\n" );
3571 output( "%s%s:\n", obj_dir_path( make, stripped ), ext );
3572 output_winegcc_command( make, make->is_cross );
3573 output_filename( "-s" );
3574 output_filename( strmake( "-Wb,-F,%s", testmodule ));
3575 output_filenames( make->extradllflags );
3576 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3577 output_filenames_obj_dir( make, make->res_files );
3578 output_filenames( all_libs );
3579 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3580 output( "\n" );
3581 output( "%s%s %s%s:", obj_dir_path( make, testmodule ), ext, obj_dir_path( make, stripped ), ext );
3582 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3583 output_filenames_obj_dir( make, make->res_files );
3584 output_filenames( dep_libs );
3585 output_filename( tools_path( make, "winebuild" ));
3586 output_filename( tools_path( make, "winegcc" ));
3587 output( "\n" );
3589 output( "programs/winetest/%s: %s%s\n", testres, obj_dir_path( make, stripped ), ext );
3590 output( "\t%secho \"%s TESTRES \\\"%s%s\\\"\" | %s -u -o $@\n", cmd_prefix( "WRC" ),
3591 testmodule, obj_dir_path( make, stripped ), ext, tools_path( make, "wrc" ));
3593 output_filenames_obj_dir( make, make->ok_files );
3594 output( ": %s%s", obj_dir_path( make, testmodule ), ext );
3595 if (parent)
3597 output_filename( parent->is_cross ? obj_dir_path( parent, make->testdll )
3598 : strmake( "%s%s", obj_dir_path( parent, make->testdll ), dll_ext ));
3599 if (parent->unixobj_files.count)
3601 char *ext, *unix_lib = xstrdup( parent->module );
3602 if ((ext = get_extension( unix_lib ))) *ext = 0;
3603 output_filename( strmake( "%s%s", obj_dir_path( parent, unix_lib ), dll_ext ));
3606 output( "\n" );
3607 output( "%s %s:", obj_dir_path( make, "check" ), obj_dir_path( make, "test" ));
3608 if (!make->disabled && parent && !parent->disabled) output_filenames_obj_dir( make, make->ok_files );
3609 output( "\n" );
3610 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "check" ));
3611 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "test" ));
3612 output( "%s::\n", obj_dir_path( make, "testclean" ));
3613 output( "\trm -f" );
3614 output_filenames_obj_dir( make, make->ok_files );
3615 output( "\n" );
3616 strarray_addall( &make->clean_files, make->ok_files );
3617 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "testclean" ));
3621 /*******************************************************************
3622 * output_programs
3624 static void output_programs( struct makefile *make )
3626 unsigned int i, j;
3628 for (i = 0; i < make->programs.count; i++)
3630 char *program_installed = NULL;
3631 char *program = strmake( "%s%s", make->programs.str[i], exe_ext );
3632 struct strarray deps = get_local_dependencies( make, make->programs.str[i], make->in_files );
3633 struct strarray all_libs = get_expanded_file_local_var( make, make->programs.str[i], "LDFLAGS" );
3634 struct strarray objs = get_expanded_file_local_var( make, make->programs.str[i], "OBJS" );
3635 struct strarray symlinks = get_expanded_file_local_var( make, make->programs.str[i], "SYMLINKS" );
3637 if (!objs.count) objs = make->object_files;
3638 if (!strarray_exists( &all_libs, "-nodefaultlibs" ))
3639 strarray_addall( &all_libs, add_unix_libraries( make, &deps ));
3641 output( "%s:", obj_dir_path( make, program ) );
3642 output_filenames_obj_dir( make, objs );
3643 output_filenames( deps );
3644 output( "\n" );
3645 output( "\t%s$(CC) -o $@", cmd_prefix( "CC" ));
3646 output_filenames_obj_dir( make, objs );
3647 output_filenames( all_libs );
3648 output_filename( "$(LDFLAGS)" );
3649 output( "\n" );
3650 strarray_add( &make->all_targets, program );
3652 for (j = 0; j < symlinks.count; j++)
3654 output( "%s: %s\n", obj_dir_path( make, symlinks.str[j] ), obj_dir_path( make, program ));
3655 output_symlink_rule( program, obj_dir_path( make, symlinks.str[j] ), 0 );
3657 strarray_addall( &make->all_targets, symlinks );
3659 add_install_rule( make, program, program_installed ? program_installed : program,
3660 strmake( "p$(bindir)/%s", program ));
3661 for (j = 0; j < symlinks.count; j++)
3662 add_install_rule( make, symlinks.str[j], program,
3663 strmake( "y$(bindir)/%s%s", symlinks.str[j], exe_ext ));
3668 /*******************************************************************
3669 * output_subdirs
3671 static void output_subdirs( struct makefile *make )
3673 struct strarray all_targets = empty_strarray;
3674 struct strarray makefile_deps = empty_strarray;
3675 struct strarray clean_files = empty_strarray;
3676 struct strarray testclean_files = empty_strarray;
3677 struct strarray distclean_files = empty_strarray;
3678 struct strarray dependencies = empty_strarray;
3679 struct strarray install_lib_deps = empty_strarray;
3680 struct strarray install_dev_deps = empty_strarray;
3681 struct strarray tooldeps_deps = empty_strarray;
3682 struct strarray buildtest_deps = empty_strarray;
3683 unsigned int i;
3685 strarray_addall( &clean_files, make->clean_files );
3686 strarray_addall( &distclean_files, make->distclean_files );
3687 strarray_addall( &all_targets, make->all_targets );
3688 for (i = 0; i < subdirs.count; i++)
3690 strarray_add( &makefile_deps, src_dir_path( submakes[i], strmake ( "%s.in", output_makefile_name )));
3691 strarray_addall_uniq( &make->phony_targets, submakes[i]->phony_targets );
3692 strarray_addall_uniq( &make->uninstall_files, submakes[i]->uninstall_files );
3693 strarray_addall_uniq( &dependencies, submakes[i]->dependencies );
3694 strarray_addall_path( &clean_files, submakes[i]->obj_dir, submakes[i]->clean_files );
3695 strarray_addall_path( &distclean_files, submakes[i]->obj_dir, submakes[i]->distclean_files );
3696 strarray_addall_path( &testclean_files, submakes[i]->obj_dir, submakes[i]->ok_files );
3697 strarray_addall_path( &make->pot_files, submakes[i]->obj_dir, submakes[i]->pot_files );
3699 if (submakes[i]->disabled) continue;
3701 strarray_addall_path( &all_targets, submakes[i]->obj_dir, submakes[i]->all_targets );
3702 if (!strcmp( submakes[i]->obj_dir, "tools" ) || !strncmp( submakes[i]->obj_dir, "tools/", 6 ))
3703 strarray_add( &tooldeps_deps, obj_dir_path( submakes[i], "all" ));
3704 if (submakes[i]->testdll)
3705 strarray_add( &buildtest_deps, obj_dir_path( submakes[i], "all" ));
3706 if (submakes[i]->install_rules[INSTALL_LIB].count)
3707 strarray_add( &install_lib_deps, obj_dir_path( submakes[i], "install-lib" ));
3708 if (submakes[i]->install_rules[INSTALL_DEV].count)
3709 strarray_add( &install_dev_deps, obj_dir_path( submakes[i], "install-dev" ));
3711 strarray_addall( &dependencies, makefile_deps );
3712 output( "all:" );
3713 output_filenames( all_targets );
3714 output( "\n" );
3715 output( "Makefile:" );
3716 output_filenames( makefile_deps );
3717 output( "\n" );
3718 output_filenames( dependencies );
3719 output( ":\n" );
3720 if (install_lib_deps.count)
3722 output( "install install-lib::" );
3723 output_filenames( install_lib_deps );
3724 output( "\n" );
3725 strarray_add_uniq( &make->phony_targets, "install" );
3726 strarray_add_uniq( &make->phony_targets, "install-lib" );
3728 if (install_dev_deps.count)
3730 output( "install install-dev::" );
3731 output_filenames( install_dev_deps );
3732 output( "\n" );
3733 strarray_add_uniq( &make->phony_targets, "install" );
3734 strarray_add_uniq( &make->phony_targets, "install-dev" );
3736 output_uninstall_rules( make );
3737 if (buildtest_deps.count)
3739 output( "buildtests:" );
3740 output_filenames( buildtest_deps );
3741 output( "\n" );
3742 strarray_add_uniq( &make->phony_targets, "buildtests" );
3744 output( "check test:" );
3745 output_filenames( testclean_files );
3746 output( "\n" );
3747 strarray_add_uniq( &make->phony_targets, "check" );
3748 strarray_add_uniq( &make->phony_targets, "test" );
3750 output( "clean::\n");
3751 output_rm_filenames( clean_files );
3752 output( "testclean::\n");
3753 output_rm_filenames( testclean_files );
3754 output( "distclean::\n");
3755 output_rm_filenames( distclean_files );
3756 strarray_add_uniq( &make->phony_targets, "distclean" );
3757 strarray_add_uniq( &make->phony_targets, "testclean" );
3759 if (tooldeps_deps.count)
3761 output( "__tooldeps__:" );
3762 output_filenames( tooldeps_deps );
3763 output( "\n" );
3764 strarray_add_uniq( &make->phony_targets, "__tooldeps__" );
3767 if (get_expanded_make_variable( make, "GETTEXTPO_LIBS" )) output_po_files( make );
3769 if (make->phony_targets.count)
3771 output( ".PHONY:" );
3772 output_filenames( make->phony_targets );
3773 output( "\n" );
3778 /*******************************************************************
3779 * output_sources
3781 static void output_sources( struct makefile *make )
3783 struct strarray all_targets = empty_strarray;
3784 struct incl_file *source;
3785 unsigned int i, j;
3787 strarray_add_uniq( &make->phony_targets, "all" );
3789 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
3791 char *obj = xstrdup( source->name );
3792 char *ext = get_extension( obj );
3794 if (!ext) fatal_error( "unsupported file type %s\n", source->name );
3795 *ext++ = 0;
3797 for (j = 0; output_source_funcs[j].ext; j++)
3798 if (!strcmp( ext, output_source_funcs[j].ext )) break;
3800 output_source_funcs[j].fn( make, source, obj );
3801 strarray_addall_uniq( &make->dependencies, source->dependencies );
3804 /* special case for winetest: add resource files from other test dirs */
3805 if (make->obj_dir && !strcmp( make->obj_dir, "programs/winetest" ))
3807 struct strarray tests = enable_tests;
3808 if (!tests.count)
3809 for (i = 0; i < subdirs.count; i++)
3810 if (submakes[i]->testdll && !submakes[i]->disabled)
3811 strarray_add( &tests, submakes[i]->testdll );
3812 for (i = 0; i < tests.count; i++)
3813 strarray_add( &make->res_files, replace_extension( tests.str[i], ".dll", "_test.res" ));
3816 if (make->dlldata_files.count)
3818 output( "%s: %s %s\n", obj_dir_path( make, "dlldata.c" ),
3819 tools_path( make, "widl" ), src_dir_path( make, "Makefile.in" ));
3820 output( "\t%s%s --dlldata-only -o $@", cmd_prefix( "WIDL" ), tools_path( make, "widl" ));
3821 output_filenames( make->dlldata_files );
3822 output( "\n" );
3825 if (make->staticlib) output_static_lib( make );
3826 else if (make->module) output_module( make );
3827 else if (make->testdll) output_test_module( make );
3828 else if (make->sharedlib) output_shared_lib( make );
3829 else if (make->programs.count) output_programs( make );
3831 for (i = 0; i < make->scripts.count; i++)
3832 add_install_rule( make, make->scripts.str[i], make->scripts.str[i],
3833 strmake( "S$(bindir)/%s", make->scripts.str[i] ));
3835 for (i = 0; i < make->extra_targets.count; i++)
3836 if (strarray_exists( &make->dependencies, obj_dir_path( make, make->extra_targets.str[i] )))
3837 strarray_add( &make->clean_files, make->extra_targets.str[i] );
3838 else
3839 strarray_add( &make->all_targets, make->extra_targets.str[i] );
3841 if (!make->src_dir) strarray_add( &make->distclean_files, ".gitignore" );
3842 strarray_add( &make->distclean_files, "Makefile" );
3843 if (make->testdll) strarray_add( &make->distclean_files, "testlist.c" );
3845 if (!make->obj_dir)
3846 strarray_addall( &make->distclean_files, get_expanded_make_var_array( make, "CONFIGURE_TARGETS" ));
3847 else if (!strcmp( make->obj_dir, "po" ))
3848 strarray_add( &make->distclean_files, "LINGUAS" );
3850 strarray_addall( &make->clean_files, make->object_files );
3851 strarray_addall( &make->clean_files, make->crossobj_files );
3852 strarray_addall( &make->clean_files, make->unixobj_files );
3853 strarray_addall( &make->clean_files, make->res_files );
3854 strarray_addall( &make->clean_files, make->pot_files );
3855 strarray_addall( &make->clean_files, make->debug_files );
3856 strarray_addall( &make->clean_files, make->all_targets );
3858 if (make == top_makefile)
3860 output_subdirs( make );
3861 return;
3864 strarray_addall( &all_targets, make->all_targets );
3865 strarray_addall( &all_targets, make->font_files );
3866 if (all_targets.count)
3868 output( "%s:", obj_dir_path( make, "all" ));
3869 output_filenames_obj_dir( make, all_targets );
3870 output( "\n" );
3871 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "all" ));
3873 output_install_rules( make, INSTALL_LIB, "install-lib" );
3874 output_install_rules( make, INSTALL_DEV, "install-dev" );
3876 if (make->clean_files.count)
3878 output( "%s::\n", obj_dir_path( make, "clean" ));
3879 output( "\trm -f" );
3880 output_filenames_obj_dir( make, make->clean_files );
3881 output( "\n" );
3882 strarray_add( &make->phony_targets, obj_dir_path( make, "clean" ));
3887 /*******************************************************************
3888 * create_temp_file
3890 static FILE *create_temp_file( const char *orig )
3892 char *name = xmalloc( strlen(orig) + 13 );
3893 unsigned int i, id = getpid();
3894 int fd;
3895 FILE *ret = NULL;
3897 for (i = 0; i < 100; i++)
3899 sprintf( name, "%s.tmp%08x", orig, id );
3900 if ((fd = open( name, O_RDWR | O_CREAT | O_EXCL, 0666 )) != -1)
3902 ret = fdopen( fd, "w" );
3903 break;
3905 if (errno != EEXIST) break;
3906 id += 7777;
3908 if (!ret) fatal_error( "failed to create output file for '%s'\n", orig );
3909 temp_file_name = name;
3910 return ret;
3914 /*******************************************************************
3915 * rename_temp_file
3917 static void rename_temp_file( const char *dest )
3919 int ret = rename( temp_file_name, dest );
3920 if (ret == -1 && errno == EEXIST)
3922 /* rename doesn't overwrite on windows */
3923 unlink( dest );
3924 ret = rename( temp_file_name, dest );
3926 if (ret == -1) fatal_error( "failed to rename output file to '%s'\n", dest );
3927 temp_file_name = NULL;
3931 /*******************************************************************
3932 * are_files_identical
3934 static int are_files_identical( FILE *file1, FILE *file2 )
3936 for (;;)
3938 char buffer1[8192], buffer2[8192];
3939 int size1 = fread( buffer1, 1, sizeof(buffer1), file1 );
3940 int size2 = fread( buffer2, 1, sizeof(buffer2), file2 );
3941 if (size1 != size2) return 0;
3942 if (!size1) return feof( file1 ) && feof( file2 );
3943 if (memcmp( buffer1, buffer2, size1 )) return 0;
3948 /*******************************************************************
3949 * rename_temp_file_if_changed
3951 static void rename_temp_file_if_changed( const char *dest )
3953 FILE *file1, *file2;
3954 int do_rename = 1;
3956 if ((file1 = fopen( dest, "r" )))
3958 if ((file2 = fopen( temp_file_name, "r" )))
3960 do_rename = !are_files_identical( file1, file2 );
3961 fclose( file2 );
3963 fclose( file1 );
3965 if (!do_rename)
3967 unlink( temp_file_name );
3968 temp_file_name = NULL;
3970 else rename_temp_file( dest );
3974 /*******************************************************************
3975 * output_linguas
3977 static void output_linguas( const struct makefile *make )
3979 const char *dest = obj_dir_path( make, "LINGUAS" );
3980 struct incl_file *source;
3982 output_file = create_temp_file( dest );
3984 output( "# Automatically generated by make depend; DO NOT EDIT!!\n" );
3985 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
3986 if (strendswith( source->name, ".po" ))
3987 output( "%s\n", replace_extension( source->name, ".po", "" ));
3989 if (fclose( output_file )) fatal_perror( "write" );
3990 output_file = NULL;
3991 rename_temp_file_if_changed( dest );
3995 /*******************************************************************
3996 * output_testlist
3998 static void output_testlist( const struct makefile *make )
4000 const char *dest = obj_dir_path( make, "testlist.c" );
4001 struct strarray files = empty_strarray;
4002 unsigned int i;
4004 for (i = 0; i < make->ok_files.count; i++)
4005 strarray_add( &files, replace_extension( make->ok_files.str[i], ".ok", "" ));
4007 output_file = create_temp_file( dest );
4009 output( "/* Automatically generated by make depend; DO NOT EDIT!! */\n\n" );
4010 output( "#define WIN32_LEAN_AND_MEAN\n" );
4011 output( "#include <windows.h>\n\n" );
4012 output( "#define STANDALONE\n" );
4013 output( "#include \"wine/test.h\"\n\n" );
4015 for (i = 0; i < files.count; i++) output( "extern void func_%s(void);\n", files.str[i] );
4016 output( "\n" );
4017 output( "const struct test winetest_testlist[] =\n" );
4018 output( "{\n" );
4019 for (i = 0; i < files.count; i++) output( " { \"%s\", func_%s },\n", files.str[i], files.str[i] );
4020 output( " { 0, 0 }\n" );
4021 output( "};\n" );
4023 if (fclose( output_file )) fatal_perror( "write" );
4024 output_file = NULL;
4025 rename_temp_file_if_changed( dest );
4029 /*******************************************************************
4030 * output_gitignore
4032 static void output_gitignore( const char *dest, struct strarray files )
4034 int i;
4036 output_file = create_temp_file( dest );
4038 output( "# Automatically generated by make depend; DO NOT EDIT!!\n" );
4039 for (i = 0; i < files.count; i++)
4041 if (!strchr( files.str[i], '/' )) output( "/" );
4042 output( "%s\n", files.str[i] );
4045 if (fclose( output_file )) fatal_perror( "write" );
4046 output_file = NULL;
4047 rename_temp_file( dest );
4051 /*******************************************************************
4052 * output_stub_makefile
4054 static void output_stub_makefile( struct makefile *make )
4056 struct strarray targets = empty_strarray;
4057 const char *make_var = strarray_get_value( &top_makefile->vars, "MAKE" );
4059 if (make_var) output( "MAKE = %s\n\n", make_var );
4060 output( "all:\n" );
4062 if (make->all_targets.count) strarray_add( &targets, "all" );
4063 if (make->install_rules[INSTALL_LIB].count || make->install_rules[INSTALL_DEV].count)
4064 strarray_add( &targets, "install" );
4065 if (make->install_rules[INSTALL_LIB].count) strarray_add( &targets, "install-lib" );
4066 if (make->install_rules[INSTALL_DEV].count) strarray_add( &targets, "install-dev" );
4067 if (make->clean_files.count) strarray_add( &targets, "clean" );
4068 if (make->ok_files.count)
4070 strarray_add( &targets, "check" );
4071 strarray_add( &targets, "test" );
4072 strarray_add( &targets, "testclean" );
4075 output_filenames( targets );
4076 output_filenames( make->clean_files );
4077 output( ":\n" );
4078 output( "\t@cd %s && $(MAKE) %s/$@\n", get_relative_path( make->obj_dir, "" ), make->obj_dir );
4079 output( ".PHONY:" );
4080 output_filenames( targets );
4081 output( "\n" );
4085 /*******************************************************************
4086 * output_silent_rules
4088 static void output_silent_rules(void)
4090 static const char *cmds[] =
4092 "AR",
4093 "BISON",
4094 "BUILD",
4095 "CC",
4096 "CCLD",
4097 "FLEX",
4098 "GEN",
4099 "LN",
4100 "MSG",
4101 "SED",
4102 "TEST",
4103 "WIDL",
4104 "WMC",
4105 "WRC"
4107 unsigned int i;
4109 output( "V = 0\n" );
4110 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++)
4112 output( "quiet_%s = $(quiet_%s_$(V))\n", cmds[i], cmds[i] );
4113 output( "quiet_%s_0 = @echo \" %-5s \" $@;\n", cmds[i], cmds[i] );
4114 output( "quiet_%s_1 =\n", cmds[i] );
4119 /*******************************************************************
4120 * output_dependencies
4122 static void output_dependencies( struct makefile *make )
4124 struct strarray ignore_files = empty_strarray;
4125 char buffer[1024];
4126 FILE *src_file;
4127 int i, found = 0;
4129 if (make->obj_dir) create_dir( make->obj_dir );
4131 output_file_name = obj_dir_path( make, output_makefile_name );
4132 output_file = create_temp_file( output_file_name );
4134 /* copy the contents of the source makefile */
4135 src_file = open_input_makefile( make );
4136 while (fgets( buffer, sizeof(buffer), src_file ) && !found)
4138 if (fwrite( buffer, 1, strlen(buffer), output_file ) != strlen(buffer)) fatal_perror( "write" );
4139 found = !strncmp( buffer, separator, strlen(separator) );
4141 if (fclose( src_file )) fatal_perror( "close" );
4142 input_file_name = NULL;
4144 if (!found) output( "\n%s (everything below this line is auto-generated; DO NOT EDIT!!)\n", separator );
4146 if (make == top_makefile)
4148 if (silent_rules) output_silent_rules();
4149 for (i = 0; i < subdirs.count; i++) output_sources( submakes[i] );
4150 output_sources( make );
4152 else output_stub_makefile( make );
4154 /* disable implicit rules */
4155 output( ".SUFFIXES:\n" );
4157 fclose( output_file );
4158 output_file = NULL;
4159 rename_temp_file( output_file_name );
4161 strarray_addall( &ignore_files, make->distclean_files );
4162 strarray_addall( &ignore_files, make->clean_files );
4163 if (make->testdll) output_testlist( make );
4164 if (make->obj_dir && !strcmp( make->obj_dir, "po" )) output_linguas( make );
4165 if (!make->src_dir) output_gitignore( obj_dir_path( make, ".gitignore" ), ignore_files );
4167 create_file_directories( make, ignore_files );
4169 output_file_name = NULL;
4173 /*******************************************************************
4174 * load_sources
4176 static void load_sources( struct makefile *make )
4178 static const char *source_vars[] =
4180 "SOURCES",
4181 "C_SRCS",
4182 "OBJC_SRCS",
4183 "RC_SRCS",
4184 "MC_SRCS",
4185 "IDL_SRCS",
4186 "BISON_SRCS",
4187 "LEX_SRCS",
4188 "HEADER_SRCS",
4189 "XTEMPLATE_SRCS",
4190 "SVG_SRCS",
4191 "FONT_SRCS",
4192 "IN_SRCS",
4193 "PO_SRCS",
4194 "MANPAGES",
4195 NULL
4197 const char **var;
4198 unsigned int i;
4199 struct strarray value;
4200 struct incl_file *file;
4202 strarray_set_value( &make->vars, "top_srcdir", root_src_dir_path( "" ));
4203 strarray_set_value( &make->vars, "srcdir", src_dir_path( make, "" ));
4205 make->parent_dir = get_expanded_make_variable( make, "PARENTSRC" );
4206 make->module = get_expanded_make_variable( make, "MODULE" );
4207 make->testdll = get_expanded_make_variable( make, "TESTDLL" );
4208 make->sharedlib = get_expanded_make_variable( make, "SHAREDLIB" );
4209 make->staticlib = get_expanded_make_variable( make, "STATICLIB" );
4210 make->importlib = get_expanded_make_variable( make, "IMPORTLIB" );
4212 make->programs = get_expanded_make_var_array( make, "PROGRAMS" );
4213 make->scripts = get_expanded_make_var_array( make, "SCRIPTS" );
4214 make->imports = get_expanded_make_var_array( make, "IMPORTS" );
4215 make->delayimports = get_expanded_make_var_array( make, "DELAYIMPORTS" );
4216 make->extradllflags = get_expanded_make_var_array( make, "EXTRADLLFLAGS" );
4217 make->install_lib = get_expanded_make_var_array( make, "INSTALL_LIB" );
4218 make->install_dev = get_expanded_make_var_array( make, "INSTALL_DEV" );
4219 make->extra_targets = get_expanded_make_var_array( make, "EXTRA_TARGETS" );
4221 if (make->module && strendswith( make->module, ".a" )) make->staticlib = make->module;
4223 make->is_win16 = strarray_exists( &make->extradllflags, "-m16" );
4224 if ((make->module && make->staticlib) || make->testdll || make->is_win16)
4225 strarray_add_uniq( &make->extradllflags, "-mno-cygwin" );
4227 strarray_addall( &make->extradllflags, get_expanded_make_var_array( make, "APPMODE" ));
4228 make->disabled = make->obj_dir && strarray_exists( &disabled_dirs, make->obj_dir );
4229 make->use_msvcrt = strarray_exists( &make->extradllflags, "-mno-cygwin" );
4230 make->is_exe = strarray_exists( &make->extradllflags, "-mconsole" ) ||
4231 strarray_exists( &make->extradllflags, "-mwindows" );
4233 if (make->module && !make->install_lib.count && !make->install_dev.count)
4235 if (make->importlib) strarray_add( &make->install_dev, make->importlib );
4236 if (make->staticlib) strarray_add( &make->install_dev, make->staticlib );
4237 else strarray_add( &make->install_lib, make->module );
4240 make->include_paths = empty_strarray;
4241 make->include_args = empty_strarray;
4242 make->define_args = empty_strarray;
4243 strarray_add( &make->define_args, "-D__WINESRC__" );
4245 value = get_expanded_make_var_array( make, "EXTRAINCL" );
4246 for (i = 0; i < value.count; i++)
4247 if (!strncmp( value.str[i], "-I", 2 ))
4248 strarray_add_uniq( &make->include_paths, value.str[i] + 2 );
4249 else if (!strncmp( value.str[i], "-D", 2 ) || !strncmp( value.str[i], "-U", 2 ))
4250 strarray_add_uniq( &make->define_args, value.str[i] );
4251 strarray_addall( &make->define_args, get_expanded_make_var_array( make, "EXTRADEFS" ));
4253 strarray_add( &make->include_args, strmake( "-I%s", obj_dir_path( make, "" )));
4254 if (make->src_dir)
4255 strarray_add( &make->include_args, strmake( "-I%s", make->src_dir ));
4256 if (make->parent_dir)
4257 strarray_add( &make->include_args, strmake( "-I%s", src_dir_path( make, make->parent_dir )));
4258 strarray_add( &make->include_args, "-Iinclude" );
4259 if (root_src_dir) strarray_add( &make->include_args, strmake( "-I%s", root_src_dir_path( "include" )));
4261 list_init( &make->sources );
4262 list_init( &make->includes );
4264 for (var = source_vars; *var; var++)
4266 value = get_expanded_make_var_array( make, *var );
4267 for (i = 0; i < value.count; i++) add_src_file( make, value.str[i] );
4270 add_generated_sources( make );
4272 if (!make->use_msvcrt && !has_object_file( make ))
4274 strarray_add( &make->extradllflags, "-mno-cygwin" );
4275 make->use_msvcrt = 1;
4278 if (make->use_msvcrt) add_crt_import( make, &make->imports, &make->define_args );
4280 LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry ) parse_file( make, file, 0 );
4281 LIST_FOR_EACH_ENTRY( file, &make->sources, struct incl_file, entry ) get_dependencies( file, file );
4283 make->is_cross = crosstarget && make->use_msvcrt;
4285 if (!*dll_ext || make->is_cross)
4286 for (i = 0; i < make->delayimports.count; i++)
4287 strarray_add_uniq( &delay_import_libs, get_base_name( make->delayimports.str[i] ));
4291 /*******************************************************************
4292 * parse_makeflags
4294 static void parse_makeflags( const char *flags )
4296 const char *p = flags;
4297 char *var, *buffer = xmalloc( strlen(flags) + 1 );
4299 while (*p)
4301 while (isspace(*p)) p++;
4302 var = buffer;
4303 while (*p && !isspace(*p))
4305 if (*p == '\\' && p[1]) p++;
4306 *var++ = *p++;
4308 *var = 0;
4309 if (var > buffer) set_make_variable( &cmdline_vars, buffer );
4314 /*******************************************************************
4315 * parse_option
4317 static int parse_option( const char *opt )
4319 if (opt[0] != '-')
4321 if (strchr( opt, '=' )) return set_make_variable( &cmdline_vars, opt );
4322 return 0;
4324 switch(opt[1])
4326 case 'f':
4327 if (opt[2]) output_makefile_name = opt + 2;
4328 break;
4329 case 'R':
4330 relative_dir_mode = 1;
4331 break;
4332 case 'S':
4333 silent_rules = 1;
4334 break;
4335 default:
4336 fprintf( stderr, "Unknown option '%s'\n%s", opt, Usage );
4337 exit(1);
4339 return 1;
4343 /*******************************************************************
4344 * main
4346 int main( int argc, char *argv[] )
4348 const char *makeflags = getenv( "MAKEFLAGS" );
4349 int i, j;
4351 if (makeflags) parse_makeflags( makeflags );
4353 i = 1;
4354 while (i < argc)
4356 if (parse_option( argv[i] ))
4358 for (j = i; j < argc; j++) argv[j] = argv[j+1];
4359 argc--;
4361 else i++;
4364 if (relative_dir_mode)
4366 char *relpath;
4368 if (argc != 3)
4370 fprintf( stderr, "Option -R needs two directories\n%s", Usage );
4371 exit( 1 );
4373 relpath = get_relative_path( argv[1], argv[2] );
4374 printf( "%s\n", relpath ? relpath : "." );
4375 exit( 0 );
4378 if (argc > 1) fatal_error( "Directory arguments not supported in this mode\n" );
4380 atexit( cleanup_files );
4381 signal( SIGTERM, exit_on_signal );
4382 signal( SIGINT, exit_on_signal );
4383 #ifdef SIGHUP
4384 signal( SIGHUP, exit_on_signal );
4385 #endif
4387 for (i = 0; i < HASH_SIZE; i++) list_init( &files[i] );
4389 top_makefile = parse_makefile( NULL );
4391 target_flags = get_expanded_make_var_array( top_makefile, "TARGETFLAGS" );
4392 msvcrt_flags = get_expanded_make_var_array( top_makefile, "MSVCRTFLAGS" );
4393 dll_flags = get_expanded_make_var_array( top_makefile, "DLLFLAGS" );
4394 extra_cflags = get_expanded_make_var_array( top_makefile, "EXTRACFLAGS" );
4395 extra_cross_cflags = get_expanded_make_var_array( top_makefile, "EXTRACROSSCFLAGS" );
4396 cpp_flags = get_expanded_make_var_array( top_makefile, "CPPFLAGS" );
4397 lddll_flags = get_expanded_make_var_array( top_makefile, "LDDLLFLAGS" );
4398 libs = get_expanded_make_var_array( top_makefile, "LIBS" );
4399 enable_tests = get_expanded_make_var_array( top_makefile, "ENABLE_TESTS" );
4400 delay_load_flag = get_expanded_make_variable( top_makefile, "DELAYLOADFLAG" );
4401 top_install_lib = get_expanded_make_var_array( top_makefile, "TOP_INSTALL_LIB" );
4402 top_install_dev = get_expanded_make_var_array( top_makefile, "TOP_INSTALL_DEV" );
4404 root_src_dir = get_expanded_make_variable( top_makefile, "srcdir" );
4405 tools_dir = get_expanded_make_variable( top_makefile, "TOOLSDIR" );
4406 tools_ext = get_expanded_make_variable( top_makefile, "TOOLSEXT" );
4407 exe_ext = get_expanded_make_variable( top_makefile, "EXEEXT" );
4408 man_ext = get_expanded_make_variable( top_makefile, "api_manext" );
4409 dll_ext = (exe_ext && !strcmp( exe_ext, ".exe" )) ? "" : ".so";
4410 arch = get_expanded_make_variable( top_makefile, "ARCH" );
4411 crosstarget = get_expanded_make_variable( top_makefile, "CROSSTARGET" );
4412 crossdebug = get_expanded_make_variable( top_makefile, "CROSSDEBUG" );
4413 fontforge = get_expanded_make_variable( top_makefile, "FONTFORGE" );
4414 convert = get_expanded_make_variable( top_makefile, "CONVERT" );
4415 flex = get_expanded_make_variable( top_makefile, "FLEX" );
4416 bison = get_expanded_make_variable( top_makefile, "BISON" );
4417 ar = get_expanded_make_variable( top_makefile, "AR" );
4418 ranlib = get_expanded_make_variable( top_makefile, "RANLIB" );
4419 rsvg = get_expanded_make_variable( top_makefile, "RSVG" );
4420 icotool = get_expanded_make_variable( top_makefile, "ICOTOOL" );
4421 dlltool = get_expanded_make_variable( top_makefile, "DLLTOOL" );
4422 msgfmt = get_expanded_make_variable( top_makefile, "MSGFMT" );
4423 sed_cmd = get_expanded_make_variable( top_makefile, "SED_CMD" );
4424 ln_s = get_expanded_make_variable( top_makefile, "LN_S" );
4426 if (root_src_dir && !strcmp( root_src_dir, "." )) root_src_dir = NULL;
4427 if (tools_dir && !strcmp( tools_dir, "." )) tools_dir = NULL;
4428 if (!exe_ext) exe_ext = "";
4429 if (!tools_ext) tools_ext = "";
4430 if (!man_ext) man_ext = "3w";
4431 if (arch)
4433 so_dir = strmake( "$(dlldir)/%s-unix", arch );
4434 pe_dir = strmake( "$(dlldir)/%s-windows", arch );
4436 else
4437 so_dir = pe_dir = "$(dlldir)";
4439 top_makefile->src_dir = root_src_dir;
4440 subdirs = get_expanded_make_var_array( top_makefile, "SUBDIRS" );
4441 disabled_dirs = get_expanded_make_var_array( top_makefile, "DISABLED_SUBDIRS" );
4442 submakes = xmalloc( subdirs.count * sizeof(*submakes) );
4444 for (i = 0; i < subdirs.count; i++) submakes[i] = parse_makefile( subdirs.str[i] );
4446 load_sources( top_makefile );
4447 for (i = 0; i < subdirs.count; i++) load_sources( submakes[i] );
4449 output_dependencies( top_makefile );
4450 for (i = 0; i < subdirs.count; i++) output_dependencies( submakes[i] );
4452 return 0;