Permalink
Browse files

[GH #302] new config dynext_libs, new ENV var PARROT_DYNEXT, new add_…

…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...
1 parent 41a11f3 commit b5e29c16cc83cf997d00aa4ad16613034eae03fc Reini Urban committed Dec 27, 2012
Showing with 87 additions and 3 deletions.
  1. +2 −0 ChangeLog
  2. +4 −1 config/init/hints/darwin.pm
  3. +3 −0 config/init/hints/openbsd.pm
  4. +69 −0 src/library.c
  5. +9 −2 t/library/lib_search_path.t
View
@@ -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
@@ -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" => (
@@ -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);
@@ -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;
}
@@ -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;
}
@@ -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(
@@ -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' );
View
@@ -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,
@@ -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))
@@ -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);
@@ -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 =
@@ -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,
@@ -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);
+ }
}
@@ -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,
@@ -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:
@@ -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;
@@ -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;

0 comments on commit b5e29c1

Please sign in to comment.