Add a new Makefile flag, RUNTIME_PREFIX_PERL, which, when enabled, configures Perl scripts to locate the Git installation's Perl support libraries by resolving against the script's path, rather than hard-coding that path at build-time. Enabling RUNTIME_PREFIX_PERL overrides the system-specific Perl script installation path generated by MakeMaker to force installation into a platform-neutral location, "<prefix>/share/perl5". This change enables Git's Perl scripts to work when their Git installation is relocated or moved to another system. Signed-off-by: Dan Jacques <dnj@xxxxxxxxxx> Thanks-to: Ævar Arnfjörð Bjarmason <avarab@xxxxxxxxx> Thanks-to: Johannes Schindelin <johannes.schindelin@xxxxxx> --- Makefile | 53 +++++++++++++++++++++++- perl/Git/I18N.pm | 2 +- perl/header_templates/runtime_prefix.template.pl | 32 ++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 perl/header_templates/runtime_prefix.template.pl diff --git a/Makefile b/Makefile index e5e81ca1b..060b47879 100644 --- a/Makefile +++ b/Makefile @@ -428,6 +428,10 @@ all:: # # When cross-compiling, define HOST_CPU as the canonical name of the CPU on # which the built Git will run (for instance "x86_64"). +# +# Define RUNTIME_PREFIX_PERL to configure Git's PERL commands to locate Git +# support libraries relative to their filesystem path instead of hard-coding +# it. GIT-VERSION-FILE: FORCE @$(SHELL_PATH) ./GIT-VERSION-GEN @@ -465,6 +469,8 @@ ARFLAGS = rcs # mandir # infodir # htmldir +# localedir +# perllibdir # This can help installing the suite in a relocatable way. prefix = $(HOME) @@ -486,9 +492,12 @@ lib = lib # DESTDIR = pathsep = : +gitexecdir_relative = $(patsubst $(prefix)/%,%,$(gitexecdir)) mandir_relative = $(patsubst $(prefix)/%,%,$(mandir)) infodir_relative = $(patsubst $(prefix)/%,%,$(infodir)) +localedir_relative = $(patsubst $(prefix)/%,%,$(localedir)) htmldir_relative = $(patsubst $(prefix)/%,%,$(htmldir)) +perllibdir_relative = $(patsubst $(prefix)/%,%,$(perllibdir)) export prefix bindir sharedir sysconfdir gitwebdir perllibdir localedir @@ -1732,10 +1741,13 @@ mandir_relative_SQ = $(subst ','\'',$(mandir_relative)) infodir_relative_SQ = $(subst ','\'',$(infodir_relative)) perllibdir_SQ = $(subst ','\'',$(perllibdir)) localedir_SQ = $(subst ','\'',$(localedir)) +localedir_relative_SQ = $(subst ','\'',$(localedir_relative)) gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) +gitexecdir_relative_SQ = $(subst ','\'',$(gitexecdir_relative)) template_dir_SQ = $(subst ','\'',$(template_dir)) htmldir_relative_SQ = $(subst ','\'',$(htmldir_relative)) prefix_SQ = $(subst ','\'',$(prefix)) +perllibdir_relative_SQ = $(subst ','\'',$(perllibdir_relative)) gitwebdir_SQ = $(subst ','\'',$(gitwebdir)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) @@ -1966,10 +1978,45 @@ git.res: git.rc GIT-VERSION-FILE # This makes sure we depend on the NO_PERL setting itself. $(SCRIPT_PERL_GEN): GIT-BUILD-OPTIONS +# Used for substitution in Perl modules. Disabled when using RUNTIME_PREFIX_PERL +# since the locale directory is injected. +perl_localedir_SQ = $(localedir_SQ) + ifndef NO_PERL PERL_HEADER_TEMPLATE = perl/header_templates/fixed_prefix.template.pl PERL_DEFINES = $(PERL_PATH_SQ):$(PERLLIB_EXTRA_SQ):$(perllibdir_SQ) +PERL_DEFINES := $(PERL_PATH_SQ) $(PERLLIB_EXTRA_SQ) $(perllibdir_SQ) +PERL_DEFINES += $(RUNTIME_PREFIX_PERL) + +# Support Perl runtime prefix. In this mode, a different header is installed +# into Perl scripts. This header requires Perl resource directories to be +# relative to the executable installation path, $(gitexecdir), and uses this +# property to resolve $(perllibdir) and $(localedir). +ifdef RUNTIME_PREFIX_PERL + +PERL_HEADER_TEMPLATE = perl/header_templates/runtime_prefix.template.pl + +# Don't export a fixed $(localedir) path; it will be resolved by the Perl header +# at runtime. +perl_localedir_SQ = + +ifneq ($(filter /%,$(firstword $(perllibdir_relative))),) +$(error RUNTIME_PREFIX_PERL requires a relative perllibdir, not: $(perllibdir)) +endif + +ifneq ($(filter /%,$(firstword $(gitexecdir_relative))),) +$(error RUNTIME_PREFIX_PERL requires a relative gitexecdir, not: $(gitexecdir)) +endif + +ifneq ($(filter /%,$(firstword $(localedir_relative))),) +$(error RUNTIME_PREFIX_PERL requires a relative localedir, not: $(localedir)) +endif + +endif + +PERL_DEFINES += $(gitexecdir) $(perllibdir) $(localedir) + $(SCRIPT_PERL_GEN): % : %.perl GIT-PERL-DEFINES GIT-PERL-HEADER GIT-VERSION-FILE $(QUIET_GEN)$(RM) $@ $@+ && \ sed -e '1{' \ @@ -1982,6 +2029,7 @@ $(SCRIPT_PERL_GEN): % : %.perl GIT-PERL-DEFINES GIT-PERL-HEADER GIT-VERSION-FILE chmod +x $@+ && \ mv $@+ $@ +PERL_DEFINES := $(subst $(space),:,$(PERL_DEFINES)) GIT-PERL-DEFINES: FORCE @FLAGS='$(PERL_DEFINES)'; \ if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \ @@ -1997,6 +2045,9 @@ GIT-PERL-HEADER: $(PERL_HEADER_TEMPLATE) GIT-PERL-DEFINES Makefile sed -e 's=@@PATHSEP@@=$(pathsep)=g' \ -e 's=@@INSTLIBDIR@@='$$INSTLIBDIR'=g' \ -e 's=@@PERLLIBDIR@@='$(perllibdir_SQ)'=g' \ + -e 's=@@PERLLIBDIR_REL@@=$(perllibdir_relative_SQ)=g' \ + -e 's=@@GITEXECDIR_REL@@=$(gitexecdir_relative_SQ)=g' \ + -e 's=@@LOCALEDIR_REL@@=$(localedir_relative_SQ)=g' \ $< >$@+ && \ mv $@+ $@ @@ -2310,7 +2361,7 @@ endif perl/build/lib/%.pm: perl/%.pm $(QUIET_GEN)mkdir -p $(dir $@) && \ - sed -e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' < $< > $@ + sed -e 's|@@LOCALEDIR@@|$(perl_localedir_SQ)|g' < $< > $@ perl/build/man/man3/Git.3pm: perl/Git.pm $(QUIET_GEN)mkdir -p $(dir $@) && \ diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm index dba96fff0..bfb4fb67a 100644 --- a/perl/Git/I18N.pm +++ b/perl/Git/I18N.pm @@ -18,7 +18,7 @@ our @EXPORT_OK = @EXPORT; sub __bootstrap_locale_messages { our $TEXTDOMAIN = 'git'; - our $TEXTDOMAINDIR = $ENV{GIT_TEXTDOMAINDIR} || '@@LOCALEDIR@@'; + our $TEXTDOMAINDIR ||= $ENV{GIT_TEXTDOMAINDIR} || '@@LOCALEDIR@@'; require POSIX; POSIX->import(qw(setlocale)); diff --git a/perl/header_templates/runtime_prefix.template.pl b/perl/header_templates/runtime_prefix.template.pl new file mode 100644 index 000000000..ff24eebc5 --- /dev/null +++ b/perl/header_templates/runtime_prefix.template.pl @@ -0,0 +1,32 @@ +# BEGIN RUNTIME_PREFIX_PERL generated code. +# +# This finds our Git::* libraries relative to the script's runtime path. +sub __git_system_path { + my ($relpath) = @_; + my $gitexecdir_relative = '@@GITEXECDIR_REL@@'; + + # GIT_EXEC_PATH is supplied by `git` or the test suite. Otherwise, resolve + # against the runtime path of this script. + require FindBin; + require File::Spec; + (my $prefix = $ENV{GIT_EXEC_PATH} || $FindBin::Bin) =~ s=${gitexecdir_relative}$==; + return File::Spec->catdir($prefix, $relpath); +} + +BEGIN { + use lib split /@@PATHSEP@@/, + ( + $ENV{GITPERLLIB} || + do { + my $perllibdir = __git_system_path('@@PERLLIBDIR_REL@@'); + (-e $perllibdir) || die("Invalid system path ($relpath): $path"); + $perllibdir; + } + ); + + # Export the system locale directory to the I18N module. The locale directory + # is only installed if NO_GETTEXT is set. + $Git::I18N::TEXTDOMAINDIR = __git_system_path('@@LOCALEDIR_REL@@'); +} + +# END RUNTIME_PREFIX_PERL generated code. -- 2.15.0.chromium12