+if ($user_cflags ne "") { $config{cflags}="$config{cflags}$user_cflags"; }
+else { $no_user_cflags=1; }
+if (@user_defines) { $config{defines}=[ @{$config{defines}}, @user_defines ]; }
+else { $no_user_defines=1; }
+
+# ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
+
+$config{afalg}="";
+if ($target =~ m/^linux/) {
+ my $minver = 4*10000 + 1*100 + 0;
+ if ($config{cross_compile_prefix} eq "") {
+ my $verstr = `uname -r`;
+ my ($ma, $mi1, $mi2) = split("\\.", $verstr);
+ ($mi2) = $mi2 =~ /(\d+)/;
+ my $ver = $ma*10000 + $mi1*100 + $mi2;
+ if ($ver < $minver) {
+ $disabled{afalg} = "too-old-kernel";
+ } else {
+ push @{$config{engdirs}}, "afalg";
+ }
+ }
+} else {
+ $disabled{afalg} = "not-linux";
+}
+
+push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalg});
+
+# If we use the unified build, collect information from build.info files
+my %unified_info = ();
+
+if ($builder eq "unified") {
+ # Store the name of the template file we will build the build file from
+ # in %config. This may be useful for the build file itself.
+ my $build_file_template =
+ catfile($srcdir, "Configurations",
+ $builder_platform."-".$target{build_file}.".tmpl");
+ $build_file_template =
+ catfile($srcdir, "Configurations", $target{build_file}.".tmpl")
+ if (! -f $build_file_template);
+ $config{build_file_template} = $build_file_template;
+
+ use lib catdir(dirname(__FILE__),"util");
+ use with_fallback qw(Text::Template);
+
+ sub cleandir {
+ my $base = shift;
+ my $dir = shift;
+ my $relativeto = shift || ".";
+
+ $dir = catdir($base,$dir) unless isabsolute($dir);
+
+ # Make sure the directories we're building in exists
+ mkpath($dir);
+
+ my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
+ #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
+ return $res;
+ }
+
+ sub cleanfile {
+ my $base = shift;
+ my $file = shift;
+ my $relativeto = shift || ".";
+
+ $file = catfile($base,$file) unless isabsolute($file);
+
+ my $d = dirname($file);
+ my $f = basename($file);
+
+ # Make sure the directories we're building in exists
+ mkpath($d);
+
+ my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
+ #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
+ return $res;
+ }
+
+ my @build_infos = ( [ ".", "build.info" ] );
+ foreach (@{$config{dirs}}) {
+ push @build_infos, [ $_, "build.info" ]
+ if (-f catfile($srcdir, $_, "build.info"));
+ }
+ foreach (@{$config{sdirs}}) {
+ push @build_infos, [ catdir("crypto", $_), "build.info" ]
+ if (-f catfile($srcdir, "crypto", $_, "build.info"));
+ }
+ foreach (@{$config{engdirs}}) {
+ push @build_infos, [ catdir("engines", $_), "build.info" ]
+ if (-f catfile($srcdir, "engines", $_, "build.info"));
+ }
+
+ $config{build_infos} = [ ];
+
+ foreach (@build_infos) {
+ my $sourced = catdir($srcdir, $_->[0]);
+ my $buildd = catdir($blddir, $_->[0]);
+
+ mkpath($buildd);
+
+ my $f = $_->[1];
+ # The basic things we're trying to build
+ my @programs = ();
+ my @libraries = ();
+ my @engines = ();
+ my @scripts = ();
+ my @extra = ();
+ my @intermediates = ();
+ my @rawlines = ();
+
+ my %ordinals = ();
+ my %sources = ();
+ my %includes = ();
+ my %depends = ();
+ my %renames = ();
+ my %sharednames = ();
+
+ push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
+ my $template = Text::Template->new(TYPE => 'FILE',
+ SOURCE => catfile($sourced, $f));
+ die "Something went wrong with $sourced/$f: $!\n" unless $template;
+ my @text =
+ split /^/m,
+ $template->fill_in(HASH => { config => \%config,
+ target => \%target,
+ disabled => \%disabled,
+ builddir => abs2rel($buildd, $blddir),
+ sourcedir => abs2rel($sourced, $blddir),
+ buildtop => abs2rel($blddir, $blddir),
+ sourcetop => abs2rel($srcdir, $blddir) },
+ DELIMITERS => [ "{-", "-}" ]);
+
+ # The top item of this stack has the following values
+ # -2 positive already run and we found ELSE (following ELSIF should fail)
+ # -1 positive already run (skip until ENDIF)
+ # 0 negatives so far (if we're at a condition, check it)
+ # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
+ # 2 positive ELSE (following ELSIF should fail)
+ my @skip = ();
+ collect_information(
+ collect_from_array([ @text ],
+ qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
+ $l1 =~ s/\\$//; $l1.$l2 }),
+ # Info we're looking for
+ qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
+ => sub { push @skip, !! $1; },
+ qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
+ => sub { die "ELSIF out of scope" if ! @skip;
+ die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
+ $skip[$#skip] = -1 if $skip[$#skip] != 0;
+ $skip[$#skip] = !! $1
+ if $skip[$#skip] == 0; },
+ qr/^\s*ELSE\s*$/
+ => sub { die "ELSE out of scope" if ! @skip;
+ $skip[$#skip] = -2 if $skip[$#skip] != 0;
+ $skip[$#skip] = 2 if $skip[$#skip] == 0; },
+ qr/^\s*ENDIF\s*$/
+ => sub { die "ENDIF out of scope" if ! @skip;
+ pop @skip; },
+ qr/^\s*PROGRAMS\s*=\s*(.*)\s*$/
+ => sub { push @programs, split(/\s+/, $1)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*LIBS\s*=\s*(.*)\s*$/
+ => sub { push @libraries, split(/\s+/, $1)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*ENGINES\s*=\s*(.*)\s*$/
+ => sub { push @engines, split(/\s+/, $1)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*SCRIPTS\s*=\s*(.*)\s*$/
+ => sub { push @scripts, split(/\s+/, $1)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*EXTRA\s*=\s*(.*)\s*$/
+ => sub { push @extra, split(/\s+/, $1)
+ if !@skip || $skip[$#skip] > 0 },
+
+ qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
+ => sub { push @{$ordinals{$1}}, split(/\s+/, $2)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+ => sub { push @{$sources{$1}}, split(/\s+/, $2)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+ => sub { push @{$includes{$1}}, split(/\s+/, $2)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*DEPEND\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+ => sub { push @{$depends{$1}}, split(/\s+/, $2)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+ => sub { push @{$renames{$1}}, split(/\s+/, $2)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
+ => sub { push @{$sharednames{$1}}, split(/\s+/, $2)
+ if !@skip || $skip[$#skip] > 0 },
+ qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
+ => sub {
+ my $lineiterator = shift;
+ my $target_kind = $1;
+ while (defined $lineiterator->()) {
+ s|\R$||;
+ if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
+ die "ENDRAW doesn't match BEGINRAW"
+ if $1 ne $target_kind;
+ last;
+ }
+ next if @skip && $skip[$#skip] <= 0;
+ push @rawlines, $_
+ if ($target_kind eq $target{build_file}
+ || $target_kind eq $target{build_file}."(".$builder_platform.")");
+ }
+ },
+ qr/^(?:#.*|\s*)$/ => sub { },
+ "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" }
+ );
+ die "runaway IF?" if (@skip);
+
+ foreach (keys %renames) {
+ die "$_ renamed to more than one thing: "
+ ,join(" ", @{$renames{$_}}),"\n"
+ if scalar @{$renames{$_}} > 1;
+ my $dest = cleanfile($buildd, $_, $blddir);
+ my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
+ die "$dest renamed to more than one thing: "
+ ,$unified_info{rename}->{$dest}, $to
+ unless !defined($unified_info{rename}->{$dest})
+ or $unified_info{rename}->{$dest} eq $to;
+ $unified_info{rename}->{$dest} = $to;
+ }
+
+ foreach (@programs) {
+ my $program = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$program}) {
+ $program = $unified_info{rename}->{$program};
+ }
+ $unified_info{programs}->{$program} = 1;
+ }
+
+ foreach (@libraries) {
+ my $library = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$library}) {
+ $library = $unified_info{rename}->{$library};
+ }
+ $unified_info{libraries}->{$library} = 1;
+ }
+
+ die <<"EOF" if scalar @engines and !$config{dynamic_engines};
+ENGINES can only be used if configured with 'dynamic-engine'.
+This is usually a fault in a build.info file.
+EOF
+ foreach (@engines) {
+ my $library = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$library}) {
+ $library = $unified_info{rename}->{$library};
+ }
+ $unified_info{engines}->{$library} = 1;
+ }
+
+ foreach (@scripts) {
+ my $script = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$script}) {
+ $script = $unified_info{rename}->{$script};
+ }
+ $unified_info{scripts}->{$script} = 1;
+ }
+
+ foreach (@extra) {
+ my $extra = cleanfile($buildd, $_, $blddir);
+ $unified_info{extra}->{$extra} = 1;
+ }
+
+ push @{$unified_info{rawlines}}, @rawlines;
+
+ unless ($disabled{shared}) {
+ # Check sharednames.
+ foreach (keys %sharednames) {
+ my $dest = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$dest}) {
+ $dest = $unified_info{rename}->{$dest};
+ }
+ die "shared_name for $dest with multiple values: "
+ ,join(" ", @{$sharednames{$_}}),"\n"
+ if scalar @{$sharednames{$_}} > 1;
+ my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
+ die "shared_name found for a library $dest that isn't defined\n"
+ unless $unified_info{libraries}->{$dest};
+ die "shared_name for $dest with multiple values: "
+ ,$unified_info{sharednames}->{$dest}, ", ", $to
+ unless !defined($unified_info{sharednames}->{$dest})
+ or $unified_info{sharednames}->{$dest} eq $to;
+ $unified_info{sharednames}->{$dest} = $to;
+ }
+
+ # Additionally, we set up sharednames for libraries that don't
+ # have any, as themselves.
+ foreach (keys %{$unified_info{libraries}}) {
+ if (!defined $unified_info{sharednames}->{$_}) {
+ $unified_info{sharednames}->{$_} = $_
+ }
+ }
+ }
+
+ foreach (keys %ordinals) {
+ my $dest = $_;
+ my $ddest = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$ddest}) {
+ $ddest = $unified_info{rename}->{$ddest};
+ }
+ foreach (@{$ordinals{$dest}}) {
+ my %known_ordinals =
+ (
+ crypto =>
+ cleanfile($sourced, catfile("util", "libcrypto.num"), $blddir),
+ ssl =>
+ cleanfile($sourced, catfile("util", "libssl.num"), $blddir)
+ );
+ my $o = $known_ordinals{$_};
+ die "Ordinals for $ddest defined more than once\n"
+ if $unified_info{ordinals}->{$ddest};
+ $unified_info{ordinals}->{$ddest} = [ $_, $o ];
+ }
+ }
+
+ foreach (keys %sources) {
+ my $dest = $_;
+ my $ddest = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$ddest}) {
+ $ddest = $unified_info{rename}->{$ddest};
+ }
+ foreach (@{$sources{$dest}}) {
+ my $s = cleanfile($sourced, $_, $blddir);
+
+ # If it isn't in the source tree, we assume it's generated
+ # in the build tree
+ if (! -f $s) {
+ $s = cleanfile($buildd, $_, $blddir);
+ }
+ # We recognise C and asm files
+ if ($s =~ /\.[csS]\b$/) {
+ (my $o = $_) =~ s/\.[csS]\b$/.o/;
+ $o = cleanfile($buildd, $o, $blddir);
+ $unified_info{sources}->{$ddest}->{$o} = 1;
+ $unified_info{sources}->{$o}->{$s} = 1;
+ } else {
+ $unified_info{sources}->{$ddest}->{$s} = 1;
+ }
+ }
+ }
+
+ foreach (keys %depends) {
+ my $dest = $_;
+ my $ddest = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$ddest}) {
+ $ddest = $unified_info{rename}->{$ddest};
+ }
+ foreach (@{$depends{$dest}}) {
+ my $d = cleanfile($sourced, $_, $blddir);
+
+ # If we know it's generated, or assume it is because we can't
+ # find it in the source tree, we set file we depend on to be
+ # in the build tree rather than the source tree, and assume
+ # and that there are lines to build it in a BEGINRAW..ENDRAW
+ # section or in the Makefile template.
+ if (! -f $d
+ || !(grep { $d eq $_ }
+ map { cleanfile($srcdir, $_, $blddir) }
+ (@generated_headers, @generated_by_make_headers))) {
+ $d = cleanfile($buildd, $_, $blddir);
+ }
+ # Take note if the file to depend on is being renamed
+ if ($unified_info{rename}->{$d}) {
+ $d = $unified_info{rename}->{$d};
+ }
+ $unified_info{depends}->{$ddest}->{$d} = 1;
+ # If we depend on a header file, let's make sure it
+ # can get included
+ if ($d =~ /\.h$/) {
+ my $i = dirname($d);
+ push @{$unified_info{includes}->{$ddest}}, $i
+ unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}};
+ }
+ }
+ }
+
+ foreach (keys %includes) {
+ my $dest = $_;
+ my $ddest = cleanfile($buildd, $_, $blddir);
+ if ($unified_info{rename}->{$ddest}) {
+ $ddest = $unified_info{rename}->{$ddest};
+ }
+ foreach (@{$includes{$dest}}) {
+ my $i = cleandir($sourced, $_, $blddir);
+ push @{$unified_info{includes}->{$ddest}}, $i
+ unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}};
+ }
+ }
+ }
+
+ ### Make unified_info a bit more efficient
+ # One level structures
+ foreach (("programs", "libraries", "engines", "scripts", "extra")) {
+ $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
+ }
+ # Two level structures
+ foreach my $l1 (("sources", "ldadd", "depends")) {
+ foreach my $l2 (sort keys %{$unified_info{$l1}}) {
+ $unified_info{$l1}->{$l2} =
+ [ sort keys %{$unified_info{$l1}->{$l2}} ];
+ }
+ }
+}
+
+# For the schemes that need it, we provide the old *_obj configs
+# from the *_asm_obj ones
+foreach (grep /_(asm|aux)_src$/, keys %target) {
+ my $src = $_;
+ (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
+ ($target{$obj} = $target{$src}) =~ s/\.[csS]\b/.o/g;
+}
+