From f4c474eb7730cf8bd199a1cdc59008504fc76d67 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 22 Jan 2025 12:20:37 -0600 Subject: [PATCH] Remove Python build dependency when LINKER_USE_RPATH=ORIGIN This change converts the makeRPath.py script to Perl. Also changes the PYTHON default to run `python3` --- configure/CONFIG_BASE | 3 +- configure/CONFIG_COMMON | 8 +-- src/tools/Makefile | 4 +- src/tools/makeRPath.pl | 135 ++++++++++++++++++++++++++++++++++++++++ src/tools/makeRPath.py | 86 ------------------------- 5 files changed, 142 insertions(+), 94 deletions(-) create mode 100644 src/tools/makeRPath.pl delete mode 100644 src/tools/makeRPath.py diff --git a/configure/CONFIG_BASE b/configure/CONFIG_BASE index a737b37fc..7d2637f00 100644 --- a/configure/CONFIG_BASE +++ b/configure/CONFIG_BASE @@ -54,8 +54,7 @@ CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl) FILTERMAKEFLAGS = $(PERL) $(call FIND_TOOL,filterMakeflags.pl) FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG) $(QUESTION_FLAG) - -MAKERPATH = $(PYTHON) $(TOOLS)/makeRPath.py +MAKERPATH = $(PERL) $(TOOLS)/makeRPath.pl #--------------------------------------------------------------- # tools for installing libraries and products diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON index 9165ae294..42129726d 100644 --- a/configure/CONFIG_COMMON +++ b/configure/CONFIG_COMMON @@ -34,11 +34,11 @@ CROSS2 = $(CROSS_COMPILER_TARGET_ARCHS$(filter-out 1,$(words $(filter $(EPICS_HO BUILD_ARCHS = $(EPICS_HOST_ARCH) $(CROSS1) $(CROSS2) #------------------------------------------------------- -# Default for perl if it's on the PATH, -# otherwise override this in os/CONFIG_SITE..Common +# Defaults for Perl and Python assume they're on $PATH. +# Python (now python3) is only needed by developers, when building docs. +# Override these in os/CONFIG_SITE..Common or CONFIG_SITE.local PERL = perl -CSD - -PYTHON = python +PYTHON = python3 #------------------------------------------------------- # Check configure/RELEASE file for consistency diff --git a/src/tools/Makefile b/src/tools/Makefile index bb47f37a0..ad57b54a2 100644 --- a/src/tools/Makefile +++ b/src/tools/Makefile @@ -37,6 +37,7 @@ PERL_SCRIPTS += fullPathName.pl PERL_SCRIPTS += installEpics.pl PERL_SCRIPTS += makeAPIheader.pl PERL_SCRIPTS += makeMakefile.pl +PERL_SCRIPTS += makeRPath.pl PERL_SCRIPTS += makeTestfile.pl PERL_SCRIPTS += mkmf.pl PERL_SCRIPTS += munch.pl @@ -49,14 +50,13 @@ PERL_SCRIPTS += testFailures.pl PERL_SCRIPTS += useManifestTool.pl PERL_SCRIPTS += genVersionHeader.pl -PERL_SCRIPTS += makeRPath.py - HTMLS = style.css HTMLS += EPICS/Getopts.html HTMLS += EPICS/Path.html HTMLS += EPICS/Readfile.html HTMLS += fullPathName.html HTMLS += makeAPIheader.html +HTMLS += makeRPath.html HTMLS += munch.html HTMLS += podToHtml.html HTMLS += podToMD.html diff --git a/src/tools/makeRPath.pl b/src/tools/makeRPath.pl new file mode 100644 index 000000000..8120ff070 --- /dev/null +++ b/src/tools/makeRPath.pl @@ -0,0 +1,135 @@ +#!/usr/bin/env perl +#************************************************************************* +# SPDX-License-Identifier: EPICS +# EPICS BASE is distributed subject to a Software License Agreement found +# in file LICENSE that is included with this distribution. +#************************************************************************* + +use strict; +use warnings; + +use Getopt::Long; +use Cwd qw(abs_path getcwd); +use File::Spec; +use File::Basename; +use Pod::Usage; + +# Example: +# target to be installed as: /build/bin/blah +# post-install will copy as: /install/bin/blah +# +# Need to link against: +# /install/lib/libA.so +# /build/lib/libB.so +# /other/lib/libC.so +# +# Want final result to be: +# -rpath $ORIGIN/../lib -rpath /other/lib \ +# -rpath-link /build/lib -rpath-link /install/lib + +warn "[" . join(' ', $0, @ARGV) . "]\n" + if $ENV{EPICS_DEBUG_RPATH} && $ENV{EPICS_DEBUG_RPATH} eq 'YES'; + +# Defaults for command-line arguments +my $final = getcwd(); +my $root = ''; +my $origin = '$ORIGIN'; +my $help = 0; + +# Parse command-line arguments +GetOptions( + 'final|F=s' => \$final, + 'root|R=s' => \$root, + 'origin|O=s' => \$origin, + 'help|h' => \$help, +) or pod2usage( + -exitval => 2, + -verbose => 1, + -noperldoc => 1, +); + +# Display help message if requested +pod2usage( + -exitval => 1, + -verbose => 2, + -noperldoc => 1, +) if $help; + +# Convert paths to absolute +$final = abs_path($final); +my @roots = map { abs_path($_) } grep { length($_) } split(/:/, $root); + +# Determine the root containing the final location +my $froot; +foreach my $root (@roots) { + my $frel = File::Spec->abs2rel($final, $root); + if ($frel !~ /^\.\./) { + $froot = $root; + last; + } +} + +if (!defined $froot) { + warn "makeRPath: Final location $final\n" . + "Not under any of: @roots\n"; + @roots = (); # Skip $ORIGIN handling below +} + +# Prepare output +my (@output, %output); +foreach my $path (@ARGV) { + $path = abs_path($path); + foreach my $root (@roots) { + my $rrel = File::Spec->abs2rel($path, $root); + if ($rrel !~ /^\.\./) { + # Add rpath-link for internal use by 'ld' + my $opt = "-Wl,-rpath-link,$path"; + push @output, $opt unless $output{$opt}++; + + # Calculate relative path + my $rel_path = File::Spec->abs2rel($rrel, $final); + my $opath = File::Spec->catfile($origin, $rel_path); + $opt = "-Wl,-rpath,$opath"; + push @output, $opt unless $output{$opt}++; + last; + } + } +} + +# Print the output +print join(' ', @output), "\n"; + +__END__ + +=head1 NAME + +makeRPath.pl - Compute and output -rpath entries for given paths + +=head1 SYNOPSIS + +makeRPath.pl [options] [path ...] + +=head1 OPTIONS + + -h, --help Display detailed help and exit + -F, --final Final install location for ELF file + -R, --root Root(s) of relocatable tree, separated by ':' + -O, --origin Origin path (default: '$ORIGIN') + +=head1 DESCRIPTION + +Computes and outputs -rpath entries for each of the given paths. +Paths under C<--root> will be computed as relative to C<--final>. + +=head1 EXAMPLE + +A library to be placed in C and linked against libraries in +C, C, and C would pass + + makeRPath.pl -F /build/lib -R /build /build/lib /build/module/lib /other/lib + +which generates + + -Wl,-rpath,$ORIGIN/. -Wl,-rpath,$ORIGIN/../module/lib -Wl,-rpath,/other/lib + +=cut diff --git a/src/tools/makeRPath.py b/src/tools/makeRPath.py deleted file mode 100644 index ec024e2a9..000000000 --- a/src/tools/makeRPath.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -#************************************************************************* -# SPDX-License-Identifier: EPICS -# EPICS BASE is distributed subject to a Software License Agreement found -# in file LICENSE that is included with this distribution. -#************************************************************************* - -from __future__ import print_function - -import sys -import os -from collections import OrderedDict # used as OrderedSet - -from argparse import ArgumentParser - -if os.environ.get('EPICS_DEBUG_RPATH','')=='YES': - sys.stderr.write('%s'%sys.argv) - -P = ArgumentParser(description='''Compute and output -rpath entries for each of the given paths. - Paths under --root will be computed as relative to --final .''', -epilog=''' -eg. A library to be placed in /build/lib and linked against libraries in -'/build/lib', '/build/module/lib', and '/other/lib' would pass: - - "makeRPath.py -F /build/lib -R /build /build/lib /build/module/lib /other/lib" -which prints "-Wl,-rpath,$ORIGIN/. -Wl,-rpath,$ORIGIN/../module/lib -Wl,-rpath,/other/lib" -''') -P.add_argument('-F','--final',default=os.getcwd(), help='Final install location for ELF file') -P.add_argument('-R','--root',default='', help='Root(s) of relocatable tree. Separate with :') -P.add_argument('-O', '--origin', default='$ORIGIN') -P.add_argument('path', nargs='*') -args = P.parse_args() - -# eg. -# target to be installed as: /build/bin/blah -# -# post-install will copy as: /install/bin/blah -# -# Need to link against: -# /install/lib/libA.so -# /build/lib/libB.so -# /other/lib/libC.so -# -# Want final result to be: -# -rpath $ORIGIN/../lib -rpath /other/lib \ -# -rpath-link /build/lib -rpath-link /install/lib - -fdir = os.path.abspath(args.final) -roots = [os.path.abspath(root) for root in args.root.split(':') if len(root)] - -# find the root which contains the final location -froot = None -for root in roots: - frel = os.path.relpath(fdir, root) - if not frel.startswith('..'): - # final dir is under this root - froot = root - break - -if froot is None: - sys.stderr.write("makeRPath: Final location %s\nNot under any of: %s\n"%(fdir, roots)) - # skip $ORIGIN handling below... - roots = [] - -output = OrderedDict() -for path in args.path: - path = os.path.abspath(path) - - for root in roots: - rrel = os.path.relpath(path, root) - if not rrel.startswith('..'): - # path is under this root - - # some older binutils don't seem to handle $ORIGIN correctly - # when locating dependencies of libraries. So also provide - # the absolute path for internal use by 'ld' only. - output['-Wl,-rpath-link,'+path] = True - - # frel is final location relative to enclosing root - # rrel is target location relative to enclosing root - path = os.path.relpath(rrel, frel) - break - - output['-Wl,-rpath,'+os.path.join(args.origin, path)] = True - -print(' '.join(output))