Skip to content

Commit

Permalink
Fixes #86 "-l somelib.dll doesn't work in recent PAR::Packer versions"
Browse files Browse the repository at this point in the history
par_setup_libpath() in myldr/mktmpdir.c used to set all known
"search path for DLLs" environment variables (e.g. LD_LIBRARY_PATH
on Linux). The search path is set up so that the first directory
searched is a packed executable's cache directory (where the shared
perl library will be extracted to, also all packed "external" DLLs).
In 2017 (by 2ac7078) it was changed to only set the variable
relevant for the OS where PAR::Packer was build on, given by
$Config{ldlibpthname}. But some perl distributions
(e.g. Strawberry on Windows) do not specify $Config{ldlibpthname}.

Hardwire "PATH" for MSWin32 and otherwise complain if this Config
variable is undefined.

Add t/85-ldlibpthname.t: check that the value of the environment
variable for searching for DLLs, usually $ENV{$Config{ldlibpthname}},
starts with the cache directory, $ENV{PAR_TEMP}.
  • Loading branch information
rschupp committed Mar 15, 2024
1 parent e65a446 commit b1da0a5
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 14 deletions.
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ t/30-current_exec.t
t/40-packer_cd_option.t
t/80-doublecolon.t
t/85-crt-glob.t
t/85-ldlibpthname.t
t/85-myfile.t
t/86-xs-exe.t
t/86-xs-par.t
Expand Down
10 changes: 9 additions & 1 deletion myldr/Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,18 @@ WriteMakefile(

sub MY::postamble
{
# Strawberry perl doesn't set $Config{ldlibpthname}
my $ldlibpthname = $^O eq 'MSWin32' ? "PATH" : $Config{ldlibpthname};
unless ($ldlibpthname) {
warn "\$Config{ldlibpthname} is not available for your OS ($^O)".
"- PAR::Packer functionality may be limited";
$ldlibpthname = "Config_ldlibpthname_not_available";
}

my $make_frag = <<"EOT";
LD=$ld
CC=$cc
CFLAGS=$cflags -DLDLIBPTHNAME=\\"$Config{ldlibpthname}\\" -DPARL_EXE=\\"parl$exe\\" -DPAR_PACKER_VERSION=\\"\$(VERSION)\\"
CFLAGS=$cflags -DLDLIBPTHNAME=$ldlibpthname -DPARL_EXE=parl$exe -DPAR_PACKER_VERSION=\$(VERSION)
OPTIMIZE=$optimize
LDFLAGS=$Config{ldflags}
PERL_LDFLAGS=$ldflags
Expand Down
2 changes: 1 addition & 1 deletion myldr/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ void spawn_perl(const char *argv0, const char *my_perl, const char *stmpdir)
}
#endif

char pp_version_info[] = "@(#) Packed by PAR::Packer " PAR_PACKER_VERSION;
char pp_version_info[] = "@(#) Packed by PAR::Packer " stringify(PAR_PACKER_VERSION);

/* the contents of this string (in the executable myldr/boot)
* will be patched by script/par.pl if option "--clean" is used with pp
Expand Down
2 changes: 1 addition & 1 deletion myldr/internals.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ XS(XS_Internals_PAR_BOOT) {
* this scalar so that a packed script may refer to the version
* of PAR::Packer it was built with.
*/
sv_setpv(get_sv("PAR::Packer::VERSION", GV_ADD), PAR_PACKER_VERSION);
sv_setpv(get_sv("PAR::Packer::VERSION", GV_ADD), stringify(PAR_PACKER_VERSION));

TAINT_NOT;

Expand Down
22 changes: 11 additions & 11 deletions myldr/mktmpdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,20 @@ static int isSafeDir(const char* val)

void par_setup_libpath( const char * stmpdir )
{
const char *val = NULL;
char *ld_path = LDLIBPTHNAME;
char *ld_path_env = NULL;
const char *ldlibpthname = stringify(LDLIBPTHNAME);
const char *val;

if ( (val = par_getenv(ld_path)) == NULL || strlen(val) == 0 ) {
par_setenv(ld_path, stmpdir);
if ( (val = par_getenv(ldlibpthname)) == NULL || strlen(val) == 0 ) {
par_setenv(ldlibpthname, stmpdir);
}
else if ( !strstr(val, stmpdir) ) {
else {
/* prepend stmpdir to (value of) environment variable */
ld_path_env = malloc(
char *new_val = malloc(
strlen(stmpdir) + strlen(path_sep) + strlen(val) + 1);
sprintf(
ld_path_env, "%s%s%s",
new_val, "%s%s%s",
stmpdir, path_sep, val);
par_setenv(ld_path, ld_path_env);
par_setenv(ldlibpthname, new_val);
}
}

Expand Down Expand Up @@ -252,11 +251,12 @@ char *par_mktmpdir ( char **argv ) {
#else
#define STREQ(a,b) (strcmp(a,b) == 0)
#endif
const char *parl_exe = stringify(PARL_EXE);
int prog_len = strlen(progname);
int parl_len = strlen(PARL_EXE);
int parl_len = strlen(parl_exe);

if (prog_len >= parl_len
&& STREQ(progname + prog_len - parl_len, PARL_EXE)
&& STREQ(progname + prog_len - parl_len, parl_exe)
&& (prog_len == parl_len || progname[prog_len - parl_len - 1] == dir_sep[0])
&& argv[1]
&& strlen(argv[1]) >= 4
Expand Down
3 changes: 3 additions & 0 deletions myldr/mktmpdir.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
#define par_lstat stat
#endif

#define _stringify(s) #s
#define stringify(s) _stringify(s)

#if defined(WIN32) || defined(OS2)
static const char *dir_sep = "\\";
static const char *path_sep = ";";
Expand Down
31 changes: 31 additions & 0 deletions t/85-ldlibpthname.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/perl -w

use strict;
use Config;
use Data::Dumper;

use Test::More;
require "./t/utils.pl";

my $ldlibpthname = $^O eq 'MSWin32' ? "PATH" : $Config{ldlibpthname};

plan skip_all => "\$Config{ldlibpthname} is not available for your OS ($^O)" unless $ldlibpthname;
plan tests => 3;

my $exe = pp_ok(-e => <<"...");
use Data::Dumper;
my \$data = {
par_temp => \$ENV{PAR_TEMP},
ldlibpth => \$ENV{$ldlibpthname},
};
print Data::Dumper->new([\$data], ['data'])->Indent(1)->Useqq(1)->Dump();
...

my ($out) = run_ok($exe);
our $data;
eval $out;
ok($data->{ldlibpth} =~ /^\Q$data->{par_temp}\E($|\Q$Config{path_sep}\E)/,
"PAR_TEMP is first item in $ldlibpthname as seen by packed executable")
or diag($out);


0 comments on commit b1da0a5

Please sign in to comment.