dwrite: Implement set builder methods that don't specify font properties.
[wine.git] / tools / makedep.c
blob913854c7f054a3583441c9d4e1fa5d022809de4e
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 cross_import_libs;
152 static struct strarray delay_import_libs;
153 static struct strarray top_install_lib;
154 static struct strarray top_install_dev;
155 static const char *root_src_dir;
156 static const char *tools_dir;
157 static const char *tools_ext;
158 static const char *exe_ext;
159 static const char *dll_ext;
160 static const char *man_ext;
161 static const char *crosstarget;
162 static const char *crossdebug;
163 static const char *fontforge;
164 static const char *convert;
165 static const char *flex;
166 static const char *bison;
167 static const char *ar;
168 static const char *ranlib;
169 static const char *rsvg;
170 static const char *icotool;
171 static const char *dlltool;
172 static const char *msgfmt;
173 static const char *ln_s;
174 static const char *sed_cmd;
175 static const char *delay_load_flag;
177 struct makefile
179 /* values determined from input makefile */
180 struct strarray vars;
181 struct strarray include_paths;
182 struct strarray include_args;
183 struct strarray define_args;
184 struct strarray programs;
185 struct strarray scripts;
186 struct strarray imports;
187 struct strarray delayimports;
188 struct strarray extradllflags;
189 struct strarray install_lib;
190 struct strarray install_dev;
191 struct strarray extra_targets;
192 struct strarray extra_imports;
193 struct list sources;
194 struct list includes;
195 const char *src_dir;
196 const char *obj_dir;
197 const char *parent_dir;
198 const char *module;
199 const char *testdll;
200 const char *sharedlib;
201 const char *staticlib;
202 const char *staticimplib;
203 const char *importlib;
204 int disabled;
205 int use_msvcrt;
206 int is_cross;
207 int is_win16;
208 int is_exe;
210 /* values generated at output time */
211 struct strarray in_files;
212 struct strarray ok_files;
213 struct strarray pot_files;
214 struct strarray clean_files;
215 struct strarray distclean_files;
216 struct strarray uninstall_files;
217 struct strarray object_files;
218 struct strarray crossobj_files;
219 struct strarray unixobj_files;
220 struct strarray res_files;
221 struct strarray font_files;
222 struct strarray c2man_files;
223 struct strarray debug_files;
224 struct strarray dlldata_files;
225 struct strarray implib_objs;
226 struct strarray all_targets;
227 struct strarray phony_targets;
228 struct strarray dependencies;
229 struct strarray install_rules[NB_INSTALL_RULES];
232 static struct makefile *top_makefile;
233 static struct makefile **submakes;
235 static const char separator[] = "### Dependencies";
236 static const char *output_makefile_name = "Makefile";
237 static const char *input_file_name;
238 static const char *output_file_name;
239 static const char *temp_file_name;
240 static int relative_dir_mode;
241 static int silent_rules;
242 static int input_line;
243 static int output_column;
244 static FILE *output_file;
246 static const char Usage[] =
247 "Usage: makedep [options] [directories]\n"
248 "Options:\n"
249 " -R from to Compute the relative path between two directories\n"
250 " -S Generate Automake-style silent rules\n"
251 " -fxxx Store output in file 'xxx' (default: Makefile)\n";
254 #ifndef __GNUC__
255 #define __attribute__(x)
256 #endif
258 static void fatal_error( const char *msg, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
259 static void fatal_perror( const char *msg, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
260 static void output( const char *format, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
261 static char *strmake( const char* fmt, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
263 /*******************************************************************
264 * fatal_error
266 static void fatal_error( const char *msg, ... )
268 va_list valist;
269 va_start( valist, msg );
270 if (input_file_name)
272 fprintf( stderr, "%s:", input_file_name );
273 if (input_line) fprintf( stderr, "%d:", input_line );
274 fprintf( stderr, " error: " );
276 else fprintf( stderr, "makedep: error: " );
277 vfprintf( stderr, msg, valist );
278 va_end( valist );
279 exit(1);
283 /*******************************************************************
284 * fatal_perror
286 static void fatal_perror( const char *msg, ... )
288 va_list valist;
289 va_start( valist, msg );
290 if (input_file_name)
292 fprintf( stderr, "%s:", input_file_name );
293 if (input_line) fprintf( stderr, "%d:", input_line );
294 fprintf( stderr, " error: " );
296 else fprintf( stderr, "makedep: error: " );
297 vfprintf( stderr, msg, valist );
298 perror( " " );
299 va_end( valist );
300 exit(1);
304 /*******************************************************************
305 * cleanup_files
307 static void cleanup_files(void)
309 if (temp_file_name) unlink( temp_file_name );
310 if (output_file_name) unlink( output_file_name );
314 /*******************************************************************
315 * exit_on_signal
317 static void exit_on_signal( int sig )
319 exit( 1 ); /* this will call the atexit functions */
323 /*******************************************************************
324 * xmalloc
326 static void *xmalloc( size_t size )
328 void *res;
329 if (!(res = malloc (size ? size : 1)))
330 fatal_error( "Virtual memory exhausted.\n" );
331 return res;
335 /*******************************************************************
336 * xrealloc
338 static void *xrealloc (void *ptr, size_t size)
340 void *res;
341 assert( size );
342 if (!(res = realloc( ptr, size )))
343 fatal_error( "Virtual memory exhausted.\n" );
344 return res;
347 /*******************************************************************
348 * xstrdup
350 static char *xstrdup( const char *str )
352 char *res = strdup( str );
353 if (!res) fatal_error( "Virtual memory exhausted.\n" );
354 return res;
358 /*******************************************************************
359 * strmake
361 static char *strmake( const char* fmt, ... )
363 int n;
364 size_t size = 100;
365 va_list ap;
367 for (;;)
369 char *p = xmalloc (size);
370 va_start(ap, fmt);
371 n = vsnprintf (p, size, fmt, ap);
372 va_end(ap);
373 if (n == -1) size *= 2;
374 else if ((size_t)n >= size) size = n + 1;
375 else return xrealloc( p, n + 1 );
376 free(p);
381 /*******************************************************************
382 * strendswith
384 static int strendswith( const char* str, const char* end )
386 size_t l = strlen( str );
387 size_t m = strlen( end );
389 return l >= m && strcmp(str + l - m, end) == 0;
393 /*******************************************************************
394 * output
396 static void output( const char *format, ... )
398 int ret;
399 va_list valist;
401 va_start( valist, format );
402 ret = vfprintf( output_file, format, valist );
403 va_end( valist );
404 if (ret < 0) fatal_perror( "output" );
405 if (format[0] && format[strlen(format) - 1] == '\n') output_column = 0;
406 else output_column += ret;
410 /*******************************************************************
411 * strarray_add
413 static void strarray_add( struct strarray *array, const char *str )
415 if (array->count == array->size)
417 if (array->size) array->size *= 2;
418 else array->size = 16;
419 array->str = xrealloc( array->str, sizeof(array->str[0]) * array->size );
421 array->str[array->count++] = str;
425 /*******************************************************************
426 * strarray_addall
428 static void strarray_addall( struct strarray *array, struct strarray added )
430 unsigned int i;
432 for (i = 0; i < added.count; i++) strarray_add( array, added.str[i] );
436 /*******************************************************************
437 * strarray_exists
439 static int strarray_exists( const struct strarray *array, const char *str )
441 unsigned int i;
443 for (i = 0; i < array->count; i++) if (!strcmp( array->str[i], str )) return 1;
444 return 0;
448 /*******************************************************************
449 * strarray_add_uniq
451 static void strarray_add_uniq( struct strarray *array, const char *str )
453 if (!strarray_exists( array, str )) strarray_add( array, str );
457 /*******************************************************************
458 * strarray_addall_uniq
460 static void strarray_addall_uniq( struct strarray *array, struct strarray added )
462 unsigned int i;
464 for (i = 0; i < added.count; i++) strarray_add_uniq( array, added.str[i] );
468 /*******************************************************************
469 * strarray_get_value
471 * Find a value in a name/value pair string array.
473 static const char *strarray_get_value( const struct strarray *array, const char *name )
475 int pos, res, min = 0, max = array->count / 2 - 1;
477 while (min <= max)
479 pos = (min + max) / 2;
480 if (!(res = strcmp( array->str[pos * 2], name ))) return array->str[pos * 2 + 1];
481 if (res < 0) min = pos + 1;
482 else max = pos - 1;
484 return NULL;
488 /*******************************************************************
489 * strarray_set_value
491 * Define a value in a name/value pair string array.
493 static void strarray_set_value( struct strarray *array, const char *name, const char *value )
495 int i, pos, res, min = 0, max = array->count / 2 - 1;
497 while (min <= max)
499 pos = (min + max) / 2;
500 if (!(res = strcmp( array->str[pos * 2], name )))
502 /* redefining a variable replaces the previous value */
503 array->str[pos * 2 + 1] = value;
504 return;
506 if (res < 0) min = pos + 1;
507 else max = pos - 1;
509 strarray_add( array, NULL );
510 strarray_add( array, NULL );
511 for (i = array->count - 1; i > min * 2 + 1; i--) array->str[i] = array->str[i - 2];
512 array->str[min * 2] = name;
513 array->str[min * 2 + 1] = value;
517 /*******************************************************************
518 * strarray_set_qsort
520 static void strarray_qsort( struct strarray *array, int (*func)(const char **, const char **) )
522 if (array->count) qsort( array->str, array->count, sizeof(*array->str), (void *)func );
526 /*******************************************************************
527 * output_filename
529 static void output_filename( const char *name )
531 if (output_column + strlen(name) + 1 > 100)
533 output( " \\\n" );
534 output( " " );
536 else if (output_column) output( " " );
537 output( "%s", name );
541 /*******************************************************************
542 * output_filenames
544 static void output_filenames( struct strarray array )
546 unsigned int i;
548 for (i = 0; i < array.count; i++) output_filename( array.str[i] );
552 /*******************************************************************
553 * output_rm_filenames
555 static void output_rm_filenames( struct strarray array )
557 static const unsigned int max_cmdline = 30000; /* to be on the safe side */
558 unsigned int i, len;
560 if (!array.count) return;
561 output( "\trm -f" );
562 for (i = len = 0; i < array.count; i++)
564 if (len > max_cmdline)
566 output( "\n" );
567 output( "\trm -f" );
568 len = 0;
570 output_filename( array.str[i] );
571 len += strlen( array.str[i] ) + 1;
573 output( "\n" );
577 /*******************************************************************
578 * get_extension
580 static char *get_extension( char *filename )
582 char *ext = strrchr( filename, '.' );
583 if (ext && strchr( ext, '/' )) ext = NULL;
584 return ext;
588 /*******************************************************************
589 * get_base_name
591 static const char *get_base_name( const char *name )
593 char *base;
594 if (!strchr( name, '.' )) return name;
595 base = strdup( name );
596 *strrchr( base, '.' ) = 0;
597 return base;
601 /*******************************************************************
602 * replace_extension
604 static char *replace_extension( const char *name, const char *old_ext, const char *new_ext )
606 char *ret;
607 size_t name_len = strlen( name );
608 size_t ext_len = strlen( old_ext );
610 if (name_len >= ext_len && !strcmp( name + name_len - ext_len, old_ext )) name_len -= ext_len;
611 ret = xmalloc( name_len + strlen( new_ext ) + 1 );
612 memcpy( ret, name, name_len );
613 strcpy( ret + name_len, new_ext );
614 return ret;
618 /*******************************************************************
619 * replace_filename
621 static char *replace_filename( const char *path, const char *name )
623 const char *p;
624 char *ret;
625 size_t len;
627 if (!path) return xstrdup( name );
628 if (!(p = strrchr( path, '/' ))) return xstrdup( name );
629 len = p - path + 1;
630 ret = xmalloc( len + strlen( name ) + 1 );
631 memcpy( ret, path, len );
632 strcpy( ret + len, name );
633 return ret;
637 /*******************************************************************
638 * strarray_replace_extension
640 static struct strarray strarray_replace_extension( const struct strarray *array,
641 const char *old_ext, const char *new_ext )
643 unsigned int i;
644 struct strarray ret;
646 ret.count = ret.size = array->count;
647 ret.str = xmalloc( sizeof(ret.str[0]) * ret.size );
648 for (i = 0; i < array->count; i++) ret.str[i] = replace_extension( array->str[i], old_ext, new_ext );
649 return ret;
653 /*******************************************************************
654 * replace_substr
656 static char *replace_substr( const char *str, const char *start, size_t len, const char *replace )
658 size_t pos = start - str;
659 char *ret = xmalloc( pos + strlen(replace) + strlen(start + len) + 1 );
660 memcpy( ret, str, pos );
661 strcpy( ret + pos, replace );
662 strcat( ret + pos, start + len );
663 return ret;
667 /*******************************************************************
668 * get_relative_path
670 * Determine where the destination path is located relative to the 'from' path.
672 static char *get_relative_path( const char *from, const char *dest )
674 const char *start;
675 char *ret, *p;
676 unsigned int dotdots = 0;
678 /* a path of "." is equivalent to an empty path */
679 if (!strcmp( from, "." )) from = "";
681 for (;;)
683 while (*from == '/') from++;
684 while (*dest == '/') dest++;
685 start = dest; /* save start of next path element */
686 if (!*from) break;
688 while (*from && *from != '/' && *from == *dest) { from++; dest++; }
689 if ((!*from || *from == '/') && (!*dest || *dest == '/')) continue;
691 /* count remaining elements in 'from' */
694 dotdots++;
695 while (*from && *from != '/') from++;
696 while (*from == '/') from++;
698 while (*from);
699 break;
702 if (!start[0] && !dotdots) return NULL; /* empty path */
704 ret = xmalloc( 3 * dotdots + strlen( start ) + 1 );
705 for (p = ret; dotdots; dotdots--, p += 3) memcpy( p, "../", 3 );
707 if (start[0]) strcpy( p, start );
708 else p[-1] = 0; /* remove trailing slash */
709 return ret;
713 /*******************************************************************
714 * concat_paths
716 static char *concat_paths( const char *base, const char *path )
718 int i, len;
719 char *ret;
721 if (!base || !base[0]) return xstrdup( path && path[0] ? path : "." );
722 if (!path || !path[0]) return xstrdup( base );
723 if (path[0] == '/') return xstrdup( path );
725 len = strlen( base );
726 while (len && base[len - 1] == '/') len--;
727 while (len && !strncmp( path, "..", 2 ) && (!path[2] || path[2] == '/'))
729 for (i = len; i > 0; i--) if (base[i - 1] == '/') break;
730 if (i == len - 2 && !memcmp( base + i, "..", 2 )) break; /* we can't go up if we already have ".." */
731 if (i != len - 1 || base[i] != '.')
733 path += 2;
734 while (*path == '/') path++;
736 /* else ignore "." element */
737 while (i > 0 && base[i - 1] == '/') i--;
738 len = i;
740 if (!len && base[0] != '/') return xstrdup( path[0] ? path : "." );
741 ret = xmalloc( len + strlen( path ) + 2 );
742 memcpy( ret, base, len );
743 ret[len++] = '/';
744 strcpy( ret + len, path );
745 return ret;
749 /*******************************************************************
750 * obj_dir_path
752 static char *obj_dir_path( const struct makefile *make, const char *path )
754 return concat_paths( make->obj_dir, path );
758 /*******************************************************************
759 * src_dir_path
761 static char *src_dir_path( const struct makefile *make, const char *path )
763 if (make->src_dir) return concat_paths( make->src_dir, path );
764 return obj_dir_path( make, path );
768 /*******************************************************************
769 * root_src_dir_path
771 static char *root_src_dir_path( const char *path )
773 return concat_paths( root_src_dir, path );
777 /*******************************************************************
778 * tools_dir_path
780 static char *tools_dir_path( const struct makefile *make, const char *path )
782 if (tools_dir) return strmake( "%s/tools/%s", tools_dir, path );
783 return strmake( "tools/%s", path );
787 /*******************************************************************
788 * tools_path
790 static char *tools_path( const struct makefile *make, const char *name )
792 return strmake( "%s/%s%s", tools_dir_path( make, name ), name, tools_ext );
796 /*******************************************************************
797 * strarray_addall_path
799 static void strarray_addall_path( struct strarray *array, const char *dir, struct strarray added )
801 unsigned int i;
803 for (i = 0; i < added.count; i++) strarray_add( array, concat_paths( dir, added.str[i] ));
807 /*******************************************************************
808 * get_line
810 static char *get_line( FILE *file )
812 static char *buffer;
813 static size_t size;
815 if (!size)
817 size = 1024;
818 buffer = xmalloc( size );
820 if (!fgets( buffer, size, file )) return NULL;
821 input_line++;
823 for (;;)
825 char *p = buffer + strlen(buffer);
826 /* if line is larger than buffer, resize buffer */
827 while (p == buffer + size - 1 && p[-1] != '\n')
829 buffer = xrealloc( buffer, size * 2 );
830 if (!fgets( buffer + size - 1, size + 1, file )) break;
831 p = buffer + strlen(buffer);
832 size *= 2;
834 if (p > buffer && p[-1] == '\n')
836 *(--p) = 0;
837 if (p > buffer && p[-1] == '\r') *(--p) = 0;
838 if (p > buffer && p[-1] == '\\')
840 *(--p) = 0;
841 /* line ends in backslash, read continuation line */
842 if (!fgets( p, size - (p - buffer), file )) return buffer;
843 input_line++;
844 continue;
847 return buffer;
852 /*******************************************************************
853 * hash_filename
855 static unsigned int hash_filename( const char *name )
857 /* FNV-1 hash */
858 unsigned int ret = 2166136261u;
859 while (*name) ret = (ret * 16777619) ^ *name++;
860 return ret % HASH_SIZE;
864 /*******************************************************************
865 * add_file
867 static struct file *add_file( const char *name )
869 struct file *file = xmalloc( sizeof(*file) );
870 memset( file, 0, sizeof(*file) );
871 file->name = xstrdup( name );
872 return file;
876 /*******************************************************************
877 * add_dependency
879 static void add_dependency( struct file *file, const char *name, enum incl_type type )
881 /* enforce some rules for the Wine tree */
883 if (!memcmp( name, "../", 3 ))
884 fatal_error( "#include directive with relative path not allowed\n" );
886 if (!strcmp( name, "config.h" ))
888 if (strendswith( file->name, ".h" ))
889 fatal_error( "config.h must not be included by a header file\n" );
890 if (file->deps_count)
891 fatal_error( "config.h must be included before anything else\n" );
893 else if (!strcmp( name, "wine/port.h" ))
895 if (strendswith( file->name, ".h" ))
896 fatal_error( "wine/port.h must not be included by a header file\n" );
897 if (!file->deps_count) fatal_error( "config.h must be included before wine/port.h\n" );
898 if (file->deps_count > 1)
899 fatal_error( "wine/port.h must be included before everything except config.h\n" );
900 if (strcmp( file->deps[0].name, "config.h" ))
901 fatal_error( "config.h must be included before wine/port.h\n" );
904 if (file->deps_count >= file->deps_size)
906 file->deps_size *= 2;
907 if (file->deps_size < 16) file->deps_size = 16;
908 file->deps = xrealloc( file->deps, file->deps_size * sizeof(*file->deps) );
910 file->deps[file->deps_count].line = input_line;
911 file->deps[file->deps_count].type = type;
912 file->deps[file->deps_count].name = xstrdup( name );
913 file->deps_count++;
917 /*******************************************************************
918 * find_src_file
920 static struct incl_file *find_src_file( const struct makefile *make, const char *name )
922 struct incl_file *file;
924 LIST_FOR_EACH_ENTRY( file, &make->sources, struct incl_file, entry )
925 if (!strcmp( name, file->name )) return file;
926 return NULL;
929 /*******************************************************************
930 * find_include_file
932 static struct incl_file *find_include_file( const struct makefile *make, const char *name )
934 struct incl_file *file;
936 LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry )
937 if (!strcmp( name, file->name )) return file;
938 return NULL;
941 /*******************************************************************
942 * add_include
944 * Add an include file if it doesn't already exists.
946 static struct incl_file *add_include( struct makefile *make, struct incl_file *parent,
947 const char *name, int line, enum incl_type type )
949 struct incl_file *include;
951 if (parent->files_count >= parent->files_size)
953 parent->files_size *= 2;
954 if (parent->files_size < 16) parent->files_size = 16;
955 parent->files = xrealloc( parent->files, parent->files_size * sizeof(*parent->files) );
958 LIST_FOR_EACH_ENTRY( include, &make->includes, struct incl_file, entry )
959 if (!parent->use_msvcrt == !include->use_msvcrt && !strcmp( name, include->name ))
960 goto found;
962 include = xmalloc( sizeof(*include) );
963 memset( include, 0, sizeof(*include) );
964 include->name = xstrdup(name);
965 include->included_by = parent;
966 include->included_line = line;
967 include->type = type;
968 include->use_msvcrt = parent->use_msvcrt;
969 list_add_tail( &make->includes, &include->entry );
970 found:
971 parent->files[parent->files_count++] = include;
972 return include;
976 /*******************************************************************
977 * add_generated_source
979 * Add a generated source file to the list.
981 static struct incl_file *add_generated_source( struct makefile *make,
982 const char *name, const char *filename )
984 struct incl_file *file;
986 if ((file = find_src_file( make, name ))) return file; /* we already have it */
987 file = xmalloc( sizeof(*file) );
988 memset( file, 0, sizeof(*file) );
989 file->file = add_file( name );
990 file->name = xstrdup( name );
991 file->basename = xstrdup( filename ? filename : name );
992 file->filename = obj_dir_path( make, file->basename );
993 file->file->flags = FLAG_GENERATED;
994 file->use_msvcrt = make->use_msvcrt;
995 list_add_tail( &make->sources, &file->entry );
996 return file;
1000 /*******************************************************************
1001 * parse_include_directive
1003 static void parse_include_directive( struct file *source, char *str )
1005 char quote, *include, *p = str;
1007 while (*p && isspace(*p)) p++;
1008 if (*p != '\"' && *p != '<' ) return;
1009 quote = *p++;
1010 if (quote == '<') quote = '>';
1011 include = p;
1012 while (*p && (*p != quote)) p++;
1013 if (!*p) fatal_error( "malformed include directive '%s'\n", str );
1014 *p = 0;
1015 add_dependency( source, include, (quote == '>') ? INCL_SYSTEM : INCL_NORMAL );
1019 /*******************************************************************
1020 * parse_pragma_directive
1022 static void parse_pragma_directive( struct file *source, char *str )
1024 char *flag, *p = str;
1026 if (!isspace( *p )) return;
1027 while (*p && isspace(*p)) p++;
1028 p = strtok( p, " \t" );
1029 if (strcmp( p, "makedep" )) return;
1031 while ((flag = strtok( NULL, " \t" )))
1033 if (!strcmp( flag, "depend" ))
1035 while ((p = strtok( NULL, " \t" ))) add_dependency( source, p, INCL_NORMAL );
1036 return;
1038 else if (!strcmp( flag, "install" )) source->flags |= FLAG_INSTALL;
1040 if (strendswith( source->name, ".idl" ))
1042 if (!strcmp( flag, "header" )) source->flags |= FLAG_IDL_HEADER;
1043 else if (!strcmp( flag, "proxy" )) source->flags |= FLAG_IDL_PROXY;
1044 else if (!strcmp( flag, "client" )) source->flags |= FLAG_IDL_CLIENT;
1045 else if (!strcmp( flag, "server" )) source->flags |= FLAG_IDL_SERVER;
1046 else if (!strcmp( flag, "ident" )) source->flags |= FLAG_IDL_IDENT;
1047 else if (!strcmp( flag, "typelib" )) source->flags |= FLAG_IDL_TYPELIB;
1048 else if (!strcmp( flag, "register" )) source->flags |= FLAG_IDL_REGISTER;
1049 else if (!strcmp( flag, "regtypelib" )) source->flags |= FLAG_IDL_REGTYPELIB;
1051 else if (strendswith( source->name, ".rc" ))
1053 if (!strcmp( flag, "po" )) source->flags |= FLAG_RC_PO;
1055 else if (strendswith( source->name, ".sfd" ))
1057 if (!strcmp( flag, "font" ))
1059 struct strarray *array = source->args;
1061 if (!array)
1063 source->args = array = xmalloc( sizeof(*array) );
1064 *array = empty_strarray;
1065 source->flags |= FLAG_SFD_FONTS;
1067 strarray_add( array, xstrdup( strtok( NULL, "" )));
1068 return;
1071 else
1073 if (!strcmp( flag, "implib" )) source->flags |= FLAG_C_IMPLIB;
1074 if (!strcmp( flag, "unix" )) source->flags |= FLAG_C_UNIX;
1080 /*******************************************************************
1081 * parse_cpp_directive
1083 static void parse_cpp_directive( struct file *source, char *str )
1085 while (*str && isspace(*str)) str++;
1086 if (*str++ != '#') return;
1087 while (*str && isspace(*str)) str++;
1089 if (!strncmp( str, "include", 7 ))
1090 parse_include_directive( source, str + 7 );
1091 else if (!strncmp( str, "import", 6 ) && strendswith( source->name, ".m" ))
1092 parse_include_directive( source, str + 6 );
1093 else if (!strncmp( str, "pragma", 6 ))
1094 parse_pragma_directive( source, str + 6 );
1098 /*******************************************************************
1099 * parse_idl_file
1101 static void parse_idl_file( struct file *source, FILE *file )
1103 char *buffer, *include;
1105 input_line = 0;
1107 while ((buffer = get_line( file )))
1109 char quote;
1110 char *p = buffer;
1111 while (*p && isspace(*p)) p++;
1113 if (!strncmp( p, "importlib", 9 ))
1115 p += 9;
1116 while (*p && isspace(*p)) p++;
1117 if (*p++ != '(') continue;
1118 while (*p && isspace(*p)) p++;
1119 if (*p++ != '"') continue;
1120 include = p;
1121 while (*p && (*p != '"')) p++;
1122 if (!*p) fatal_error( "malformed importlib directive\n" );
1123 *p = 0;
1124 add_dependency( source, include, INCL_IMPORTLIB );
1125 continue;
1128 if (!strncmp( p, "import", 6 ))
1130 p += 6;
1131 while (*p && isspace(*p)) p++;
1132 if (*p != '"') continue;
1133 include = ++p;
1134 while (*p && (*p != '"')) p++;
1135 if (!*p) fatal_error( "malformed import directive\n" );
1136 *p = 0;
1137 add_dependency( source, include, INCL_IMPORT );
1138 continue;
1141 /* check for #include inside cpp_quote */
1142 if (!strncmp( p, "cpp_quote", 9 ))
1144 p += 9;
1145 while (*p && isspace(*p)) p++;
1146 if (*p++ != '(') continue;
1147 while (*p && isspace(*p)) p++;
1148 if (*p++ != '"') continue;
1149 if (*p++ != '#') continue;
1150 while (*p && isspace(*p)) p++;
1151 if (strncmp( p, "include", 7 )) continue;
1152 p += 7;
1153 while (*p && isspace(*p)) p++;
1154 if (*p == '\\' && p[1] == '"')
1156 p += 2;
1157 quote = '"';
1159 else
1161 if (*p++ != '<' ) continue;
1162 quote = '>';
1164 include = p;
1165 while (*p && (*p != quote)) p++;
1166 if (!*p || (quote == '"' && p[-1] != '\\'))
1167 fatal_error( "malformed #include directive inside cpp_quote\n" );
1168 if (quote == '"') p--; /* remove backslash */
1169 *p = 0;
1170 add_dependency( source, include, (quote == '>') ? INCL_CPP_QUOTE_SYSTEM : INCL_CPP_QUOTE );
1171 continue;
1174 parse_cpp_directive( source, p );
1178 /*******************************************************************
1179 * parse_c_file
1181 static void parse_c_file( struct file *source, FILE *file )
1183 char *buffer;
1185 input_line = 0;
1186 while ((buffer = get_line( file )))
1188 parse_cpp_directive( source, buffer );
1193 /*******************************************************************
1194 * parse_rc_file
1196 static void parse_rc_file( struct file *source, FILE *file )
1198 char *buffer, *include;
1200 input_line = 0;
1201 while ((buffer = get_line( file )))
1203 char quote;
1204 char *p = buffer;
1205 while (*p && isspace(*p)) p++;
1207 if (p[0] == '/' && p[1] == '*') /* check for magic makedep comment */
1209 p += 2;
1210 while (*p && isspace(*p)) p++;
1211 if (strncmp( p, "@makedep:", 9 )) continue;
1212 p += 9;
1213 while (*p && isspace(*p)) p++;
1214 quote = '"';
1215 if (*p == quote)
1217 include = ++p;
1218 while (*p && *p != quote) p++;
1220 else
1222 include = p;
1223 while (*p && !isspace(*p) && *p != '*') p++;
1225 if (!*p)
1226 fatal_error( "malformed makedep comment\n" );
1227 *p = 0;
1228 add_dependency( source, include, (quote == '>') ? INCL_SYSTEM : INCL_NORMAL );
1229 continue;
1232 parse_cpp_directive( source, buffer );
1237 /*******************************************************************
1238 * parse_in_file
1240 static void parse_in_file( struct file *source, FILE *file )
1242 char *p, *buffer;
1244 /* make sure it gets rebuilt when the version changes */
1245 add_dependency( source, "config.h", INCL_SYSTEM );
1247 if (!strendswith( source->name, ".man.in" )) return; /* not a man page */
1249 input_line = 0;
1250 while ((buffer = get_line( file )))
1252 if (strncmp( buffer, ".TH", 3 )) continue;
1253 if (!(p = strtok( buffer, " \t" ))) continue; /* .TH */
1254 if (!(p = strtok( NULL, " \t" ))) continue; /* program name */
1255 if (!(p = strtok( NULL, " \t" ))) continue; /* man section */
1256 source->args = xstrdup( p );
1257 return;
1262 /*******************************************************************
1263 * parse_sfd_file
1265 static void parse_sfd_file( struct file *source, FILE *file )
1267 char *p, *eol, *buffer;
1269 input_line = 0;
1270 while ((buffer = get_line( file )))
1272 if (strncmp( buffer, "UComments:", 10 )) continue;
1273 p = buffer + 10;
1274 while (*p == ' ') p++;
1275 if (p[0] == '"' && p[1] && buffer[strlen(buffer) - 1] == '"')
1277 p++;
1278 buffer[strlen(buffer) - 1] = 0;
1280 while ((eol = strstr( p, "+AAoA" )))
1282 *eol = 0;
1283 while (*p && isspace(*p)) p++;
1284 if (*p++ == '#')
1286 while (*p && isspace(*p)) p++;
1287 if (!strncmp( p, "pragma", 6 )) parse_pragma_directive( source, p + 6 );
1289 p = eol + 5;
1291 while (*p && isspace(*p)) p++;
1292 if (*p++ != '#') return;
1293 while (*p && isspace(*p)) p++;
1294 if (!strncmp( p, "pragma", 6 )) parse_pragma_directive( source, p + 6 );
1295 return;
1300 static const struct
1302 const char *ext;
1303 void (*parse)( struct file *file, FILE *f );
1304 } parse_functions[] =
1306 { ".c", parse_c_file },
1307 { ".h", parse_c_file },
1308 { ".inl", parse_c_file },
1309 { ".l", parse_c_file },
1310 { ".m", parse_c_file },
1311 { ".rh", parse_c_file },
1312 { ".x", parse_c_file },
1313 { ".y", parse_c_file },
1314 { ".idl", parse_idl_file },
1315 { ".rc", parse_rc_file },
1316 { ".in", parse_in_file },
1317 { ".sfd", parse_sfd_file }
1320 /*******************************************************************
1321 * load_file
1323 static struct file *load_file( const char *name )
1325 struct file *file;
1326 FILE *f;
1327 unsigned int i, hash = hash_filename( name );
1329 LIST_FOR_EACH_ENTRY( file, &files[hash], struct file, entry )
1330 if (!strcmp( name, file->name )) return file;
1332 if (!(f = fopen( name, "r" ))) return NULL;
1334 file = add_file( name );
1335 list_add_tail( &files[hash], &file->entry );
1336 input_file_name = file->name;
1337 input_line = 0;
1339 for (i = 0; i < sizeof(parse_functions) / sizeof(parse_functions[0]); i++)
1341 if (!strendswith( name, parse_functions[i].ext )) continue;
1342 parse_functions[i].parse( file, f );
1343 break;
1346 fclose( f );
1347 input_file_name = NULL;
1349 return file;
1353 /*******************************************************************
1354 * open_include_path_file
1356 * Open a file from a directory on the include path.
1358 static struct file *open_include_path_file( const struct makefile *make, const char *dir,
1359 const char *name, char **filename )
1361 char *src_path = concat_paths( dir, name );
1362 struct file *ret = load_file( src_path );
1364 if (ret) *filename = src_path;
1365 return ret;
1369 /*******************************************************************
1370 * open_file_same_dir
1372 * Open a file in the same directory as the parent.
1374 static struct file *open_file_same_dir( const struct incl_file *parent, const char *name, char **filename )
1376 char *src_path = replace_filename( parent->file->name, name );
1377 struct file *ret = load_file( src_path );
1379 if (ret) *filename = replace_filename( parent->filename, name );
1380 return ret;
1384 /*******************************************************************
1385 * open_local_file
1387 * Open a file in the source directory of the makefile.
1389 static struct file *open_local_file( const struct makefile *make, const char *path, char **filename )
1391 char *src_path = src_dir_path( make, path );
1392 struct file *ret = load_file( src_path );
1394 /* if not found, try parent dir */
1395 if (!ret && make->parent_dir)
1397 free( src_path );
1398 path = strmake( "%s/%s", make->parent_dir, path );
1399 src_path = src_dir_path( make, path );
1400 ret = load_file( src_path );
1403 if (ret) *filename = src_path;
1404 return ret;
1408 /*******************************************************************
1409 * open_global_file
1411 * Open a file in the top-level source directory.
1413 static struct file *open_global_file( const struct makefile *make, const char *path, char **filename )
1415 char *src_path = root_src_dir_path( path );
1416 struct file *ret = load_file( src_path );
1418 if (ret) *filename = src_path;
1419 return ret;
1423 /*******************************************************************
1424 * open_global_header
1426 * Open a file in the global include source directory.
1428 static struct file *open_global_header( const struct makefile *make, const char *path, char **filename )
1430 return open_global_file( make, strmake( "include/%s", path ), filename );
1434 /*******************************************************************
1435 * open_src_file
1437 static struct file *open_src_file( const struct makefile *make, struct incl_file *pFile )
1439 struct file *file = open_local_file( make, pFile->name, &pFile->filename );
1441 if (!file) fatal_perror( "open %s", pFile->name );
1442 return file;
1446 /*******************************************************************
1447 * open_include_file
1449 static struct file *open_include_file( const struct makefile *make, struct incl_file *pFile )
1451 struct file *file = NULL;
1452 char *filename;
1453 unsigned int i, len;
1455 errno = ENOENT;
1457 /* check for generated bison header */
1459 if (strendswith( pFile->name, ".tab.h" ) &&
1460 (file = open_local_file( make, replace_extension( pFile->name, ".tab.h", ".y" ), &filename )))
1462 pFile->sourcename = filename;
1463 pFile->filename = obj_dir_path( make, pFile->name );
1464 return file;
1467 /* check for corresponding idl file in source dir */
1469 if (strendswith( pFile->name, ".h" ) &&
1470 (file = open_local_file( make, replace_extension( pFile->name, ".h", ".idl" ), &filename )))
1472 pFile->sourcename = filename;
1473 pFile->filename = obj_dir_path( make, pFile->name );
1474 return file;
1477 /* check for corresponding tlb file in source dir */
1479 if (strendswith( pFile->name, ".tlb" ) &&
1480 (file = open_local_file( make, replace_extension( pFile->name, ".tlb", ".idl" ), &filename )))
1482 pFile->sourcename = filename;
1483 pFile->filename = obj_dir_path( make, pFile->name );
1484 return file;
1487 /* check for extra targets */
1488 if (strarray_exists( &make->extra_targets, pFile->name ))
1490 pFile->sourcename = src_dir_path( make, pFile->name );
1491 pFile->filename = obj_dir_path( make, pFile->name );
1492 return NULL;
1495 /* now try in source dir */
1496 if ((file = open_local_file( make, pFile->name, &pFile->filename ))) return file;
1498 /* check for corresponding idl file in global includes */
1500 if (strendswith( pFile->name, ".h" ) &&
1501 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".idl" ), &filename )))
1503 pFile->sourcename = filename;
1504 pFile->filename = strmake( "include/%s", pFile->name );
1505 return file;
1508 /* check for corresponding .in file in global includes (for config.h.in) */
1510 if (strendswith( pFile->name, ".h" ) &&
1511 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".h.in" ), &filename )))
1513 pFile->sourcename = filename;
1514 pFile->filename = strmake( "include/%s", pFile->name );
1515 return file;
1518 /* check for corresponding .x file in global includes */
1520 if (strendswith( pFile->name, "tmpl.h" ) &&
1521 (file = open_global_header( make, replace_extension( pFile->name, ".h", ".x" ), &filename )))
1523 pFile->sourcename = filename;
1524 pFile->filename = strmake( "include/%s", pFile->name );
1525 return file;
1528 /* check for corresponding .tlb file in global includes */
1530 if (strendswith( pFile->name, ".tlb" ) &&
1531 (file = open_global_header( make, replace_extension( pFile->name, ".tlb", ".idl" ), &filename )))
1533 pFile->sourcename = filename;
1534 pFile->filename = strmake( "include/%s", pFile->name );
1535 return file;
1538 /* check in global includes source dir */
1540 if ((file = open_global_header( make, pFile->name, &pFile->filename ))) return file;
1542 /* check in global msvcrt includes */
1543 if (pFile->use_msvcrt &&
1544 (file = open_global_header( make, strmake( "msvcrt/%s", pFile->name ), &pFile->filename )))
1545 return file;
1547 /* now search in include paths */
1548 for (i = 0; i < make->include_paths.count; i++)
1550 const char *dir = make->include_paths.str[i];
1552 if (root_src_dir)
1554 len = strlen( root_src_dir );
1555 if (!strncmp( dir, root_src_dir, len ) && (!dir[len] || dir[len] == '/'))
1557 while (dir[len] == '/') len++;
1558 file = open_global_file( make, concat_paths( dir + len, pFile->name ), &pFile->filename );
1559 if (file) return file;
1561 continue; /* ignore paths that don't point to the top source dir */
1563 if (*dir != '/')
1565 if ((file = open_include_path_file( make, dir, pFile->name, &pFile->filename )))
1566 return file;
1570 if (pFile->type == INCL_SYSTEM && pFile->use_msvcrt)
1572 if (!strcmp( pFile->name, "stdarg.h" )) return NULL;
1573 fprintf( stderr, "%s:%d: error: system header %s cannot be used with msvcrt\n",
1574 pFile->included_by->file->name, pFile->included_line, pFile->name );
1575 exit(1);
1578 if (pFile->type == INCL_SYSTEM) return NULL; /* ignore system files we cannot find */
1580 /* try in src file directory */
1581 if ((file = open_file_same_dir( pFile->included_by, pFile->name, &pFile->filename ))) return file;
1583 fprintf( stderr, "%s:%d: error: ", pFile->included_by->file->name, pFile->included_line );
1584 perror( pFile->name );
1585 pFile = pFile->included_by;
1586 while (pFile && pFile->included_by)
1588 const char *parent = pFile->included_by->sourcename;
1589 if (!parent) parent = pFile->included_by->file->name;
1590 fprintf( stderr, "%s:%d: note: %s was first included here\n",
1591 parent, pFile->included_line, pFile->name );
1592 pFile = pFile->included_by;
1594 exit(1);
1598 /*******************************************************************
1599 * add_all_includes
1601 static void add_all_includes( struct makefile *make, struct incl_file *parent, struct file *file )
1603 unsigned int i;
1605 parent->files_count = 0;
1606 parent->files_size = file->deps_count;
1607 parent->files = xmalloc( parent->files_size * sizeof(*parent->files) );
1608 for (i = 0; i < file->deps_count; i++)
1610 switch (file->deps[i].type)
1612 case INCL_NORMAL:
1613 case INCL_IMPORT:
1614 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1615 break;
1616 case INCL_IMPORTLIB:
1617 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_IMPORTLIB );
1618 break;
1619 case INCL_SYSTEM:
1620 add_include( make, parent, file->deps[i].name, file->deps[i].line, INCL_SYSTEM );
1621 break;
1622 case INCL_CPP_QUOTE:
1623 case INCL_CPP_QUOTE_SYSTEM:
1624 break;
1630 /*******************************************************************
1631 * parse_file
1633 static void parse_file( struct makefile *make, struct incl_file *source, int src )
1635 struct file *file = src ? open_src_file( make, source ) : open_include_file( make, source );
1637 if (!file) return;
1639 source->file = file;
1640 source->files_count = 0;
1641 source->files_size = file->deps_count;
1642 source->files = xmalloc( source->files_size * sizeof(*source->files) );
1643 if (file->flags & FLAG_C_UNIX) source->use_msvcrt = 0;
1644 else if (file->flags & FLAG_C_IMPLIB) source->use_msvcrt = 1;
1646 if (source->sourcename)
1648 if (strendswith( source->sourcename, ".idl" ))
1650 unsigned int i;
1652 if (strendswith( source->name, ".tlb" )) return; /* typelibs don't include anything */
1654 /* generated .h file always includes these */
1655 add_include( make, source, "rpc.h", 0, INCL_NORMAL );
1656 add_include( make, source, "rpcndr.h", 0, INCL_NORMAL );
1657 for (i = 0; i < file->deps_count; i++)
1659 switch (file->deps[i].type)
1661 case INCL_IMPORT:
1662 if (strendswith( file->deps[i].name, ".idl" ))
1663 add_include( make, source, replace_extension( file->deps[i].name, ".idl", ".h" ),
1664 file->deps[i].line, INCL_NORMAL );
1665 else
1666 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1667 break;
1668 case INCL_CPP_QUOTE:
1669 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_NORMAL );
1670 break;
1671 case INCL_CPP_QUOTE_SYSTEM:
1672 add_include( make, source, file->deps[i].name, file->deps[i].line, INCL_SYSTEM );
1673 break;
1674 case INCL_NORMAL:
1675 case INCL_SYSTEM:
1676 case INCL_IMPORTLIB:
1677 break;
1680 return;
1682 if (strendswith( source->sourcename, ".y" ))
1683 return; /* generated .tab.h doesn't include anything */
1686 add_all_includes( make, source, file );
1690 /*******************************************************************
1691 * add_src_file
1693 * Add a source file to the list.
1695 static struct incl_file *add_src_file( struct makefile *make, const char *name )
1697 struct incl_file *file;
1699 if ((file = find_src_file( make, name ))) return file; /* we already have it */
1700 file = xmalloc( sizeof(*file) );
1701 memset( file, 0, sizeof(*file) );
1702 file->name = xstrdup(name);
1703 file->use_msvcrt = make->use_msvcrt;
1704 list_add_tail( &make->sources, &file->entry );
1705 parse_file( make, file, 1 );
1706 return file;
1710 /*******************************************************************
1711 * open_input_makefile
1713 static FILE *open_input_makefile( const struct makefile *make )
1715 FILE *ret;
1717 if (make->obj_dir)
1718 input_file_name = root_src_dir_path( obj_dir_path( make, strmake( "%s.in", output_makefile_name )));
1719 else
1720 input_file_name = output_makefile_name; /* always use output name for main Makefile */
1722 input_line = 0;
1723 if (!(ret = fopen( input_file_name, "r" ))) fatal_perror( "open" );
1724 return ret;
1728 /*******************************************************************
1729 * get_make_variable
1731 static const char *get_make_variable( const struct makefile *make, const char *name )
1733 const char *ret;
1735 if ((ret = strarray_get_value( &cmdline_vars, name ))) return ret;
1736 if ((ret = strarray_get_value( &make->vars, name ))) return ret;
1737 if (top_makefile && (ret = strarray_get_value( &top_makefile->vars, name ))) return ret;
1738 return NULL;
1742 /*******************************************************************
1743 * get_expanded_make_variable
1745 static char *get_expanded_make_variable( const struct makefile *make, const char *name )
1747 const char *var;
1748 char *p, *end, *expand, *tmp;
1750 var = get_make_variable( make, name );
1751 if (!var) return NULL;
1753 p = expand = xstrdup( var );
1754 while ((p = strchr( p, '$' )))
1756 if (p[1] == '(')
1758 if (!(end = strchr( p + 2, ')' ))) fatal_error( "syntax error in '%s'\n", expand );
1759 *end++ = 0;
1760 if (strchr( p + 2, ':' )) fatal_error( "pattern replacement not supported for '%s'\n", p + 2 );
1761 var = get_make_variable( make, p + 2 );
1762 tmp = replace_substr( expand, p, end - p, var ? var : "" );
1763 /* switch to the new string */
1764 p = tmp + (p - expand);
1765 free( expand );
1766 expand = tmp;
1768 else if (p[1] == '{') /* don't expand ${} variables */
1770 if (!(end = strchr( p + 2, '}' ))) fatal_error( "syntax error in '%s'\n", expand );
1771 p = end + 1;
1773 else if (p[1] == '$')
1775 p += 2;
1777 else fatal_error( "syntax error in '%s'\n", expand );
1780 /* consider empty variables undefined */
1781 p = expand;
1782 while (*p && isspace(*p)) p++;
1783 if (*p) return expand;
1784 free( expand );
1785 return NULL;
1789 /*******************************************************************
1790 * get_expanded_make_var_array
1792 static struct strarray get_expanded_make_var_array( const struct makefile *make, const char *name )
1794 struct strarray ret = empty_strarray;
1795 char *value, *token;
1797 if ((value = get_expanded_make_variable( make, name )))
1798 for (token = strtok( value, " \t" ); token; token = strtok( NULL, " \t" ))
1799 strarray_add( &ret, token );
1800 return ret;
1804 /*******************************************************************
1805 * get_expanded_file_local_var
1807 static struct strarray get_expanded_file_local_var( const struct makefile *make, const char *file,
1808 const char *name )
1810 char *p, *var = strmake( "%s_%s", file, name );
1812 for (p = var; *p; p++) if (!isalnum( *p )) *p = '_';
1813 return get_expanded_make_var_array( make, var );
1817 /*******************************************************************
1818 * set_make_variable
1820 static int set_make_variable( struct strarray *array, const char *assignment )
1822 char *p, *name;
1824 p = name = xstrdup( assignment );
1825 while (isalnum(*p) || *p == '_') p++;
1826 if (name == p) return 0; /* not a variable */
1827 if (isspace(*p))
1829 *p++ = 0;
1830 while (isspace(*p)) p++;
1832 if (*p != '=') return 0; /* not an assignment */
1833 *p++ = 0;
1834 while (isspace(*p)) p++;
1836 strarray_set_value( array, name, p );
1837 return 1;
1841 /*******************************************************************
1842 * parse_makefile
1844 static struct makefile *parse_makefile( const char *path )
1846 char *buffer;
1847 FILE *file;
1848 struct makefile *make = xmalloc( sizeof(*make) );
1850 memset( make, 0, sizeof(*make) );
1851 make->obj_dir = path;
1852 if (root_src_dir) make->src_dir = root_src_dir_path( make->obj_dir );
1854 file = open_input_makefile( make );
1855 while ((buffer = get_line( file )))
1857 if (!strncmp( buffer, separator, strlen(separator) )) break;
1858 if (*buffer == '\t') continue; /* command */
1859 while (isspace( *buffer )) buffer++;
1860 if (*buffer == '#') continue; /* comment */
1861 set_make_variable( &make->vars, buffer );
1863 fclose( file );
1864 input_file_name = NULL;
1865 return make;
1869 /*******************************************************************
1870 * add_generated_sources
1872 static void add_generated_sources( struct makefile *make )
1874 unsigned int i;
1875 struct incl_file *source, *next, *file;
1876 struct strarray objs = get_expanded_make_var_array( make, "EXTRA_OBJS" );
1878 LIST_FOR_EACH_ENTRY_SAFE( source, next, &make->sources, struct incl_file, entry )
1880 if (source->file->flags & FLAG_IDL_CLIENT)
1882 file = add_generated_source( make, replace_extension( source->name, ".idl", "_c.c" ), NULL );
1883 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1884 add_all_includes( make, file, file->file );
1886 if (source->file->flags & FLAG_IDL_SERVER)
1888 file = add_generated_source( make, replace_extension( source->name, ".idl", "_s.c" ), NULL );
1889 add_dependency( file->file, "wine/exception.h", INCL_NORMAL );
1890 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1891 add_all_includes( make, file, file->file );
1893 if (source->file->flags & FLAG_IDL_IDENT)
1895 file = add_generated_source( make, replace_extension( source->name, ".idl", "_i.c" ), NULL );
1896 add_dependency( file->file, "rpc.h", INCL_NORMAL );
1897 add_dependency( file->file, "rpcndr.h", INCL_NORMAL );
1898 add_dependency( file->file, "guiddef.h", INCL_NORMAL );
1899 add_all_includes( make, file, file->file );
1901 if (source->file->flags & FLAG_IDL_PROXY)
1903 file = add_generated_source( make, "dlldata.o", "dlldata.c" );
1904 add_dependency( file->file, "objbase.h", INCL_NORMAL );
1905 add_dependency( file->file, "rpcproxy.h", INCL_NORMAL );
1906 add_all_includes( make, file, file->file );
1907 file = add_generated_source( make, replace_extension( source->name, ".idl", "_p.c" ), NULL );
1908 add_dependency( file->file, "objbase.h", INCL_NORMAL );
1909 add_dependency( file->file, "rpcproxy.h", INCL_NORMAL );
1910 add_dependency( file->file, "wine/exception.h", INCL_NORMAL );
1911 add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
1912 add_all_includes( make, file, file->file );
1914 if (source->file->flags & FLAG_IDL_TYPELIB)
1916 add_generated_source( make, replace_extension( source->name, ".idl", ".tlb" ), NULL );
1918 if (source->file->flags & FLAG_IDL_REGTYPELIB)
1920 add_generated_source( make, replace_extension( source->name, ".idl", "_t.res" ), NULL );
1922 if (source->file->flags & FLAG_IDL_REGISTER)
1924 add_generated_source( make, replace_extension( source->name, ".idl", "_r.res" ), NULL );
1926 if (source->file->flags & FLAG_IDL_HEADER)
1928 add_generated_source( make, replace_extension( source->name, ".idl", ".h" ), NULL );
1930 if (!source->file->flags && strendswith( source->name, ".idl" ))
1932 add_generated_source( make, replace_extension( source->name, ".idl", ".h" ), NULL );
1934 if (strendswith( source->name, ".x" ))
1936 add_generated_source( make, replace_extension( source->name, ".x", ".h" ), NULL );
1938 if (strendswith( source->name, ".y" ))
1940 file = add_generated_source( make, replace_extension( source->name, ".y", ".tab.c" ), NULL );
1941 /* steal the includes list from the source file */
1942 file->files_count = source->files_count;
1943 file->files_size = source->files_size;
1944 file->files = source->files;
1945 source->files_count = source->files_size = 0;
1946 source->files = NULL;
1948 if (strendswith( source->name, ".l" ))
1950 file = add_generated_source( make, replace_extension( source->name, ".l", ".yy.c" ), NULL );
1951 /* steal the includes list from the source file */
1952 file->files_count = source->files_count;
1953 file->files_size = source->files_size;
1954 file->files = source->files;
1955 source->files_count = source->files_size = 0;
1956 source->files = NULL;
1958 if (source->file->flags & FLAG_C_IMPLIB)
1960 if (!make->staticimplib && make->importlib && *dll_ext)
1961 make->staticimplib = strmake( "lib%s.a", make->importlib );
1963 if (strendswith( source->name, ".po" ))
1965 if (!make->disabled)
1966 strarray_add_uniq( &linguas, replace_extension( source->name, ".po", "" ));
1968 if (strendswith( source->name, ".spec" ))
1970 char *obj = replace_extension( source->name, ".spec", "" );
1971 strarray_addall_uniq( &make->extra_imports,
1972 get_expanded_file_local_var( make, obj, "IMPORTS" ));
1975 if (make->testdll)
1977 file = add_generated_source( make, "testlist.o", "testlist.c" );
1978 add_dependency( file->file, "wine/test.h", INCL_NORMAL );
1979 add_all_includes( make, file, file->file );
1981 for (i = 0; i < objs.count; i++)
1983 /* default to .c for unknown extra object files */
1984 if (strendswith( objs.str[i], ".o" ))
1986 file = add_generated_source( make, objs.str[i], replace_extension( objs.str[i], ".o", ".c" ));
1987 if (make->module || make->staticlib) file->file->flags |= FLAG_C_UNIX;
1989 else if (strendswith( objs.str[i], ".res" ))
1990 add_generated_source( make, replace_extension( objs.str[i], ".res", ".rc" ), NULL );
1991 else
1992 add_generated_source( make, objs.str[i], NULL );
1997 /*******************************************************************
1998 * create_dir
2000 static void create_dir( const char *dir )
2002 char *p, *path;
2004 p = path = xstrdup( dir );
2005 while ((p = strchr( p, '/' )))
2007 *p = 0;
2008 if (mkdir( path, 0755 ) == -1 && errno != EEXIST) fatal_perror( "mkdir %s", path );
2009 *p++ = '/';
2010 while (*p == '/') p++;
2012 if (mkdir( path, 0755 ) == -1 && errno != EEXIST) fatal_perror( "mkdir %s", path );
2013 free( path );
2017 /*******************************************************************
2018 * create_file_directories
2020 * Create the base directories of all the files.
2022 static void create_file_directories( const struct makefile *make, struct strarray files )
2024 struct strarray subdirs = empty_strarray;
2025 unsigned int i;
2026 char *dir;
2028 for (i = 0; i < files.count; i++)
2030 if (!strchr( files.str[i], '/' )) continue;
2031 dir = obj_dir_path( make, files.str[i] );
2032 *strrchr( dir, '/' ) = 0;
2033 strarray_add_uniq( &subdirs, dir );
2036 for (i = 0; i < subdirs.count; i++) create_dir( subdirs.str[i] );
2040 /*******************************************************************
2041 * output_filenames_obj_dir
2043 static void output_filenames_obj_dir( const struct makefile *make, struct strarray array )
2045 unsigned int i;
2047 for (i = 0; i < array.count; i++) output_filename( obj_dir_path( make, array.str[i] ));
2051 /*******************************************************************
2052 * get_dependencies
2054 static void get_dependencies( struct incl_file *file, struct incl_file *source )
2056 unsigned int i;
2058 if (!file->filename) return;
2060 if (file != source)
2062 if (file->owner == source) return; /* already processed */
2063 if (file->type == INCL_IMPORTLIB &&
2064 !(source->file->flags & (FLAG_IDL_TYPELIB | FLAG_IDL_REGTYPELIB)))
2065 return; /* library is imported only when building a typelib */
2066 file->owner = source;
2067 strarray_add( &source->dependencies, file->filename );
2069 for (i = 0; i < file->files_count; i++) get_dependencies( file->files[i], source );
2073 /*******************************************************************
2074 * get_local_dependencies
2076 * Get the local dependencies of a given target.
2078 static struct strarray get_local_dependencies( const struct makefile *make, const char *name,
2079 struct strarray targets )
2081 unsigned int i;
2082 struct strarray deps = get_expanded_file_local_var( make, name, "DEPS" );
2084 for (i = 0; i < deps.count; i++)
2086 if (strarray_exists( &targets, deps.str[i] ))
2087 deps.str[i] = obj_dir_path( make, deps.str[i] );
2088 else
2089 deps.str[i] = src_dir_path( make, deps.str[i] );
2091 return deps;
2095 /*******************************************************************
2096 * get_static_lib
2098 * Check if makefile builds the named static library and return the full lib path.
2100 static const char *get_static_lib( const struct makefile *make, const char *name )
2102 if (!make->staticlib) return NULL;
2103 if (strncmp( make->staticlib, "lib", 3 )) return NULL;
2104 if (strncmp( make->staticlib + 3, name, strlen(name) )) return NULL;
2105 if (strcmp( make->staticlib + 3 + strlen(name), ".a" )) return NULL;
2106 return obj_dir_path( make, make->staticlib );
2110 /*******************************************************************
2111 * get_parent_makefile
2113 static struct makefile *get_parent_makefile( struct makefile *make )
2115 char *dir, *p;
2116 int i;
2118 if (!make->obj_dir) return NULL;
2119 dir = xstrdup( make->obj_dir );
2120 if (!(p = strrchr( dir, '/' ))) return NULL;
2121 *p = 0;
2122 for (i = 0; i < subdirs.count; i++)
2123 if (!strcmp( submakes[i]->obj_dir, dir )) return submakes[i];
2124 return NULL;
2128 /*******************************************************************
2129 * needs_cross_lib
2131 static int needs_cross_lib( const struct makefile *make )
2133 const char *name;
2134 if (!crosstarget) return 0;
2135 if (make->importlib) name = make->importlib;
2136 else if (make->staticlib)
2138 name = replace_extension( make->staticlib, ".a", "" );
2139 if (!strncmp( name, "lib", 3 )) name += 3;
2141 else return 0;
2142 if (strarray_exists( &cross_import_libs, name )) return 1;
2143 if (delay_load_flag && strarray_exists( &delay_import_libs, name )) return 1;
2144 return 0;
2148 /*******************************************************************
2149 * needs_delay_lib
2151 static int needs_delay_lib( const struct makefile *make )
2153 if (delay_load_flag) return 0;
2154 if (*dll_ext && !crosstarget) return 0;
2155 if (!make->importlib) return 0;
2156 return strarray_exists( &delay_import_libs, make->importlib );
2160 /*******************************************************************
2161 * needs_implib_symlink
2163 static int needs_implib_symlink( const struct makefile *make )
2165 if (!make->module) return 0;
2166 if (!make->importlib) return 0;
2167 if (make->is_win16 && make->disabled) return 0;
2168 if (strncmp( make->obj_dir, "dlls/", 5 )) return 0;
2169 if (!strcmp( make->module, make->importlib )) return 0;
2170 if (!strchr( make->importlib, '.' ) &&
2171 !strncmp( make->module, make->importlib, strlen( make->importlib )) &&
2172 !strcmp( make->module + strlen( make->importlib ), ".dll" ))
2173 return 0;
2174 return 1;
2178 /*******************************************************************
2179 * add_unix_libraries
2181 static struct strarray add_unix_libraries( const struct makefile *make, struct strarray *deps )
2183 struct strarray ret = empty_strarray;
2184 struct strarray all_libs = empty_strarray;
2185 unsigned int i, j;
2187 strarray_add( &all_libs, "-lwine_port" );
2188 strarray_addall( &all_libs, get_expanded_make_var_array( make, "EXTRALIBS" ));
2189 strarray_addall( &all_libs, libs );
2191 for (i = 0; i < all_libs.count; i++)
2193 const char *lib = NULL;
2195 if (!strncmp( all_libs.str[i], "-l", 2 ))
2197 const char *name = all_libs.str[i] + 2;
2199 for (j = 0; j < subdirs.count; j++)
2200 if ((lib = get_static_lib( submakes[j], name ))) break;
2203 if (lib)
2205 strarray_add( deps, lib );
2206 strarray_add( &ret, lib );
2208 else strarray_add( &ret, all_libs.str[i] );
2210 return ret;
2214 /*******************************************************************
2215 * add_import_libs
2217 static struct strarray add_import_libs( const struct makefile *make, struct strarray *deps,
2218 struct strarray imports, int delay, int is_unix )
2220 struct strarray ret = empty_strarray;
2221 unsigned int i, j;
2222 int is_cross = make->is_cross && !is_unix;
2224 for (i = 0; i < imports.count; i++)
2226 const char *name = get_base_name( imports.str[i] );
2227 const char *lib = NULL;
2229 for (j = 0; j < subdirs.count; j++)
2231 if (submakes[j]->importlib && !strcmp( submakes[j]->importlib, name ))
2233 if (is_cross || !*dll_ext || submakes[j]->staticimplib)
2234 lib = obj_dir_path( submakes[j], strmake( "lib%s.a", name ));
2235 else
2237 strarray_add( deps, strmake( "%s/lib%s.def", submakes[j]->obj_dir, name ));
2238 if (needs_implib_symlink( submakes[j] ))
2239 strarray_add( deps, strmake( "dlls/lib%s.def", name ));
2241 break;
2244 if ((lib = get_static_lib( submakes[j], name ))) break;
2247 if (lib)
2249 const char *ext = NULL;
2251 if (delay && !delay_load_flag && (is_cross || !*dll_ext)) ext = ".delay.a";
2252 else if (is_cross) ext = ".cross.a";
2253 if (ext) lib = replace_extension( lib, ".a", ext );
2254 strarray_add( deps, lib );
2255 strarray_add( &ret, lib );
2256 if (needs_implib_symlink( submakes[j] ))
2257 strarray_add( deps, strmake( "dlls/lib%s%s", name, ext ? ext : ".a" ));
2259 else strarray_add( &ret, strmake( "-l%s", name ));
2261 return ret;
2265 /*******************************************************************
2266 * get_default_imports
2268 static struct strarray get_default_imports( const struct makefile *make )
2270 struct strarray ret = empty_strarray;
2272 if (strarray_exists( &make->extradllflags, "-nodefaultlibs" )) return ret;
2273 strarray_add( &ret, "winecrt0" );
2274 if (make->is_win16) strarray_add( &ret, "kernel" );
2275 strarray_add( &ret, "kernel32" );
2276 strarray_add( &ret, "ntdll" );
2277 return ret;
2281 /*******************************************************************
2282 * is_crt_module
2284 static int is_crt_module( const char *file )
2286 return !strncmp( file, "msvcr", 5 ) || !strncmp( file, "ucrt", 4 ) || !strcmp( file, "crtdll.dll" );
2290 /*******************************************************************
2291 * add_crt_import
2293 static void add_crt_import( const struct makefile *make, struct strarray *imports, struct strarray *defs )
2295 unsigned int i;
2296 const char *crt_dll = NULL;
2298 for (i = 0; i < imports->count; i++)
2300 if (!is_crt_module( imports->str[i])) continue;
2301 if (crt_dll) fatal_error( "More than one C runtime DLL imported: %s and %s\n", crt_dll, imports->str[i] );
2302 crt_dll = imports->str[i];
2304 if (!crt_dll && !strarray_exists( &make->extradllflags, "-nodefaultlibs" ))
2306 if (make->module && is_crt_module( make->module ))
2308 crt_dll = make->module;
2310 else
2312 crt_dll = !make->testdll && !make->staticlib ? "ucrtbase" : "msvcrt";
2313 strarray_add( imports, crt_dll );
2317 if (!defs) return;
2318 if (crt_dll && !strncmp( crt_dll, "ucrt", 4 )) strarray_add( defs, "-D_UCRT" );
2319 else
2321 unsigned int version = 0;
2322 if (crt_dll) sscanf( crt_dll, "msvcr%u", &version );
2323 strarray_add( defs, strmake( "-D_MSVCR_VER=%u", version ));
2328 /*******************************************************************
2329 * add_install_rule
2331 static void add_install_rule( struct makefile *make, const char *target,
2332 const char *file, const char *dest )
2334 if (strarray_exists( &make->install_lib, target ) ||
2335 strarray_exists( &top_install_lib, make->obj_dir ) ||
2336 strarray_exists( &top_install_lib, obj_dir_path( make, target )))
2338 strarray_add( &make->install_rules[INSTALL_LIB], file );
2339 strarray_add( &make->install_rules[INSTALL_LIB], dest );
2341 else if (strarray_exists( &make->install_dev, target ) ||
2342 strarray_exists( &top_install_dev, make->obj_dir ) ||
2343 strarray_exists( &top_install_dev, obj_dir_path( make, target )))
2345 strarray_add( &make->install_rules[INSTALL_DEV], file );
2346 strarray_add( &make->install_rules[INSTALL_DEV], dest );
2351 /*******************************************************************
2352 * get_include_install_path
2354 * Determine the installation path for a given include file.
2356 static const char *get_include_install_path( const char *name )
2358 if (!strncmp( name, "wine/", 5 )) return name + 5;
2359 if (!strncmp( name, "msvcrt/", 7 )) return name;
2360 return strmake( "windows/%s", name );
2364 /*******************************************************************
2365 * get_shared_library_name
2367 * Determine possible names for a shared library with a version number.
2369 static struct strarray get_shared_lib_names( const char *libname )
2371 struct strarray ret = empty_strarray;
2372 const char *ext, *p;
2373 char *name, *first, *second;
2374 size_t len = 0;
2376 strarray_add( &ret, libname );
2378 for (p = libname; (p = strchr( p, '.' )); p++)
2379 if ((len = strspn( p + 1, "0123456789." ))) break;
2381 if (!len) return ret;
2382 ext = p + 1 + len;
2383 if (*ext && ext[-1] == '.') ext--;
2385 /* keep only the first group of digits */
2386 name = xstrdup( libname );
2387 first = name + (p - libname);
2388 if ((second = strchr( first + 1, '.' )))
2390 strcpy( second, ext );
2391 strarray_add( &ret, xstrdup( name ));
2393 return ret;
2397 /*******************************************************************
2398 * get_source_defines
2400 static struct strarray get_source_defines( struct makefile *make, struct incl_file *source,
2401 const char *obj )
2403 unsigned int i;
2404 struct strarray ret = empty_strarray;
2406 strarray_addall( &ret, make->include_args );
2407 if (source->use_msvcrt)
2408 strarray_add( &ret, strmake( "-I%s", root_src_dir_path( "include/msvcrt" )));
2409 for (i = 0; i < make->include_paths.count; i++)
2410 strarray_add( &ret, strmake( "-I%s", make->include_paths.str[i] ));
2411 strarray_addall( &ret, make->define_args );
2412 strarray_addall( &ret, get_expanded_file_local_var( make, obj, "EXTRADEFS" ));
2413 if ((source->file->flags & FLAG_C_UNIX) && *dll_ext) strarray_add( &ret, "-DWINE_UNIX_LIB" );
2414 return ret;
2418 /*******************************************************************
2419 * get_debug_file
2421 static const char *get_debug_file( struct makefile *make, const char *name )
2423 const char *debug_file = NULL;
2424 if (!make->is_cross || !crossdebug) return NULL;
2425 if (!strcmp( crossdebug, "pdb" )) debug_file = strmake( "%s.pdb", get_base_name( name ));
2426 else if(!strncmp( crossdebug, "split", 5 )) debug_file = strmake( "%s.debug", name );
2427 if (debug_file) strarray_add( &make->debug_files, debug_file );
2428 return debug_file;
2432 /*******************************************************************
2433 * cmd_prefix
2435 static const char *cmd_prefix( const char *cmd )
2437 if (!silent_rules) return "";
2438 return strmake( "$(quiet_%s)", cmd );
2442 /*******************************************************************
2443 * output_winegcc_command
2445 static void output_winegcc_command( struct makefile *make, int is_cross )
2447 output( "\t%s%s -o $@", cmd_prefix( "CCLD" ), tools_path( make, "winegcc" ));
2448 output_filename( "--wine-objdir ." );
2449 if (tools_dir)
2451 output_filename( "--winebuild" );
2452 output_filename( tools_path( make, "winebuild" ));
2454 if (is_cross)
2456 output_filename( "-b" );
2457 output_filename( crosstarget );
2458 output_filename( "--lib-suffix=.cross.a" );
2460 else
2462 output_filenames( target_flags );
2463 output_filenames( lddll_flags );
2468 /*******************************************************************
2469 * output_symlink_rule
2471 * Output a rule to create a symlink.
2473 static void output_symlink_rule( const char *src_name, const char *link_name, int create_dir )
2475 const char *name = strrchr( link_name, '/' );
2476 char *dir = NULL;
2478 if (name)
2480 dir = xstrdup( link_name );
2481 dir[name - link_name] = 0;
2484 output( "\t%s", cmd_prefix( "LN" ));
2485 if (create_dir && dir && *dir) output( "%s -d %s && ", root_src_dir_path( "tools/install-sh" ), dir );
2486 output( "rm -f %s && ", link_name );
2488 /* dest path with a directory needs special handling if ln -s isn't supported */
2489 if (dir && strcmp( ln_s, "ln -s" ))
2490 output( "cd %s && %s %s %s\n", *dir ? dir : "/", ln_s, src_name, name + 1 );
2491 else
2492 output( "%s %s %s\n", ln_s, src_name, link_name );
2494 free( dir );
2498 /*******************************************************************
2499 * output_srcdir_symlink
2501 * Output rule to create a symlink back to the source directory, for source files
2502 * that are needed at run-time.
2504 static void output_srcdir_symlink( struct makefile *make, const char *obj )
2506 char *src_file, *dst_file, *src_name;
2508 if (!make->src_dir) return;
2509 src_file = src_dir_path( make, obj );
2510 dst_file = obj_dir_path( make, obj );
2511 output( "%s: %s\n", dst_file, src_file );
2513 src_name = src_file;
2514 if (src_name[0] != '/' && make->obj_dir)
2515 src_name = concat_paths( get_relative_path( make->obj_dir, "" ), src_name );
2517 output_symlink_rule( src_name, dst_file, 0 );
2518 strarray_add( &make->all_targets, obj );
2522 /*******************************************************************
2523 * output_install_commands
2525 static void output_install_commands( struct makefile *make, struct strarray files )
2527 unsigned int i;
2528 char *install_sh = root_src_dir_path( "tools/install-sh" );
2530 for (i = 0; i < files.count; i += 2)
2532 const char *file = files.str[i];
2533 const char *dest = strmake( "$(DESTDIR)%s", files.str[i + 1] + 1 );
2535 switch (*files.str[i + 1])
2537 case 'c': /* cross-compiled program */
2538 output( "\tSTRIPPROG=%s-strip %s -m 644 $(INSTALL_PROGRAM_FLAGS) %s %s\n",
2539 crosstarget, install_sh, obj_dir_path( make, file ), dest );
2540 output( "\t%s --builtin %s\n", tools_path( make, "winebuild" ), dest );
2541 break;
2542 case 'd': /* data file */
2543 output( "\t%s -m 644 $(INSTALL_DATA_FLAGS) %s %s\n",
2544 install_sh, obj_dir_path( make, file ), dest );
2545 break;
2546 case 'D': /* data file in source dir */
2547 output( "\t%s -m 644 $(INSTALL_DATA_FLAGS) %s %s\n",
2548 install_sh, src_dir_path( make, file ), dest );
2549 break;
2550 case 'p': /* program file */
2551 output( "\tSTRIPPROG=\"$(STRIP)\" %s $(INSTALL_PROGRAM_FLAGS) %s %s\n",
2552 install_sh, obj_dir_path( make, file ), dest );
2553 break;
2554 case 's': /* script */
2555 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2556 install_sh, obj_dir_path( make, file ), dest );
2557 break;
2558 case 'S': /* script in source dir */
2559 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2560 install_sh, src_dir_path( make, file ), dest );
2561 break;
2562 case 't': /* script in tools dir */
2563 output( "\t%s $(INSTALL_SCRIPT_FLAGS) %s %s\n",
2564 install_sh, tools_dir_path( make, files.str[i] ), dest );
2565 break;
2566 case 'y': /* symlink */
2567 output_symlink_rule( files.str[i], dest, 1 );
2568 break;
2569 default:
2570 assert(0);
2572 strarray_add( &make->uninstall_files, dest );
2577 /*******************************************************************
2578 * output_install_rules
2580 * Rules are stored as a (file,dest) pair of values.
2581 * The first char of dest indicates the type of install.
2583 static void output_install_rules( struct makefile *make, enum install_rules rules, const char *target )
2585 unsigned int i;
2586 struct strarray files = make->install_rules[rules];
2587 struct strarray targets = empty_strarray;
2589 if (!files.count) return;
2591 for (i = 0; i < files.count; i += 2)
2593 const char *file = files.str[i];
2594 switch (*files.str[i + 1])
2596 case 'c': /* cross-compiled program */
2597 case 'd': /* data file */
2598 case 'p': /* program file */
2599 case 's': /* script */
2600 strarray_add_uniq( &targets, obj_dir_path( make, file ));
2601 break;
2602 case 't': /* script in tools dir */
2603 strarray_add_uniq( &targets, tools_dir_path( make, file ));
2604 break;
2608 output( "%s %s::", obj_dir_path( make, "install" ), obj_dir_path( make, target ));
2609 output_filenames( targets );
2610 output( "\n" );
2611 output_install_commands( make, files );
2612 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "install" ));
2613 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, target ));
2617 static int cmp_string_length( const char **a, const char **b )
2619 int paths_a = 0, paths_b = 0;
2620 const char *p;
2622 for (p = *a; *p; p++) if (*p == '/') paths_a++;
2623 for (p = *b; *p; p++) if (*p == '/') paths_b++;
2624 if (paths_b != paths_a) return paths_b - paths_a;
2625 return strcmp( *a, *b );
2628 /*******************************************************************
2629 * output_uninstall_rules
2631 static void output_uninstall_rules( struct makefile *make )
2633 static const char *dirs_order[] =
2634 { "$(includedir)", "$(mandir)", "$(fontdir)", "$(datadir)", "$(dlldir)" };
2636 struct strarray uninstall_dirs = empty_strarray;
2637 unsigned int i, j;
2639 if (!make->uninstall_files.count) return;
2640 output( "uninstall::\n" );
2641 output_rm_filenames( make->uninstall_files );
2642 strarray_add_uniq( &make->phony_targets, "uninstall" );
2644 if (!subdirs.count) return;
2645 for (i = 0; i < make->uninstall_files.count; i++)
2647 char *dir = xstrdup( make->uninstall_files.str[i] );
2648 while (strchr( dir, '/' ))
2650 *strrchr( dir, '/' ) = 0;
2651 strarray_add_uniq( &uninstall_dirs, xstrdup(dir) );
2654 strarray_qsort( &uninstall_dirs, cmp_string_length );
2655 output( "\t-rmdir" );
2656 for (i = 0; i < sizeof(dirs_order)/sizeof(dirs_order[0]); i++)
2658 for (j = 0; j < uninstall_dirs.count; j++)
2660 if (!uninstall_dirs.str[j]) continue;
2661 if (strncmp( uninstall_dirs.str[j] + strlen("$(DESTDIR)"), dirs_order[i], strlen(dirs_order[i]) ))
2662 continue;
2663 output_filename( uninstall_dirs.str[j] );
2664 uninstall_dirs.str[j] = NULL;
2667 for (j = 0; j < uninstall_dirs.count; j++)
2668 if (uninstall_dirs.str[j]) output_filename( uninstall_dirs.str[j] );
2669 output( "\n" );
2673 /*******************************************************************
2674 * output_importlib_symlinks
2676 static struct strarray output_importlib_symlinks( const struct makefile *make )
2678 struct strarray ret = empty_strarray;
2679 const char *lib, *dst, *ext[4];
2680 int i, count = 0;
2682 ext[count++] = (*dll_ext && !make->implib_objs.count) ? "def" : "a";
2683 if (needs_delay_lib( make )) ext[count++] = "delay.a";
2684 if (needs_cross_lib( make )) ext[count++] = "cross.a";
2686 for (i = 0; i < count; i++)
2688 lib = strmake( "lib%s.%s", make->importlib, ext[i] );
2689 dst = strmake( "dlls/%s", lib );
2690 output( "%s: %s\n", dst, obj_dir_path( make, lib ));
2691 output_symlink_rule( concat_paths( make->obj_dir + strlen("dlls/"), lib ), dst, 0 );
2692 strarray_add( &ret, dst );
2694 return ret;
2698 /*******************************************************************
2699 * output_po_files
2701 static void output_po_files( const struct makefile *make )
2703 const char *po_dir = src_dir_path( make, "po" );
2704 unsigned int i;
2706 if (linguas.count)
2708 for (i = 0; i < linguas.count; i++)
2709 output_filename( strmake( "%s/%s.po", po_dir, linguas.str[i] ));
2710 output( ": %s/wine.pot\n", po_dir );
2711 output( "\t%smsgmerge --previous -q $@ %s/wine.pot | msgattrib --no-obsolete -o $@.new && mv $@.new $@\n",
2712 cmd_prefix( "MSG" ), po_dir );
2713 output( "po:" );
2714 for (i = 0; i < linguas.count; i++)
2715 output_filename( strmake( "%s/%s.po", po_dir, linguas.str[i] ));
2716 output( "\n" );
2718 output( "%s/wine.pot:", po_dir );
2719 output_filenames( make->pot_files );
2720 output( "\n" );
2721 output( "\t%smsgcat -o $@", cmd_prefix( "MSG" ));
2722 output_filenames( make->pot_files );
2723 output( "\n" );
2727 /*******************************************************************
2728 * output_source_y
2730 static void output_source_y( struct makefile *make, struct incl_file *source, const char *obj )
2732 /* add source file dependency for parallel makes */
2733 char *header = strmake( "%s.tab.h", obj );
2735 if (find_include_file( make, header ))
2737 output( "%s: %s\n", obj_dir_path( make, header ), source->filename );
2738 output( "\t%s%s -p %s_ -o %s.tab.c -d %s\n",
2739 cmd_prefix( "BISON" ), bison, obj, obj_dir_path( make, obj ), source->filename );
2740 output( "%s.tab.c: %s %s\n", obj_dir_path( make, obj ),
2741 source->filename, obj_dir_path( make, header ));
2742 strarray_add( &make->clean_files, header );
2744 else output( "%s.tab.c: %s\n", obj_dir_path( make, obj ), source->filename );
2746 output( "\t%s%s -p %s_ -o $@ %s\n", cmd_prefix( "BISON" ), bison, obj, source->filename );
2750 /*******************************************************************
2751 * output_source_l
2753 static void output_source_l( struct makefile *make, struct incl_file *source, const char *obj )
2755 output( "%s.yy.c: %s\n", obj_dir_path( make, obj ), source->filename );
2756 output( "\t%s%s -o$@ %s\n", cmd_prefix( "FLEX" ), flex, source->filename );
2760 /*******************************************************************
2761 * output_source_h
2763 static void output_source_h( struct makefile *make, struct incl_file *source, const char *obj )
2765 if (source->file->flags & FLAG_GENERATED)
2766 strarray_add( &make->all_targets, source->name );
2767 else
2768 add_install_rule( make, source->name, source->name,
2769 strmake( "D$(includedir)/wine/%s", get_include_install_path( source->name ) ));
2773 /*******************************************************************
2774 * output_source_rc
2776 static void output_source_rc( struct makefile *make, struct incl_file *source, const char *obj )
2778 struct strarray defines = get_source_defines( make, source, obj );
2779 const char *po_dir = NULL;
2780 unsigned int i;
2782 if (source->file->flags & FLAG_GENERATED) strarray_add( &make->clean_files, source->name );
2783 if (linguas.count && (source->file->flags & FLAG_RC_PO)) po_dir = "po";
2784 strarray_add( &make->res_files, strmake( "%s.res", obj ));
2785 if (source->file->flags & FLAG_RC_PO)
2787 strarray_add( &make->pot_files, strmake( "%s.pot", obj ));
2788 output( "%s.pot ", obj_dir_path( make, obj ) );
2790 output( "%s.res: %s", obj_dir_path( make, obj ), source->filename );
2791 output_filename( tools_path( make, "wrc" ));
2792 output_filenames( source->dependencies );
2793 output( "\n" );
2794 output( "\t%s%s -u -o $@", cmd_prefix( "WRC" ), tools_path( make, "wrc" ) );
2795 if (make->is_win16) output_filename( "-m16" );
2796 else output_filenames( target_flags );
2797 output_filename( "--nostdinc" );
2798 if (po_dir) output_filename( strmake( "--po-dir=%s", po_dir ));
2799 output_filenames( defines );
2800 output_filename( source->filename );
2801 output( "\n" );
2802 if (po_dir)
2804 output( "%s.res:", obj_dir_path( make, obj ));
2805 for (i = 0; i < linguas.count; i++)
2806 output_filename( strmake( "%s/%s.mo", po_dir, linguas.str[i] ));
2807 output( "\n" );
2812 /*******************************************************************
2813 * output_source_mc
2815 static void output_source_mc( struct makefile *make, struct incl_file *source, const char *obj )
2817 unsigned int i;
2818 char *obj_path = obj_dir_path( make, obj );
2820 strarray_add( &make->res_files, strmake( "%s.res", obj ));
2821 strarray_add( &make->pot_files, strmake( "%s.pot", obj ));
2822 output( "%s.pot %s.res: %s", obj_path, obj_path, source->filename );
2823 output_filename( tools_path( make, "wmc" ));
2824 output_filenames( source->dependencies );
2825 output( "\n" );
2826 output( "\t%s%s -u -o $@ %s", cmd_prefix( "WMC" ), tools_path( make, "wmc" ), source->filename );
2827 if (linguas.count)
2829 output_filename( "--po-dir=po" );
2830 output( "\n" );
2831 output( "%s.res:", obj_dir_path( make, obj ));
2832 for (i = 0; i < linguas.count; i++)
2833 output_filename( strmake( "po/%s.mo", linguas.str[i] ));
2835 output( "\n" );
2839 /*******************************************************************
2840 * output_source_res
2842 static void output_source_res( struct makefile *make, struct incl_file *source, const char *obj )
2844 strarray_add( &make->res_files, source->name );
2848 /*******************************************************************
2849 * output_source_idl
2851 static void output_source_idl( struct makefile *make, struct incl_file *source, const char *obj )
2853 struct strarray defines = get_source_defines( make, source, obj );
2854 struct strarray targets = empty_strarray;
2855 char *dest;
2856 unsigned int i;
2858 if (!source->file->flags) source->file->flags |= FLAG_IDL_HEADER | FLAG_INSTALL;
2859 if (find_include_file( make, strmake( "%s.h", obj ))) source->file->flags |= FLAG_IDL_HEADER;
2861 for (i = 0; i < sizeof(idl_outputs) / sizeof(idl_outputs[0]); i++)
2863 if (!(source->file->flags & idl_outputs[i].flag)) continue;
2864 dest = strmake( "%s%s", obj, idl_outputs[i].ext );
2865 if (!find_src_file( make, dest )) strarray_add( &make->clean_files, dest );
2866 strarray_add( &targets, dest );
2868 if (source->file->flags & FLAG_IDL_PROXY) strarray_add( &make->dlldata_files, source->name );
2869 if (source->file->flags & FLAG_INSTALL)
2871 add_install_rule( make, source->name, xstrdup( source->name ),
2872 strmake( "D$(includedir)/wine/%s.idl", get_include_install_path( obj ) ));
2873 if (source->file->flags & FLAG_IDL_HEADER)
2874 add_install_rule( make, source->name, strmake( "%s.h", obj ),
2875 strmake( "d$(includedir)/wine/%s.h", get_include_install_path( obj ) ));
2876 if (source->file->flags & FLAG_IDL_TYPELIB)
2877 add_install_rule( make, source->name, strmake( "%s.tlb", obj ),
2878 strmake( "d$(includedir)/wine/%s.tlb", get_include_install_path( obj ) ));
2880 if (!targets.count) return;
2882 output_filenames_obj_dir( make, targets );
2883 output( ": %s\n", tools_path( make, "widl" ));
2884 output( "\t%s%s -o $@", cmd_prefix( "WIDL" ), tools_path( make, "widl" ) );
2885 output_filenames( target_flags );
2886 output_filename( "--nostdinc" );
2887 output_filenames( defines );
2888 output_filenames( get_expanded_make_var_array( make, "EXTRAIDLFLAGS" ));
2889 output_filenames( get_expanded_file_local_var( make, obj, "EXTRAIDLFLAGS" ));
2890 output_filename( source->filename );
2891 output( "\n" );
2892 output_filenames_obj_dir( make, targets );
2893 output( ": %s", source->filename );
2894 output_filenames( source->dependencies );
2895 output( "\n" );
2899 /*******************************************************************
2900 * output_source_tlb
2902 static void output_source_tlb( struct makefile *make, struct incl_file *source, const char *obj )
2904 strarray_add( &make->all_targets, source->name );
2908 /*******************************************************************
2909 * output_source_x
2911 static void output_source_x( struct makefile *make, struct incl_file *source, const char *obj )
2913 output( "%s.h: %s%s %s\n", obj_dir_path( make, obj ),
2914 tools_dir_path( make, "make_xftmpl" ), tools_ext, source->filename );
2915 output( "\t%s%s%s -H -o $@ %s\n", cmd_prefix( "GEN" ),
2916 tools_dir_path( make, "make_xftmpl" ), tools_ext, source->filename );
2917 if (source->file->flags & FLAG_INSTALL)
2919 add_install_rule( make, source->name, source->name,
2920 strmake( "D$(includedir)/wine/%s", get_include_install_path( source->name ) ));
2921 add_install_rule( make, source->name, strmake( "%s.h", obj ),
2922 strmake( "d$(includedir)/wine/%s.h", get_include_install_path( obj ) ));
2927 /*******************************************************************
2928 * output_source_sfd
2930 static void output_source_sfd( struct makefile *make, struct incl_file *source, const char *obj )
2932 unsigned int i;
2933 char *ttf_obj = strmake( "%s.ttf", obj );
2934 char *ttf_file = src_dir_path( make, ttf_obj );
2936 if (fontforge && !make->src_dir)
2938 output( "%s: %s\n", ttf_file, source->filename );
2939 output( "\t%s%s -script %s %s $@\n", cmd_prefix( "GEN" ),
2940 fontforge, root_src_dir_path( "fonts/genttf.ff" ), source->filename );
2941 if (!(source->file->flags & FLAG_SFD_FONTS)) strarray_add( &make->font_files, ttf_obj );
2943 if (source->file->flags & FLAG_INSTALL)
2945 add_install_rule( make, source->name, ttf_obj, strmake( "D$(fontdir)/%s", ttf_obj ));
2946 output_srcdir_symlink( make, ttf_obj );
2949 if (source->file->flags & FLAG_SFD_FONTS)
2951 struct strarray *array = source->file->args;
2953 for (i = 0; i < array->count; i++)
2955 char *font = strtok( xstrdup(array->str[i]), " \t" );
2956 char *args = strtok( NULL, "" );
2958 strarray_add( &make->all_targets, xstrdup( font ));
2959 output( "%s: %s %s\n", obj_dir_path( make, font ),
2960 tools_path( make, "sfnt2fon" ), ttf_file );
2961 output( "\t%s%s -q -o $@ %s %s\n", cmd_prefix( "GEN" ),
2962 tools_path( make, "sfnt2fon" ), ttf_file, args );
2963 add_install_rule( make, source->name, xstrdup(font), strmake( "d$(fontdir)/%s", font ));
2969 /*******************************************************************
2970 * output_source_svg
2972 static void output_source_svg( struct makefile *make, struct incl_file *source, const char *obj )
2974 static const char * const images[] = { "bmp", "cur", "ico", NULL };
2975 unsigned int i;
2977 if (convert && rsvg && icotool && !make->src_dir)
2979 for (i = 0; images[i]; i++)
2980 if (find_include_file( make, strmake( "%s.%s", obj, images[i] ))) break;
2982 if (images[i])
2984 output( "%s.%s: %s\n", src_dir_path( make, obj ), images[i], source->filename );
2985 output( "\t%sCONVERT=\"%s\" ICOTOOL=\"%s\" RSVG=\"%s\" %s %s $@\n",
2986 cmd_prefix( "GEN" ), convert, icotool, rsvg,
2987 root_src_dir_path( "tools/buildimage" ), source->filename );
2993 /*******************************************************************
2994 * output_source_nls
2996 static void output_source_nls( struct makefile *make, struct incl_file *source, const char *obj )
2998 add_install_rule( make, source->name, source->name,
2999 strmake( "D$(nlsdir)/%s", source->name ));
3000 output_srcdir_symlink( make, strmake( "%s.nls", obj ));
3004 /*******************************************************************
3005 * output_source_desktop
3007 static void output_source_desktop( struct makefile *make, struct incl_file *source, const char *obj )
3009 add_install_rule( make, source->name, source->name,
3010 strmake( "D$(datadir)/applications/%s", source->name ));
3014 /*******************************************************************
3015 * output_source_po
3017 static void output_source_po( struct makefile *make, struct incl_file *source, const char *obj )
3019 output( "%s.mo: %s\n", obj_dir_path( make, obj ), source->filename );
3020 output( "\t%s%s -o $@ %s\n", cmd_prefix( "MSG" ), msgfmt, source->filename );
3021 strarray_add( &make->all_targets, strmake( "%s.mo", obj ));
3025 /*******************************************************************
3026 * output_source_in
3028 static void output_source_in( struct makefile *make, struct incl_file *source, const char *obj )
3030 unsigned int i;
3032 if (strendswith( obj, ".man" ) && source->file->args)
3034 struct strarray symlinks;
3035 char *dir, *dest = replace_extension( obj, ".man", "" );
3036 char *lang = strchr( dest, '.' );
3037 char *section = source->file->args;
3038 if (lang)
3040 *lang++ = 0;
3041 dir = strmake( "$(mandir)/%s/man%s", lang, section );
3043 else dir = strmake( "$(mandir)/man%s", section );
3044 add_install_rule( make, dest, xstrdup(obj), strmake( "d%s/%s.%s", dir, dest, section ));
3045 symlinks = get_expanded_file_local_var( make, dest, "SYMLINKS" );
3046 for (i = 0; i < symlinks.count; i++)
3047 add_install_rule( make, symlinks.str[i], strmake( "%s.%s", dest, section ),
3048 strmake( "y%s/%s.%s", dir, symlinks.str[i], section ));
3049 free( dest );
3050 free( dir );
3052 strarray_add( &make->in_files, xstrdup(obj) );
3053 strarray_add( &make->all_targets, xstrdup(obj) );
3054 output( "%s: %s\n", obj_dir_path( make, obj ), source->filename );
3055 output( "\t%s%s %s >$@ || (rm -f $@ && false)\n", cmd_prefix( "SED" ), sed_cmd, source->filename );
3056 output( "%s:", obj_dir_path( make, obj ));
3057 output_filenames( source->dependencies );
3058 output( "\n" );
3059 add_install_rule( make, obj, xstrdup( obj ), strmake( "d$(datadir)/wine/%s", obj ));
3063 /*******************************************************************
3064 * output_source_spec
3066 static void output_source_spec( struct makefile *make, struct incl_file *source, const char *obj )
3068 struct strarray imports = get_expanded_file_local_var( make, obj, "IMPORTS" );
3069 struct strarray dll_flags = get_expanded_file_local_var( make, obj, "EXTRADLLFLAGS" );
3070 struct strarray all_libs, dep_libs = empty_strarray;
3071 char *dll_name, *obj_name, *output_file;
3072 const char *debug_file;
3074 if (!imports.count) imports = make->imports;
3075 else if (make->use_msvcrt) add_crt_import( make, &imports, NULL );
3077 if (!dll_flags.count) dll_flags = make->extradllflags;
3078 all_libs = add_import_libs( make, &dep_libs, imports, 0, 0 );
3079 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
3080 dll_name = strmake( "%s.dll%s", obj, make->is_cross ? "" : dll_ext );
3081 obj_name = strmake( "%s%s", obj_dir_path( make, obj ), make->is_cross ? ".cross.o" : ".o" );
3082 output_file = obj_dir_path( make, dll_name );
3084 strarray_add( &make->clean_files, dll_name );
3085 strarray_add( &make->res_files, strmake( "%s.res", obj ));
3086 output( "%s.res:", obj_dir_path( make, obj ));
3087 output_filename( obj_dir_path( make, dll_name ));
3088 output_filename( tools_path( make, "wrc" ));
3089 output( "\n" );
3090 output( "\t%secho \"%s.dll TESTDLL \\\"%s\\\"\" | %s -u -o $@\n", cmd_prefix( "WRC" ), obj, output_file,
3091 tools_path( make, "wrc" ));
3093 output( "%s:", output_file);
3094 output_filename( source->filename );
3095 output_filename( obj_name );
3096 output_filenames( dep_libs );
3097 output_filename( tools_path( make, "winebuild" ));
3098 output_filename( tools_path( make, "winegcc" ));
3099 output( "\n" );
3100 output_winegcc_command( make, make->is_cross );
3101 output_filename( "-s" );
3102 output_filenames( dll_flags );
3103 output_filename( "-shared" );
3104 output_filename( source->filename );
3105 output_filename( obj_name );
3106 if ((debug_file = get_debug_file( make, dll_name )))
3107 output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
3108 output_filenames( all_libs );
3109 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3110 output( "\n" );
3114 /*******************************************************************
3115 * output_source_default
3117 static void output_source_default( struct makefile *make, struct incl_file *source, const char *obj )
3119 struct strarray defines = get_source_defines( make, source, obj );
3120 int is_dll_src = (make->testdll &&
3121 strendswith( source->name, ".c" ) &&
3122 find_src_file( make, replace_extension( source->name, ".c", ".spec" )));
3123 int need_cross = (crosstarget &&
3124 !(source->file->flags & FLAG_C_UNIX) &&
3125 (make->is_cross ||
3126 ((source->file->flags & FLAG_C_IMPLIB) &&
3127 (needs_cross_lib( make ) || needs_delay_lib( make ))) ||
3128 (make->staticlib && needs_cross_lib( make ))));
3129 int need_obj = ((*dll_ext || !(source->file->flags & FLAG_C_UNIX)) &&
3130 (!need_cross ||
3131 (source->file->flags & FLAG_C_IMPLIB) ||
3132 (make->module && make->staticlib)));
3134 if ((source->file->flags & FLAG_GENERATED) &&
3135 (!make->testdll || !strendswith( source->filename, "testlist.c" )))
3136 strarray_add( &make->clean_files, source->basename );
3137 if (source->file->flags & FLAG_C_IMPLIB) strarray_add( &make->implib_objs, strmake( "%s.o", obj ));
3139 if (need_obj)
3141 if ((source->file->flags & FLAG_C_UNIX) && *dll_ext)
3142 strarray_add( &make->unixobj_files, strmake( "%s.o", obj ));
3143 else if (!is_dll_src && !(source->file->flags & FLAG_C_IMPLIB))
3144 strarray_add( &make->object_files, strmake( "%s.o", obj ));
3145 else
3146 strarray_add( &make->clean_files, strmake( "%s.o", obj ));
3147 output( "%s.o: %s\n", obj_dir_path( make, obj ), source->filename );
3148 output( "\t%s$(CC) -c -o $@ %s", cmd_prefix( "CC" ), source->filename );
3149 output_filenames( defines );
3150 if (make->module || make->staticlib || make->sharedlib || make->testdll)
3152 output_filenames( dll_flags );
3153 if (source->use_msvcrt) output_filenames( msvcrt_flags );
3155 output_filenames( extra_cflags );
3156 output_filenames( cpp_flags );
3157 output_filename( "$(CFLAGS)" );
3158 output( "\n" );
3160 if (need_cross)
3162 if (!is_dll_src && !(source->file->flags & FLAG_C_IMPLIB))
3163 strarray_add( &make->crossobj_files, strmake( "%s.cross.o", obj ));
3164 else
3165 strarray_add( &make->clean_files, strmake( "%s.cross.o", obj ));
3166 output( "%s.cross.o: %s\n", obj_dir_path( make, obj ), source->filename );
3167 output( "\t%s$(CROSSCC) -c -o $@ %s", cmd_prefix( "CC" ), source->filename );
3168 output_filenames( defines );
3169 output_filenames( extra_cross_cflags );
3170 if (source->file->flags & FLAG_C_IMPLIB || (make->module && is_crt_module( make->module )))
3171 output_filename( "-fno-builtin" );
3172 output_filenames( cpp_flags );
3173 output_filename( "$(CROSSCFLAGS)" );
3174 output( "\n" );
3176 if (strendswith( source->name, ".c" ) && !(source->file->flags & FLAG_GENERATED))
3178 strarray_add( &make->c2man_files, source->filename );
3179 if (make->testdll && !is_dll_src)
3181 strarray_add( &make->ok_files, strmake( "%s.ok", obj ));
3182 output( "%s.ok:\n", obj_dir_path( make, obj ));
3183 output( "\t%s%s $(RUNTESTFLAGS) -T . -M %s -p %s%s %s && touch $@\n",
3184 cmd_prefix( "TEST" ),
3185 root_src_dir_path( "tools/runtest" ), make->testdll,
3186 obj_dir_path( make, replace_extension( make->testdll, ".dll", "_test.exe" )),
3187 make->is_cross ? "" : dll_ext, obj );
3190 if (need_obj) output_filename( strmake( "%s.o", obj_dir_path( make, obj )));
3191 if (need_cross) output_filename( strmake( "%s.cross.o", obj_dir_path( make, obj )));
3192 output( ":" );
3193 output_filenames( source->dependencies );
3194 output( "\n" );
3198 /* dispatch table to output rules for a single source file */
3199 static const struct
3201 const char *ext;
3202 void (*fn)( struct makefile *make, struct incl_file *source, const char *obj );
3203 } output_source_funcs[] =
3205 { "y", output_source_y },
3206 { "l", output_source_l },
3207 { "h", output_source_h },
3208 { "rh", output_source_h },
3209 { "inl", output_source_h },
3210 { "rc", output_source_rc },
3211 { "mc", output_source_mc },
3212 { "res", output_source_res },
3213 { "idl", output_source_idl },
3214 { "tlb", output_source_tlb },
3215 { "sfd", output_source_sfd },
3216 { "svg", output_source_svg },
3217 { "nls", output_source_nls },
3218 { "desktop", output_source_desktop },
3219 { "po", output_source_po },
3220 { "in", output_source_in },
3221 { "x", output_source_x },
3222 { "spec", output_source_spec },
3223 { NULL, output_source_default }
3227 /*******************************************************************
3228 * has_object_file
3230 static int has_object_file( struct makefile *make )
3232 struct incl_file *source;
3233 int i;
3235 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
3237 char *ext = get_extension( source->name );
3239 if (!ext) fatal_error( "unsupported file type %s\n", source->name );
3240 ext++;
3242 for (i = 0; output_source_funcs[i].ext; i++)
3243 if (!strcmp( ext, output_source_funcs[i].ext )) break;
3245 if (!output_source_funcs[i].ext) return 1; /* default extension builds to an object file */
3247 return 0;
3251 /*******************************************************************
3252 * output_man_pages
3254 static void output_man_pages( struct makefile *make )
3256 if (make->c2man_files.count)
3258 char *spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" ));
3260 output( "manpages::\n" );
3261 output( "\t%s -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3262 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3263 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3264 output_filename( strmake( "-o documentation/man%s", man_ext ));
3265 output_filenames( make->c2man_files );
3266 output( "\n" );
3267 output( "htmlpages::\n" );
3268 output( "\t%s -Th -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3269 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3270 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3271 output_filename( "-o documentation/html" );
3272 output_filenames( make->c2man_files );
3273 output( "\n" );
3274 output( "sgmlpages::\n" );
3275 output( "\t%s -Ts -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3276 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3277 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3278 output_filename( "-o documentation/api-guide" );
3279 output_filenames( make->c2man_files );
3280 output( "\n" );
3281 output( "xmlpages::\n" );
3282 output( "\t%s -Tx -w %s", root_src_dir_path( "tools/c2man.pl" ), spec_file );
3283 output_filename( strmake( "-R%s", root_src_dir_path( "" )));
3284 output_filename( strmake( "-I%s", root_src_dir_path( "include" )));
3285 output_filename( "-o documentation/api-guide-xml" );
3286 output_filenames( make->c2man_files );
3287 output( "\n" );
3288 strarray_add( &make->phony_targets, "manpages" );
3289 strarray_add( &make->phony_targets, "htmlpages" );
3290 strarray_add( &make->phony_targets, "sgmlpages" );
3291 strarray_add( &make->phony_targets, "xmlpages" );
3296 /*******************************************************************
3297 * output_module
3299 static void output_module( struct makefile *make )
3301 struct strarray all_libs = empty_strarray;
3302 struct strarray dep_libs = empty_strarray;
3303 char *module_path = obj_dir_path( make, make->module );
3304 const char *debug_file = NULL;
3305 char *spec_file = NULL;
3306 unsigned int i;
3308 if (!make->is_exe) spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" ));
3309 strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->delayimports, 1, 0 ));
3310 strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->imports, 0, 0 ));
3311 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
3313 if (make->is_cross)
3315 if (delay_load_flag)
3317 for (i = 0; i < make->delayimports.count; i++)
3318 strarray_add( &all_libs, strmake( "%s%s%s", delay_load_flag, make->delayimports.str[i],
3319 strchr( make->delayimports.str[i], '.' ) ? "" : ".dll" ));
3321 strarray_add( &make->all_targets, strmake( "%s", make->module ));
3322 add_install_rule( make, make->module, strmake( "%s", make->module ),
3323 strmake( "c$(dlldir)/%s", make->module ));
3324 debug_file = get_debug_file( make, make->module );
3325 output( "%s:", module_path );
3327 else if (*dll_ext)
3329 if (!make->use_msvcrt) strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3330 for (i = 0; i < make->delayimports.count; i++)
3331 strarray_add( &all_libs, strmake( "-Wl,-delayload,%s%s", make->delayimports.str[i],
3332 strchr( make->delayimports.str[i], '.' ) ? "" : ".dll" ));
3333 strarray_add( &make->all_targets, strmake( "%s%s", make->module, dll_ext ));
3334 strarray_add( &make->all_targets, strmake( "%s.fake", make->module ));
3335 add_install_rule( make, make->module, strmake( "%s%s", make->module, dll_ext ),
3336 strmake( "p$(dlldir)/%s%s", make->module, dll_ext ));
3337 add_install_rule( make, make->module, strmake( "%s.fake", make->module ),
3338 strmake( "d$(dlldir)/fakedlls/%s", make->module ));
3339 output( "%s%s %s.fake:", module_path, dll_ext, module_path );
3341 else
3343 strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3344 strarray_add( &make->all_targets, make->module );
3345 add_install_rule( make, make->module, make->module,
3346 strmake( "p$(%s)/%s", spec_file ? "dlldir" : "bindir", make->module ));
3347 debug_file = get_debug_file( make, make->module );
3348 output( "%s:", module_path );
3351 if (spec_file) output_filename( spec_file );
3352 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3353 output_filenames_obj_dir( make, make->res_files );
3354 output_filenames( dep_libs );
3355 output_filename( tools_path( make, "winebuild" ));
3356 output_filename( tools_path( make, "winegcc" ));
3357 output( "\n" );
3358 output_winegcc_command( make, make->is_cross );
3359 if (make->is_cross) output_filename( "-Wl,--wine-builtin" );
3360 if (spec_file)
3362 output_filename( "-shared" );
3363 output_filename( spec_file );
3365 output_filenames( make->extradllflags );
3366 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3367 output_filenames_obj_dir( make, make->res_files );
3368 if (debug_file) output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
3369 output_filenames( all_libs );
3370 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3371 output( "\n" );
3373 if (make->unixobj_files.count)
3375 struct strarray unix_imports = empty_strarray;
3376 struct strarray unix_libs = empty_strarray;
3377 struct strarray unix_deps = empty_strarray;
3378 char *ext, *unix_lib = xmalloc( strlen( make->module ) + strlen( dll_ext ) + 1 );
3379 strcpy( unix_lib, make->module );
3380 if ((ext = get_extension( unix_lib ))) *ext = 0;
3381 strcat( unix_lib, dll_ext );
3383 if (!strarray_exists( &make->extradllflags, "-nodefaultlibs" ))
3384 strarray_add( &unix_imports, "ntdll" );
3385 strarray_add( &unix_imports, "winecrt0" );
3387 strarray_addall( &unix_libs, add_import_libs( make, &unix_deps, unix_imports, 0, 1 ));
3388 strarray_addall( &unix_libs, add_unix_libraries( make, &unix_deps ));
3390 strarray_add( &make->all_targets, unix_lib );
3391 add_install_rule( make, make->module, unix_lib, strmake( "p$(dlldir)/%s", unix_lib ));
3392 output( "%s:", obj_dir_path( make, unix_lib ));
3393 if (spec_file) output_filename( spec_file );
3394 output_filenames_obj_dir( make, make->unixobj_files );
3395 output_filenames( unix_deps );
3396 output_filename( tools_path( make, "winebuild" ));
3397 output_filename( tools_path( make, "winegcc" ));
3398 output( "\n" );
3399 output_winegcc_command( make, 0 );
3400 output_filename( "-munix" );
3401 output_filename( "-shared" );
3402 if (spec_file) output_filename( spec_file );
3403 if (strarray_exists( &make->extradllflags, "-nodefaultlibs" )) output_filename( "-nodefaultlibs" );
3404 output_filenames_obj_dir( make, make->unixobj_files );
3405 output_filenames( unix_libs );
3406 output_filename( "$(LDFLAGS)" );
3407 output( "\n" );
3410 if (spec_file && make->importlib)
3412 char *importlib_path = obj_dir_path( make, strmake( "lib%s", make->importlib ));
3413 if (*dll_ext && !make->implib_objs.count)
3415 strarray_add( &make->clean_files, strmake( "lib%s.def", make->importlib ));
3416 output( "%s.def: %s %s\n", importlib_path, tools_path( make, "winebuild" ), spec_file );
3417 output( "\t%s%s -w --def -o $@", cmd_prefix( "BUILD" ), tools_path( make, "winebuild" ) );
3418 output_filenames( target_flags );
3419 if (make->is_win16) output_filename( "-m16" );
3420 output_filename( "--export" );
3421 output_filename( spec_file );
3422 output( "\n" );
3423 add_install_rule( make, make->importlib,
3424 strmake( "lib%s.def", make->importlib ),
3425 strmake( "d$(dlldir)/lib%s.def", make->importlib ));
3427 else
3429 strarray_add( &make->clean_files, strmake( "lib%s.a", make->importlib ));
3430 if (!*dll_ext && needs_delay_lib( make ))
3432 strarray_add( &make->clean_files, strmake( "lib%s.delay.a", make->importlib ));
3433 output( "%s.delay.a ", importlib_path );
3435 output( "%s.a: %s %s", importlib_path, tools_path( make, "winebuild" ), spec_file );
3436 output_filenames_obj_dir( make, make->implib_objs );
3437 output( "\n" );
3438 output( "\t%s%s -w --implib -o $@", cmd_prefix( "BUILD" ), tools_path( make, "winebuild" ) );
3439 output_filenames( target_flags );
3440 if (make->is_win16) output_filename( "-m16" );
3441 output_filename( "--export" );
3442 output_filename( spec_file );
3443 output_filenames_obj_dir( make, make->implib_objs );
3444 output( "\n" );
3445 add_install_rule( make, make->importlib,
3446 strmake( "lib%s.a", make->importlib ),
3447 strmake( "d$(dlldir)/lib%s.a", make->importlib ));
3449 if (crosstarget && (needs_cross_lib( make ) || needs_delay_lib( make )))
3451 struct strarray cross_files = strarray_replace_extension( &make->implib_objs, ".o", ".cross.o" );
3452 if (needs_cross_lib( make ))
3454 strarray_add( &make->clean_files, strmake( "lib%s.cross.a", make->importlib ));
3455 output_filename( strmake( "%s.cross.a", importlib_path ));
3457 if (needs_delay_lib( make ))
3459 strarray_add( &make->clean_files, strmake( "lib%s.delay.a", make->importlib ));
3460 output_filename( strmake( "%s.delay.a", importlib_path ));
3462 output( ": %s %s", tools_path( make, "winebuild" ), spec_file );
3463 output_filenames_obj_dir( make, cross_files );
3464 output( "\n" );
3465 output( "\t%s%s -b %s -w --implib -o $@", cmd_prefix( "BUILD" ),
3466 tools_path( make, "winebuild" ), crosstarget );
3467 if (make->is_win16) output_filename( "-m16" );
3468 output_filename( "--export" );
3469 output_filename( spec_file );
3470 output_filenames_obj_dir( make, cross_files );
3471 output( "\n" );
3473 if (needs_implib_symlink( make ))
3474 strarray_addall( &top_makefile->clean_files, output_importlib_symlinks( make ));
3477 if (spec_file)
3478 output_man_pages( make );
3479 else if (*dll_ext && !make->is_win16 && strendswith( make->module, ".exe" ))
3481 char *binary = replace_extension( make->module, ".exe", "" );
3482 add_install_rule( make, binary, "wineapploader", strmake( "t$(bindir)/%s", binary ));
3487 /*******************************************************************
3488 * output_static_lib
3490 static void output_static_lib( struct makefile *make )
3492 strarray_add( &make->all_targets, make->staticlib );
3493 output( "%s:", obj_dir_path( make, make->staticlib ));
3494 output_filenames_obj_dir( make, make->object_files );
3495 output_filenames_obj_dir( make, make->unixobj_files );
3496 output( "\n\t%srm -f $@ && %s rc $@", cmd_prefix( "AR" ), ar );
3497 output_filenames_obj_dir( make, make->object_files );
3498 output_filenames_obj_dir( make, make->unixobj_files );
3499 output( " && %s $@\n", ranlib );
3500 add_install_rule( make, make->staticlib, make->staticlib,
3501 strmake( "d$(dlldir)/%s", make->staticlib ));
3502 if (needs_cross_lib( make ))
3504 char *name = replace_extension( make->staticlib, ".a", ".cross.a" );
3506 strarray_add( &make->all_targets, name );
3507 output( "%s: %s", obj_dir_path( make, name ), tools_path( make, "winebuild" ));
3508 output_filenames_obj_dir( make, make->crossobj_files );
3509 output( "\n" );
3510 output( "\t%s%s -b %s -w --staticlib -o $@", cmd_prefix( "BUILD" ),
3511 tools_path( make, "winebuild" ), crosstarget );
3512 output_filenames_obj_dir( make, make->crossobj_files );
3513 output( "\n" );
3518 /*******************************************************************
3519 * output_shared_lib
3521 static void output_shared_lib( struct makefile *make )
3523 unsigned int i;
3524 char *basename, *p;
3525 struct strarray names = get_shared_lib_names( make->sharedlib );
3526 struct strarray all_libs = empty_strarray;
3527 struct strarray dep_libs = empty_strarray;
3529 basename = xstrdup( make->sharedlib );
3530 if ((p = strchr( basename, '.' ))) *p = 0;
3532 strarray_addall( &dep_libs, get_local_dependencies( make, basename, make->in_files ));
3533 strarray_addall( &all_libs, get_expanded_file_local_var( make, basename, "LDFLAGS" ));
3534 strarray_addall( &all_libs, add_unix_libraries( make, &dep_libs ));
3536 output( "%s:", obj_dir_path( make, make->sharedlib ));
3537 output_filenames_obj_dir( make, make->object_files );
3538 output_filenames( dep_libs );
3539 output( "\n" );
3540 output( "\t%s$(CC) -o $@", cmd_prefix( "CC" ));
3541 output_filenames_obj_dir( make, make->object_files );
3542 output_filenames( all_libs );
3543 output_filename( "$(LDFLAGS)" );
3544 output( "\n" );
3545 add_install_rule( make, make->sharedlib, make->sharedlib,
3546 strmake( "p$(libdir)/%s", make->sharedlib ));
3547 for (i = 1; i < names.count; i++)
3549 output( "%s: %s\n", obj_dir_path( make, names.str[i] ), obj_dir_path( make, names.str[i-1] ));
3550 output_symlink_rule( names.str[i-1], obj_dir_path( make, names.str[i] ), 0 );
3551 add_install_rule( make, names.str[i], names.str[i-1],
3552 strmake( "y$(libdir)/%s", names.str[i] ));
3554 strarray_addall( &make->all_targets, names );
3558 /*******************************************************************
3559 * output_test_module
3561 static void output_test_module( struct makefile *make )
3563 char *testmodule = replace_extension( make->testdll, ".dll", "_test.exe" );
3564 char *stripped = replace_extension( make->testdll, ".dll", "_test-stripped.exe" );
3565 char *testres = replace_extension( make->testdll, ".dll", "_test.res" );
3566 struct strarray dep_libs = empty_strarray;
3567 struct strarray all_libs = add_import_libs( make, &dep_libs, make->imports, 0, 0 );
3568 struct makefile *parent = get_parent_makefile( make );
3569 const char *ext = make->is_cross ? "" : dll_ext;
3570 const char *debug_file;
3571 char *output_file;
3573 add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */
3574 strarray_add( &make->all_targets, strmake( "%s%s", testmodule, ext ));
3575 strarray_add( &make->clean_files, strmake( "%s%s", stripped, ext ));
3576 output_file = strmake( "%s%s", obj_dir_path( make, testmodule ), ext );
3577 output( "%s:\n", output_file );
3578 output_winegcc_command( make, make->is_cross );
3579 output_filenames( make->extradllflags );
3580 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3581 output_filenames_obj_dir( make, make->res_files );
3582 if ((debug_file = get_debug_file( make, testmodule )))
3583 output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file )));
3584 output_filenames( all_libs );
3585 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3586 output( "\n" );
3587 output( "%s%s:\n", obj_dir_path( make, stripped ), ext );
3588 output_winegcc_command( make, make->is_cross );
3589 output_filename( "-s" );
3590 output_filename( strmake( "-Wb,-F,%s", testmodule ));
3591 output_filenames( make->extradllflags );
3592 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3593 output_filenames_obj_dir( make, make->res_files );
3594 output_filenames( all_libs );
3595 output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" );
3596 output( "\n" );
3597 output( "%s%s %s%s:", obj_dir_path( make, testmodule ), ext, obj_dir_path( make, stripped ), ext );
3598 output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files );
3599 output_filenames_obj_dir( make, make->res_files );
3600 output_filenames( dep_libs );
3601 output_filename( tools_path( make, "winebuild" ));
3602 output_filename( tools_path( make, "winegcc" ));
3603 output( "\n" );
3605 output( "programs/winetest/%s: %s%s\n", testres, obj_dir_path( make, stripped ), ext );
3606 output( "\t%secho \"%s TESTRES \\\"%s%s\\\"\" | %s -u -o $@\n", cmd_prefix( "WRC" ),
3607 testmodule, obj_dir_path( make, stripped ), ext, tools_path( make, "wrc" ));
3609 output_filenames_obj_dir( make, make->ok_files );
3610 output( ": %s%s", obj_dir_path( make, testmodule ), ext );
3611 if (parent)
3613 output_filename( parent->is_cross ? obj_dir_path( parent, make->testdll )
3614 : strmake( "%s%s", obj_dir_path( parent, make->testdll ), dll_ext ));
3615 if (parent->unixobj_files.count)
3617 char *ext, *unix_lib = xstrdup( parent->module );
3618 if ((ext = get_extension( unix_lib ))) *ext = 0;
3619 output_filename( strmake( "%s%s", obj_dir_path( parent, unix_lib ), dll_ext ));
3622 output( "\n" );
3623 output( "%s %s:", obj_dir_path( make, "check" ), obj_dir_path( make, "test" ));
3624 if (!make->disabled && parent && !parent->disabled) output_filenames_obj_dir( make, make->ok_files );
3625 output( "\n" );
3626 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "check" ));
3627 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "test" ));
3628 output( "%s::\n", obj_dir_path( make, "testclean" ));
3629 output( "\trm -f" );
3630 output_filenames_obj_dir( make, make->ok_files );
3631 output( "\n" );
3632 strarray_addall( &make->clean_files, make->ok_files );
3633 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "testclean" ));
3637 /*******************************************************************
3638 * output_programs
3640 static void output_programs( struct makefile *make )
3642 unsigned int i, j;
3644 for (i = 0; i < make->programs.count; i++)
3646 char *program_installed = NULL;
3647 char *program = strmake( "%s%s", make->programs.str[i], exe_ext );
3648 struct strarray deps = get_local_dependencies( make, make->programs.str[i], make->in_files );
3649 struct strarray all_libs = get_expanded_file_local_var( make, make->programs.str[i], "LDFLAGS" );
3650 struct strarray objs = get_expanded_file_local_var( make, make->programs.str[i], "OBJS" );
3651 struct strarray symlinks = get_expanded_file_local_var( make, make->programs.str[i], "SYMLINKS" );
3653 if (!objs.count) objs = make->object_files;
3654 if (!strarray_exists( &all_libs, "-nodefaultlibs" ))
3655 strarray_addall( &all_libs, add_unix_libraries( make, &deps ));
3657 output( "%s:", obj_dir_path( make, program ) );
3658 output_filenames_obj_dir( make, objs );
3659 output_filenames( deps );
3660 output( "\n" );
3661 output( "\t%s$(CC) -o $@", cmd_prefix( "CC" ));
3662 output_filenames_obj_dir( make, objs );
3663 output_filenames( all_libs );
3664 output_filename( "$(LDFLAGS)" );
3665 output( "\n" );
3666 strarray_add( &make->all_targets, program );
3668 for (j = 0; j < symlinks.count; j++)
3670 output( "%s: %s\n", obj_dir_path( make, symlinks.str[j] ), obj_dir_path( make, program ));
3671 output_symlink_rule( program, obj_dir_path( make, symlinks.str[j] ), 0 );
3673 strarray_addall( &make->all_targets, symlinks );
3675 add_install_rule( make, program, program_installed ? program_installed : program,
3676 strmake( "p$(bindir)/%s", program ));
3677 for (j = 0; j < symlinks.count; j++)
3678 add_install_rule( make, symlinks.str[j], program,
3679 strmake( "y$(bindir)/%s%s", symlinks.str[j], exe_ext ));
3684 /*******************************************************************
3685 * output_subdirs
3687 static void output_subdirs( struct makefile *make )
3689 struct strarray all_targets = empty_strarray;
3690 struct strarray makefile_deps = empty_strarray;
3691 struct strarray clean_files = empty_strarray;
3692 struct strarray testclean_files = empty_strarray;
3693 struct strarray distclean_files = empty_strarray;
3694 struct strarray dependencies = empty_strarray;
3695 struct strarray install_lib_deps = empty_strarray;
3696 struct strarray install_dev_deps = empty_strarray;
3697 struct strarray tooldeps_deps = empty_strarray;
3698 struct strarray buildtest_deps = empty_strarray;
3699 unsigned int i;
3701 strarray_addall( &clean_files, make->clean_files );
3702 strarray_addall( &distclean_files, make->distclean_files );
3703 strarray_addall( &all_targets, make->all_targets );
3704 for (i = 0; i < subdirs.count; i++)
3706 strarray_add( &makefile_deps, src_dir_path( submakes[i], strmake ( "%s.in", output_makefile_name )));
3707 strarray_addall_uniq( &make->phony_targets, submakes[i]->phony_targets );
3708 strarray_addall_uniq( &make->uninstall_files, submakes[i]->uninstall_files );
3709 strarray_addall_uniq( &dependencies, submakes[i]->dependencies );
3710 strarray_addall_path( &clean_files, submakes[i]->obj_dir, submakes[i]->clean_files );
3711 strarray_addall_path( &distclean_files, submakes[i]->obj_dir, submakes[i]->distclean_files );
3712 strarray_addall_path( &testclean_files, submakes[i]->obj_dir, submakes[i]->ok_files );
3713 strarray_addall_path( &make->pot_files, submakes[i]->obj_dir, submakes[i]->pot_files );
3715 if (submakes[i]->disabled) continue;
3717 strarray_addall_path( &all_targets, submakes[i]->obj_dir, submakes[i]->all_targets );
3718 if (!strcmp( submakes[i]->obj_dir, "tools" ) || !strncmp( submakes[i]->obj_dir, "tools/", 6 ))
3719 strarray_add( &tooldeps_deps, obj_dir_path( submakes[i], "all" ));
3720 if (submakes[i]->testdll)
3721 strarray_add( &buildtest_deps, obj_dir_path( submakes[i], "all" ));
3722 if (submakes[i]->install_rules[INSTALL_LIB].count)
3723 strarray_add( &install_lib_deps, obj_dir_path( submakes[i], "install-lib" ));
3724 if (submakes[i]->install_rules[INSTALL_DEV].count)
3725 strarray_add( &install_dev_deps, obj_dir_path( submakes[i], "install-dev" ));
3727 strarray_addall( &dependencies, makefile_deps );
3728 output( "all:" );
3729 output_filenames( all_targets );
3730 output( "\n" );
3731 output( "Makefile:" );
3732 output_filenames( makefile_deps );
3733 output( "\n" );
3734 output_filenames( dependencies );
3735 output( ":\n" );
3736 if (install_lib_deps.count)
3738 output( "install install-lib::" );
3739 output_filenames( install_lib_deps );
3740 output( "\n" );
3741 strarray_add_uniq( &make->phony_targets, "install" );
3742 strarray_add_uniq( &make->phony_targets, "install-lib" );
3744 if (install_dev_deps.count)
3746 output( "install install-dev::" );
3747 output_filenames( install_dev_deps );
3748 output( "\n" );
3749 strarray_add_uniq( &make->phony_targets, "install" );
3750 strarray_add_uniq( &make->phony_targets, "install-dev" );
3752 output_uninstall_rules( make );
3753 if (buildtest_deps.count)
3755 output( "buildtests:" );
3756 output_filenames( buildtest_deps );
3757 output( "\n" );
3758 strarray_add_uniq( &make->phony_targets, "buildtests" );
3760 output( "check test:" );
3761 output_filenames( testclean_files );
3762 output( "\n" );
3763 strarray_add_uniq( &make->phony_targets, "check" );
3764 strarray_add_uniq( &make->phony_targets, "test" );
3766 output( "clean::\n");
3767 output_rm_filenames( clean_files );
3768 output( "testclean::\n");
3769 output_rm_filenames( testclean_files );
3770 output( "distclean::\n");
3771 output_rm_filenames( distclean_files );
3772 strarray_add_uniq( &make->phony_targets, "distclean" );
3773 strarray_add_uniq( &make->phony_targets, "testclean" );
3775 if (tooldeps_deps.count)
3777 output( "__tooldeps__:" );
3778 output_filenames( tooldeps_deps );
3779 output( "\n" );
3780 strarray_add_uniq( &make->phony_targets, "__tooldeps__" );
3783 if (get_expanded_make_variable( make, "GETTEXTPO_LIBS" )) output_po_files( make );
3785 if (make->phony_targets.count)
3787 output( ".PHONY:" );
3788 output_filenames( make->phony_targets );
3789 output( "\n" );
3794 /*******************************************************************
3795 * output_sources
3797 static void output_sources( struct makefile *make )
3799 struct strarray all_targets = empty_strarray;
3800 struct incl_file *source;
3801 unsigned int i, j;
3803 strarray_add_uniq( &make->phony_targets, "all" );
3805 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
3807 char *obj = xstrdup( source->name );
3808 char *ext = get_extension( obj );
3810 if (!ext) fatal_error( "unsupported file type %s\n", source->name );
3811 *ext++ = 0;
3813 for (j = 0; output_source_funcs[j].ext; j++)
3814 if (!strcmp( ext, output_source_funcs[j].ext )) break;
3816 output_source_funcs[j].fn( make, source, obj );
3817 strarray_addall_uniq( &make->dependencies, source->dependencies );
3820 /* special case for winetest: add resource files from other test dirs */
3821 if (make->obj_dir && !strcmp( make->obj_dir, "programs/winetest" ))
3823 struct strarray tests = enable_tests;
3824 if (!tests.count)
3825 for (i = 0; i < subdirs.count; i++)
3826 if (submakes[i]->testdll && !submakes[i]->disabled)
3827 strarray_add( &tests, submakes[i]->testdll );
3828 for (i = 0; i < tests.count; i++)
3829 strarray_add( &make->res_files, replace_extension( tests.str[i], ".dll", "_test.res" ));
3832 if (make->dlldata_files.count)
3834 output( "%s: %s %s\n", obj_dir_path( make, "dlldata.c" ),
3835 tools_path( make, "widl" ), src_dir_path( make, "Makefile.in" ));
3836 output( "\t%s%s --dlldata-only -o $@", cmd_prefix( "WIDL" ), tools_path( make, "widl" ));
3837 output_filenames( make->dlldata_files );
3838 output( "\n" );
3841 if (make->staticlib) output_static_lib( make );
3842 else if (make->module) output_module( make );
3843 else if (make->testdll) output_test_module( make );
3844 else if (make->sharedlib) output_shared_lib( make );
3845 else if (make->programs.count) output_programs( make );
3847 for (i = 0; i < make->scripts.count; i++)
3848 add_install_rule( make, make->scripts.str[i], make->scripts.str[i],
3849 strmake( "S$(bindir)/%s", make->scripts.str[i] ));
3851 for (i = 0; i < make->extra_targets.count; i++)
3852 if (strarray_exists( &make->dependencies, obj_dir_path( make, make->extra_targets.str[i] )))
3853 strarray_add( &make->clean_files, make->extra_targets.str[i] );
3854 else
3855 strarray_add( &make->all_targets, make->extra_targets.str[i] );
3857 if (!make->src_dir) strarray_add( &make->distclean_files, ".gitignore" );
3858 strarray_add( &make->distclean_files, "Makefile" );
3859 if (make->testdll) strarray_add( &make->distclean_files, "testlist.c" );
3861 if (!make->obj_dir)
3862 strarray_addall( &make->distclean_files, get_expanded_make_var_array( make, "CONFIGURE_TARGETS" ));
3863 else if (!strcmp( make->obj_dir, "po" ))
3864 strarray_add( &make->distclean_files, "LINGUAS" );
3866 strarray_addall( &make->clean_files, make->object_files );
3867 strarray_addall( &make->clean_files, make->crossobj_files );
3868 strarray_addall( &make->clean_files, make->unixobj_files );
3869 strarray_addall( &make->clean_files, make->res_files );
3870 strarray_addall( &make->clean_files, make->pot_files );
3871 strarray_addall( &make->clean_files, make->debug_files );
3872 strarray_addall( &make->clean_files, make->all_targets );
3874 if (make == top_makefile)
3876 output_subdirs( make );
3877 return;
3880 strarray_addall( &all_targets, make->all_targets );
3881 strarray_addall( &all_targets, make->font_files );
3882 if (all_targets.count)
3884 output( "%s:", obj_dir_path( make, "all" ));
3885 output_filenames_obj_dir( make, all_targets );
3886 output( "\n" );
3887 strarray_add_uniq( &make->phony_targets, obj_dir_path( make, "all" ));
3889 output_install_rules( make, INSTALL_LIB, "install-lib" );
3890 output_install_rules( make, INSTALL_DEV, "install-dev" );
3892 if (make->clean_files.count)
3894 output( "%s::\n", obj_dir_path( make, "clean" ));
3895 output( "\trm -f" );
3896 output_filenames_obj_dir( make, make->clean_files );
3897 output( "\n" );
3898 strarray_add( &make->phony_targets, obj_dir_path( make, "clean" ));
3903 /*******************************************************************
3904 * create_temp_file
3906 static FILE *create_temp_file( const char *orig )
3908 char *name = xmalloc( strlen(orig) + 13 );
3909 unsigned int i, id = getpid();
3910 int fd;
3911 FILE *ret = NULL;
3913 for (i = 0; i < 100; i++)
3915 sprintf( name, "%s.tmp%08x", orig, id );
3916 if ((fd = open( name, O_RDWR | O_CREAT | O_EXCL, 0666 )) != -1)
3918 ret = fdopen( fd, "w" );
3919 break;
3921 if (errno != EEXIST) break;
3922 id += 7777;
3924 if (!ret) fatal_error( "failed to create output file for '%s'\n", orig );
3925 temp_file_name = name;
3926 return ret;
3930 /*******************************************************************
3931 * rename_temp_file
3933 static void rename_temp_file( const char *dest )
3935 int ret = rename( temp_file_name, dest );
3936 if (ret == -1 && errno == EEXIST)
3938 /* rename doesn't overwrite on windows */
3939 unlink( dest );
3940 ret = rename( temp_file_name, dest );
3942 if (ret == -1) fatal_error( "failed to rename output file to '%s'\n", dest );
3943 temp_file_name = NULL;
3947 /*******************************************************************
3948 * are_files_identical
3950 static int are_files_identical( FILE *file1, FILE *file2 )
3952 for (;;)
3954 char buffer1[8192], buffer2[8192];
3955 int size1 = fread( buffer1, 1, sizeof(buffer1), file1 );
3956 int size2 = fread( buffer2, 1, sizeof(buffer2), file2 );
3957 if (size1 != size2) return 0;
3958 if (!size1) return feof( file1 ) && feof( file2 );
3959 if (memcmp( buffer1, buffer2, size1 )) return 0;
3964 /*******************************************************************
3965 * rename_temp_file_if_changed
3967 static void rename_temp_file_if_changed( const char *dest )
3969 FILE *file1, *file2;
3970 int do_rename = 1;
3972 if ((file1 = fopen( dest, "r" )))
3974 if ((file2 = fopen( temp_file_name, "r" )))
3976 do_rename = !are_files_identical( file1, file2 );
3977 fclose( file2 );
3979 fclose( file1 );
3981 if (!do_rename)
3983 unlink( temp_file_name );
3984 temp_file_name = NULL;
3986 else rename_temp_file( dest );
3990 /*******************************************************************
3991 * output_linguas
3993 static void output_linguas( const struct makefile *make )
3995 const char *dest = obj_dir_path( make, "LINGUAS" );
3996 struct incl_file *source;
3998 output_file = create_temp_file( dest );
4000 output( "# Automatically generated by make depend; DO NOT EDIT!!\n" );
4001 LIST_FOR_EACH_ENTRY( source, &make->sources, struct incl_file, entry )
4002 if (strendswith( source->name, ".po" ))
4003 output( "%s\n", replace_extension( source->name, ".po", "" ));
4005 if (fclose( output_file )) fatal_perror( "write" );
4006 output_file = NULL;
4007 rename_temp_file_if_changed( dest );
4011 /*******************************************************************
4012 * output_testlist
4014 static void output_testlist( const struct makefile *make )
4016 const char *dest = obj_dir_path( make, "testlist.c" );
4017 struct strarray files = empty_strarray;
4018 unsigned int i;
4020 for (i = 0; i < make->ok_files.count; i++)
4021 strarray_add( &files, replace_extension( make->ok_files.str[i], ".ok", "" ));
4023 output_file = create_temp_file( dest );
4025 output( "/* Automatically generated by make depend; DO NOT EDIT!! */\n\n" );
4026 output( "#define WIN32_LEAN_AND_MEAN\n" );
4027 output( "#include <windows.h>\n\n" );
4028 output( "#define STANDALONE\n" );
4029 output( "#include \"wine/test.h\"\n\n" );
4031 for (i = 0; i < files.count; i++) output( "extern void func_%s(void);\n", files.str[i] );
4032 output( "\n" );
4033 output( "const struct test winetest_testlist[] =\n" );
4034 output( "{\n" );
4035 for (i = 0; i < files.count; i++) output( " { \"%s\", func_%s },\n", files.str[i], files.str[i] );
4036 output( " { 0, 0 }\n" );
4037 output( "};\n" );
4039 if (fclose( output_file )) fatal_perror( "write" );
4040 output_file = NULL;
4041 rename_temp_file_if_changed( dest );
4045 /*******************************************************************
4046 * output_gitignore
4048 static void output_gitignore( const char *dest, struct strarray files )
4050 int i;
4052 output_file = create_temp_file( dest );
4054 output( "# Automatically generated by make depend; DO NOT EDIT!!\n" );
4055 for (i = 0; i < files.count; i++)
4057 if (!strchr( files.str[i], '/' )) output( "/" );
4058 output( "%s\n", files.str[i] );
4061 if (fclose( output_file )) fatal_perror( "write" );
4062 output_file = NULL;
4063 rename_temp_file( dest );
4067 /*******************************************************************
4068 * output_stub_makefile
4070 static void output_stub_makefile( struct makefile *make )
4072 struct strarray targets = empty_strarray;
4073 const char *make_var = strarray_get_value( &top_makefile->vars, "MAKE" );
4075 if (make_var) output( "MAKE = %s\n\n", make_var );
4076 output( "all:\n" );
4078 if (make->all_targets.count) strarray_add( &targets, "all" );
4079 if (make->install_rules[INSTALL_LIB].count || make->install_rules[INSTALL_DEV].count)
4080 strarray_add( &targets, "install" );
4081 if (make->install_rules[INSTALL_LIB].count) strarray_add( &targets, "install-lib" );
4082 if (make->install_rules[INSTALL_DEV].count) strarray_add( &targets, "install-dev" );
4083 if (make->clean_files.count) strarray_add( &targets, "clean" );
4084 if (make->ok_files.count)
4086 strarray_add( &targets, "check" );
4087 strarray_add( &targets, "test" );
4088 strarray_add( &targets, "testclean" );
4091 output_filenames( targets );
4092 output_filenames( make->clean_files );
4093 output( ":\n" );
4094 output( "\t@cd %s && $(MAKE) %s/$@\n", get_relative_path( make->obj_dir, "" ), make->obj_dir );
4095 output( ".PHONY:" );
4096 output_filenames( targets );
4097 output( "\n" );
4101 /*******************************************************************
4102 * output_silent_rules
4104 static void output_silent_rules(void)
4106 static const char *cmds[] =
4108 "AR",
4109 "BISON",
4110 "BUILD",
4111 "CC",
4112 "CCLD",
4113 "FLEX",
4114 "GEN",
4115 "LN",
4116 "MSG",
4117 "SED",
4118 "TEST",
4119 "WIDL",
4120 "WMC",
4121 "WRC"
4123 unsigned int i;
4125 output( "V = 0\n" );
4126 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++)
4128 output( "quiet_%s = $(quiet_%s_$(V))\n", cmds[i], cmds[i] );
4129 output( "quiet_%s_0 = @echo \" %-5s \" $@;\n", cmds[i], cmds[i] );
4130 output( "quiet_%s_1 =\n", cmds[i] );
4135 /*******************************************************************
4136 * output_dependencies
4138 static void output_dependencies( struct makefile *make )
4140 struct strarray ignore_files = empty_strarray;
4141 char buffer[1024];
4142 FILE *src_file;
4143 int i, found = 0;
4145 if (make->obj_dir) create_dir( make->obj_dir );
4147 output_file_name = obj_dir_path( make, output_makefile_name );
4148 output_file = create_temp_file( output_file_name );
4150 /* copy the contents of the source makefile */
4151 src_file = open_input_makefile( make );
4152 while (fgets( buffer, sizeof(buffer), src_file ) && !found)
4154 if (fwrite( buffer, 1, strlen(buffer), output_file ) != strlen(buffer)) fatal_perror( "write" );
4155 found = !strncmp( buffer, separator, strlen(separator) );
4157 if (fclose( src_file )) fatal_perror( "close" );
4158 input_file_name = NULL;
4160 if (!found) output( "\n%s (everything below this line is auto-generated; DO NOT EDIT!!)\n", separator );
4162 if (make == top_makefile)
4164 if (silent_rules) output_silent_rules();
4165 for (i = 0; i < subdirs.count; i++) output_sources( submakes[i] );
4166 output_sources( make );
4168 else output_stub_makefile( make );
4170 /* disable implicit rules */
4171 output( ".SUFFIXES:\n" );
4173 fclose( output_file );
4174 output_file = NULL;
4175 rename_temp_file( output_file_name );
4177 strarray_addall( &ignore_files, make->distclean_files );
4178 strarray_addall( &ignore_files, make->clean_files );
4179 if (make->testdll) output_testlist( make );
4180 if (make->obj_dir && !strcmp( make->obj_dir, "po" )) output_linguas( make );
4181 if (!make->src_dir) output_gitignore( obj_dir_path( make, ".gitignore" ), ignore_files );
4183 create_file_directories( make, ignore_files );
4185 output_file_name = NULL;
4189 /*******************************************************************
4190 * load_sources
4192 static void load_sources( struct makefile *make )
4194 static const char *source_vars[] =
4196 "SOURCES",
4197 "C_SRCS",
4198 "OBJC_SRCS",
4199 "RC_SRCS",
4200 "MC_SRCS",
4201 "IDL_SRCS",
4202 "BISON_SRCS",
4203 "LEX_SRCS",
4204 "HEADER_SRCS",
4205 "XTEMPLATE_SRCS",
4206 "SVG_SRCS",
4207 "FONT_SRCS",
4208 "IN_SRCS",
4209 "PO_SRCS",
4210 "MANPAGES",
4211 NULL
4213 const char **var;
4214 unsigned int i;
4215 struct strarray value;
4216 struct incl_file *file;
4218 strarray_set_value( &make->vars, "top_srcdir", root_src_dir_path( "" ));
4219 strarray_set_value( &make->vars, "srcdir", src_dir_path( make, "" ));
4221 make->parent_dir = get_expanded_make_variable( make, "PARENTSRC" );
4222 make->module = get_expanded_make_variable( make, "MODULE" );
4223 make->testdll = get_expanded_make_variable( make, "TESTDLL" );
4224 make->sharedlib = get_expanded_make_variable( make, "SHAREDLIB" );
4225 make->staticlib = get_expanded_make_variable( make, "STATICLIB" );
4226 make->importlib = get_expanded_make_variable( make, "IMPORTLIB" );
4228 make->programs = get_expanded_make_var_array( make, "PROGRAMS" );
4229 make->scripts = get_expanded_make_var_array( make, "SCRIPTS" );
4230 make->imports = get_expanded_make_var_array( make, "IMPORTS" );
4231 make->delayimports = get_expanded_make_var_array( make, "DELAYIMPORTS" );
4232 make->extradllflags = get_expanded_make_var_array( make, "EXTRADLLFLAGS" );
4233 make->install_lib = get_expanded_make_var_array( make, "INSTALL_LIB" );
4234 make->install_dev = get_expanded_make_var_array( make, "INSTALL_DEV" );
4235 make->extra_targets = get_expanded_make_var_array( make, "EXTRA_TARGETS" );
4237 if (make->module && strendswith( make->module, ".a" )) make->staticlib = make->module;
4239 make->is_win16 = strarray_exists( &make->extradllflags, "-m16" );
4240 if ((make->module && make->staticlib) || make->testdll || make->is_win16)
4241 strarray_add_uniq( &make->extradllflags, "-mno-cygwin" );
4243 strarray_addall( &make->extradllflags, get_expanded_make_var_array( make, "APPMODE" ));
4244 make->disabled = make->obj_dir && strarray_exists( &disabled_dirs, make->obj_dir );
4245 make->use_msvcrt = strarray_exists( &make->extradllflags, "-mno-cygwin" );
4246 make->is_exe = strarray_exists( &make->extradllflags, "-mconsole" ) ||
4247 strarray_exists( &make->extradllflags, "-mwindows" );
4249 if (make->module && !make->install_lib.count && !make->install_dev.count)
4251 if (make->importlib) strarray_add( &make->install_dev, make->importlib );
4252 if (make->staticlib) strarray_add( &make->install_dev, make->staticlib );
4253 else strarray_add( &make->install_lib, make->module );
4256 make->include_paths = empty_strarray;
4257 make->include_args = empty_strarray;
4258 make->define_args = empty_strarray;
4259 strarray_add( &make->define_args, "-D__WINESRC__" );
4261 value = get_expanded_make_var_array( make, "EXTRAINCL" );
4262 for (i = 0; i < value.count; i++)
4263 if (!strncmp( value.str[i], "-I", 2 ))
4264 strarray_add_uniq( &make->include_paths, value.str[i] + 2 );
4265 else
4266 strarray_add_uniq( &make->define_args, value.str[i] );
4267 strarray_addall( &make->define_args, get_expanded_make_var_array( make, "EXTRADEFS" ));
4269 strarray_add( &make->include_args, strmake( "-I%s", obj_dir_path( make, "" )));
4270 if (make->src_dir)
4271 strarray_add( &make->include_args, strmake( "-I%s", make->src_dir ));
4272 if (make->parent_dir)
4273 strarray_add( &make->include_args, strmake( "-I%s", src_dir_path( make, make->parent_dir )));
4274 strarray_add( &make->include_args, "-Iinclude" );
4275 if (root_src_dir) strarray_add( &make->include_args, strmake( "-I%s", root_src_dir_path( "include" )));
4277 list_init( &make->sources );
4278 list_init( &make->includes );
4280 for (var = source_vars; *var; var++)
4282 value = get_expanded_make_var_array( make, *var );
4283 for (i = 0; i < value.count; i++) add_src_file( make, value.str[i] );
4286 add_generated_sources( make );
4288 if (!make->use_msvcrt && !has_object_file( make ))
4290 strarray_add( &make->extradllflags, "-mno-cygwin" );
4291 make->use_msvcrt = 1;
4294 if (make->use_msvcrt) add_crt_import( make, &make->imports, &make->define_args );
4296 LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry ) parse_file( make, file, 0 );
4297 LIST_FOR_EACH_ENTRY( file, &make->sources, struct incl_file, entry ) get_dependencies( file, file );
4299 make->is_cross = crosstarget && make->use_msvcrt;
4301 if (make->is_cross)
4303 strarray_addall_uniq( &cross_import_libs, make->imports );
4304 strarray_addall_uniq( &cross_import_libs, make->extra_imports );
4305 if (make->is_win16) strarray_add_uniq( &cross_import_libs, "kernel" );
4306 strarray_add_uniq( &cross_import_libs, "winecrt0" );
4307 strarray_add_uniq( &cross_import_libs, "kernel32" );
4308 strarray_add_uniq( &cross_import_libs, "ntdll" );
4311 if (!*dll_ext || make->is_cross)
4312 for (i = 0; i < make->delayimports.count; i++)
4313 strarray_add_uniq( &delay_import_libs, get_base_name( make->delayimports.str[i] ));
4317 /*******************************************************************
4318 * parse_makeflags
4320 static void parse_makeflags( const char *flags )
4322 const char *p = flags;
4323 char *var, *buffer = xmalloc( strlen(flags) + 1 );
4325 while (*p)
4327 while (isspace(*p)) p++;
4328 var = buffer;
4329 while (*p && !isspace(*p))
4331 if (*p == '\\' && p[1]) p++;
4332 *var++ = *p++;
4334 *var = 0;
4335 if (var > buffer) set_make_variable( &cmdline_vars, buffer );
4340 /*******************************************************************
4341 * parse_option
4343 static int parse_option( const char *opt )
4345 if (opt[0] != '-')
4347 if (strchr( opt, '=' )) return set_make_variable( &cmdline_vars, opt );
4348 return 0;
4350 switch(opt[1])
4352 case 'f':
4353 if (opt[2]) output_makefile_name = opt + 2;
4354 break;
4355 case 'R':
4356 relative_dir_mode = 1;
4357 break;
4358 case 'S':
4359 silent_rules = 1;
4360 break;
4361 default:
4362 fprintf( stderr, "Unknown option '%s'\n%s", opt, Usage );
4363 exit(1);
4365 return 1;
4369 /*******************************************************************
4370 * main
4372 int main( int argc, char *argv[] )
4374 const char *makeflags = getenv( "MAKEFLAGS" );
4375 int i, j;
4377 if (makeflags) parse_makeflags( makeflags );
4379 i = 1;
4380 while (i < argc)
4382 if (parse_option( argv[i] ))
4384 for (j = i; j < argc; j++) argv[j] = argv[j+1];
4385 argc--;
4387 else i++;
4390 if (relative_dir_mode)
4392 char *relpath;
4394 if (argc != 3)
4396 fprintf( stderr, "Option -R needs two directories\n%s", Usage );
4397 exit( 1 );
4399 relpath = get_relative_path( argv[1], argv[2] );
4400 printf( "%s\n", relpath ? relpath : "." );
4401 exit( 0 );
4404 if (argc > 1) fatal_error( "Directory arguments not supported in this mode\n" );
4406 atexit( cleanup_files );
4407 signal( SIGTERM, exit_on_signal );
4408 signal( SIGINT, exit_on_signal );
4409 #ifdef SIGHUP
4410 signal( SIGHUP, exit_on_signal );
4411 #endif
4413 for (i = 0; i < HASH_SIZE; i++) list_init( &files[i] );
4415 top_makefile = parse_makefile( NULL );
4417 target_flags = get_expanded_make_var_array( top_makefile, "TARGETFLAGS" );
4418 msvcrt_flags = get_expanded_make_var_array( top_makefile, "MSVCRTFLAGS" );
4419 dll_flags = get_expanded_make_var_array( top_makefile, "DLLFLAGS" );
4420 extra_cflags = get_expanded_make_var_array( top_makefile, "EXTRACFLAGS" );
4421 extra_cross_cflags = get_expanded_make_var_array( top_makefile, "EXTRACROSSCFLAGS" );
4422 cpp_flags = get_expanded_make_var_array( top_makefile, "CPPFLAGS" );
4423 lddll_flags = get_expanded_make_var_array( top_makefile, "LDDLLFLAGS" );
4424 libs = get_expanded_make_var_array( top_makefile, "LIBS" );
4425 enable_tests = get_expanded_make_var_array( top_makefile, "ENABLE_TESTS" );
4426 delay_load_flag = get_expanded_make_variable( top_makefile, "DELAYLOADFLAG" );
4427 top_install_lib = get_expanded_make_var_array( top_makefile, "TOP_INSTALL_LIB" );
4428 top_install_dev = get_expanded_make_var_array( top_makefile, "TOP_INSTALL_DEV" );
4430 root_src_dir = get_expanded_make_variable( top_makefile, "srcdir" );
4431 tools_dir = get_expanded_make_variable( top_makefile, "TOOLSDIR" );
4432 tools_ext = get_expanded_make_variable( top_makefile, "TOOLSEXT" );
4433 exe_ext = get_expanded_make_variable( top_makefile, "EXEEXT" );
4434 man_ext = get_expanded_make_variable( top_makefile, "api_manext" );
4435 dll_ext = (exe_ext && !strcmp( exe_ext, ".exe" )) ? "" : ".so";
4436 crosstarget = get_expanded_make_variable( top_makefile, "CROSSTARGET" );
4437 crossdebug = get_expanded_make_variable( top_makefile, "CROSSDEBUG" );
4438 fontforge = get_expanded_make_variable( top_makefile, "FONTFORGE" );
4439 convert = get_expanded_make_variable( top_makefile, "CONVERT" );
4440 flex = get_expanded_make_variable( top_makefile, "FLEX" );
4441 bison = get_expanded_make_variable( top_makefile, "BISON" );
4442 ar = get_expanded_make_variable( top_makefile, "AR" );
4443 ranlib = get_expanded_make_variable( top_makefile, "RANLIB" );
4444 rsvg = get_expanded_make_variable( top_makefile, "RSVG" );
4445 icotool = get_expanded_make_variable( top_makefile, "ICOTOOL" );
4446 dlltool = get_expanded_make_variable( top_makefile, "DLLTOOL" );
4447 msgfmt = get_expanded_make_variable( top_makefile, "MSGFMT" );
4448 sed_cmd = get_expanded_make_variable( top_makefile, "SED_CMD" );
4449 ln_s = get_expanded_make_variable( top_makefile, "LN_S" );
4451 if (root_src_dir && !strcmp( root_src_dir, "." )) root_src_dir = NULL;
4452 if (tools_dir && !strcmp( tools_dir, "." )) tools_dir = NULL;
4453 if (!exe_ext) exe_ext = "";
4454 if (!tools_ext) tools_ext = "";
4455 if (!man_ext) man_ext = "3w";
4457 top_makefile->src_dir = root_src_dir;
4458 subdirs = get_expanded_make_var_array( top_makefile, "SUBDIRS" );
4459 disabled_dirs = get_expanded_make_var_array( top_makefile, "DISABLED_SUBDIRS" );
4460 submakes = xmalloc( subdirs.count * sizeof(*submakes) );
4462 for (i = 0; i < subdirs.count; i++) submakes[i] = parse_makefile( subdirs.str[i] );
4464 load_sources( top_makefile );
4465 for (i = 0; i < subdirs.count; i++) load_sources( submakes[i] );
4467 output_dependencies( top_makefile );
4468 for (i = 0; i < subdirs.count; i++) output_dependencies( submakes[i] );
4470 return 0;