msvcrt: Fix write() behaviour on "no console" file descriptors.
[wine.git] / tools / make_makefiles
blob8411ecb5670db84e6408e2c76d1fb273ee195c15
1 #!/usr/bin/perl -w
3 # Build the auto-generated parts of the Wine makefiles.
5 # Copyright 2006 Alexandre Julliard
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 use strict;
24 # Dlls and programs that are 16-bit specific
25 my %modules16 =
27 "ifsmgr.vxd" => 1,
28 "mmdevldr.vxd" => 1,
29 "monodebg.vxd" => 1,
30 "vdhcp.vxd" => 1,
31 "vmm.vxd" => 1,
32 "vnbt.vxd" => 1,
33 "vnetbios.vxd" => 1,
34 "vtdapi.vxd" => 1,
35 "vwin32.vxd" => 1,
36 "w32skrnl.dll" => 1,
37 "winevdm.exe" => 1,
38 "wow32.dll" => 1,
41 my %exported_wine_headers = (
42 "wine/debug.h" => 1,
43 "wine/exception.h" => 1,
44 "wine/library.h" => 1,
45 "wine/unicode.h" => 1,
46 "wine/itss.idl" => 1,
47 "wine/svcctl.idl" => 1,
50 my %ignored_source_files = (
51 "dlls/wineps.drv/afm2c.c" => 1,
52 "dlls/wineps.drv/mkagl.c" => 1,
53 "include/config.h.in" => 1,
54 "include/stamp-h.in" => 1,
55 "programs/winetest/dist.rc" => 1,
56 "tools/makedep.c" => 1,
59 my @source_vars = (
60 "BISON_SRCS",
61 "C_SRCS",
62 "FONT_SRCS",
63 "HEADER_SRCS",
64 "IDL_SRCS",
65 "IN_SRCS",
66 "LEX_SRCS",
67 "MANPAGES",
68 "MC_SRCS",
69 "OBJC_SRCS",
70 "PO_SRCS",
71 "RC_SRCS",
72 "SVG_SRCS",
73 "XTEMPLATE_SRCS"
76 my (@makefiles, %makefiles);
78 sub dirname($)
80 my $ret = shift;
81 return "" unless $ret =~ /\//;
82 $ret =~ s!/[^/]*$!!;
83 return $ret;
86 # update a file if changed
87 sub update_file($$)
89 my $file = shift;
90 my $new = shift;
92 open FILE, ">$file.new" or die "cannot create $file.new";
93 print FILE $new;
94 close FILE;
95 rename "$file.new", "$file";
96 print "$file updated\n";
97 if ($file eq "configure.ac")
99 system "autoconf";
100 print "configure updated\n";
104 # replace some lines in a file between two markers
105 sub replace_in_file($$$@)
107 my $file = shift;
108 my $start = shift;
109 my $end = shift;
110 my ($old, $new);
112 open OLD_FILE, "$file" or die "cannot open $file";
113 while (<OLD_FILE>)
115 $old .= $_;
116 last if /$start/;
117 $new .= $_;
120 $new .= join "", @_;
122 my $skip = 1;
123 while (<OLD_FILE>)
125 $old .= $_;
126 $new .= $_ unless $skip;
127 $skip = 0 if /$end/;
130 close OLD_FILE;
131 update_file($file, $new) if $old ne $new;
134 # replace all source variables in a makefile
135 sub replace_makefile_variables($)
137 my $file = shift;
138 my $make = $makefiles{$file};
139 my $source_vars_regexp = join "|", @source_vars;
140 my %replaced;
141 my $old;
142 my $new;
144 open OLD_FILE, "$file.in" or die "cannot open $file.in";
145 while (<OLD_FILE>)
147 $old .= $_;
148 if (/^\s*($source_vars_regexp)(\s*)=/)
150 # try to preserve formatting
151 my $var = $1;
152 my $spaces = $2;
153 my $replaced = 0;
154 my @values;
156 if (defined ${$make}{"=$var"})
158 @values = @{${$make}{"=$var"}};
159 ${$make}{$var} = \@values;
161 else
163 undef ${$make}{$var};
165 my $multiline = /\\$/ || (@values > 1);
166 my $old_str = $_;
167 while (/\\$/)
169 $_ = <OLD_FILE>;
170 last unless $_;
171 $old .= $_;
172 $old_str .= $_;
174 my $new_str = "";
175 if (!@values)
177 # nothing
179 elsif ($multiline)
181 $new_str = "$var = \\\n\t" . join(" \\\n\t", sort @values) . "\n";
182 $new .= $new_str;
184 else
186 $new_str = "$var$spaces= @values\n";
187 $new .= $new_str;
189 $replaced{$var} = 1;
190 next;
192 $new .= $_;
194 foreach my $var (@source_vars)
196 next if defined $replaced{$var};
197 next unless defined ${$make}{"=$var"};
198 my @values = @{${$make}{"=$var"}};
199 next unless @values;
200 $new .= "\n$var = \\\n\t" . join(" \\\n\t", sort @values) . "\n";
202 close OLD_FILE;
203 update_file("$file.in", $new) if $old ne $new;
206 # parse the specified makefile and load the variables
207 sub parse_makefile($)
209 my $file = shift;
210 my %make;
212 ($make{"=dir"} = $file) =~ s/[^\/]+$//;
214 open MAKE, "$file.in" or die "cannot open $file.in\n";
216 while (<MAKE>)
218 chomp;
219 next if (/^\s*#/);
220 while (/\\$/) { chop; $_ .= <MAKE>; chomp; } # merge continued lines
221 next if (/^\s*$/);
223 if (/\@[A-Z_]+\@/) # config.status substitution variable
225 die "Configure substitution is not allowed in $file" unless $file eq "Makefile";
227 if (/^\s*(MODULE|IMPORTLIB|TESTDLL|PARENTSRC|APPMODE)\s*=\s*(.*)/)
229 my $var = $1;
230 $make{$var} = $2;
231 ${$make{"=flags"}}{"implib"} = 1 if $var eq "IMPORTLIB";
232 next;
234 my $source_vars_regexp = join "|", @source_vars;
235 if (/^\s*($source_vars_regexp|PROGRAMS|EXTRA_TARGETS|EXTRA_OBJS|INSTALL_LIB|INSTALL_DEV)\s*=\s*(.*)/)
237 my $var = $1;
238 my @list = split(/\s+/, $2);
239 $make{$var} = \@list;
240 next;
242 if (/(install-lib|install-dev|clean)\s*:/)
244 ${$make{"=flags"}}{$1} = 1;
245 next;
247 if (/^\s*(TOPSRCDIR|TOPOBJDIR|SRCDIR|VPATH)\s*=\s*(.*)/)
249 die "Variable $1 in $file.in is obsolete";
253 if ($file =~ /^programs\/([^\/]+)\/Makefile/)
255 my $prog = $1;
256 if (defined $make{"INSTALL_LIB"})
258 ${$make{"=flags"}}{"install"} = 1 if grep { "$prog.exe" eq $_; } @{$make{"INSTALL_LIB"}};
259 ${$make{"=flags"}}{"installbin"} = 1 if grep { $prog eq $_; } @{$make{"INSTALL_LIB"}};
261 else
263 ${$make{"=flags"}}{"install"} = 1;
267 unless (defined $make{"MODULE"})
269 ${$make{"=flags"}}{"install-lib"} = 1 if defined $make{"INSTALL_LIB"};
270 ${$make{"=flags"}}{"install-dev"} = 1 if defined $make{"INSTALL_DEV"};
272 ${$make{"=flags"}}{"clean"} = 1 if defined $make{"PROGRAMS"} || defined $make{"EXTRA_TARGETS"} || defined $make{"EXTRA_OBJS"};
274 if (defined $make{"=flags"} && defined $make{"MODULE"})
276 die "Custom install-lib rule not allowed in $file" if defined ${$make{"=flags"}}{"install-lib"};
277 die "Custom install-dev rule not allowed in $file" if defined ${$make{"=flags"}}{"install-dev"};
280 return %make;
283 # read pragma makedep flags from a source file
284 sub get_makedep_flags($)
286 my $file = shift;
287 my %flags;
289 open FILE, $file or die "cannot open $file";
290 if ($file =~ /\.sfd$/)
292 while (<FILE>)
294 next unless /^UComments:\s*\"(.*)\"$/;
295 foreach my $pragma (split /\+AAoA/, $1)
297 next unless $pragma =~ /^#\s*pragma\s+makedep\s+(.*)/;
298 foreach my $flag (split /\s+/, $1)
300 $flags{$flag} = 1;
301 last if $flag eq "font";
306 else
308 while (<FILE>)
310 next unless /^#\s*pragma\s+makedep\s+(.*)/;
311 foreach my $flag (split /\s+/, $1)
313 last if $flag eq "depend";
314 $flags{$flag} = 1;
318 close FILE;
319 return %flags;
322 sub get_parent_makefile($)
324 my $file = shift;
325 my %make = %{$makefiles{$file}};
326 my $reldir = $make{"PARENTSRC"} || "";
327 return "" unless $reldir;
328 (my $path = $file) =~ s/\/Makefile$/\//;
329 while ($reldir =~ /^\.\.\//)
331 $reldir =~ s/^\.\.\///;
332 $path =~ s/[^\/]+\/$//;
334 return "$path$reldir/Makefile";
337 # preserve shared source files that are listed in the existing makefile
338 sub preserve_shared_source_files($$$)
340 my ($make, $parent, $var) = @_;
341 my %srcs;
343 return unless defined ${$parent}{"=$var"};
344 foreach my $file (@{${$parent}{"=$var"}}) { $srcs{$file} = 1; }
345 foreach my $file (@{${$make}{"=$var"}}) { $srcs{$file} = 0; }
347 foreach my $file (@{${$make}{$var}})
349 next unless defined $srcs{$file} && $srcs{$file} == 1;
350 push @{${$make}{"=$var"}}, $file;
354 # assign source files to their respective makefile
355 sub assign_sources_to_makefiles(@)
357 foreach my $file (@_)
359 next if defined $ignored_source_files{$file};
360 next if $file =~ /Makefile\.in$/;
361 my $dir = dirname( $file );
362 my $subdir = $dir;
364 while ($dir && !defined $makefiles{"$dir/Makefile"}) { $dir = dirname( $dir ); }
365 $subdir =~ s/^$dir\/?//;
366 next unless $dir;
368 die "no makefile found for $file\n" unless defined $makefiles{"$dir/Makefile"};
370 my $make = $makefiles{"$dir/Makefile"};
371 my $name = substr( $file, length($dir) + 1 );
372 my %flags = get_makedep_flags( $file );
374 next if $file =~ /^include\/wine\// && !%flags && !$exported_wine_headers{$name};
376 ${$make}{"=flags"}{"clean"} = 1 if $subdir;
378 if ($name =~ /\.m$/) { push @{${$make}{"=OBJC_SRCS"}}, $name; }
379 elsif ($name =~ /\.l$/) { push @{${$make}{"=LEX_SRCS"}}, $name; }
380 elsif ($name =~ /\.y$/) { push @{${$make}{"=BISON_SRCS"}}, $name; }
381 elsif ($name =~ /\.x$/) { push @{${$make}{"=XTEMPLATE_SRCS"}}, $name; }
382 elsif ($name =~ /\.rh$/) { push @{${$make}{"=HEADER_SRCS"}}, $name; }
383 elsif ($name =~ /\.inl$/) { push @{${$make}{"=HEADER_SRCS"}}, $name; }
384 elsif ($name =~ /\.svg$/) { push @{${$make}{"=SVG_SRCS"}}, $name; }
385 elsif ($name =~ /\.sfd$/)
387 ${${$make}{"=flags"}}{"clean"} = 1 if defined $flags{"font"};
388 ${${$make}{"=flags"}}{"install-lib"} = 1 if defined $flags{"install"};
389 push @{${$make}{"=FONT_SRCS"}}, $name;
391 elsif ($name =~ /\.c$/)
393 ${${$make}{"=flags"}}{"staticimplib"} = 1 if defined $flags{"implib"};
394 push @{${$make}{"=C_SRCS"}}, $name;
396 elsif ($name =~ /\.h$/)
398 next if $dir ne "include";
399 push @{${$make}{"=HEADER_SRCS"}}, $name;
400 ${${$make}{"=flags"}}{"install-dev"} = 1;
402 elsif ($name =~ /\.rc$/)
404 ${${$make}{"=flags"}}{"clean"} = 1 if defined $flags{"po"};
405 push @{${$make}{"=RC_SRCS"}}, $name;
407 elsif ($name =~ /\.mc$/)
409 push @{${$make}{"=MC_SRCS"}}, $name;
410 ${${$make}{"=flags"}}{"clean"} = 1;
412 elsif ($name =~ /\.po$/)
414 push @{${$make}{"=PO_SRCS"}}, $name;
415 ${${$make}{"=flags"}}{"clean"} = 1;
417 elsif ($name =~ /\.idl$/)
419 die "no makedep flags specified in $file" unless %flags || $dir eq "include";
420 push @{${$make}{"=IDL_SRCS"}}, $name;
421 ${${$make}{"=flags"}}{"clean"} = 1;
423 elsif ($name =~ /\.man\.in$/)
425 push @{${$make}{"=MANPAGES"}}, $name;
426 ${${$make}{"=flags"}}{($file =~ /^programs\//) ? "manpage" : "clean"} = 1;
428 elsif ($name =~ /\.in$/)
430 push @{${$make}{"=IN_SRCS"}}, $name;
434 # preserve shared source files from the parent makefile
435 foreach my $file (@makefiles)
437 my $make = $makefiles{$file};
438 my $parent = get_parent_makefile( $file );
439 next unless $parent;
440 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "C_SRCS" );
441 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "IDL_SRCS" );
442 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "LEX_SRCS" );
443 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "BISON_SRCS" );
444 ${${$make}{"=flags"}}{"clean"} = 1 if defined ${$make}{"=IDL_SRCS"} && @{${$make}{"=IDL_SRCS"}};
448 ################################################################
449 # update the makefile list in configure.ac
451 sub update_makefiles(@)
453 my (@lines);
455 foreach my $file (sort @_)
457 my %make = %{$makefiles{$file}};
458 my $args = "";
459 my $is_win16 = $make{"MODULE"} && ($make{"MODULE"} =~ /16$/ || $modules16{$make{"MODULE"}});
460 my $flag_args = defined $make{"=flags"} ? ",[" . join(",",sort keys %{$make{"=flags"}}) ."]" : "";
461 if (defined($make{"TESTDLL"})) # test
463 die "TESTDLL should not be defined in $file" unless $file =~ /\/tests\/Makefile$/;
464 die "MODULE should not be defined in $file" if defined $make{"MODULE"};
465 die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"};
466 (my $dir = $file) =~ s/^(.*)\/Makefile/$1/;
467 push @lines, "WINE_CONFIG_TEST($dir$flag_args)\n";
469 elsif (defined($make{"MODULE"}) && $make{"MODULE"} =~ /\.a$/) # import lib
471 die "MODULE should not be defined as static lib in $file" unless $file =~ /^dlls\//;
472 die "APPMODE should not be defined in $file" if defined $make{"APPMODE"};
473 die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"};
474 (my $name = $file) =~ s/^dlls\/(.*)\/Makefile/$1/;
475 push @lines, "WINE_CONFIG_LIB($name$flag_args)\n";
477 elsif (defined($make{"MODULE"}) && defined($make{"APPMODE"})) # program
479 die "APPMODE should not be defined in $file" unless $file =~ /^programs\//;
480 die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"};
481 (my $name = $file) =~ s/^programs\/(.*)\/Makefile/$1/;
482 if ($name =~ /\./)
484 die "Invalid MODULE in $file" unless $make{"MODULE"} eq $name;
486 else
488 die "Invalid MODULE in $file" unless $make{"MODULE"} eq "$name.exe";
490 $args .= "," if $is_win16 || defined $make{"=flags"};
491 $args .= "enable_win16" if $is_win16;
492 push @lines, "WINE_CONFIG_PROGRAM($name$args$flag_args)\n";
494 elsif (defined($make{"MODULE"})) # dll
496 die "APPMODE should be defined in $file" if $file =~ /^programs\//;
497 die "MODULE should not be defined in $file" unless $file =~ /^dlls\//;
498 die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"};
499 (my $name = $file) =~ s/^dlls\/(.*)\/Makefile/$1/;
500 if ($name =~ /\./)
502 die "Invalid MODULE in $file" unless $make{"MODULE"} eq $name;
504 else
506 die "Invalid MODULE in $file" unless $make{"MODULE"} eq "$name.dll";
508 my $implib = $make{"IMPORTLIB"} || "";
509 die "Invalid IMPORTLIB name in $file" if $implib =~ /\./;
510 $args .= "," if $is_win16 || defined $make{"=flags"};
511 $args .= "enable_win16" if $is_win16;
512 $args .= $flag_args;
513 $args .= ",[$implib]" if $implib && $implib ne $name;
514 push @lines, "WINE_CONFIG_DLL($name$args)\n";
516 elsif ($file =~ /^tools.*\/Makefile$/)
518 die "APPMODE should not be defined in $file" if defined $make{"APPMODE"};
519 die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"};
520 (my $name = $file) =~ s/^(.*)\/Makefile/$1/;
521 push @lines, "WINE_CONFIG_TOOL($name$flag_args)\n";
523 elsif ($file =~ /\/Makefile$/)
525 (my $name = $file) =~ s/^(.*)\/Makefile/$1/;
526 $args = "[$name]";
527 $args .= "," if defined $make{"=flags"};
528 push @lines, "WINE_CONFIG_MAKEFILE($args$flag_args)\n";
532 # update the source variables in all the makefiles
534 foreach my $file (sort @_) { replace_makefile_variables( $file ); }
536 push @lines, "dnl End of auto-generated output commands\n";
537 replace_in_file( "configure.ac", '^WINE_CONFIG_DLL', '^dnl End of auto-generated output commands\n$', @lines);
541 my $git_dir = $ENV{GIT_DIR} || ".git";
542 die "needs to be run from a git checkout" unless -d $git_dir;
544 my @all_files = split /\0/, `git ls-files -c -z`;
545 @makefiles = map { (my $ret = $_) =~ s/\.in$//; $ret; } grep /Makefile.in$/, @all_files;
547 foreach my $file (sort @makefiles)
549 my %make = parse_makefile( $file );
550 $makefiles{$file} = \%make;
553 assign_sources_to_makefiles( @all_files );
554 update_makefiles( @makefiles );