msvideo: Consistently use %I printf format for ULONG_PTR values.
[wine.git] / tools / make_makefiles
blob2025b45b75c4811da3cc6c77937b34932865c221
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 %ignored_source_files = (
42 "dlls/wineps.drv/afm2c.c" => 1,
43 "dlls/wineps.drv/mkagl.c" => 1,
44 "tools/makedep.c" => 1,
47 my @source_vars = (
48 "BISON_SRCS",
49 "C_SRCS",
50 "FONT_SRCS",
51 "HEADER_SRCS",
52 "IDL_SRCS",
53 "IN_SRCS",
54 "LEX_SRCS",
55 "MANPAGES",
56 "MC_SRCS",
57 "OBJC_SRCS",
58 "PO_SRCS",
59 "RC_SRCS",
60 "SOURCES",
61 "SVG_SRCS",
62 "XTEMPLATE_SRCS"
65 my (@makefiles, %makefiles);
66 my @nls_files;
68 sub dirname($)
70 my $ret = shift;
71 return "" unless $ret =~ /\//;
72 $ret =~ s!/[^/]*$!!;
73 return $ret;
76 # update a file if changed
77 sub update_file($$)
79 my $file = shift;
80 my $new = shift;
82 open FILE, ">$file.new" or die "cannot create $file.new";
83 print FILE $new;
84 close FILE;
85 rename "$file.new", "$file";
86 print "$file updated\n";
87 if ($file eq "configure.ac")
89 system "autoconf";
90 print "configure updated\n";
94 # replace some lines in a file between two markers
95 sub replace_in_file($$$@)
97 my $file = shift;
98 my $start = shift;
99 my $end = shift;
100 my ($old, $new);
102 open OLD_FILE, "$file" or die "cannot open $file";
103 while (<OLD_FILE>)
105 $old .= $_;
106 last if /$start/;
107 $new .= $_;
110 $new .= join "", @_;
112 my $skip = 1;
113 while (<OLD_FILE>)
115 $old .= $_;
116 $new .= $_ unless $skip;
117 $skip = 0 if /$end/;
120 close OLD_FILE;
121 update_file($file, $new) if $old ne $new;
124 # replace all source variables in a makefile
125 sub replace_makefile_variables($)
127 my $file = shift;
128 my $make = $makefiles{$file};
129 my $source_vars_regexp = join "|", @source_vars;
130 my %replaced;
131 my %files;
132 my $old;
133 my $new;
135 open OLD_FILE, $file or die "cannot open $file";
136 while (<OLD_FILE>)
138 $old .= $_;
139 if (/^\s*($source_vars_regexp)(\s*)=/)
141 # try to preserve formatting
142 my $var = $1;
143 my $spaces = $2;
144 my $replaced = 0;
145 my @values;
147 if (defined ${$make}{"=$var"})
149 @values = @{${$make}{"=$var"}};
150 ${$make}{$var} = \@values;
152 else
154 undef ${$make}{$var};
156 my $multiline = /\\$/ || (@values > 1);
157 my $old_str = $_;
158 while (/\\$/)
160 $_ = <OLD_FILE>;
161 last unless $_;
162 $old .= $_;
163 $old_str .= $_;
165 my $new_str = "";
166 if (!@values)
168 # nothing
170 elsif ($multiline)
172 $new_str = "$var = \\\n\t" . join(" \\\n\t", sort @values) . "\n";
173 $new .= $new_str;
175 else
177 $new_str = "$var$spaces= @values\n";
178 $new .= $new_str;
180 $replaced{$var} = 1;
181 foreach my $val (@values)
183 die "$file: duplicate file $val" if defined $files{$val};
184 $files{$val} = 1;
186 next;
188 $new .= $_;
190 # if we are using SOURCES, ignore the other variables
191 unless ($replaced{"SOURCES"})
193 foreach my $var (@source_vars)
195 next if defined $replaced{$var};
196 next if $var eq "SOURCES";
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";
203 close OLD_FILE;
204 update_file($file, $new) if $old ne $new;
207 # parse the specified makefile and load the variables
208 sub parse_makefile($)
210 my $file = shift;
211 my %make;
213 ($make{"=dir"} = $file) =~ s/[^\/]+$//;
215 open MAKE, $file or die "cannot open $file\n";
217 while (<MAKE>)
219 chomp;
220 next if (/^\s*#/);
221 while (/\\$/) { chop; $_ .= <MAKE>; chomp; } # merge continued lines
222 next if (/^\s*$/);
224 if (/\@[A-Z_]+\@/) # config.status substitution variable
226 die "Configure substitution is not allowed in $file" unless $file eq "Makefile.in";
228 if (/^\s*(MODULE|IMPORTLIB|TESTDLL|STATICLIB|PARENTSRC|EXTRADLLFLAGS)\s*=\s*(.*)/)
230 my $var = $1;
231 $make{$var} = $2;
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 (/^\s*(TOPSRCDIR|TOPOBJDIR|SRCDIR|VPATH)\s*=\s*(.*)/)
244 die "Variable $1 in $file is obsolete";
248 return %make;
251 # read pragma makedep flags from a source file
252 sub get_makedep_flags($)
254 my $file = shift;
255 my %flags;
257 open FILE, $file or die "cannot open $file";
258 if ($file =~ /\.sfd$/)
260 while (<FILE>)
262 next unless /^UComments:\s*\"(.*)\"$/;
263 foreach my $pragma (split /\+AAoA/, $1)
265 next unless $pragma =~ /^#\s*pragma\s+makedep\s+(.*)/;
266 foreach my $flag (split /\s+/, $1)
268 $flags{$flag} = 1;
269 last if $flag eq "font";
274 else
276 while (<FILE>)
278 next unless /^#\s*pragma\s+makedep\s+(.*)/;
279 foreach my $flag (split /\s+/, $1)
281 last if $flag eq "depend";
282 $flags{$flag} = 1;
286 close FILE;
287 return %flags;
290 sub get_parent_makefile($)
292 my $file = shift;
293 my %make = %{$makefiles{$file}};
294 my $reldir = $make{"PARENTSRC"} || "";
295 return "" unless $reldir;
296 (my $path = $file) =~ s/\/Makefile\.in$/\//;
297 while ($reldir =~ /^\.\.\//)
299 $reldir =~ s/^\.\.\///;
300 $path =~ s/[^\/]+\/$//;
302 return "$path$reldir/Makefile.in";
305 # preserve shared source files that are listed in the existing makefile
306 sub preserve_shared_source_files($$$)
308 my ($make, $parent, $var) = @_;
309 my %srcs;
311 return unless defined ${$parent}{"=$var"};
312 foreach my $file (@{${$parent}{"=$var"}}) { $srcs{$file} = 1; }
313 foreach my $file (@{${$make}{"=$var"}}) { $srcs{$file} = 0; }
315 foreach my $file (@{${$make}{$var}})
317 next unless defined $srcs{$file} && $srcs{$file} == 1;
318 push @{${$make}{"=$var"}}, $file;
322 # assign source files to their respective makefile
323 sub assign_sources_to_makefiles(@)
325 foreach my $file (@_)
327 next if defined $ignored_source_files{$file};
328 next if $file =~ /Makefile\.in$/;
329 my $dir = dirname( $file );
330 my $subdir = $dir;
332 while ($dir && !defined $makefiles{"$dir/Makefile.in"}) { $dir = dirname( $dir ); }
333 $subdir =~ s/^$dir\/?//;
334 next unless $dir;
336 die "no makefile found for $file\n" unless defined $makefiles{"$dir/Makefile.in"};
338 my $make = $makefiles{"$dir/Makefile.in"};
339 my $name = substr( $file, length($dir) + 1 );
341 if ($name =~ /\.m$/) { push @{${$make}{"=OBJC_SRCS"}}, $name; }
342 elsif ($name =~ /\.l$/) { push @{${$make}{"=LEX_SRCS"}}, $name; }
343 elsif ($name =~ /\.y$/) { push @{${$make}{"=BISON_SRCS"}}, $name; }
344 elsif ($name =~ /\.svg$/) { push @{${$make}{"=SVG_SRCS"}}, $name; }
345 elsif ($name =~ /\.sfd$/)
347 push @{${$make}{"=FONT_SRCS"}}, $name;
349 elsif ($name =~ /\.c$/)
351 push @{${$make}{"=C_SRCS"}}, $name;
353 elsif ($name =~ /\.h$/ || $name =~ /\.rh$/ || $name =~ /\.inl$/ || $name =~ /\.x$/)
355 next if $dir ne "include";
357 elsif ($name =~ /\.rc$/)
359 push @{${$make}{"=RC_SRCS"}}, $name;
361 elsif ($name =~ /\.mc$/)
363 push @{${$make}{"=MC_SRCS"}}, $name;
365 elsif ($name =~ /\.po$/)
367 push @{${$make}{"=PO_SRCS"}}, $name;
369 elsif ($name =~ /\.idl$/)
371 die "no makedep flags specified in $file" unless $dir eq "include" || get_makedep_flags($file);
372 push @{${$make}{"=IDL_SRCS"}}, $name;
374 elsif ($name =~ /\.man\.in$/)
376 push @{${$make}{"=MANPAGES"}}, $name;
378 elsif ($name =~ /\.in$/)
380 push @{${$make}{"=IN_SRCS"}}, $name;
382 elsif ($name =~ /\.spec$/)
384 next unless defined ${$make}{"TESTDLL"};
386 elsif ($name =~ /\.nls$/)
388 push @nls_files, $name if $dir eq "nls";
390 elsif ($dir ne "loader") # loader dir contains misc files
392 next;
394 push @{${$make}{"=SOURCES"}}, $name;
397 # preserve shared source files from the parent makefile
398 foreach my $file (@makefiles)
400 my $make = $makefiles{$file};
401 my $parent = get_parent_makefile( $file );
402 next unless $parent;
403 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "C_SRCS" );
404 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "RC_SRCS" );
405 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "IDL_SRCS" );
406 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "LEX_SRCS" );
407 preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "BISON_SRCS" );
411 ################################################################
412 # update the makefile list in configure.ac
414 sub update_makefiles(@)
416 my (@lines);
418 foreach my $file (sort @_)
420 next if $file eq "Makefile.in";
421 my %make = %{$makefiles{$file}};
422 (my $dir = $file) =~ s/^(.*)\/Makefile\.in/$1/;
423 my $args = "";
424 if (defined($make{"TESTDLL"})) # test
426 die "TESTDLL should not be defined in $file" unless $file =~ /\/tests\/Makefile\.in$/;
427 die "MODULE should not be defined in $file" if defined $make{"MODULE"};
428 die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"};
430 elsif (defined($make{"STATICLIB"}))
432 die "MODULE should not be defined in $file" if defined $make{"MODULE"};
433 die "invalid STATICLIB name" unless $make{"STATICLIB"} =~ /\.a$/;
435 elsif (defined($make{"MODULE"})) # dll or program
437 (my $name = $file) =~ s/^(dlls|programs)\/(.*)\/Makefile\.in/$2/;
438 my $dllflags = $make{"EXTRADLLFLAGS"} || "";
439 die "invalid MODULE name" if $make{"MODULE"} =~ /\.a$/;
440 die "MODULE should not be defined in $file" unless $file =~ /^(dlls|programs)\//;
441 die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"};
442 if ($file =~ /^programs\//)
444 die "EXTRADLLFLAGS should be defined in $file" unless $dllflags;
445 die "EXTRADLLFLAGS should contain -mconsole or -mwindows in $file" unless $dllflags =~ /-m(console|windows)/;
446 die "Invalid MODULE in $file" unless ($name =~ /\./ && $make{"MODULE"} eq $name) || $make{"MODULE"} eq "$name.exe";
448 else
450 die "EXTRADLLFLAGS should not contain -mconsole or -mwindows in $file" if $dllflags =~ /-m(console|windows)/;
451 die "Invalid MODULE in $file" unless ($name =~ /\./ && $make{"MODULE"} eq $name) || $make{"MODULE"} eq "$name.dll";
453 if (defined $make{"IMPORTLIB"})
455 die "IMPORTLIB not allowed in programs\n" if $file =~ /^programs\//;
456 die "Invalid IMPORTLIB name in $file" if $make{"IMPORTLIB"} =~ /\./;
458 $args = ",enable_win16" if $make{"MODULE"} =~ /16$/ || $modules16{$make{"MODULE"}};
460 elsif ($file =~ /^tools.*\/Makefile\.in$/)
462 die "MODULE should not be defined in $file" if defined $make{"MODULE"};
463 die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"};
464 die "EXTRADLLFLAGS should not be defined in $file" if defined $make{"EXTRADLLFLAGS"};
465 $args = ",,[test \"x\$enable_tools\" = xno]";
467 push @lines, "WINE_CONFIG_MAKEFILE($dir$args)\n";
470 # update the source variables in all the makefiles
472 foreach my $file (sort @_) { replace_makefile_variables( $file ); }
474 push @lines, "dnl End of auto-generated output commands\n";
475 replace_in_file( "configure.ac", '^WINE_CONFIG_MAKEFILE', '^dnl End of auto-generated output commands\n$', @lines);
478 sub update_wine_inf()
480 my @lines;
481 push @lines, "[NlsFiles]", sort grep(!/^sort/, @nls_files);
482 push @lines, "\n[SortFiles]", sort grep(/^sort/, @nls_files);
483 push @lines, "\n[WineSourceDirs]\n";
484 replace_in_file "loader/wine.inf.in", '^\[NlsFiles\]', '^\[WineSourceDirs\]', join( "\n", @lines );
487 my $git_dir = $ENV{GIT_DIR} || ".git";
488 die "needs to be run from a git checkout" unless -e $git_dir;
490 my @all_files = split /\0/, `git ls-files -c -z`;
491 map { $ignored_source_files{$_} = 1; } split /\0/, `git ls-files -d -z`;
492 @makefiles = grep /Makefile.in$/, @all_files;
494 foreach my $file (sort @makefiles)
496 my %make = parse_makefile( $file );
497 $makefiles{$file} = \%make;
500 assign_sources_to_makefiles( @all_files );
501 update_makefiles( @makefiles );
502 update_wine_inf();