diff options
Diffstat (limited to 'source4/build/smb_build/config_mk.pm')
-rw-r--r-- | source4/build/smb_build/config_mk.pm | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/source4/build/smb_build/config_mk.pm b/source4/build/smb_build/config_mk.pm new file mode 100644 index 0000000000..8c7d75221c --- /dev/null +++ b/source4/build/smb_build/config_mk.pm @@ -0,0 +1,284 @@ +# Samba Build System +# - config.mk parsing functions +# +# Copyright (C) Stefan (metze) Metzmacher 2004 +# Copyright (C) Jelmer Vernooij 2005 +# Released under the GNU GPL +# + +package smb_build::config_mk; +use smb_build::input; +use File::Basename; + +use strict; + +my $section_types = { + "EXT_LIB" => { + "LIBS" => "list", + "CFLAGS" => "list", + "CPPFLAGS" => "list", + "LDFLAGS" => "list", + }, + "PYTHON" => { + "LIBRARY_REALNAME" => "string", + "PRIVATE_DEPENDENCIES" => "list", + "PUBLIC_DEPENDENCIES" => "list", + "ENABLE" => "bool", + "LDFLAGS" => "list", + }, + "SUBSYSTEM" => { + "PRIVATE_DEPENDENCIES" => "list", + "PUBLIC_DEPENDENCIES" => "list", + + "ENABLE" => "bool", + + "CFLAGS" => "list", + "LDFLAGS" => "list", + "STANDARD_VISIBILITY" => "string", + "INIT_FUNCTION_SENTINEL" => "string" + }, + "MODULE" => { + "SUBSYSTEM" => "string", + + "INIT_FUNCTION" => "string", + + "PRIVATE_DEPENDENCIES" => "list", + + "ALIASES" => "list", + + "ENABLE" => "bool", + + "OUTPUT_TYPE" => "list", + + "CFLAGS" => "list" + }, + "BINARY" => { + + "PRIVATE_DEPENDENCIES" => "list", + + "ENABLE" => "bool", + + "INSTALLDIR" => "string", + "LDFLAGS" => "list", + "STANDARD_VISIBILITY" => "string", + + "USE_HOSTCC" => "bool" + }, + "LIBRARY" => { + "LIBRARY_REALNAME" => "string", + + "INIT_FUNCTION_TYPE" => "string", + "INIT_FUNCTION_SENTINEL" => "string", + "OUTPUT_TYPE" => "list", + + "PRIVATE_DEPENDENCIES" => "list", + "PUBLIC_DEPENDENCIES" => "list", + + "ENABLE" => "bool", + + "CFLAGS" => "list", + "LDFLAGS" => "list", + "STANDARD_VISIBILITY" => "string" + } +}; + +use vars qw(@parsed_files); + +@parsed_files = (); + +sub _read_config_file($$$) +{ + use Cwd; + + my ($srcdir, $builddir, $filename) = @_; + my @dirlist; + + # We need to change our working directory because config.mk files can + # give shell commands as the argument to "include". These shell + # commands can take arguments that are relative paths and we don't have + # a way of sensibly rewriting these. + my $cwd = getcwd; + chomp $cwd; + + if ($srcdir ne $builddir) { + # Push the builddir path on the front, so we prefer builddir + # to srcdir when the file exists in both. + @dirlist = ($builddir, $srcdir); + } else { + @dirlist = ($srcdir); + } + + foreach my $d (@dirlist) { + my @lines; + my $basedir; + + chdir $cwd; + chdir $d; + + # We need to catch the exception from open in the case where + # the filename is actually a shell pipeline. Why is this + # different to opening a regular file? Because this is perl! + eval { + open(CONFIG_MK, "./$filename"); + @lines = <CONFIG_MK>; + close(CONFIG_MK); + }; + + chdir $cwd; + next unless (@lines); + + # I blame abartlett for this crazy hack -- jpeach + if ($filename =~ /\|$/) { + $basedir = $builddir; + } else { + $basedir = dirname($filename); + push(@parsed_files, $filename); + } + $basedir =~ s!^($builddir|$srcdir)[/]!!; + return ($filename, $basedir, @lines); + } + + chdir $cwd; + return; +} + +########################################################### +# The parsing function which parses the file +# +# $result = _parse_config_mk($input, $srcdir, $builddir, $filename) +# +# $filename - the path of the config.mk file +# which should be parsed +sub run_config_mk($$$$) +{ + sub run_config_mk($$$$); + my ($input, $srcdir, $builddir, $filename) = @_; + my $result; + my $linenum = -1; + my $infragment = 0; + my $section = "GLOBAL"; + my $makefile = ""; + + my $basedir; + + my $parsing_file; + my @lines; + + $ENV{builddir} = $builddir; + $ENV{srcdir} = $srcdir; + + ($parsing_file, $basedir, @lines) = + _read_config_file($srcdir, $builddir, $filename); + + die ("$0: can't open '$filename'") + unless ($parsing_file and $basedir and @lines); + + my $line = ""; + my $prev = ""; + + # Emit a line that lets us match up final makefile output with the + # corresponding input files. The curlies are so you can match the + # BEGIN/END pairs in a text editor. + $makefile .= "# BEGIN{ $parsing_file\n"; + + foreach (@lines) { + $linenum++; + + # lines beginning with '#' are ignored + next if (/^\#.*$/); + + if (/^(.*)\\$/) { + $prev .= $1; + next; + } else { + $line = "$prev$_"; + $prev = ""; + } + + if ($line =~ /^\[([-a-zA-Z0-9_.:]+)\][\t ]*$/) + { + $section = $1; + $infragment = 0; + + $result->{$section}{EXISTS}{KEY} = "EXISTS"; + $result->{$section}{EXISTS}{VAL} = 1; + next; + } + + # include + if ($line =~ /^mkinclude (.*)$/) { + my $subfile= $1; + my $subdir = dirname($filename); + $subdir =~ s/^\.$//g; + $subdir =~ s/^\.\///g; + $subdir .= "/" if ($subdir ne ""); + $makefile .= "basedir := $subdir\n"; + $makefile .= run_config_mk($input, $srcdir, $builddir, $subdir.$subfile); + next; + } + + # empty line + if ($line =~ /^[ \t]*$/) { + $section = "GLOBAL"; + if ($infragment) { $makefile.="\n"; } + next; + } + + # global stuff is considered part of the makefile + if ($section eq "GLOBAL") { + if (!$infragment) { $makefile.="\n"; } + $makefile .= $line; + $infragment = 1; + next; + } + + # Assignment + if ($line =~ /^([a-zA-Z0-9_]+)[\t ]*=(.*)$/) { + $result->{$section}{$1}{VAL} = $2; + $result->{$section}{$1}{KEY} = $1; + + next; + } + + die("$parsing_file:$linenum: Bad line"); + } + + $makefile .= "# }END $parsing_file\n"; + + foreach my $section (keys %{$result}) { + my ($type, $name) = split(/::/, $section, 2); + + my $sectype = $section_types->{$type}; + if (not defined($sectype)) { + die($parsing_file.":[".$section."] unknown section type \"".$type."\"!"); + } + + $input->{$name}{NAME} = $name; + $input->{$name}{TYPE} = $type; + $input->{$name}{MK_FILE} = $parsing_file; + $input->{$name}{BASEDIR} = $basedir; + + foreach my $key (values %{$result->{$section}}) { + next if ($key->{KEY} eq "EXISTS"); + $key->{VAL} = smb_build::input::strtrim($key->{VAL}); + my $vartype = $sectype->{$key->{KEY}}; + if (not defined($vartype)) { + die($parsing_file.":[".$section."]: unknown attribute type \"$key->{KEY}\"!"); + } + if ($vartype eq "string") { + $input->{$name}{$key->{KEY}} = $key->{VAL}; + } elsif ($vartype eq "list") { + $input->{$name}{$key->{KEY}} = [smb_build::input::str2array($key->{VAL})]; + } elsif ($vartype eq "bool") { + if (($key->{VAL} ne "YES") and ($key->{VAL} ne "NO")) { + die("Invalid value for bool attribute $key->{KEY}: $key->{VAL} in section $section"); + } + $input->{$name}{$key->{KEY}} = $key->{VAL}; + } + } + } + + return $makefile; +} + +1; |