perlPackages: Deprecate shortenPerlShebang

This commit is contained in:
polyfloyd
2025-07-09 00:03:35 +02:00
committed by Stig Palmquist
parent ea55a49b7f
commit 637727353c
4 changed files with 117 additions and 129 deletions

View File

@@ -71,7 +71,7 @@ To install it with `nix-env` instead: `nix-env -f. -iA perlPackages.ClassC3`.
So what does `buildPerlPackage` do? It does the following:
1. In the configure phase, it calls `perl Makefile.PL` to generate a Makefile. You can set the variable `makeMakerFlags` to pass flags to `Makefile.PL`
2. It adds the contents of the `PERL5LIB` environment variable to `#! .../bin/perl` line of Perl scripts as `-Idir` flags. This ensures that a script can find its dependencies. (This can cause this shebang line to become too long for Darwin to handle; see the note below.)
2. It adds the contents of the `PERL5LIB` environment variable to a use lib statement at the start of Perl scripts. This ensures that a script can find its dependencies.
3. In the fixup phase, it writes the propagated build inputs (`propagatedBuildInputs`) to the file `$out/nix-support/propagated-user-env-packages`. `nix-env` recursively installs all packages listed in this file when you install a package that has it. This ensures that a Perl package can find its dependencies.
`buildPerlPackage` is built on top of `stdenv`, so everything can be customised in the usual way. For instance, the `BerkeleyDB` module has a `preConfigure` hook to generate a configuration file used by `Makefile.PL`:
@@ -120,37 +120,6 @@ Dependencies on other Perl packages can be specified in the `buildInputs` and `p
}
```
On Darwin, if a script has too many `-Idir` flags in its first line (its “shebang line”), it will not run. This can be worked around by calling the `shortenPerlShebang` function from the `postInstall` phase:
```nix
{
lib,
stdenv,
buildPerlPackage,
fetchurl,
shortenPerlShebang,
}:
{
ImageExifTool = buildPerlPackage {
pname = "Image-ExifTool";
version = "12.50";
src = fetchurl {
url = "https://exiftool.org/Image-ExifTool-${version}.tar.gz";
hash = "sha256-vOhB/FwQMC8PPvdnjDvxRpU6jAZcC6GMQfc0AH4uwKg=";
};
nativeBuildInputs = lib.optional stdenv.hostPlatform.isDarwin shortenPerlShebang;
postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
shortenPerlShebang $out/bin/exiftool
'';
};
}
```
This will remove the `-I` flags from the shebang line, rewrite them in the `use lib` form, and put them on the next line instead. This function can be given any number of Perl scripts as arguments; it will modify them in-place.
### Generation from CPAN {#ssec-generation-from-CPAN}
Nix expressions for Perl packages can be generated (almost) automatically from CPAN. This is done by the program `nix-generate-from-cpan`, which can be installed as follows:

View File

@@ -1,88 +1,4 @@
# This setup hook modifies a Perl script so that any "-I" flags in its shebang
# line are rewritten into a "use lib ..." statement on the next line. This gets
# around a limitation in Darwin, which will not properly handle a script whose
# shebang line exceeds 511 characters.
#
# Each occurrence of "-I /path/to/lib1" or "-I/path/to/lib2" is removed from
# the shebang line, along with the single space that preceded it. These library
# paths are placed into a new line of the form
#
# use lib "/path/to/lib1", "/path/to/lib2";
#
# immediately following the shebang line. If a library appeared in the original
# list more than once, only its first occurrence will appear in the output
# list. In other words, the libraries are deduplicated, but the ordering of the
# first appearance of each one is preserved.
#
# Any flags other than "-I" in the shebang line are left as-is, and the
# interpreter is also left alone (although the script will abort if the
# interpreter does not seem to be either "perl" or else "env" with "perl" as
# its argument). Each line after the shebang line is left unchanged. Each file
# is modified in place.
#
# Usage:
# shortenPerlShebang SCRIPT...
# Deprecated. Invocation in derivations can be safely removed.
shortenPerlShebang() {
while [ $# -gt 0 ]; do
_shortenPerlShebang "$1"
shift
done
}
_shortenPerlShebang() {
local program="$1"
echo "shortenPerlShebang: rewriting shebang line in $program"
if ! isScript "$program"; then
die "shortenPerlShebang: refusing to modify $program because it is not a script"
fi
local temp="$(mktemp)"
gawk '
(NR == 1) {
if (!($0 ~ /\/(perl|env +perl)\>/)) {
print "shortenPerlShebang: script does not seem to be a Perl script" > "/dev/stderr"
exit 1
}
idx = 0
while (match($0, / -I ?([^ ]+)/, pieces)) {
matches[idx] = pieces[1]
idx++
$0 = gensub(/ -I ?[^ ]+/, "", 1, $0)
}
print $0
if (idx > 0) {
prefix = "use lib "
for (idx in matches) {
path = matches[idx]
if (!(path in seen)) {
printf "%s\"%s\"", prefix, path
seen[path] = 1
prefix = ", "
}
}
print ";"
}
}
(NR > 1 ) {
print
}
' "$program" > "$temp" || die
# Preserve the mode of the original file
cp --preserve=mode --attributes-only "$program" "$temp"
mv "$temp" "$program"
# Measure the new shebang line length and make sure it's okay. We subtract
# one to account for the trailing newline that "head" included in its
# output.
local new_length=$(( $(head -n 1 "$program" | wc -c) - 1 ))
# Darwin is okay when the shebang line contains 511 characters, but not
# when it contains 512 characters.
if [ $new_length -ge 512 ]; then
die "shortenPerlShebang: shebang line is $new_length characters--still too long for Darwin!"
fi
:
}

View File

@@ -1,9 +1,10 @@
PERL5LIB="$PERL5LIB${PERL5LIB:+:}$out/lib/perl5/site_perl"
perlFlags=
perlUseLibs='use lib'
for i in $(IFS=:; echo $PERL5LIB); do
perlFlags="$perlFlags -I$i"
perlUseLibs="$perlUseLibs \"$i\","
done
perlUseLibs=$(echo "$perlUseLibs" | sed 's/,$/;/')
oldPreConfigure="$preConfigure"
preConfigure() {
@@ -15,7 +16,7 @@ preConfigure() {
first=$(dd if="$fn" count=2 bs=1 2> /dev/null)
if test "$first" = "#!"; then
echo "patching $fn..."
sed -i "$fn" -e "s|^#\!\(.*\bperl\b.*\)$|#\!\1$perlFlags|"
sed -i "$fn" -e "s|^#\!\(.*\bperl\b.*\)$|#\!\1\n$perlUseLibs|"
fi
fi
done

View File

@@ -2798,6 +2798,10 @@ with self;
};
propagatedBuildInputs = [ TaskWeaken ];
buildInputs = [ ExtUtilsDepends ];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/utils/40walk.t
'';
meta = {
description = "Helper functions for op tree manipulation";
homepage = "https://search.cpan.org/dist/B-Utils";
@@ -4438,6 +4442,11 @@ with self;
TestWarn
];
propagatedBuildInputs = [ HTMLParser ];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/rt-84767.t
rm t/param_list_context.t
'';
meta = {
description = "Handle Common Gateway Interface requests and responses";
homepage = "https://metacpan.org/module/CGI";
@@ -5293,6 +5302,12 @@ with self;
url = "mirror://cpan/authors/id/K/KM/KMX/Class-Throwable-0.13.tar.gz";
hash = "sha256-3JoR4Nq1bcIg3qjJT+PEfbXn3Xwe0E3IF4qlu3v7vM4=";
};
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/10_Class_Throwable_test.t
rm t/20_Class_Throwable_subException_test.t
rm t/35_Class_Throwable_sub_class_test.t
'';
meta = {
description = "Minimal lightweight exception class";
license = with lib.licenses; [
@@ -10215,6 +10230,10 @@ with self;
SafeIsa
TextBrew
];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/ResultSet/Errors.t
'';
meta = {
description = "Simplify the common case stuff for DBIx::Class";
homepage = "https://github.com/frioux/DBIx-Class-Helpers";
@@ -14402,6 +14421,10 @@ with self;
DirSelf
TestFatal
];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/eating_strict_error.t
'';
meta = {
description = "Define functions and methods with parameter lists (\"subroutine signatures\")";
license = with lib.licenses; [
@@ -22027,6 +22050,10 @@ with self;
TestDeep
TestNoWarnings
];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/20_parse_self.t
'';
meta = {
description = "Find out what modules are used";
license = with lib.licenses; [
@@ -27792,6 +27819,11 @@ with self;
postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
shortenPerlShebang $out/bin/perlcritic
'';
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/20_policy_require_tidy_code.t
rm t/03_pragmas.t
'';
meta = {
description = "Critique Perl source code for best-practices";
homepage = "http://perlcritic.com";
@@ -28510,6 +28542,10 @@ with self;
postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
shortenPerlShebang $out/bin/pls
'';
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/02document-new.t
'';
meta = {
description = "Perl Language Server";
homepage = "https://github.com/FractalBoy/perl-language-server";
@@ -28630,10 +28666,12 @@ with self;
TaskWeaken
];
# Remove test that fails due to unexpected shebang after
# patchShebang.
preCheck = "rm t/03_document.t";
preCheck = "
# Remove test that fails due to unexpected shebang after patchShebang.
rm t/03_document.t
# Remove tests with hardcoded line numbers.
rm t/29_logical_filename.t
";
meta = {
description = "Parse, Analyze and Manipulate Perl (without perl)";
homepage = "https://github.com/Perl-Critic/PPI";
@@ -29209,6 +29247,10 @@ with self;
url = "mirror://cpan/authors/id/M/MA/MAREKR/Pod-Checker-1.75.tar.gz";
hash = "sha256-82O1dOxmCvbtvT5dTJ/8UVodRsvxx8ytmkbO0oh5wiE=";
};
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/pod/podchkenc.t
'';
meta = {
description = "Verifies POD documentation contents for compliance with the POD format specifications";
license = with lib.licenses; [
@@ -29319,6 +29361,10 @@ with self;
};
propagatedBuildInputs = [ MixinLinewise ];
buildInputs = [ TestDeep ];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/non-pod.t
'';
meta = {
description = "Read a POD document as a series of trivial events";
homepage = "https://github.com/rjbs/Pod-Eventual";
@@ -30198,6 +30244,10 @@ with self;
AnyEvent
DataSExpression
];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/06.query.t
'';
meta = {
description = "Asynchronous Remote Procedure Stack";
license = with lib.licenses; [
@@ -32052,6 +32102,11 @@ with self;
url = "mirror://cpan/authors/id/R/RG/RGARCIA/Sub-Identify-0.14.tar.gz";
hash = "sha256-Bo0nIIZRTdHoQrakCxvtuv7mOQDlsIiQ72cAA53vrW8=";
};
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/04codelocation-pureperl.t
rm t/04codelocation.t
'';
meta = {
description = "Retrieve names of code references";
license = with lib.licenses; [
@@ -32306,6 +32361,10 @@ with self;
url = "mirror://cpan/authors/id/D/DE/DEXTER/Symbol-Util-0.0203.tar.gz";
hash = "sha256-VbZh3SL5zpub5afgo/UomsAM0lTCHj2GAyiaVlrm3DI=";
};
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/10use.t
'';
meta = {
description = "Additional utils for Perl symbols manipulation";
license = with lib.licenses; [
@@ -33526,6 +33585,10 @@ with self;
hash = "sha256-/NzkHVcnOIFYGt9oCiCmrfUaTDt+McP2mGb7kQk3AoA=";
};
propagatedBuildInputs = [ LogTrace ];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/Test-Assertions.t
'';
meta = {
description = "Simple set of building blocks for both unit and runtime testing";
license = with lib.licenses; [ gpl2Only ];
@@ -33621,6 +33684,14 @@ with self;
ModuleRuntime
TryTiny
];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/runtests_die.t
rm t/runtests_die_empty.t
rm t/runtests_die_nearlyempty.t
rm t/runtests_result.t
rm t/todo.t
'';
meta = {
description = "Easily create test classes in an xUnit/JUnit style";
license = with lib.licenses; [
@@ -33946,6 +34017,10 @@ with self;
hash = "sha256-FWsT8Hdk92bYtFpDco8kOa+Bo1EmJUON6reDt4g+tTM=";
};
propagatedBuildInputs = [ SubUplevel ];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/return.t
'';
meta = {
description = "Test exception-based code";
license = with lib.licenses; [
@@ -34327,6 +34402,11 @@ with self;
url = "mirror://cpan/authors/id/L/LE/LEEJO/Test-LeakTrace-0.17.tar.gz";
hash = "sha256-d31k0pOPXqWGMA7vl+8D6stD1MGFPJw7EJHrMxFGeXA=";
};
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/09_info_more.t
rm t/11_logfp.t
'';
meta = {
description = "Traces memory leaks";
homepage = "https://metacpan.org/release/Test-LeakTrace";
@@ -34608,6 +34688,10 @@ with self;
url = "mirror://cpan/authors/id/S/SY/SYP/Test-Mojibake-1.3.tar.gz";
hash = "sha256-j/51/5tpNSSIcn3Kc9uR+KoUtZ8voQTrdxfA1xpfGzM=";
};
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/02-bad-source.t
'';
meta = {
description = "Check your source for encoding misbehavior";
homepage = "https://github.com/creaktive/Test-Mojibake";
@@ -34820,6 +34904,13 @@ with self;
TextDiff
];
buildInputs = [ TestPerlCritic ];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/perltidy.t
rm t/list_files.t
rm t/exclude_files.t
rm t/exclude_perltidy.t
'';
meta = {
description = "Check that all your files are tidy";
homepage = "https://metacpan.org/release/Test-PerlTidy";
@@ -35217,13 +35308,15 @@ with self;
url = "mirror://cpan/authors/id/P/PL/PLICEASE/Test-Script-1.29.tar.gz";
hash = "sha256-iS5+bB6nsWcQkJlCz1wL2rcO7i79SqnBbqlS4rkPiVA=";
};
buildInputs = [ Test2Suite ];
propagatedBuildInputs = [
CaptureTiny
ProbePerl
];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/test_script__script_compiles.t
'';
meta = {
description = "Basic cross-platform tests for scripts";
license = with lib.licenses; [
@@ -35488,6 +35581,9 @@ with self;
hash = "sha256-mMoy5/L16om4v7mgYJl389FT4kLi5RcFEmy5VPGga1c=";
};
propagatedBuildInputs = [ SubUplevel ];
# Tests fail because they hardcode line numbers which have been shifted due to the inclusion of
# libraries.
doCheck = false;
meta = {
description = "Perl extension to test methods for warnings";
license = with lib.licenses; [
@@ -35651,6 +35747,10 @@ with self;
hash = "sha256-36phHnFGrZyXabW89oiUmXa4Ny3354ekC5M6FI2JIDk=";
};
propagatedBuildInputs = [ XMLLibXML ];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/simple.t
'';
meta = {
description = "Test XML and HTML content and structure with XPath expressions";
license = with lib.licenses; [
@@ -36496,9 +36596,11 @@ with self;
url = "mirror://cpan/authors/id/G/GF/GFUJI/Test-Vars-0.015.tar.gz";
hash = "sha256-4Y3RWCcuTsmTnh37M8dDGrTnXGtAsoDDi16AT9pHGlQ=";
};
buildInputs = [ ModuleBuildTiny ];
preCheck = ''
# Remove tests with hardcoded line numbers.
rm t/03_warned.t
'';
meta = {
description = "Detects unused variables in perl modules";
homepage = "https://github.com/houseabsolute/p5-Test-Vars";