1 #! /usr/bin/env perl 2 # Copyright 2021-2026 The OpenSSL Project Authors. All Rights Reserved. 3 # 4 # Licensed under the Apache License 2.0 (the "License"). You may not use 5 # this file except in compliance with the License. You can obtain a copy 6 # in the file LICENSE in the source distribution or at 7 # https://www.openssl.org/source/license.html 8 9 # All variables are supposed to come from Makefile, in environment variable 10 # form, or passed as variable assignments on the command line. 11 # The result is a Perl module creating the package OpenSSL::safe::installdata. 12 13 use 5.10.0; 14 use strict; 15 use warnings; 16 use Carp; 17 18 use File::Spec; 19 #use List::Util qw(pairs); 20 sub _pairs (@); 21 22 # These are expected to be set up as absolute directories 23 my @absolutes = qw(PREFIX libdir); 24 # These may be absolute directories, and if not, they are expected to be set up 25 # as subdirectories to PREFIX or LIBDIR. The order of the pairs is important, 26 # since the LIBDIR subdirectories depend on the calculation of LIBDIR from 27 # PREFIX. 28 my @subdirs = _pairs (PREFIX => [ qw(BINDIR LIBDIR INCLUDEDIR APPLINKDIR) ], 29 LIBDIR => [ qw(ENGINESDIR MODULESDIR PKGCONFIGDIR 30 CMAKECONFIGDIR) ]); 31 # For completeness, other expected variables 32 my @others = qw(VERSION LDLIBS); 33 34 my %all = ( ); 35 foreach (@absolutes) { $all{$_} = 1 } 36 foreach (@subdirs) { foreach (@{$_->[1]}) { $all{$_} = 1 } } 37 foreach (@others) { $all{$_} = 1 } 38 print STDERR "DEBUG: all keys: ", join(", ", sort keys %all), "\n"; 39 40 my %keys = (); 41 my %values = (); 42 foreach (@ARGV) { 43 (my $k, my $v) = m|^([^=]*)=(.*)$|; 44 $keys{$k} = 1; 45 push @{$values{$k}}, $v; 46 } 47 48 # special case for LIBDIR vs libdir. 49 # For installations, They both get their value from ./Configure's --libdir or 50 # corresponding config target attribute, but LIBDIR only gets a value if the 51 # configuration is a relative path, while libdir always gets a value, so if 52 # the former doesn't have a value, we give it the latter's value, and rely 53 # on mechanisms further down to do the rest of the processing. 54 # If they're both empty, it's still fine. 55 print STDERR "DEBUG: LIBDIR = $values{LIBDIR}->[0], libdir = $values{libdir}->[0] => "; 56 $values{LIBDIR}->[0] = $values{libdir}->[0] unless $values{LIBDIR}->[0]; 57 print STDERR "LIBDIR = $values{LIBDIR}->[0]\n"; 58 59 # warn if there are missing values, and also if there are unexpected values 60 foreach my $k (sort keys %all) { 61 warn "No value given for $k\n" unless $keys{$k}; 62 } 63 foreach my $k (sort keys %keys) { 64 warn "Unknown variable $k\n" unless $all{$k}; 65 } 66 67 # This shouldn't be needed, but just in case we get relative paths that 68 # should be absolute, make sure they actually are. 69 foreach my $k (@absolutes) { 70 my $v = $values{$k} || [ '.' ]; 71 die "Can't have more than one $k\n" if scalar @$v > 1; 72 print STDERR "DEBUG: $k = $v->[0] => "; 73 $v = [ map { File::Spec->rel2abs($_) } @$v ]; 74 $values{$k} = $v; 75 print STDERR "$k = $v->[0]\n"; 76 } 77 78 # Absolute paths for the subdir variables are computed. This provides 79 # the usual form of values for names that have become norm, known as GNU 80 # installation paths. 81 # For the benefit of those that need it, the subdirectories are preserved 82 # as they are, using the same variable names, suffixed with '_REL_{var}', 83 # if they are indeed subdirectories. The '{var}' part of the name tells 84 # which other variable value they are relative to. 85 foreach my $pair (@subdirs) { 86 my ($var, $subdir_vars) = @$pair; 87 foreach my $k (@$subdir_vars) { 88 my $kr = "${k}_REL_${var}"; 89 my $v2 = $values{$k} || [ '.' ]; 90 $values{$k} = []; # We're rebuilding it 91 print STDERR "DEBUG: $k = ", 92 (scalar @$v2 > 1 ? "[ " . join(", ", @$v2) . " ]" : $v2->[0]), 93 " => "; 94 foreach my $v (@$v2) { 95 if (File::Spec->file_name_is_absolute($v)) { 96 push @{$values{$k}}, $v; 97 push @{$values{$kr}}, 98 File::Spec->abs2rel($v, $values{$var}->[0]); 99 } else { 100 push @{$values{$kr}}, $v; 101 push @{$values{$k}}, 102 File::Spec->rel2abs($v, $values{$var}->[0]); 103 } 104 } 105 print STDERR join(", ", 106 map { 107 my $v = $values{$_}; 108 "$_ = " . (scalar @$v > 1 109 ? "[ " . join(", ", @$v) . " ]" 110 : $v->[0]); 111 } ($k, $kr)), 112 "\n"; 113 } 114 } 115 116 print <<_____; 117 package OpenSSL::safe::installdata; 118 119 use strict; 120 use warnings; 121 use Exporter; 122 our \@ISA = qw(Exporter); 123 our \@EXPORT = qw( 124 _____ 125 126 foreach my $k (@absolutes) { 127 print " \@$k\n"; 128 } 129 foreach my $pair (@subdirs) { 130 my ($var, $subdir_vars) = @$pair; 131 foreach my $k (@$subdir_vars) { 132 my $k2 = "${k}_REL_${var}"; 133 print " \@$k \@$k2\n"; 134 } 135 } 136 137 print <<_____; 138 \$VERSION \@LDLIBS 139 ); 140 141 _____ 142 143 foreach my $k (@absolutes) { 144 print "our \@$k" . ' ' x (27 - length($k)) . "= ( '", 145 join("', '", @{$values{$k}}), 146 "' );\n"; 147 } 148 foreach my $pair (@subdirs) { 149 my ($var, $subdir_vars) = @$pair; 150 foreach my $k (@$subdir_vars) { 151 my $k2 = "${k}_REL_${var}"; 152 print "our \@$k" . ' ' x (27 - length($k)) . "= ( '", 153 join("', '", @{$values{$k}}), 154 "' );\n"; 155 print "our \@$k2" . ' ' x (27 - length($k2)) . "= ( '", 156 join("', '", @{$values{$k2}}), 157 "' );\n"; 158 } 159 } 160 161 print <<_____; 162 our \$VERSION = '$values{VERSION}->[0]'; 163 our \@LDLIBS = 164 # Unix and Windows use space separation, VMS uses comma separation 165 \$^O eq 'VMS' 166 ? split(/ *, */, '$values{LDLIBS}->[0]') 167 : split(/ +/, '$values{LDLIBS}->[0]'); 168 169 1; 170 _____ 171 172 ######## Helpers 173 174 # _pairs LIST 175 # 176 # This operates on an even-sized list, and returns a list of "ARRAY" 177 # references, each containing two items from the given LIST. 178 # 179 # It is a quick cheap reimplementation of List::Util::pairs(), a function 180 # we cannot use, because it only appeared in perl v5.19.3, and we claim to 181 # support perl versions all the way back to v5.10. 182 183 sub _pairs (@) { 184 croak "Odd number of arguments" if @_ & 1; 185 186 my @pairlist = (); 187 188 while (@_) { 189 my $x = [ shift, shift ]; 190 push @pairlist, $x; 191 } 192 return @pairlist; 193 } 194