From 738aedb2f3e4c28c94374a3ca48da92b8372c9d0 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sun, 7 Mar 2004 12:36:53 +0000 Subject: [PATCH] Fix for PR automake/285: * automake.in (handle_ltlibraries): Keep track of installation directories for each condition, then define a $(am_TARGET_rpath) variable to hold the -rpath flags of Libtool libraries conditionally installed in different directories. * lib/Automake/DisjConditions.pm (merge): New function. * tests/libtool6.test: Adjust. * tests/libtool8.test: New file. * tests/Makefile.am (TEST): Add libtool8.test. --- ChangeLog | 10 +++ NEWS | 10 +++ automake.in | 141 +++++++++++++++++++++------------ lib/Automake/DisjConditions.pm | 22 ++++- tests/Makefile.am | 1 + tests/Makefile.in | 1 + tests/libtool6.test | 13 ++- tests/libtool8.test | 56 +++++++++++++ 8 files changed, 197 insertions(+), 57 deletions(-) create mode 100755 tests/libtool8.test diff --git a/ChangeLog b/ChangeLog index abe5e293..930808b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2004-03-07 Alexandre Duret-Lutz + Fix for PR automake/285: + * automake.in (handle_ltlibraries): Keep track of installation + directories for each condition, then define a $(am_TARGET_rpath) + variable to hold the -rpath flags of Libtool libraries conditionally + installed in different directories. + * lib/Automake/DisjConditions.pm (merge): New function. + * tests/libtool6.test: Adjust. + * tests/libtool8.test: New file. + * tests/Makefile.am (TEST): Add libtool8.test. + * lib/Automake/Variable.pm (traverse_recursively, _do_recursive_traversal): Honor the skip_ac_subst option. * automake.in (handle_dist): Use skip_ac_subst. diff --git a/NEWS b/NEWS index e90e9a44..7e9156c1 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,16 @@ New in 1.8a: * Support for conditional _LISP. +* Automake is now able to handle setups where a libtool library is + conditionally installed in different directories, as in + + if COND + lib_LTLIBRARIES = liba.la + else + pkglib_LTLIBRARIES = liba.la + endif + liba_la_SOURCES = ... + New in 1.8: diff --git a/automake.in b/automake.in index bd233012..c7f59c3b 100755 --- a/automake.in +++ b/automake.in @@ -2386,7 +2386,6 @@ sub handle_ltlibraries 'noinst', 'lib', 'pkglib', 'check'); return if ! @liblist; - my %instdirs; my @prefix = am_primary_prefixes ('LTLIBRARIES', 0, 'lib', 'pkglib', 'noinst', 'check'); @@ -2396,6 +2395,8 @@ sub handle_ltlibraries $var->requires_variables ('Libtool library used', 'LIBTOOL'); } + my %instdirs = (); + my %instconds = (); my %liblocations = (); # Location (in Makefile.am) of each library. foreach my $key (@prefix) @@ -2403,39 +2404,66 @@ sub handle_ltlibraries # Get the installation directory of each library. (my $dir = $key) =~ s/^nobase_//; my $var = rvar ($key . '_LTLIBRARIES'); - for my $pair ($var->value_as_list_recursive (location => 1)) - { - my ($where, $lib) = @$pair; - # We reject libraries which are installed in several places, - # because we don't handle this in the rules (think `-rpath'). - # - # However, we allow the same library to be listed many times - # for the same directory. This is for users who need setups - # like - # if COND1 - # lib_LTLIBRARIES = libfoo.la - # endif - # if COND2 - # lib_LTLIBRARIES = libfoo.la - # endif - # - # Actually this will also allow - # lib_LTLIBRARIES = libfoo.la libfoo.la - # Diagnosing this case doesn't seem worth the plain (we'd - # have to fill $instdirs on a per-condition basis, check - # implied conditions, etc.) - if (defined $instdirs{$lib} && $instdirs{$lib} ne $dir) - { - error ($where, "`$lib' is already going to be installed in " - . "`$instdirs{$lib}'", partial => 1); - error ($liblocations{$lib}, "`$lib' previously declared here"); - } - else - { - $instdirs{$lib} = $dir; - $liblocations{$lib} = $where->clone; - } - } + + # We reject libraries which are installed in several places + # in the same condition, because we can only specify one + # `-rpath' option. + $var->traverse_recursively + (sub + { + my ($var, $val, $cond, $full_cond) = @_; + my $hcond = $full_cond->human; + my $where = $var->rdef ($cond)->location; + # A library cannot be installed in different directory + # in overlapping conditions. + if (exists $instconds{$val}) + { + my ($msg, $acond) = + $instconds{$val}->ambiguous_p ($val, $full_cond); + + if ($msg) + { + error ($where, $msg, partial => 1); + + my $dirtxt = "installed in `$dir'"; + $dirtxt = "built for `$dir'" + if $dir eq 'EXTRA' || $dir eq 'noinst' || $dir eq 'check'; + my $dircond = + $full_cond->true ? "" : " in condition $hcond"; + + error ($where, "`$val' should be $dirtxt$dircond ...", + partial => 1); + + my $hacond = $acond->human; + my $adir = $instdirs{$val}{$acond}; + my $adirtxt = "installed in `$adir'"; + $adirtxt = "built for `$adir'" + if ($adir eq 'EXTRA' || $adir eq 'noinst' + || $adir eq 'check'); + my $adircond = $acond->true ? "" : " in condition $hacond"; + + my $onlyone = ($dir ne $adir) ? + ("\nLibtool libraries can be built for only one " + . "destination.") : ""; + + error ($liblocations{$val}{$acond}, + "... and should also be $adirtxt$adircond.$onlyone"); + return; + } + } + else + { + $instconds{$val} = new Automake::DisjConditions; + } + $instdirs{$val}{$full_cond} = $dir; + $liblocations{$val}{$full_cond} = $where; + $instconds{$val} = $instconds{$val}->merge ($full_cond); + }, + sub + { + return (); + }, + skip_ac_subst => 1); } foreach my $pair (@liblist) @@ -2505,21 +2533,36 @@ sub handle_ltlibraries $xlink = $linker ? $linker : 'LINK'; } - my $rpath; - if ($instdirs{$onelib} eq 'EXTRA' - || $instdirs{$onelib} eq 'noinst' - || $instdirs{$onelib} eq 'check') - { - # It's an EXTRA_ library, so we can't specify -rpath, - # because we don't know where the library will end up. - # The user probably knows, but generally speaking automake - # doesn't -- and in fact configure could decide - # dynamically between two different locations. - $rpath = ''; - } - else - { - $rpath = ('-rpath $(' . $instdirs{$onelib} . 'dir)'); + my $rpathvar = "am_${xlib}_rpath"; + my $rpath = "\$($rpathvar)"; + foreach my $rcond ($instconds{$onelib}->conds) + { + my $val; + if ($instdirs{$onelib}{$rcond} eq 'EXTRA' + || $instdirs{$onelib}{$rcond} eq 'noinst' + || $instdirs{$onelib}{$rcond} eq 'check') + { + # It's an EXTRA_ library, so we can't specify -rpath, + # because we don't know where the library will end up. + # The user probably knows, but generally speaking automake + # doesn't -- and in fact configure could decide + # dynamically between two different locations. + $val = ''; + } + else + { + $val = ('-rpath $(' . $instdirs{$onelib}{$rcond} . 'dir)'); + } + if ($rcond->true) + { + # If $rcond is true there is only one condition and + # there is no point defining an helper variable. + $rpath = $val; + } + else + { + define_pretty_variable ($rpathvar, $rcond, INTERNAL, $val); + } } # If the resulting library lies into a subdirectory, diff --git a/lib/Automake/DisjConditions.pm b/lib/Automake/DisjConditions.pm index 9204b76b..45745c4a 100644 --- a/lib/Automake/DisjConditions.pm +++ b/lib/Automake/DisjConditions.pm @@ -1,4 +1,4 @@ -# Copyright (C) 1997, 2001, 2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 1997, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -61,6 +61,9 @@ Automake::DisjConditions - record a disjunction of Conditions # "(COND1 and !COND2) or (!COND3)" my $str = $set->human; + # Merge (OR) several DisjConditions. + my $all = $set->merge($set2, $set3, ...) + # Invert a DisjConditions, i.e., create a new DisjConditions # that complements $set. my $inv = $set->invert; @@ -289,6 +292,23 @@ sub human ($ ) } +=item C<$newcond = $cond-Emerge (@otherconds)> + +Return a new C which is the disjunction of +C<$cond> and C<@otherconds>. Items in C<@otherconds> can be +@Cs or C. + +=cut + +sub merge ($@) +{ + my ($self, @otherconds) = @_; + new Automake::DisjConditions ( + map { $_->isa ("Automake::DisjConditions") ? $_->conds : $_ } + ($self, @otherconds)); +} + + =item C<$prod = $set1-Emultiply ($set2)> Multiply two conditional sets. diff --git a/tests/Makefile.am b/tests/Makefile.am index a1333479..67adfad7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -283,6 +283,7 @@ libtool4.test \ libtool5.test \ libtool6.test \ libtool7.test \ +libtool8.test \ license.test \ link_c_cxx.test \ link_dist.test \ diff --git a/tests/Makefile.in b/tests/Makefile.in index 8b808575..5ae0e5e8 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -398,6 +398,7 @@ libtool4.test \ libtool5.test \ libtool6.test \ libtool7.test \ +libtool8.test \ license.test \ link_c_cxx.test \ link_dist.test \ diff --git a/tests/libtool6.test b/tests/libtool6.test index fc18d7c1..bc190a94 100755 --- a/tests/libtool6.test +++ b/tests/libtool6.test @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (C) 2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. # # This file is part of GNU Automake. # @@ -18,8 +18,8 @@ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. -# Make sure it's not ok to install a library under different conditions -# in different directories. +# Make sure it's OK to install a library under different conditions +# in different directories. PR/285. required='libtoolize' . ./defs || exit 1 @@ -45,7 +45,6 @@ END libtoolize $ACLOCAL -AUTOMAKE_fails -grep 'liba\.la.* installed .*lib' stderr -grep 'Makefile.am:5:' stderr -grep 'Makefile.am:2:' stderr +$AUTOMAKE --add-missing +# am_liba_la_rpath is defined twice, and used once +test 3 = `grep 'am_liba_la_rpath' Makefile.in | wc -l` diff --git a/tests/libtool8.test b/tests/libtool8.test new file mode 100755 index 00000000..18b1d182 --- /dev/null +++ b/tests/libtool8.test @@ -0,0 +1,56 @@ +#!/bin/sh +# Copyright (C) 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Automake. +# +# GNU Automake is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Automake is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Automake; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# Make sure Automake diagnoses conflicting installations. + +required='libtoolize' +. ./defs || exit 1 + +set -e + +cat >>configure.in <<'END' +AM_CONDITIONAL([COND1], [true]) +AM_CONDITIONAL([COND2], [false]) +AC_PROG_CC +AC_PROG_LIBTOOL +AC_OUTPUT +END + +cat >Makefile.am <<'END' +if COND1 + lib_LTLIBRARIES = liba.la + EXTRA_LTLIBRARIES = libc.la libc.la libb.la +else + lib_LTLIBRARIES = libb.la +endif +if COND2 +if COND1 + pkglib_LTLIBRARIES = liba.la +endif +endif +END + +libtoolize +$ACLOCAL +AUTOMAKE_fails --add-missing +grep libb stderr && exit 1 +grep 'Makefile.am:3:.*libc.la.*multiply defined' stderr +grep 'Makefile.am:9:.*`pkglib' stderr +grep 'Makefile.am:2:.*`lib' stderr -- 2.43.5