X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=util%2Fadd-depends.pl;h=1a87cdd36490886591bb3029655e46e942e8d7a4;hp=1ffebc9fd79d4e1d26c6ecbf905da8aa161f44d6;hb=HEAD;hpb=433e857214731b45565668931d83b11c894b7a29 diff --git a/util/add-depends.pl b/util/add-depends.pl index 1ffebc9fd7..5f21adecbf 100644 --- a/util/add-depends.pl +++ b/util/add-depends.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy # in the file LICENSE in the source distribution or at # https://www.openssl.org/source/license.html @@ -14,6 +14,7 @@ use configdata; use File::Spec::Functions qw(:DEFAULT rel2abs); use File::Compare qw(compare_text); +use feature 'state'; # When using stat() on Windows, we can get it to perform better by avoid some # data. This doesn't affect the mtime field, so we're not losing anything... @@ -22,6 +23,7 @@ ${^WIN32_SLOPPY_STAT} = 1; my $debug = $ENV{ADD_DEPENDS_DEBUG}; my $buildfile = $config{build_file}; my $build_mtime = (stat($buildfile))[9]; +my $configdata_mtime = (stat('configdata.pm'))[9]; my $rebuild = 0; my $depext = $target{dep_extension} || ".d"; my @depfiles = @@ -29,14 +31,18 @@ my @depfiles = grep { # This grep has side effects. Not only does if check the existence # of the dependency file given in $_, but it also checks if it's - # newer than the build file, and if it is, sets $rebuild. + # newer than the build file or older than configdata.pm, and if it + # is, sets $rebuild. my @st = stat($_); - $rebuild = 1 if @st && $st[9] > $build_mtime; + $rebuild = 1 + if @st && ($st[9] > $build_mtime || $st[9] < $configdata_mtime); scalar @st > 0; # Determines the grep result } map { (my $x = $_) =~ s|\.o$|$depext|; $x; } - grep { $unified_info{sources}->{$_}->[0] =~ /\.cc?$/ } - keys %{$unified_info{sources}}; + ( ( grep { $unified_info{sources}->{$_}->[0] =~ /\.cc?$/ } + keys %{$unified_info{sources}} ), + ( grep { $unified_info{shared_sources}->{$_}->[0] =~ /\.cc?$/ } + keys %{$unified_info{shared_sources}} ) ); exit 0 unless $rebuild; @@ -45,8 +51,10 @@ exit 0 unless $rebuild; my $producer = shift @ARGV; die "Producer not given\n" unless $producer; -my $abs_srcdir = rel2abs($config{sourcedir}); -my $abs_blddir = rel2abs($config{builddir}); +my $srcdir = $config{sourcedir}; +my $blddir = $config{builddir}; +my $abs_srcdir = rel2abs($srcdir); +my $abs_blddir = rel2abs($blddir); # Convenient cache of absolute to relative map. We start with filling it # with mappings for the known generated header files. They are relative to @@ -60,11 +68,45 @@ my $abs_blddir = rel2abs($config{builddir}); # files we depend on in the same directory that only differ by character case, # we're fine. my %depconv_cache = - map { lc catfile($abs_blddir, $_) => $_ } + map { catfile($abs_blddir, $_) => $_ } keys %{$unified_info{generate}}; my %procedures = ( - 'gcc' => undef, # gcc style dependency files needs no mods + 'gcc' => + sub { + (my $objfile = shift) =~ s|\.d$|.o|i; + my $line = shift; + + # Remove the original object file + $line =~ s|^.*\.o: | |; + # All we got now is a dependency, shave off surrounding spaces + $line =~ s/^\s+//; + $line =~ s/\s+$//; + # Also, shave off any continuation + $line =~ s/\s*\\$//; + + # Split the line into individual header files, and keep those + # that exist in some form + my @headers; + for (split(/\s+/, $line)) { + my $x = rel2abs($_); + + if (!$depconv_cache{$x}) { + if (-f $x) { + $depconv_cache{$x} = $_; + } + } + + if ($depconv_cache{$x}) { + push @headers, $_; + } else { + print STDERR "DEBUG[$producer]: ignoring $objfile <- $line\n" + if $debug; + } + } + return ($objfile, join(' ', @headers)) if @headers; + return undef; + }, 'makedepend' => sub { # makedepend, in its infinite wisdom, wants to have the object file @@ -94,6 +136,14 @@ my %procedures = ( }, 'VMS C' => sub { + state $abs_srcdir_shaved = undef; + state $srcdir_shaved = undef; + + unless (defined $abs_srcdir_shaved) { + ($abs_srcdir_shaved = $abs_srcdir) =~ s|[>\]]$||; + ($srcdir_shaved = $srcdir) =~ s|[>\]]$||; + } + # current versions of DEC / Compaq / HP / VSI C strips away all # directory information from the object file, so we must insert it # back. To make life simpler, we simply replace it with the @@ -125,19 +175,48 @@ my %procedures = ( # All we got now is a dependency, just shave off surrounding spaces $line =~ s/^\s+//; $line =~ s/\s+$//; - return ($objfile, $line); + + # VMS C gives us absolute paths, always. Let's see if we can + # make them relative instead. + $line = canonpath($line); + + unless (defined $depconv_cache{$line}) { + my $dep = $line; + # Since we have already pre-populated the cache with + # mappings for generated headers, we only need to deal + # with the source tree. + if ($dep =~ s|^\Q$abs_srcdir_shaved\E([\.>\]])?|$srcdir_shaved$1|i) { + # Also check that the header actually exists + if (-f $line) { + $depconv_cache{$line} = $dep; + } + } + } + return ($objfile, $depconv_cache{$line}) + if defined $depconv_cache{$line}; + print STDERR "DEBUG[$producer]: ignoring $objfile <- $line\n" + if $debug; + + return undef; }, 'VC' => sub { - # For the moment, we only support Visual C on native Windows, or - # compatible compilers. With those, the flags /Zs /showIncludes - # give us the necessary output to be able to create dependencies - # that nmake (or any 'make' implementation) should be able to read, - # with a bit of help. The output we're interested in looks like - # this (it always starts the same) + # With Microsoft Visual C the flags /Zs /showIncludes give us the + # necessary output to be able to create dependencies that nmake + # (or any 'make' implementation) should be able to read, with a + # bit of help. The output we're interested in looks something + # like this (it always starts the same) # # Note: including file: {whatever header file} # + # This output is localized, so for example, the German pack gives + # us this: + # + # Hinweis: Einlesen der Datei: {whatever header file} + # + # To accommodate, we need to use a very general regular expression + # to parse those lines. + # # Since there's no object file name at all in that information, # we must construct it ourselves. @@ -148,13 +227,13 @@ my %procedures = ( # warnings, so we simply discard anything that doesn't start with # the Note: - if (/^Note: including file: */) { + if (/^[^:]*: [^:]*: */) { (my $tail = $') =~ s/\s*\R$//; # VC gives us absolute paths for all include files, so to # remove system header dependencies, we need to check that # they don't match $abs_srcdir or $abs_blddir. - $tail = lc canonpath($tail); + $tail = canonpath($tail); unless (defined $depconv_cache{$tail}) { my $dep = $tail; @@ -162,12 +241,64 @@ my %procedures = ( # mappings for generated headers, we only need to deal # with the source tree. if ($dep =~ s|^\Q$abs_srcdir\E\\|\$(SRCDIR)\\|i) { - $depconv_cache{$tail} = $dep; + # Also check that the header actually exists + if (-f $line) { + $depconv_cache{$tail} = $dep; + } } } return ($objfile, '"'.$depconv_cache{$tail}.'"') if defined $depconv_cache{$tail}; - print STDERR "DEBUG[VC]: ignoring $objfile <- $tail\n" + print STDERR "DEBUG[$producer]: ignoring $objfile <- $tail\n" + if $debug; + } + + return undef; + }, + 'embarcadero' => + sub { + # With Embarcadero C++Builder's preprocessor (cpp32.exe) the -Sx -Hp + # flags give us the list of #include files read, like the following: + # + # Including ->->{whatever header file} + # + # where each "->" indicates the nesting level of the #include. The + # logic here is otherwise the same as the 'VC' scheme. + # + # Since there's no object file name at all in that information, + # we must construct it ourselves. + + (my $objfile = shift) =~ s|\.d$|.obj|i; + my $line = shift; + + # There are also other lines mixed in, for example compiler + # warnings, so we simply discard anything that doesn't start with + # the Note: + + if (/^Including (->)*/) { + (my $tail = $') =~ s/\s*\R$//; + + # C++Builder gives us relative paths when possible, so to + # remove system header dependencies, we convert them to + # absolute paths and check that they don't match $abs_srcdir + # or $abs_blddir, just as the 'VC' scheme. + $tail = rel2abs($tail); + + unless (defined $depconv_cache{$tail}) { + my $dep = $tail; + # Since we have already pre-populated the cache with + # mappings for generated headers, we only need to deal + # with the source tree. + if ($dep =~ s|^\Q$abs_srcdir\E\\|\$(SRCDIR)\\|i) { + # Also check that the header actually exists + if (-f $line) { + $depconv_cache{$tail} = $dep; + } + } + } + return ($objfile, '"'.$depconv_cache{$tail}.'"') + if defined $depconv_cache{$tail}; + print STDERR "DEBUG[$producer]: ignoring $objfile <- $tail\n" if $debug; } @@ -175,10 +306,11 @@ my %procedures = ( }, ); my %continuations = ( - 'gcc' => undef, + 'gcc' => "\\", 'makedepend' => "\\", 'VMS C' => "-", 'VC' => "\\", + 'embarcadero' => "\\", ); die "Producer unrecognised: $producer\n" @@ -190,16 +322,14 @@ my $continuation = $continuations{$producer}; my $buildfile_new = "$buildfile-$$"; my %collect = (); -if (defined $procedure) { - foreach my $depfile (@depfiles) { - open IDEP,$depfile or die "Trying to read $depfile: $!\n"; - while () { - s|\R$||; # The better chomp - my ($target, $deps) = $procedure->($depfile, $_); - $collect{$target}->{$deps} = 1 if defined $target; - } - close IDEP; +foreach my $depfile (@depfiles) { + open IDEP,$depfile or die "Trying to read $depfile: $!\n"; + while () { + s|\R$||; # The better chomp + my ($target, $deps) = $procedure->($depfile, $_); + $collect{$target}->{$deps} = 1 if defined $target; } + close IDEP; } open IBF, $buildfile or die "Trying to read $buildfile: $!\n"; @@ -212,31 +342,21 @@ close IBF; print OBF "# DO NOT DELETE THIS LINE -- make depend depends on it.\n"; -if (defined $procedure) { - foreach my $target (sort keys %collect) { - my $prefix = $target . ' :'; - my @deps = sort keys %{$collect{$target}}; - - while (@deps) { - my $buf = $prefix; - $prefix = ''; +foreach my $target (sort keys %collect) { + my $prefix = $target . ' :'; + my @deps = sort keys %{$collect{$target}}; - while (@deps && ($buf eq '' - || length($buf) + length($deps[0]) <= 77)) { - $buf .= ' ' . shift @deps; - } - $buf .= ' '.$continuation if @deps; + while (@deps) { + my $buf = $prefix; + $prefix = ''; - print OBF $buf,"\n" or die "Trying to print: $!\n" - } - } -} else { - foreach my $depfile (@depfiles) { - open IDEP,$depfile or die "Trying to read $depfile: $!\n"; - while () { - print OBF or die "Trying to print: $!\n"; + while (@deps && ($buf eq '' + || length($buf) + length($deps[0]) <= 77)) { + $buf .= ' ' . shift @deps; } - close IDEP; + $buf .= ' '.$continuation if @deps; + + print OBF $buf,"\n" or die "Trying to print: $!\n" } }