#! /usr/bin/env perl
# -*- mode: perl; -*-
-# Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
my @argvcopy=@ARGV;
if (grep /^reconf(igure)?$/, @argvcopy) {
+ die "reconfiguring with other arguments present isn't supported"
+ if scalar @argvcopy > 1;
if (-f "./configdata.pm") {
my $file = "./configdata.pm";
unless (my $return = do $file) {
# All of the following is disabled by default (RC5 was enabled before 0.9.8):
our %disabled = ( # "what" => "comment"
- "aria" => "default",
"asan" => "default",
"crypto-mdebug" => "default",
"crypto-mdebug-backtrace" => "default",
$config{openssl_thread_defines}=[];
$config{openssl_sys_defines}=[];
$config{openssl_other_defines}=[];
+my $ldflags="";
my $libs="";
my $target="";
$config{options}="";
while (@argvcopy)
{
$_ = shift @argvcopy;
+
+ # Support env variable assignments among the options
+ if (m|^(\w+)=(.+)?$|)
+ {
+ $config{perlenv}->{$1} = $2;
+ next;
+ }
+
# VMS is a case insensitive environment, and depending on settings
# out of our control, we may receive options uppercased. Let's
# downcase at least the part before any equal sign.
{
read_config $1;
}
- elsif (/^-[lL](.*)$/ or /^-Wl,/)
+ elsif (/^-L(.*)$/)
+ {
+ $ldflags.=$_." ";
+ }
+ elsif (/^-l(.*)$/ or /^-Wl,/)
{
$libs.=$_." ";
}
&usage if (!%target || $target{template});
+%target = ( %{$table{DEFAULTS}}, %target );
+
+# Make the flags to build DSOs the same as for shared libraries unless they
+# are already defined
+$target{dso_cflags} = $target{shared_cflag} unless defined $target{dso_cflags};
+$target{dso_cxxflags} = $target{shared_cxxflag} unless defined $target{dso_cxxflags};
+$target{dso_lflags} = $target{shared_ldflag} unless defined $target{dso_lflags};
+{
+ my $shared_info_pl =
+ catfile(dirname($0), "Configurations", "shared-info.pl");
+ my %shared_info = read_eval_file($shared_info_pl);
+ push @{$target{_conf_fname_int}}, $shared_info_pl;
+ my $si = $target{shared_target};
+ while (ref $si ne "HASH") {
+ last if ! defined $si;
+ if (ref $si eq "CODE") {
+ $si = $si->();
+ } else {
+ $si = $shared_info{$si};
+ }
+ }
+
+ # Some of the 'shared_target' values don't have any entried in
+ # %shared_info. That's perfectly fine, AS LONG AS the build file
+ # template knows how to handle this. That is currently the case for
+ # Windows and VMS.
+ if (defined $si) {
+ # Just as above, copy certain shared_* attributes to the corresponding
+ # dso_ attribute unless the latter is already defined
+ $si->{dso_cflags} = $si->{shared_cflag} unless defined $si->{dso_cflags};
+ $si->{dso_cxxflags} = $si->{shared_cxxflag} unless defined $si->{dso_cxxflags};
+ $si->{dso_lflags} = $si->{shared_ldflag} unless defined $si->{dso_lflags};
+ foreach (sort keys %$si) {
+ $target{$_} = defined $target{$_}
+ ? add($si->{$_})->($target{$_})
+ : $si->{$_};
+ }
+ }
+}
+
my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
$config{conf_files} = [ sort keys %conf_files ];
-%target = ( %{$table{DEFAULTS}}, %target );
foreach my $feature (@{$target{disable}}) {
if (exists $deprecated_disablables{$feature}) {
$config{defines} = [];
$config{cflags} = "";
$config{cxxflags} = "";
+$config{lflags} = "";
$config{ex_libs} = "";
$config{shared_ldflag} = "";
}
$config{ex_libs}="$libs$config{ex_libs}" if ($libs ne "");
+$config{lflags}="$config{lflags}$ldflags" if ($ldflags ne "");
# If threads aren't disabled, check how possible they are
unless ($disabled{threads}) {
# This saves the build files from having to check
if ($disabled{pic})
{
- $target{shared_cflag} = $target{shared_ldflag} =
- $target{shared_rcflag} = "";
+ foreach (qw(shared_cflag shared_cxxflag shared_ldflag
+ dso_cflags dso_cxxflags dso_lflags))
+ {
+ $target{$_} = "";
+ }
}
else
{
}
}
-my %predefined;
-
-if ($^O ne "VMS") {
- my $cc = "$config{cross_compile_prefix}$target{cc}";
-
- # collect compiler pre-defines from gcc or gcc-alike...
- open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
- while (<PIPE>) {
- m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
- $predefined{$1} = $2 // "";
- }
- close(PIPE);
-
- if (!$disabled{makedepend}) {
- # We know that GNU C version 3 and up as well as all clang
- # versions support dependency generation
- if ($predefined{__GNUC__} >= 3) {
- $config{makedepprog} = $cc;
- } else {
- $config{makedepprog} = which('makedepend');
- $disabled{makedepend} = "unavailable" unless $config{makedepprog};
- }
+my %predefined = compiler_predefined($target{cc});
+
+# Check for makedepend capabilities.
+if (!$disabled{makedepend}) {
+ if ($config{target} =~ /^(VC|vms)-/) {
+ # For VC- and vms- targets, there's nothing more to do here. The
+ # functionality is hard coded in the corresponding build files for
+ # cl (Windows) and CC/DECC (VMS).
+ } elsif ($predefined{__GNUC__} >= 3) {
+ # We know that GNU C version 3 and up as well as all clang
+ # versions support dependency generation
+ $config{makedepprog} = "\$(CROSS_COMPILE)$target{cc}";
+ } else {
+ # In all other cases, we look for 'makedepend', and disable the
+ # capability if not found.
+ $config{makedepprog} = which('makedepend');
+ $disabled{makedepend} = "unavailable" unless $config{makedepprog};
}
}
-
# Deal with bn_ops ###################################################
$config{bn_ll} =0;
$config{build_infos} = [ ];
+ my %ordinals = ();
foreach (@build_infos) {
my $sourced = catdir($srcdir, $_->[0]);
my $buildd = catdir($blddir, $_->[0]);
my @intermediates = ();
my @rawlines = ();
- my %ordinals = ();
my %sources = ();
my %shared_sources = ();
my %includes = ();
if @doubles;
}
- 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 (! -f $s) {
$s = cleanfile($buildd, $_, $blddir);
}
- # We recognise C++, C and asm files
+
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
+ # We recognise C++, C and asm files
my $o = $_;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$o = cleanfile($buildd, $o, $blddir);
$unified_info{shared_sources}->{$ddest}->{$o} = 1;
$unified_info{sources}->{$o}->{$s} = 1;
+ } elsif ($s =~ /\.rc$/) {
+ # We also recognise resource files
+ my $o = $_;
+ $o =~ s/\.rc$/.res/; # Resource configuration
+ my $o = cleanfile($buildd, $o, $blddir);
+ $unified_info{shared_sources}->{$ddest}->{$o} = 1;
+ $unified_info{sources}->{$o}->{$s} = 1;
+ } elsif ($s =~ /\.(def|map|opt)$/) {
+ # We also recognise .def / .map / .opt files
+ # We know they are generated files
+ my $def = cleanfile($buildd, $s, $blddir);
+ $unified_info{shared_sources}->{$ddest}->{$def} = 1;
} else {
die "unrecognised source file type for shared library: $s\n";
}
}
$d .= $e;
$unified_info{depends}->{$ddest}->{$d} = 1;
- # If we depend on a header file or a perl module, let's make
- # sure it can get included
- if ($dest ne "" && $d =~ /\.(h|pm)$/) {
- my $i = dirname($d);
- push @{$unified_info{includes}->{$ddest}->{source}}, $i
- unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}->{source}};
- }
}
}
}
}
+ my $ordinals_text = join(', ', sort keys %ordinals);
+ warn <<"EOF" if $ordinals_text;
+
+WARNING: ORDINALS were specified for $ordinals_text
+They are ignored and should be replaced with a combination of GENERATE,
+DEPEND and SHARED_SOURCE.
+EOF
+
+ # Massage the result
+
+ # If we depend on a header file or a perl module, add an inclusion of
+ # its directory to allow smoothe inclusion
+ foreach my $dest (keys %{$unified_info{depends}}) {
+ next if $dest eq "";
+ foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
+ next unless $d =~ /\.(h|pm)$/;
+ if ($d eq "configdata.pm"
+ || defined($unified_info{generate}->{$d})) {
+ my $i = cleandir($blddir, dirname($d));
+ push @{$unified_info{includes}->{$dest}->{build}}, $i
+ unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{build}};
+ } else {
+ my $i = cleandir($srcdir, dirname($d));
+ push @{$unified_info{includes}->{$dest}->{source}}, $i
+ unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{source}};
+ }
+ }
+ }
+
+ # Trickle down includes placed on libraries, engines and programs to
+ # their sources (i.e. object files)
+ foreach my $dest (keys %{$unified_info{engines}},
+ keys %{$unified_info{libraries}},
+ keys %{$unified_info{programs}}) {
+ foreach my $k (("source", "build")) {
+ next unless defined($unified_info{includes}->{$dest}->{$k});
+ my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}};
+ foreach my $obj (grep /\.o$/,
+ (keys %{$unified_info{sources}->{$dest}},
+ keys %{$unified_info{shared_sources}->{$dest}})) {
+ foreach my $inc (@incs) {
+ unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc
+ unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}};
+ }
+ }
+ }
+ delete $unified_info{includes}->{$dest};
+ }
+
### Make unified_info a bit more efficient
# One level structures
foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
# Includes
foreach my $dest (sort keys %{$unified_info{includes}}) {
if (defined($unified_info{includes}->{$dest}->{build})) {
- my @source_includes =
- ( @{$unified_info{includes}->{$dest}->{source}} );
+ my @source_includes = ();
+ @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
+ if defined($unified_info{includes}->{$dest}->{source});
$unified_info{includes}->{$dest} =
[ @{$unified_info{includes}->{$dest}->{build}} ];
foreach my $inc (@source_includes) {
#print "RANLIB =", $target{ranlib} eq '$(CROSS_COMPILE)ranlib' ?
# "$config{cross_compile_prefix}ranlib" :
# "$target{ranlib}", "\n";
+print "LDFLAGS =$config{lflags} $target{lflags}\n";
print "EX_LIBS =$target{ex_libs} $config{ex_libs}\n";
my %builders = (
sub { _add($separator, @_, @x) };
}
+sub read_eval_file {
+ my $fname = shift;
+ my $content;
+ my @result;
+
+ open F, "< $fname" or die "Can't open '$fname': $!\n";
+ {
+ undef local $/;
+ $content = <F>;
+ }
+ close F;
+ {
+ local $@;
+
+ @result = ( eval $content );
+ warn $@ if $@;
+ }
+ return wantarray ? @result : $result[0];
+}
+
# configuration reader, evaluates the input file as a perl script and expects
# it to fill %targets with target configurations. Those are then added to
# %table.
sub read_config {
my $fname = shift;
- open(CONFFILE, "< $fname")
- or die "Can't open configuration file '$fname'!\n";
- my $x = $/;
- undef $/;
- my $content = <CONFFILE>;
- $/ = $x;
- close(CONFFILE);
- my %targets = ();
+ my %targets;
+
{
# Protect certain tables from tampering
- local %table = %::table;
+ local %table = ();
- eval $content;
- warn $@ if $@;
+ %targets = read_eval_file($fname);
}
+ my %preexisting = ();
+ foreach (sort keys %targets) {
+ $preexisting{$_} = 1 if $table{$_};
+ }
+ die <<"EOF",
+The following config targets from $fname
+shadow pre-existing config targets with the same name:
+EOF
+ map { " $_\n" } sort keys %preexisting
+ if %preexisting;
+
# For each target, check that it's configured with a hash table.
foreach (keys %targets) {
rename("$out.new", $out) || die "Can't rename $out.new, $!";
}
+sub compiler_predefined {
+ state %predefined;
+ my $default_compiler = shift;
+
+ return () if $^O eq 'VMS';
+
+ die 'compiler_predefines called without a default compiler'
+ unless $default_compiler;
+
+ if (! $predefined{$default_compiler}) {
+ my $cc = "$config{cross_compile_prefix}$default_compiler";
+
+ $predefined{$default_compiler} = {};
+
+ # collect compiler pre-defines from gcc or gcc-alike...
+ open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
+ while (my $l = <PIPE>) {
+ $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
+ $predefined{$default_compiler}->{$1} = $2 // '';
+ }
+ close(PIPE);
+ }
+
+ return %{$predefined{$default_compiler}};
+}
+
sub which
{
my ($name)=@_;
{
my $name = shift;
- return $config{perlenv}->{$name} if exists $config{perlenv}->{$name};
- $config{perlenv}->{$name} = $ENV{$name};
+ # Note that if $ENV{$name} doesn't exist or is undefined,
+ # $config{perlenv}->{$name} will be created with the value
+ # undef. This is intentional.
+
+ $config{perlenv}->{$name} = $ENV{$name}
+ if ! exists $config{perlenv}->{$name};
return $config{perlenv}->{$name};
}