wine/tools/make_makefiles
André Hentschel 31f0f09a17 configure: Install view.
(better subject, maybe)

I still think "view" should be available to users, so the only thing between the user and "view" is they have to compile Wine theirselves and that should change.
It's very hard to find good wmf/emf viewers for Linux(and most likely other OS), but "view" is a great program for people who need to take a look at wmf/emf files.
2011-09-05 19:32:32 +02:00

613 lines
18 KiB
Perl
Executable File

#!/usr/bin/perl -w
#
# Build the auto-generated parts of the Wine makefiles.
#
# Copyright 2006 Alexandre Julliard
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#
use strict;
# Make rules files
my %makerules =
(
"MAKE_RULES" => "Make.rules",
"MAKE_DLL_RULES" => "dlls/Makedll.rules",
"MAKE_IMPLIB_RULES" => "dlls/Makeimplib.rules",
"MAKE_TEST_RULES" => "Maketest.rules",
"MAKE_PROG_RULES" => "programs/Makeprog.rules",
);
# Programs that we want to install in the bin directory too
my %bin_install =
(
"msiexec" => 1,
"notepad" => 1,
"regedit" => 1,
"regsvr32" => 1,
"wineboot" => 1,
"winecfg" => 1,
"wineconsole" => 1,
"winedbg" => 1,
"winefile" => 1,
"winemine" => 1,
"winepath" => 1,
);
# Programs that we don't want to install at all
my %dont_install =
(
"cmdlgtst" => 1,
"winetest" => 1,
);
# Dlls and programs that are 16-bit specific
my %modules16 =
(
"ifsmgr.vxd" => 1,
"mmdevldr.vxd" => 1,
"monodebg.vxd" => 1,
"vdhcp.vxd" => 1,
"vmm.vxd" => 1,
"vnbt.vxd" => 1,
"vnetbios.vxd" => 1,
"vtdapi.vxd" => 1,
"vwin32.vxd" => 1,
"w32skrnl.dll" => 1,
"winevdm.exe" => 1,
"wow32.dll" => 1,
);
# Default patterns for top-level .gitignore
my @ignores = (
"*.[oa]",
"*.exe",
"*.fake",
"*.man",
"*.ok",
"*.res",
"*.so",
"/autom4te.cache",
"/config.cache",
"/config.log",
"/config.status",
"/configure.lineno",
"/TAGS",
"/tags",
"/wine",
"/wine64",
"Makefile",
"dlldata.c",
"dlls/*/*.def",
"dlls/shell32/AUTHORS",
"*/*/tests/testlist.c",
"include/config.h",
"include/stamp-h",
"msg.pot",
"programs/winetest/build.nfo",
"programs/winetest/build.rc",
"rsrc.pot",
"tools/makedep",
);
# Source files and their resulting target to ignore
my @ignore_srcs = (
[ 'BISON_SRCS', '\.y', '.tab.c' ],
[ 'BISON_SRCS', '\.y', '.tab.h' ],
[ 'LEX_SRCS', '\.l', '.yy.c' ],
[ 'IDL_TLB_SRCS', '\.idl', '.tlb' ],
[ 'IDL_H_SRCS', '\.idl', '.h' ],
[ 'IDL_C_SRCS', '\.idl', '.h' ],
[ 'IDL_I_SRCS', '\.idl', '.h' ],
[ 'IDL_P_SRCS', '\.idl', '.h' ],
[ 'IDL_S_SRCS', '\.idl', '.h' ],
[ 'IDL_C_SRCS', '\.idl', '_c.c' ],
[ 'IDL_I_SRCS', '\.idl', '_i.c' ],
[ 'IDL_P_SRCS', '\.idl', '_p.c' ],
[ 'IDL_S_SRCS', '\.idl', '_s.c' ],
[ 'PUBLIC_IDL_H_SRCS', '\.idl', '.h' ],
[ 'PRIVATE_IDL_H_SRCS', '\.idl', '.h' ],
[ 'XTEMPLATE_SRCS', '\.x', '.h' ],
);
my %exported_wine_headers = (
"wine/debug.h" => 1,
"wine/exception.h" => 1,
"wine/library.h" => 1,
"wine/unicode.h" => 1,
"wine/itss.idl" => 1,
"wine/svcctl.idl" => 1,
);
my %private_idl_headers = (
"access.idl" => 1,
"asynot.idl" => 1,
"asysta.idl" => 1,
"axcore.idl" => 1,
"axextend.idl" => 1,
"binres.idl" => 1,
"cmdbas.idl" => 1,
"cmdtxt.idl" => 1,
"crtrow.idl" => 1,
"dbccmd.idl" => 1,
"dbcses.idl" => 1,
"dbdsad.idl" => 1,
"dbinit.idl" => 1,
"dbprop.idl" => 1,
"dbs.idl" => 1,
"devenum.idl" => 1,
"dyngraph.idl" => 1,
"opnrst.idl" => 1,
"row.idl" => 1,
"rowchg.idl" => 1,
"rstbas.idl" => 1,
"rstinf.idl" => 1,
"rstloc.idl" => 1,
"sesprp.idl" => 1,
"vmrender.idl" => 1,
"xmldom.idl" => 1,
"xmldso.idl" => 1,
"wine/winedxgi.idl" => 1,
);
my %ignored_source_files = (
"dlls/wineps.drv/afm2c.c" => 1,
"dlls/wineps.drv/mkagl.c" => 1,
"programs/winetest/dist.rc" => 1,
);
my (@linguas, @makefiles, %makefiles);
sub dirname($)
{
my $ret = shift;
return "" unless $ret =~ /\//;
$ret =~ s!/[^/]*$!!;
return $ret;
}
# update a file if changed
sub update_file($)
{
my $file = shift;
my $ret = !(-f $file) || system "cmp $file $file.new >/dev/null";
if (!$ret)
{
unlink "$file.new";
}
else
{
rename "$file.new", "$file";
print "$file updated\n";
if ($file eq "configure.ac")
{
system "autoconf";
print "configure updated\n";
}
}
return $ret;
}
# replace some lines in a file between two markers
sub replace_in_file($$$@)
{
my $file = shift;
my $start = shift;
my $end = shift;
open NEW_FILE, ">$file.new" or die "cannot create $file.new";
if (defined($start))
{
open OLD_FILE, "$file" or die "cannot open $file";
while (<OLD_FILE>)
{
last if /$start/;
print NEW_FILE $_;
}
}
print NEW_FILE @_;
if (defined($end))
{
my $skip=1;
while (<OLD_FILE>)
{
print NEW_FILE $_ unless $skip;
$skip = 0 if /$end/;
}
}
close OLD_FILE if defined($start);
close NEW_FILE;
return update_file($file);
}
# replace a variable in a makefile
sub replace_makefile_variable($$)
{
my ($file, $var) = @_;
my $make = $makefiles{$file};
my $replaced = 0;
return unless defined ${$make}{"=$var"};
my @values = @{${$make}{"=$var"}};
${$make}{$var} = \@values;
open NEW_FILE, ">$file.in.new" or die "cannot create $file.in.new";
open OLD_FILE, "$file.in" or die "cannot open $file.in";
while (<OLD_FILE>)
{
if (/^\s*($var\s*)=/)
{
# try to preserve formatting
my $prefix = $1;
my $multiline = /\\$/ || (@values > 1);
while (/\\$/)
{
$_ = <OLD_FILE>;
last unless $_;
}
if ($multiline)
{
print NEW_FILE "$var = \\\n\t" . join(" \\\n\t", sort @values) . "\n";
}
else
{
print NEW_FILE "$prefix= @values\n";
}
$replaced = 1;
next;
}
if (/^\@MAKE/ && !$replaced)
{
print NEW_FILE "$var = \\\n\t" . join(" \\\n\t", sort @values) . "\n";
}
print NEW_FILE $_;
}
close OLD_FILE;
close NEW_FILE;
return update_file("$file.in");
}
# parse the specified makefile and load the variables
sub parse_makefile($)
{
my $file = shift;
my %make;
($make{"=dir"} = $file) =~ s/[^\/]+$//;
open MAKE, "$file.in" or die "cannot open $file.in\n";
while (<MAKE>)
{
chomp;
next if (/^\s*#/);
while (/\\$/) { chop; $_ .= <MAKE>; chomp; } # merge continued lines
next if (/^\s*$/);
if (/^\@(MAKE.*RULES)\@/)
{
my $var = $1;
$make{"=rules"} = $makerules{$var};
next;
}
if (/^\s*(MODULE|IMPORTLIB|TESTDLL|MANPAGE)\s*=\s*(.*)/)
{
my $var = $1;
$make{$var} = $2;
push @{$make{"=flags"}}, "implib" if $var eq "IMPORTLIB";
push @{$make{"=flags"}}, "manpage" if $var eq "MANPAGE";
next;
}
if (/^\s*(BISON_SRCS|LEX_SRCS|IDL_[CHIPRS]_SRCS|IDL_TLB_SRCS|IMPLIB_SRCS|C_SRCS|MC_SRCS|RC_SRCS|PO_SRCS|SVG_SRCS|PROGRAMS)\s*=\s*(.*)/)
{
my $var = $1;
my @list = split(/\s+/, $2);
$make{$var} = \@list;
push @{$make{"=flags"}}, "mc" if $var eq "MC_SRCS";
push @{$make{"=flags"}}, "po" if $var eq "PO_SRCS";
push @{$make{"=flags"}}, "staticimplib" if $var eq "IMPLIB_SRCS";
next;
}
if (/(install-lib|install-dev)\s*:/)
{
push @{$make{"=flags"}}, $1;
next;
}
if (/^\s*(TOPSRCDIR|TOPOBJDIR|SRCDIR|VPATH)\s*=\s*(.*)/)
{
die "Variable $1 in $file.in is obsolete";
}
}
if ($file =~ /^programs\/([^\/]+)\/Makefile/)
{
push @{$make{"=flags"}}, "install" unless $dont_install{$1};
push @{$make{"=flags"}}, "installbin" if $bin_install{$1};
}
return %make;
}
# assign source files to their respective makefile
sub assign_sources_to_makefiles(@)
{
my %subdirs;
foreach my $file (@_)
{
next if defined $ignored_source_files{$file};
my $dir = dirname( $file );
my $subdir = $dir;
while ($dir && !defined $makefiles{"$dir/Makefile"}) { $dir = dirname( $dir ); }
$subdir =~ s/^$dir\/?//;
$subdirs{"$dir/ $subdir"} = 1 if $subdir;
next unless $dir;
die "no makefile found for $file\n" unless defined $makefiles{"$dir/Makefile"};
my $make = $makefiles{"$dir/Makefile"};
my $name = substr( $file, length($dir) + 1 );
if ($dir eq "include")
{
next if ($name =~ /\.in$/);
if ($name =~ /^wine\// && !$exported_wine_headers{$name})
{
if ($private_idl_headers{$name}) { push @{${$make}{"=PRIVATE_IDL_H_SRCS"}}, $name; }
next;
}
if ($name =~ /stdole2\.idl$/) { push @{${$make}{"=IDL_TLB_SRCS"}}, $name; }
elsif ($private_idl_headers{$name}) { push @{${$make}{"=SRCDIR_INCLUDES"}}, $name; }
elsif ($name =~ /\.h$/) { push @{${$make}{"=SRCDIR_INCLUDES"}}, $name; }
elsif ($name =~ /\.x$/) { push @{${$make}{"=XTEMPLATE_SRCS"}}, $name; }
elsif ($name =~ /\.rh$/) { push @{${$make}{"=SRCDIR_INCLUDES"}}, $name; }
elsif ($name =~ /\.inl$/) { push @{${$make}{"=SRCDIR_INCLUDES"}}, $name; }
elsif ($name =~ /\.idl$/) { push @{${$make}{"=PUBLIC_IDL_H_SRCS"}}, $name; }
else { die "unknown file $name in include dir"; }
}
else
{
if ($name =~ /\.c$/) { push @{${$make}{"=C_SRCS"}}, $name; }
elsif ($name =~ /\.l$/) { push @{${$make}{"=LEX_SRCS"}}, $name; }
elsif ($name =~ /\.y$/) { push @{${$make}{"=BISON_SRCS"}}, $name; }
elsif ($name =~ /\.rc$/) { push @{${$make}{"=RC_SRCS"}}, $name; }
elsif ($name =~ /\.mc$/) { push @{${$make}{"=MC_SRCS"}}, $name; }
elsif ($name =~ /\.svg$/) { push @{${$make}{"=SVG_SRCS"}}, $name; }
}
}
foreach my $key (keys %subdirs)
{
my ($dir, $subdir) = split " ", $key;
if ($dir eq "/") { $dir = ""; }
push @{${$makefiles{"${dir}Makefile"}}{"=EXTRASUBDIRS"}}, $subdir;
}
# add extra variables to include source list
my $make = $makefiles{"include/Makefile"};
unshift @{${$make}{"=SRCDIR_INCLUDES"}}, "\$(XTEMPLATE_SRCS)";
unshift @{${$make}{"=SRCDIR_INCLUDES"}}, "\$(PUBLIC_IDL_H_SRCS)";
unshift @{${$make}{"=SRCDIR_INCLUDES"}}, "\$(IDL_TLB_SRCS)";
}
################################################################
# update the makefile list in configure.ac
sub update_makefiles(@)
{
my (@lines);
foreach my $var (sort { $makerules{$a} cmp $makerules{$b}; } keys %makerules)
{
my $file = $makerules{$var};
my %make = %{$makefiles{$file}};
my $rules = $make{"=rules"} ? ",[$make{\"=rules\"}]" : "";
push @lines, "WINE_CONFIG_MAKERULES([$file],[$var]$rules)\n";
}
push @lines, "\n";
foreach my $file (sort @_)
{
my %make = %{$makefiles{$file}};
my $rules = $make{"=rules"};
my $args = "";
my $is_win16 = $make{"MODULE"} && ($make{"MODULE"} =~ /16$/ || $modules16{$make{"MODULE"}});
my $flag_args = defined $make{"=flags"} ? ",[" . join(",",sort @{$make{"=flags"}}) ."]" : "";
if ($rules eq $makerules{"MAKE_DLL_RULES"})
{
(my $name = $file) =~ s/^dlls\/(.*)\/Makefile/$1/;
if ($name =~ /\./)
{
die "Invalid MODULE in $file" unless $make{"MODULE"} eq $name;
}
else
{
die "Invalid MODULE in $file" unless $make{"MODULE"} eq "$name.dll";
}
my $implib = $make{"IMPORTLIB"} || "";
$args .= "," if $is_win16 || defined $make{"=flags"};
$args .= "enable_win16" if $is_win16;
$args .= $flag_args;
$args .= ",[$implib]" if $implib && $implib ne $name;
push @lines, "WINE_CONFIG_DLL($name$args)\n";
}
elsif ($rules eq $makerules{"MAKE_PROG_RULES"})
{
(my $name = $file) =~ s/^programs\/(.*)\/Makefile/$1/;
if ($name =~ /\./)
{
die "Invalid MODULE in $file" unless $make{"MODULE"} eq $name;
}
else
{
die "Invalid MODULE in $file" unless $make{"MODULE"} eq "$name.exe";
}
$args .= "," if $is_win16 || defined $make{"=flags"};
$args .= "enable_win16" if $is_win16;
push @lines, "WINE_CONFIG_PROGRAM($name$args$flag_args)\n";
}
elsif ($rules eq $makerules{"MAKE_TEST_RULES"})
{
(my $dir = $file) =~ s/^(.*)\/Makefile/$1/;
push @lines, "WINE_CONFIG_TEST($dir$flag_args)\n";
}
elsif ($rules eq $makerules{"MAKE_IMPLIB_RULES"})
{
(my $name = $file) =~ s/^dlls\/(.*)\/Makefile/$1/;
push @lines, "WINE_CONFIG_LIB($name$flag_args)\n";
}
elsif ($file =~ /^tools.*\/Makefile$/)
{
(my $name = $file) =~ s/^(.*)\/Makefile/$1/;
push @lines, "WINE_CONFIG_TOOL($name$flag_args)\n";
}
elsif ($file =~ /\/Makefile$/)
{
(my $name = $file) =~ s/^(.*)\/Makefile/$1/;
$args = "[$name]";
$args .= "," if defined $make{"=flags"};
push @lines, "WINE_CONFIG_MAKEFILE($args$flag_args)\n";
}
}
push @lines, "\nAC_SUBST([LINGUAS],[\"\\\n", join( " \\\n", sort @linguas ), "\"])\n\n";
# update the source variables in all the makefiles
foreach my $file (sort @_)
{
replace_makefile_variable( $file, "LEX_SRCS" );
replace_makefile_variable( $file, "BISON_SRCS" );
replace_makefile_variable( $file, "MC_SRCS" );
replace_makefile_variable( $file, "SVG_SRCS" );
replace_makefile_variable( $file, "C_SRCS" );
replace_makefile_variable( $file, "RC_SRCS" );
replace_makefile_variable( $file, "PRIVATE_IDL_H_SRCS" );
replace_makefile_variable( $file, "PUBLIC_IDL_H_SRCS" );
replace_makefile_variable( $file, "IDL_TLB_SRCS" );
replace_makefile_variable( $file, "XTEMPLATE_SRCS" );
replace_makefile_variable( $file, "SRCDIR_INCLUDES" );
replace_makefile_variable( $file, "EXTRASUBDIRS" );
}
push @lines, "dnl End of auto-generated output commands\n";
replace_in_file( "configure.ac", '^WINE_CONFIG_MAKERULES', '^dnl End of auto-generated output commands\n$', @lines);
}
################################################################
# process ignore targets for generic source files
sub update_ignores(@)
{
my @ignores;
foreach my $file (sort @_)
{
my %makefile = %{$makefiles{$file}};
my @list;
foreach my $src (@ignore_srcs)
{
my @pattern = @{$src};
next unless defined $makefile{$pattern[0]};
next if $pattern[0] eq "IDL_TLB_SRCS" && $makefile{"=rules"} eq "dlls/Makedll.rules";
push @list, map { (my $ret = $_) =~ s/$pattern[1]$/$pattern[2]/; $ret; } @{$makefile{$pattern[0]}};
}
foreach my $f (@list)
{
push @ignores, $makefile{"=dir"} . $f unless $f =~ /\$\(.*\)/; # skip make variables
}
if (defined $makefile{"IMPORTLIB"})
{
if ($makefile{"IMPORTLIB"} =~ /^([a-zA-Z0-9_.]+)/)
{
if ("dlls/$1/" ne $makefile{"=dir"}) { push @ignores, "dlls/lib$1.def"; }
}
else
{
die "invalid importlib name $makefile{IMPORTLIB} in $file";
}
}
}
return @ignores;
}
################################################################
# update the main .gitignore
sub update_gitignore(@)
{
my @ignores = values %makerules;
foreach my $make (@makefiles)
{
my %makefile = %{$makefiles{$make}};
my $dir = $makefile{"=dir"};
if (defined $makefile{"PROGRAMS"})
{
push @ignores, map { s/\$\(EXEEXT\)//; $dir . $_; } @{$makefile{"PROGRAMS"}};
}
}
# prepend a slash to paths that don't have one
@ignores = map { $_ =~ s/^([^\/]+)$/\/$1/; $_; } @ignores;
# get rid of duplicates
my %ignores = ();
foreach my $i (@ignores, @_) { $ignores{$i} = 1; }
replace_in_file( ".gitignore", undef, undef,
"# Automatically generated by make_makefiles; DO NOT EDIT!!\n",
join("\n", sort keys %ignores), "\n" );
}
################################################################
# update the LINGUAS file
sub update_linguas(@)
{
replace_in_file( "po/LINGUAS", undef, undef, join("\n", sort @_), "\n" );
}
die "needs to be run from a git checkout" unless -d ".git";
my @all_files = split /\0/, `git ls-files -c -z`;
@linguas = map { (my $ret = $_) =~ s/^po\/(.*)\.po/$1/; $ret; } grep /^po\/.*\.po$/, @all_files;
@makefiles = map { (my $ret = $_) =~ s/\.in$//; $ret; } grep /Makefile.in$/, @all_files;
foreach my $file (sort values %makerules, @makefiles)
{
my %make = parse_makefile( $file );
$makefiles{$file} = \%make;
}
assign_sources_to_makefiles( @all_files );
update_linguas( @linguas );
update_makefiles( @makefiles );
push @ignores, update_ignores( @makefiles );
update_gitignore( @ignores );