Skip to content

Commit

Permalink
[GH #302] new config dynext_libs, new ENV var PARROT_DYNEXT, new add_…
Browse files Browse the repository at this point in the history
…env_paths()

On some systems a special library dir is in the cc library search, or added by -L to the libpath
but this path is missing from the loader configuration, so runtime dlopen attempts will fail.
Most prominently pcre on macports or fink, missing /opt/local/lib.
Hints may add a new key dynext_libs to add such a path to DYNEXT for loadlib.
Also provide a new PARROT_DYNEXT to manually set such paths for the runtime.
Add a helper function add_env_paths() to add multiple paths from an enviroment variable
to some library search path. Currently PARROT_INCLUDE and PARROT_LIBRARY only accept one path element.
(See #903)
  • Loading branch information
Reini Urban committed Jan 2, 2013
1 parent 41a11f3 commit b5e29c1
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 3 deletions.
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
+ Install libraries tgc.pbc, NCI/Utils.pbc, OpenGL/Math.pbc, PCT/Dumper.pbc,
postgres.pbc, ProfTest.pbc and ProfTest/*pbc, String/Utils.pbc, URI/Escape.pbc,
YAML/Dumper/Base.pbc, YAML/Dumper/Default.pbc
+ New experimental PARROT_DYNEXT environment variable
+ New experimental dynext_libs config entry (same as PARROT_DYNEXT)
- Build
+ Generate MANIFEST.generated, cleanup MANIFEST,
removed MANIFEST_configure.generated, add installation of forgotten files
Expand Down
5 changes: 4 additions & 1 deletion config/init/hints/darwin.pm
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ sub runstep {
. $conf->data->get('share_ext')
. '"'
);
$darwin_selections{dynext_libs} = $flagsref->{dynext_libs} if $flagsref->{dynext_libs};
my $darwin_hints = "Darwin hints settings:\n";
for my $k (sort keys %darwin_selections) {
$darwin_hints .= sprintf(" %-24s => %s\n" => (
Expand Down Expand Up @@ -181,7 +182,7 @@ sub _probe_for_fink {
# regardless of where Fink itself is installed.
my $fink_conf = $defaults{fink_conf};
unless (-f $fink_conf) {
$conf->debug("Fink configuration file not located\n");
$conf->debug("Fink configuration file $fink_conf not located\n");
return;
}
my $fink_conf_str = Parrot::BuildUtil::slurp_file($fink_conf);
Expand Down Expand Up @@ -212,6 +213,7 @@ sub _probe_for_fink {
linkflags => "-L$fink_lib_dir",
ldflags => "-L$fink_lib_dir",
ccflags => "-isystem $fink_include_dir",
dynext_libs => $fink_lib_dir,
);
return \%addl_flags;
}
Expand All @@ -235,6 +237,7 @@ sub _probe_for_macports {
linkflags => "-L$ports_lib_dir",
ldflags => "-L$ports_lib_dir",
ccflags => "-isystem $ports_include_dir",
dynext_libs => $ports_lib_dir,
);
return \%addl_flags;
}
Expand Down
3 changes: 3 additions & 0 deletions config/init/hints/openbsd.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ sub runstep {
}

my $ldflags = $conf->data->get('ldflags');
my $dynext_libs;
if ( $ldflags !~ m|-L/usr/local/lib\b| ) {
$ldflags .= ' -L/usr/local/lib';
$dynext_libs = '/usr/local/lib';
}

$conf->data->set(
Expand All @@ -38,6 +40,7 @@ sub runstep {
libparrot_shared_alias => "libparrot$share_ext",
libparrot_soname => "-Wl,-soname=libparrot$share_ext.$version",
);
$conf->data->set( dynext_libs => $dynext_libs ) if $dynext_libs;

if ( ( split( m/-/, $conf->data->get('archname_provisional'), 2 ) )[0] eq 'powerpc' ) {
$conf->data->set( as => 'as -mregnames' );
Expand Down
69 changes: 69 additions & 0 deletions src/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ dynext files (via C<loadlib>).
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */

static void add_env_paths(PARROT_INTERP,
ARGIN(PMC *libpath),
ARGIN(const STRING *envstr))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
static STRING * cnv_to_win32_filesep(PARROT_INTERP,
Expand Down Expand Up @@ -73,6 +80,10 @@ static STRING* try_load_path(PARROT_INTERP, ARGIN(STRING* path))
__attribute__nonnull__(1)
__attribute__nonnull__(2);

#define ASSERT_ARGS_add_env_paths __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(libpath) \
, PARROT_ASSERT_ARG(envstr))
#define ASSERT_ARGS_cnv_to_win32_filesep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(path))
Expand Down Expand Up @@ -178,6 +189,14 @@ parrot_init_library_paths(PARROT_INTERP)
PARROT_LIB_PATH_DYNEXT, paths);
entry = CONST_STRING(interp, "dynext/");
VTABLE_push_string(interp, paths, entry);
{ /* EXPERIMENTAL: add dynext path from environment */
STRING *dynext_libs = Parrot_getenv(interp, CONST_STRING(interp, "PARROT_DYNEXT"));
Parrot_warn_experimental(interp, "PARROT_DYNEXT environment variable is experimental");
if (!STRING_IS_NULL(dynext_libs) && !STRING_IS_EMPTY(dynext_libs)) {
add_env_paths(interp, paths, dynext_libs);
}
}


/* shared exts */
paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
Expand Down Expand Up @@ -215,6 +234,7 @@ Parrot_lib_update_paths_from_config_hash(PARROT_INTERP)
STRING * versionlib = NULL;
STRING * entry = NULL;
STRING * builddir = NULL;
STRING * dynext_libs = NULL;
PMC * const lib_paths =
VTABLE_get_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_LIB_PATHS);
PMC * const config_hash =
Expand All @@ -226,10 +246,12 @@ Parrot_lib_update_paths_from_config_hash(PARROT_INTERP)
STRING * const verkey = CONST_STRING(interp, "versiondir");
STRING * const builddirkey = CONST_STRING(interp, "build_dir");
STRING * const installed = CONST_STRING(interp, "installed");
STRING * const dynextkey = CONST_STRING(interp, "dynext_libs");

versionlib = VTABLE_get_string_keyed_str(interp, config_hash, libkey);
entry = VTABLE_get_string_keyed_str(interp, config_hash, verkey);
versionlib = Parrot_str_concat(interp, versionlib, entry);
dynext_libs = VTABLE_get_string_keyed_str(interp, config_hash, dynextkey);

if (!VTABLE_get_integer_keyed_str(interp, config_hash, installed))
builddir = VTABLE_get_string_keyed_str(interp,
Expand Down Expand Up @@ -283,6 +305,9 @@ Parrot_lib_update_paths_from_config_hash(PARROT_INTERP)
entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/dynext/"));
VTABLE_push_string(interp, paths, entry);
}
if (!STRING_IS_NULL(dynext_libs) && !STRING_IS_EMPTY(dynext_libs)) {
add_env_paths(interp, paths, dynext_libs);
}
}


Expand Down Expand Up @@ -474,6 +499,50 @@ path_concat(PARROT_INTERP, ARGIN(STRING *l_path),

/*
=item C<static void add_env_paths(PARROT_INTERP, PMC *libpath, const STRING
*envstr)>
Split the env string into its components and add the entries to the libpath.
=cut
*/

static void
add_env_paths(PARROT_INTERP, ARGIN(PMC *libpath),
ARGIN(const STRING *envstr))
{
ASSERT_ARGS(add_env_paths)

if (!STRING_IS_NULL(envstr)) {
#ifdef WIN32
STRING * const env_search_path_sep = CONST_STRING(interp, ";");
#else
STRING * const env_search_path_sep = CONST_STRING(interp, ":");
#endif
INTVAL start = 0;
INTVAL index;

if ((index = STRING_index(interp, envstr, env_search_path_sep, start)) >= 0) {
STRING * entry;
do {
entry = STRING_substr(interp, envstr, start, index - start);
if (!STRING_IS_EMPTY(entry)) /* skip empty, as in ":/path" */
VTABLE_push_string(interp, libpath, entry);
start = index + 1;
} while ((index = STRING_index(interp, envstr, env_search_path_sep, start)) >= 0);
entry = STRING_substr(interp, envstr, start, STRING_length(envstr) - start);
if (!STRING_IS_EMPTY(entry))
VTABLE_push_string(interp, libpath, entry);
}
else {
VTABLE_push_string(interp, libpath, envstr);
}
}
}

/*
=item C<static STRING* try_load_path(PARROT_INTERP, STRING* path)>
Attempts to load a file with name C<path>. If the file is successfully located,
Expand Down
11 changes: 9 additions & 2 deletions t/library/lib_search_path.t
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,17 @@ Check for proper libpath order.
dynext:
if parrot is installed:
$ENV{PARROT_LIBRARY}
$ENV{PARROT_DYNEXT}
dynext/
$prefix/parrot/$ver/dynext/
$Config{dynext_libs}
if not installed:
$ENV{PARROT_LIBRARY}
$ENV{PARROT_DYNEXT}
dynext/
$build_dir/runtime/parrot/dynext
$Config{dynext_libs}
library (similar for include):
if parrot is installed:
Expand All @@ -62,6 +64,7 @@ no duplicates

local $ENV{PARROT_LIBRARY} = 'libenvdir';
local $ENV{PARROT_INCLUDE} = 'incenvdir';
local $ENV{PARROT_DYNEXT} = '/dynenvdir1:/dynenvdir2';

my ($builddir, $versiondir, $libdir, $prefix) = @PConfig{qw(build_dir versiondir libdir)};
my $versionlib = $libdir . $versiondir;
Expand Down Expand Up @@ -90,11 +93,15 @@ my $code = <<"CODE";
CODE

my $dynext = Parrot::Test::_pir_stdin_output_slurp('', $code);
my $dynext_libs = $PConfig{dynext_libs};
my $expected =
"dynext/
/dynenvdir1
/dynenvdir2
$builddir/runtime/parrot/dynext/
$versionlib/dynext/
";
$expected .= join("\n", split /:/, $dynext_libs)."\n" if $dynext_libs;
is ($dynext, $expected, "dynext");

my $library = $code;
Expand Down

0 comments on commit b5e29c1

Please sign in to comment.