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 <d...@google.com>
Thanks-to: Ævar Arnfjörð Bjarmason <ava...@gmail.com>
Thanks-to: Johannes Schindelin <johannes.schinde...@gmx.de>
---
 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

Reply via email to