delibtoolize.pl revision 1111
98N/A#! /usr/perl5/bin/perl
98N/A#
1111N/A# Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
98N/A#
235N/A# Permission is hereby granted, free of charge, to any person obtaining a
919N/A# copy of this software and associated documentation files (the "Software"),
919N/A# to deal in the Software without restriction, including without limitation
919N/A# the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A# and/or sell copies of the Software, and to permit persons to whom the
919N/A# Software is furnished to do so, subject to the following conditions:
493N/A#
919N/A# The above copyright notice and this permission notice (including the next
919N/A# paragraph) shall be included in all copies or substantial portions of the
919N/A# Software.
493N/A#
919N/A# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A# DEALINGS IN THE SOFTWARE.
235N/A#
98N/A#
98N/A
98N/A#
98N/A# Undo libtool damage to makefiles to allow us to control the linker
98N/A# settings that libtool tries to force on us.
98N/A#
241N/A# Usage: delibtoolize.pl [-P] <path>
241N/A# -P - Use large pic flags (-KPIC/-fPIC) instead of default/small (-Kpic/-fpic)
520N/A# -s - Only track libraries from a single file at a time, instead of across all
520N/A# files in a project
98N/A
98N/Ause strict;
98N/Ause warnings;
98N/Ause integer;
241N/Ause Getopt::Std;
98N/A
98N/Ause File::Find;
98N/A
241N/Amy %opts;
520N/Agetopts('Ps', \%opts);
241N/A
241N/Amy $pic_size = "pic";
241N/Aif (exists($opts{'P'})) {
241N/A $pic_size = "PIC";
241N/A}
241N/A
520N/Amy $single_file;
520N/Aif (exists($opts{'s'})) {
520N/A $single_file = 1;
520N/A}
520N/A
493N/Amy %compiler_pic_flags = ( 'cc' => "-K$pic_size -DPIC",
493N/A 'gcc' => "-f$pic_size -DPIC" );
493N/Amy %compiler_sharedobj_flags = ( 'cc' => '-G -z allextract',
493N/A 'gcc' => '-shared -Wl,-z,allextract' );
493N/A
493N/Amy %so_versions = ();
577N/Amy %ltlib_names = ();
493N/Amy @Makefiles;
493N/A
577N/Asub rulename_to_filename {
577N/A my $rulename = $_[0];
577N/A if (exists($ltlib_names{$rulename})) {
577N/A return $ltlib_names{$rulename};
577N/A } else {
577N/A return $rulename;
577N/A }
577N/A}
577N/A
1029N/A# Expands make macros in a string
1029N/Asub expand_macros {
1029N/A my ($in, $macro_ref) = @_;
1029N/A
1029N/A $in =~ s{\$\(([^\)]+)\)}{
1029N/A exists($macro_ref->{$1}) ? $macro_ref->{$1} : "" }msgex;
1029N/A
1029N/A return $in;
1029N/A}
1029N/A
493N/Asub scan_file {
235N/A if ($_ eq 'Makefile' && -f $_) {
493N/A my $old_file = $_;
98N/A
235N/A open my $OLD, '<', $old_file
235N/A or die "Can't open $old_file for reading: $!\n";
98N/A
98N/A # Read in original file and preprocess for data we'll need later
493N/A my $l = "";
577N/A my %makefile_macros = ();
577N/A my %makefile_ldflags = ();
1029N/A my @makefile_ltlibs = ();
577N/A
493N/A while (my $n = <$OLD>) {
493N/A $l .= $n;
493N/A # handle line continuation
493N/A next if ($n =~ m/\\$/);
98N/A
577N/A # Save macros for later expansion if needed
1029N/A if ($l =~ m/^([^\#\s]*)\s*=\s*(.*?)\s*$/ms) {
577N/A $makefile_macros{$1} = $2;
577N/A }
577N/A
493N/A if ($l =~ m/^([^\#\s]*)_la_LDFLAGS\s*=(.*)/ms) {
493N/A my $libname = $1;
493N/A my $flags = $2;
520N/A
577N/A $makefile_ldflags{$libname} = $flags;
577N/A }
577N/A elsif ($l =~ m/^[^\#\s]*_LTLIBRARIES\s*=(.*)$/ms) {
1029N/A push @makefile_ltlibs, $1;
98N/A }
493N/A $l = "";
98N/A }
235N/A close($OLD) or die;
98N/A
1029N/A foreach my $ltline ( @makefile_ltlibs ) {
1029N/A my $ltline_exp = expand_macros($ltline, \%makefile_macros);
1029N/A foreach my $ltl (split /\s+/, $ltline_exp) {
1029N/A $ltl =~ s{\.la$}{}ms;
1029N/A my $transformed = $ltl;
1029N/A $transformed =~ s{[^\w\@]}{_}msg;
1029N/A $ltlib_names{$transformed} = $ltl;
1029N/A }
1029N/A }
1029N/A
577N/A foreach my $librulename (keys %makefile_ldflags) {
577N/A my $libname = rulename_to_filename($librulename);
1029N/A my $flags = expand_macros($makefile_ldflags{$librulename},
1029N/A \%makefile_macros);
577N/A my $vers;
577N/A
577N/A if ($flags =~ m/[\b\s]-version-(number|info)\s+(\S+)/ms) {
577N/A my $vtype = $1;
577N/A my $v = $2;
577N/A
577N/A if (($vtype eq "info") && ($v =~ m/^(\d+):\d+:(\d+)$/ms)) {
577N/A $vers = $1 - $2;
577N/A } elsif ($v =~ m/^(\d+)[:\d]*$/ms) {
577N/A $vers = $1;
577N/A } else {
577N/A $vers = $v;
577N/A }
577N/A }
577N/A elsif ($flags =~ m/-avoid-version\b/ms) {
577N/A $vers = 'none';
577N/A }
577N/A
577N/A my $ln = $libname;
577N/A if ($single_file) {
577N/A $ln = $File::Find::name . "::" . $libname;
577N/A }
577N/A if (defined($vers) && !defined($so_versions{$ln})) {
577N/A $so_versions{$ln} = $vers;
577N/A# print "Set version to $so_versions{$ln} for $ln.\n";
577N/A }
577N/A }
577N/A
493N/A push @Makefiles, $File::Find::name;
98N/A }
98N/A}
98N/A
493N/Asub modify_file {
493N/A my ($filename) = @_;
493N/A
493N/A print "delibtoolizing $filename...\n";
493N/A
493N/A my $old_file = $filename . '~';
493N/A my $new_file = $filename;
493N/A rename($new_file, $old_file) or
493N/A die "Can't rename $new_file to $old_file: $!\n";
493N/A
493N/A open my $OLD, '<', $old_file
493N/A or die "Can't open $old_file for reading: $!\n";
493N/A open my $NEW, '>', $new_file
493N/A or die "Can't open $new_file for writing: $!\n";
493N/A
493N/A my $compiler;
493N/A my @inlines = ();
493N/A
493N/A # Read in original file and preprocess for data we'll need later
493N/A my $l = "";
493N/A while (my $n = <$OLD>) {
493N/A $l .= $n;
493N/A # handle line continuation
493N/A next if ($n =~ m/\\$/);
493N/A
1054N/A if ($l =~ m/^\s*CC\s*=(?:.*\s+)?(\S*cc)/) {
493N/A $compiler = $1;
493N/A }
493N/A
493N/A push @inlines, $l;
493N/A $l = "";
493N/A }
493N/A close($OLD) or die;
493N/A
493N/A my $compiler_type = 'cc'; # default to Sun Studio
493N/A if (defined($compiler) && ($compiler =~ m/gcc/)) {
493N/A $compiler_type = 'gcc';
493N/A }
493N/A
493N/A my $picflags = $compiler_pic_flags{$compiler_type};
493N/A my $sharedobjflags = $compiler_sharedobj_flags{$compiler_type};
493N/A
493N/A my $curtarget = "";
493N/A
493N/A foreach $l (@inlines) {
493N/A chomp $l;
493N/A
493N/A # Remove libtool script from compile steps &
493N/A # add PIC flags that libtool normally provides
493N/A $l =~ s{\$\(LIBTOOL\)
493N/A (?:[\\\s]+ \$\(LT_QUIET\))?
851N/A (?:[\\\s]+ \$\(AM_V_lt\))?
493N/A (?:[\\\s]+ --tag=(?:CC|CXX))?
493N/A (?:[\\\s]+ \$\(AM_LIBTOOLFLAGS\) [\\\s]+ \$\(LIBTOOLFLAGS\))?
493N/A [\\\s]+ --mode=compile
684N/A [\\\s]+ (\$\(CC\)|\$\(CCAS\)|\$\(CXX\)|\$\(COMPILE\))
493N/A }{$1 $picflags}xs;
493N/A
493N/A # Remove libtool script from link step
493N/A $l =~ s{\$\(LIBTOOL\)
493N/A (?:[\\\s]+ \$\(LT_QUIET\))?
851N/A (?:[\\\s]+ \$\(AM_V_lt\))?
493N/A (?:[\\\s]+ --tag=(?:CC|CXX))?
493N/A (?:[\\\s]+ \$\(AM_LIBTOOLFLAGS\) [\\\s]+ \$\(LIBTOOLFLAGS\))?
493N/A [\\\s]+ --mode=link
493N/A }{}xs;
493N/A
493N/A # Change -rpath to -R in link arguments
493N/A $l =~ s{(\s*)-rpath(\s*)}{$1-R$2}msg;
493N/A
493N/A # Change flags for building shared object from arguments to libtool
493N/A # script into arguments to linker
493N/A if ($l =~ m/_la_LDFLAGS\s*=/) {
493N/A $l =~ s{(\s*$sharedobjflags)+\b}{}msg;
493N/A $l =~ s{(_la_LDFLAGS\s*=\s*)}{$1 $sharedobjflags }ms;
493N/A $l =~ s{(\s+)-avoid-version\b}{$1}ms;
493N/A $l =~ s{(\s+)-module\b}{$1}ms;
493N/A $l =~ s{(\s+)-version-(?:number|info)\s+\S+}{$1-h \$\@}ms;
493N/A $l =~ s{(\s+)-no-undefined\b}{$1-z defs}ms;
493N/A }
493N/A
493N/A # Change file names
520N/A my @so_list = keys %so_versions;
520N/A if ($single_file) {
520N/A my $pat = $filename . "::";
520N/A @so_list = grep(/^$pat/, @so_list);
520N/A }
520N/A foreach my $so (@so_list) {
577N/A my $v = $so_versions{$so};
577N/A if ($v eq 'none') {
493N/A $l =~ s{$so\.la\b}{$so.so}msg;
493N/A } else {
577N/A $l =~ s{$so\.la\b}{$so.so.$v}msg;
493N/A }
493N/A }
493N/A $l =~ s{\.la\b}{.a}msg;
577N/A $l =~ s{\.libs/([\*%])\.o\b}{$1.lo}msg;
493N/A $l =~ s{\.lo\b}{.o}msg;
493N/A
493N/A my $newtarget = $curtarget;
493N/A if ($l =~ m/^(\S+):/) {
493N/A $newtarget = $1;
493N/A } elsif ($l =~ m/^\s*$/) {
493N/A $newtarget = "";
493N/A }
493N/A
493N/A if ($curtarget ne $newtarget) { # end of rules for a target
493N/A # Need to add in .so links that libtool makes for .la installs
493N/A if ($curtarget =~ m/^install-(.*)LTLIBRARIES$/ms) {
493N/A my $dirname = $1;
493N/A my $installrule = <<'END_RULE';
493N/A list='$(<DIRNAME>_LTLIBRARIES)'; for p in $$list; do \
1111N/A so=$${p%.[[:digit:]]} ; \
684N/A if [[ "$$p" != "$$so" ]] ; then \
493N/A echo "rm -f $(DESTDIR)$(<DIRNAME>dir)/$$so" ; \
493N/A rm -f $(DESTDIR)$(<DIRNAME>dir)/$$so ; \
493N/A echo "ln -s $$p $(DESTDIR)$(<DIRNAME>dir)/$$so" ; \
493N/A ln -s $$p $(DESTDIR)$(<DIRNAME>dir)/$$so ; \
493N/A fi; \
493N/A done
493N/AEND_RULE
493N/A $installrule =~ s/\<DIRNAME\>/$dirname/msg;
493N/A $l .= $installrule;
493N/A }
493N/A
493N/A $curtarget = $newtarget;
493N/A }
493N/A
493N/A # Static libraries
493N/A if ($curtarget =~ m/^.*\.a$/) {
493N/A $l =~ s{\$\(\w*LINK\)}{\$(AR) cru $curtarget}ms;
493N/A $l =~ s{\$\(\w*(?:LIBS|LIBADD)\)}{}msg;
493N/A $l =~ s{(\$\((?:\w*_)?AR\).*\s+)-R\s*\$\(libdir\)}{$1}msg;
493N/A }
493N/A
493N/A print $NEW $l, "\n";
493N/A $l = "";
493N/A }
493N/A close($NEW) or die;
493N/A}
493N/A
493N/Afind(\&scan_file, @ARGV);
493N/A
493N/Aforeach my $mf ( @Makefiles ) {
493N/A modify_file($mf);
493N/A}