mirror of
https://github.com/openssl/openssl.git
synced 2024-12-18 22:43:41 +08:00
186a31e510
Very simply, support having the .a extension to denote depending on static libraries. Note that this is not supported on native Windows when building shared libraries, as there is not static library then, just an import library with the same name. Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/1889)
257 lines
9.7 KiB
Perl
257 lines
9.7 KiB
Perl
{- # -*- Mode: perl -*-
|
|
|
|
use File::Basename;
|
|
|
|
# A cache of objects for which a recipe has already been generated
|
|
my %cache;
|
|
|
|
# resolvedepends and reducedepends work in tandem to make sure
|
|
# there are no duplicate dependencies and that they are in the
|
|
# right order. This is especially used to sort the list of
|
|
# libraries that a build depends on.
|
|
sub extensionlesslib {
|
|
my @result = map { $_ =~ /(\.a)?$/; $` } @_;
|
|
return @result if wantarray;
|
|
return $result[0];
|
|
}
|
|
sub resolvedepends {
|
|
my $thing = shift;
|
|
my $extensionlessthing = extensionlesslib($thing);
|
|
my @listsofar = @_; # to check if we're looping
|
|
my @list = @{$unified_info{depends}->{$extensionlessthing}};
|
|
my @newlist = ();
|
|
if (scalar @list) {
|
|
foreach my $item (@list) {
|
|
my $extensionlessitem = extensionlesslib($item);
|
|
# It's time to break off when the dependency list starts looping
|
|
next if grep { extensionlesslib($_) eq $extensionlessitem } @listsofar;
|
|
push @newlist, $item, resolvedepends($item, @listsofar, $item);
|
|
}
|
|
}
|
|
@newlist;
|
|
}
|
|
sub reducedepends {
|
|
my @list = @_;
|
|
my @newlist = ();
|
|
while (@list) {
|
|
my $item = shift @list;
|
|
my $extensionlessitem = extensionlesslib($item);
|
|
push @newlist, $item
|
|
unless grep { $extensionlessitem eq extensionlesslib($_) } @list;
|
|
}
|
|
@newlist;
|
|
}
|
|
|
|
# is_installed checks if a given file will be installed (i.e. they are
|
|
# not defined _NO_INST in build.info)
|
|
sub is_installed {
|
|
my $product = shift;
|
|
if (grep { $product eq $_ }
|
|
map { (@{$unified_info{install}->{$_}}) }
|
|
keys %{$unified_info{install}}) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
# dogenerate is responsible for producing all the recipes that build
|
|
# generated source files. It recurses in case a dependency is also a
|
|
# generated source file.
|
|
sub dogenerate {
|
|
my $src = shift;
|
|
return "" if $cache{$src};
|
|
my $obj = shift;
|
|
my $bin = shift;
|
|
my %opts = @_;
|
|
if ($unified_info{generate}->{$src}) {
|
|
die "$src is generated by Configure, should not appear in build file\n"
|
|
if ref $unified_info{generate}->{$src} eq "";
|
|
my $script = $unified_info{generate}->{$src}->[0];
|
|
$OUT .= generatesrc(src => $src,
|
|
generator => $unified_info{generate}->{$src},
|
|
generator_incs => $unified_info{includes}->{$script},
|
|
generator_deps => $unified_info{depends}->{$script},
|
|
deps => $unified_info{depends}->{$src},
|
|
incs => [ @{$unified_info{includes}->{$bin}},
|
|
@{$unified_info{includes}->{$obj}} ],
|
|
%opts);
|
|
foreach (@{$unified_info{depends}->{$src}}) {
|
|
dogenerate($_, $obj, $bin, %opts);
|
|
}
|
|
}
|
|
$cache{$src} = 1;
|
|
}
|
|
|
|
# doobj is responsible for producing all the recipes that build
|
|
# object files as well as dependency files.
|
|
sub doobj {
|
|
my $obj = shift;
|
|
return "" if $cache{$obj};
|
|
(my $obj_no_o = $obj) =~ s|\.o$||;
|
|
my $bin = shift;
|
|
my %opts = @_;
|
|
if (@{$unified_info{sources}->{$obj}}) {
|
|
$OUT .= src2obj(obj => $obj_no_o,
|
|
product => $bin,
|
|
srcs => $unified_info{sources}->{$obj},
|
|
deps => $unified_info{depends}->{$obj},
|
|
incs => [ @{$unified_info{includes}->{$bin}},
|
|
@{$unified_info{includes}->{$obj}} ],
|
|
%opts);
|
|
foreach ((@{$unified_info{sources}->{$obj}},
|
|
@{$unified_info{depends}->{$obj}})) {
|
|
dogenerate($_, $obj, $bin, %opts);
|
|
}
|
|
}
|
|
$cache{$obj} = 1;
|
|
}
|
|
|
|
# dolib is responsible for building libraries. It will call
|
|
# libobj2shlib is shared libraries are produced, and obj2lib in all
|
|
# cases. It also makes sure all object files for the library are
|
|
# built.
|
|
sub dolib {
|
|
my $lib = shift;
|
|
return "" if $cache{$lib};
|
|
unless ($disabled{shared}) {
|
|
my %ordinals =
|
|
$unified_info{ordinals}->{$lib}
|
|
? (ordinals => $unified_info{ordinals}->{$lib}) : ();
|
|
$OUT .= libobj2shlib(shlib => $unified_info{sharednames}->{$lib},
|
|
lib => $lib,
|
|
objs => [ map { (my $x = $_) =~ s|\.o$||; $x }
|
|
(@{$unified_info{sources}->{$lib}},
|
|
@{$unified_info{shared_sources}->{$lib}}) ],
|
|
deps => [ reducedepends(resolvedepends($lib)) ],
|
|
installed => is_installed($lib),
|
|
%ordinals);
|
|
foreach (@{$unified_info{shared_sources}->{$lib}}) {
|
|
doobj($_, $lib, intent => "lib", installed => is_installed($lib));
|
|
}
|
|
}
|
|
$OUT .= obj2lib(lib => $lib,
|
|
objs => [ map { (my $x = $_) =~ s|\.o$||; $x }
|
|
@{$unified_info{sources}->{$lib}} ]);
|
|
foreach (@{$unified_info{sources}->{$lib}}) {
|
|
doobj($_, $lib, intent => "lib");
|
|
}
|
|
$cache{$lib} = 1;
|
|
}
|
|
|
|
# doengine is responsible for building engines. It will call
|
|
# obj2dso, and also makes sure all object files for the library
|
|
# are built.
|
|
sub doengine {
|
|
my $lib = shift;
|
|
return "" if $cache{$lib};
|
|
$OUT .= obj2dso(lib => $lib,
|
|
objs => [ map { (my $x = $_) =~ s|\.o$||; $x }
|
|
(@{$unified_info{sources}->{$lib}},
|
|
@{$unified_info{shared_sources}->{$lib}}) ],
|
|
deps => [ resolvedepends($lib) ],
|
|
installed => is_installed($lib));
|
|
foreach ((@{$unified_info{sources}->{$lib}},
|
|
@{$unified_info{shared_sources}->{$lib}})) {
|
|
doobj($_, $lib, intent => "dso", installed => is_installed($lib));
|
|
}
|
|
$cache{$lib} = 1;
|
|
}
|
|
|
|
# dobin is responsible for building programs. It will call obj2bin,
|
|
# and also makes sure all object files for the library are built.
|
|
sub dobin {
|
|
my $bin = shift;
|
|
return "" if $cache{$bin};
|
|
my $deps = [ reducedepends(resolvedepends($bin)) ];
|
|
$OUT .= obj2bin(bin => $bin,
|
|
objs => [ map { (my $x = $_) =~ s|\.o$||; $x }
|
|
@{$unified_info{sources}->{$bin}} ],
|
|
deps => $deps,
|
|
installed => is_installed($bin));
|
|
foreach (@{$unified_info{sources}->{$bin}}) {
|
|
doobj($_, $bin, intent => "bin", installed => is_installed($bin));
|
|
}
|
|
$cache{$bin} = 1;
|
|
}
|
|
|
|
# dobin is responsible for building scripts from templates. It will
|
|
# call in2script.
|
|
sub doscript {
|
|
my $script = shift;
|
|
return "" if $cache{$script};
|
|
$OUT .= in2script(script => $script,
|
|
sources => $unified_info{sources}->{$script},
|
|
installed => is_installed($script));
|
|
$cache{$script} = 1;
|
|
}
|
|
|
|
sub dodir {
|
|
my $dir = shift;
|
|
return "" if !exists(&generatedir) or $cache{$dir};
|
|
$OUT .= generatedir(dir => $dir,
|
|
deps => $unified_info{dirinfo}->{$dir}->{deps},
|
|
%{$unified_info{dirinfo}->{$_}->{products}});
|
|
$cache{$dir} = 1;
|
|
}
|
|
|
|
# Start with populating the cache with all the overrides
|
|
%cache = map { $_ => 1 } @{$unified_info{overrides}};
|
|
|
|
# For convenience collect information regarding directories where
|
|
# files are generated, those generated files and the end product
|
|
# they end up in where applicable. Then, add build rules for those
|
|
# directories
|
|
if (exists &generatedir) {
|
|
my %loopinfo = ( "dso" => [ @{$unified_info{engines}} ],
|
|
"lib" => [ @{$unified_info{libraries}} ],
|
|
"bin" => [ @{$unified_info{programs}} ],
|
|
"script" => [ @{$unified_info{scripts}} ] );
|
|
foreach my $type (keys %loopinfo) {
|
|
foreach my $product (@{$loopinfo{$type}}) {
|
|
my %dirs = ();
|
|
my $pd = dirname($product);
|
|
|
|
# We already have a "test" target, and the current directory
|
|
# is just silly to make a target for
|
|
$dirs{$pd} = 1 unless $pd eq "test" || $pd eq ".";
|
|
|
|
foreach (@{$unified_info{sources}->{$product}}) {
|
|
my $d = dirname($_);
|
|
|
|
# We don't want to create targets for source directories
|
|
# when building out of source
|
|
next if ($config{sourcedir} ne $config{builddir}
|
|
&& $d =~ m|^\Q$config{sourcedir}\E|);
|
|
# We already have a "test" target, and the current directory
|
|
# is just silly to make a target for
|
|
next if $d eq "test" || $d eq ".";
|
|
|
|
$dirs{$d} = 1;
|
|
push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
|
|
if $d ne $pd;
|
|
}
|
|
foreach (keys %dirs) {
|
|
push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
|
|
$product;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Build mandatory generated headers
|
|
foreach (@{$unified_info{depends}->{""}}) { dogenerate($_); }
|
|
|
|
# Build all known libraries, engines, programs and scripts.
|
|
# Everything else will be handled as a consequence.
|
|
foreach (@{$unified_info{libraries}}) { dolib($_); }
|
|
foreach (@{$unified_info{engines}}) { doengine($_); }
|
|
foreach (@{$unified_info{programs}}) { dobin($_); }
|
|
foreach (@{$unified_info{scripts}}) { doscript($_); }
|
|
|
|
foreach (sort keys %{$unified_info{dirinfo}}) { dodir($_); }
|
|
|
|
# Finally, should there be any applicable BEGINRAW/ENDRAW sections,
|
|
# they are added here.
|
|
$OUT .= $_."\n" foreach @{$unified_info{rawlines}};
|
|
-}
|