Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions modules/packages/DynamicLoading.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,51 @@ record binary {
return new binary(bin!);
}

/*
Return the expected dynamic library file extension for the current
platform. The file extension does not include a prefix ``.``.
*/
proc type libSuffix param {
use ChplConfig;
if CHPL_TARGET_PLATFORM == 'darwin' then return 'dylib';
return 'so';
}

/*
Given the basename of a dynamic library (e.g., "baz") and an optional
directory path (e.g., "foo/bar"), return a path suitable for loading
"baz" on the current platform. On Linux, the above example would return
the relative path "foo/bar/libbaz.so".

:arg basename: The name of the library without prefix or extension
:type basename: `string`

:arg directory: An optional directory path to be used as a prefix
:type basename: `string`
*/
proc type libName(basename: string, directory: string="") {
import Path;

const fileName = 'lib' + basename + '.' + binary.libSuffix;
const ret = Path.normPath(Path.joinPath(directory, fileName));
return ret;
}

/*
Create a record representing a dynamically loaded binary using a string
that stores the path to a dynamic library file.

This procedure constructs a path using ``basename`` and ``directory``
that abides by the naming conventions used for dynamic libraries on the
current platform. The path constructed is equivalent to the one produced
by :proc:`libName`. In all other respects, this procedure behaves
identically to :proc:`binary.load`.
*/
proc type loadLib(basename: string, directory: string="") throws {
const path = libName(basename, directory);
return load(path);
}

/*
Fetch a procedure from a dynamically loaded binary. Throws an error if
no procedure could be found.
Expand Down
10 changes: 2 additions & 8 deletions test/dynamic-loading/ChapelLibraryTestCommon.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,9 @@ module ChapelLibraryTestCommon {
// Toggle this to 'true' when confident it will work.
var printUsingWriteln = false;

// TODO: We should provide this.
inline proc chapelLibraryExtension param {
use ChplConfig;
if CHPL_TARGET_PLATFORM == 'darwin' then return 'dylib';
return 'so';
}

inline proc chapelLibraryPath param {
return './lib/libChapelLibrary.' + chapelLibraryExtension;
use DynamicLoading;
return './lib/libChapelLibrary.' + binary.libSuffix;
}

inline proc debugf() {
Expand Down
5 changes: 1 addition & 4 deletions test/dynamic-loading/DemoLoadChapelLibrary.chpl
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use DynamicLoading;

// Provides the correct extension based on platform, e.g., '.dylib' or '.so'.
use ChapelLibraryTestCommon only chapelLibraryExtension;

proc main() {
const path = "./lib/libDemoChapelLibrary." + chapelLibraryExtension;
const path = "./lib/libDemoChapelLibrary." + binary.libSuffix;
var lib = binary.load(path);
type testType = proc(): void;
const testProc = try! lib.retrieve("test1", testType);
Expand Down
3 changes: 3 additions & 0 deletions test/library/packages/DynamicLoading/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
TestCLibraryToLoad.so
libTestCLibrary.so
libTestCLibrary.dylib
lib/
46 changes: 43 additions & 3 deletions test/library/packages/DynamicLoading/LoadForeignLibrary.chpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use DynamicLoading;
use Reflection;
use ChplConfig;

proc test1() {
writeln(Reflection.getRoutineName());
writeln();

const bin = try! binary.load("./TestCLibraryToLoad.so");

Expand All @@ -20,9 +20,49 @@ proc test1() {
writeln(here, ' got: ', x);
writeln('---');
}
writeln();
}

proc test2() {
writeln(Reflection.getRoutineName());

const suffix = binary.libSuffix;

if CHPL_TARGET_PLATFORM == 'darwin' {
assert(suffix == 'dylib');
} else {
assert(suffix == 'so');
}
}

proc test3() {
writeln(Reflection.getRoutineName());

const suffix = binary.libSuffix;
const libName1 = binary.libName('foo');
assert(libName1 == 'libfoo.' + suffix);

const libName2 = binary.libName('baz', 'foo/bar');
assert(libName2 == 'foo/bar/libbaz.' + suffix);
}

proc test4() {
writeln(Reflection.getRoutineName());

const bin = try! binary.loadLib('TestCLibrary');
}

proc test5() {
writeln(Reflection.getRoutineName());

const bin1 = try! binary.loadLib('TestCLibrary', 'lib');
const bin2 = try! binary.loadLib('TestCLibrary', 'lib/');
const bin3 = try! binary.loadLib('TestCLibrary', 'lib//');
}

proc main() {
test1();
const tests = [ test1, test2, test3, test4, test5 ];
for test in tests {
test();
if test != tests.last then writeln();
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
TestCLibraryToLoad.so
libTestCLibrary.so
libTestCLibrary.dylib
lib/libTestCLibrary.so
lib/libTestCLibrary.dylib
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
test1

extern proc(_: int, _: int): int

LOCALE0 got: 0
---

test2

test3

test4

test5
8 changes: 7 additions & 1 deletion test/library/packages/DynamicLoading/LoadForeignLibrary.good
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
test1

extern proc(_: int, _: int): int

LOCALE0 got: 0
Expand All @@ -11,3 +10,10 @@ LOCALE2 got: 4
LOCALE3 got: 6
---

test2

test3

test4

test5
22 changes: 18 additions & 4 deletions test/library/packages/DynamicLoading/LoadForeignLibrary.precomp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,22 @@

chpl=$3
chpl_home=$($chpl --print-chpl-home)
compiler=$($chpl_home/util/printchplenv --value --only CHPL_HOST_CC)
libname="TestCLibraryToLoad"
c_compiler=$($chpl_home/util/printchplenv --value --only CHPL_HOST_CC)
platform=$($CHPL_HOME/util/printchplenv --value --only CHPL_TARGET_PLATFORM)
ext=$([ "$platform" == "darwin" ] && echo "dylib" || echo "so")
source_file="TestCLibraryToLoad.c"
old_lib_name="TestCLibraryToLoad.so"
proper_lib_name="libTestCLibrary.$ext"

echo Building shared library: $libname.so
$compiler -shared -fPIC -o $libname.so $libname.c
echo "Building shared library: $old_lib_name"
$c_compiler -shared -fPIC -o $old_lib_name $source_file

# We copy instead of symbolic link to appease the dynamic loader.
echo "Copying $old_lib_name to $proper_lib_name"
cp $old_lib_name $proper_lib_name

mkdir lib

# We copy instead of symbolic link to appease the dynamic loader.
echo "Copying $old_lib_name to lib/$proper_lib_name"
cp $old_lib_name lib/$proper_lib_name
Loading