mirror of
https://github.com/apple/pkl.git
synced 2026-08-27 22:24:03 +02:00
Split libpkl libraries between shared and static libs (#1812)
This adds a `libpkl-static.pc` so pkg-config users can link either statically or dynamically via `pkg-config --libs libpkl`, or `pkg-config --libs libpkl-static`. Additionally, this fixes an issue where the replace tokens wasn't doing anything, leaving the `@version@` token intact in the archive. Additionally, this adds an `-install_name` when building the dylib for macOS. Co-authored-by: Islon Scherer <islonscherer@gmail.com>
This commit is contained in:
co-authored by
Islon Scherer
parent
b3698683ab
commit
c5896d76d0
@@ -1,4 +1,5 @@
|
|||||||
= libpkl
|
= libpkl
|
||||||
|
include::ROOT:partial$component-attributes.adoc[]
|
||||||
|
|
||||||
libpkl is a C library for driving Pkl evaluation.
|
libpkl is a C library for driving Pkl evaluation.
|
||||||
|
|
||||||
@@ -32,9 +33,10 @@ The archive has the following structure:
|
|||||||
├── include
|
├── include
|
||||||
│ └── pkl.h
|
│ └── pkl.h
|
||||||
├── lib
|
├── lib
|
||||||
|
│ ├── libpkl.<shared library extension>
|
||||||
│ ├── libpkl.<static library extension>
|
│ ├── libpkl.<static library extension>
|
||||||
│ ├── libpkl.<dynamic library extension>
|
|
||||||
│ └── pkgconfig
|
│ └── pkgconfig
|
||||||
|
│ ├── libpkl-static.pc
|
||||||
│ └── libpkl.pc
|
│ └── libpkl.pc
|
||||||
├── LICENSE.txt
|
├── LICENSE.txt
|
||||||
├── README.md
|
├── README.md
|
||||||
@@ -43,7 +45,7 @@ The archive has the following structure:
|
|||||||
|
|
||||||
The file extensions are as follows:
|
The file extensions are as follows:
|
||||||
|===
|
|===
|
||||||
|OS |Static Library Extension |Dynamic library extension
|
|OS |Static Library Extension |Shared library extension
|
||||||
|
|
||||||
|macOS
|
|macOS
|
||||||
|`.a`
|
|`.a`
|
||||||
@@ -58,6 +60,44 @@ The file extensions are as follows:
|
|||||||
|`.dll`
|
|`.dll`
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
=== Linking to the static vs. shared library
|
||||||
|
|
||||||
|
The simplest way to configure your compiler to link to either the static or the shared library is to use https://en.wikipedia.org/wiki/Pkg-config[pkg-config].
|
||||||
|
|
||||||
|
The libpkl library ships with two pkg-config files: `libpkl.pc`, and `libpkl-static.pc`.
|
||||||
|
|
||||||
|
The normal `libpkl.pc` links to the shared library.
|
||||||
|
|
||||||
|
To unambiguously link to the static library, use `libpkl-static.pc`.
|
||||||
|
|
||||||
|
For example, when using `cc`:
|
||||||
|
|
||||||
|
[source,shell]
|
||||||
|
----
|
||||||
|
# Link against the shared library
|
||||||
|
cc -o myprogram myprogram.c $(pkg-config --libs --cflags libpkl)
|
||||||
|
|
||||||
|
# Link against the static library
|
||||||
|
cc -o myprogram myprogram.c $(pkg-config --static --libs --cflags libpkl-static)
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
If libpkl is installed in a non-system directory, set `PKG_CONFIG_PATH` to the subpath `lib/pkgconfig` within the directory that contains libpkl. For example, given libpkl directory `/path/to/libpkl`, the environment variable should have `/path/to/libpkl/lib/pkgconfig`.
|
||||||
|
|
||||||
|
NOTE: Windows can use pkg-config through the https://www.msys2.org/docs/pkgconfig/[MSYS2 toolchain]. Using pkg-config on Windows implies compiling with gcc-style compiler like https://code.visualstudio.com/docs/cpp/config-mingw[MinGW], instead of MSVC.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
It's also possible to link to the static library with the normal `libpkl.pc`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
[source,shell]
|
||||||
|
----
|
||||||
|
cc -Wl,-Bstatic $(pkg-config --libs --cflags libpkl)
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
== Building libpkl from source
|
== Building libpkl from source
|
||||||
|
|
||||||
To build libpkl from source, the apple/pkl repository first must be cloned down to a host OS.
|
To build libpkl from source, the apple/pkl repository first must be cloned down to a host OS.
|
||||||
@@ -79,7 +119,10 @@ cd pkl/
|
|||||||
./gradlew libpkl:buildNative
|
./gradlew libpkl:buildNative
|
||||||
----
|
----
|
||||||
|
|
||||||
The resulting archive will be written to `libpkl/build/distributions`.
|
This results in two directories of interest:
|
||||||
|
|
||||||
|
* `libpkl/build/distributions/`: directory containing archives (`.zip` on Windows, `.tar.gz` on macOS/Linux) of C libraries.
|
||||||
|
* `libpkl/build/native-libs/<os>-<arch>`: directory containing the built library files (the inner structure of the archive).
|
||||||
|
|
||||||
Cross-compilation is not supported.
|
Cross-compilation is not supported.
|
||||||
|
|
||||||
|
|||||||
+20
-15
@@ -251,16 +251,11 @@ val buildSharedLibrary =
|
|||||||
frameworks.addAll("Foundation", "CoreServices")
|
frameworks.addAll("Foundation", "CoreServices")
|
||||||
linkerFlags.addAll("-current_version", project.version.toString())
|
linkerFlags.addAll("-current_version", project.version.toString())
|
||||||
linkerFlags.addAll("-compatibility_version", "0.1.0")
|
linkerFlags.addAll("-compatibility_version", "0.1.0")
|
||||||
|
// prevent JNI symbols from being exported and clobbering the symbol table
|
||||||
// libpkl_internal_s bundles Native Image's own JNI-named implementations of JDK native
|
|
||||||
// methods (e.g. Java_sun_nio_ch_UnixFileDispatcherImpl_write0), which by default get
|
|
||||||
// exported with global visibility. Loading libpkl.dylib into a JVM process (e.g. via JNA)
|
|
||||||
// then lets the host JVM's own native-method resolution bind to these internal
|
|
||||||
// implementations instead of the JDK's real ones, silently corrupting unrelated file I/O.
|
|
||||||
// Restrict the dylib's exported symbols to just the public pkl_* API to prevent this.
|
|
||||||
val exportedSymbolsFile = file("src/main/c/pkl.exported_symbols")
|
val exportedSymbolsFile = file("src/main/c/pkl.exported_symbols")
|
||||||
inputs.file(exportedSymbolsFile)
|
inputs.file(exportedSymbolsFile)
|
||||||
linkerFlags.addAll("-exported_symbols_list", exportedSymbolsFile.absolutePath)
|
linkerFlags.addAll("-exported_symbols_list", exportedSymbolsFile.absolutePath)
|
||||||
|
compilerArgs.addAll("-install_name", "@rpath/libpkl.dylib")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetMachine.os.isWindows) {
|
if (targetMachine.os.isWindows) {
|
||||||
@@ -276,9 +271,7 @@ val buildSharedLibrary =
|
|||||||
|
|
||||||
if (targetMachine.os.isLinux) {
|
if (targetMachine.os.isLinux) {
|
||||||
libraries.add("dl")
|
libraries.add("dl")
|
||||||
|
// prevent JNI symbols from being exported and clobbering the symbol table
|
||||||
// Same symbol-collision hazard as the macOS case above (see comment there), but scoped via
|
|
||||||
// a GNU ld version script instead of an exported-symbols list.
|
|
||||||
val versionScriptFile = file("src/main/c/pkl.map")
|
val versionScriptFile = file("src/main/c/pkl.map")
|
||||||
inputs.file(versionScriptFile)
|
inputs.file(versionScriptFile)
|
||||||
linkerFlags.add("--version-script=${versionScriptFile.absolutePath}")
|
linkerFlags.add("--version-script=${versionScriptFile.absolutePath}")
|
||||||
@@ -317,7 +310,7 @@ val distZip =
|
|||||||
into(baseName)
|
into(baseName)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.assembleNative { dependsOn(distZip, distTar) }
|
tasks.assembleNative { dependsOn(distZip, distTar, processFiles) }
|
||||||
|
|
||||||
val processFiles =
|
val processFiles =
|
||||||
tasks.register<Copy>("processFiles") {
|
tasks.register<Copy>("processFiles") {
|
||||||
@@ -329,9 +322,23 @@ val processFiles =
|
|||||||
includeEmptyDirs = true
|
includeEmptyDirs = true
|
||||||
into(buildInfo.targetMachine.outputDir)
|
into(buildInfo.targetMachine.outputDir)
|
||||||
|
|
||||||
filesMatching("libpkl.pc") {
|
val tokens = buildMap {
|
||||||
filter<ReplaceTokens>("tokens" to mapOf("version" to buildInfo.pklVersion))
|
this["version"] = buildInfo.pklVersion
|
||||||
|
this["static_lib_filename"] = "libpkl.${buildInfo.os.staticLibraryExtension}"
|
||||||
|
this["extra_static_libs"] =
|
||||||
|
when {
|
||||||
|
buildInfo.os.isMacOS -> " -lz -framework Foundation -framework CoreServices"
|
||||||
|
buildInfo.os.isWindows -> ""
|
||||||
|
else -> " -lz"
|
||||||
|
}
|
||||||
|
this["extra_shared_libs"] =
|
||||||
|
when {
|
||||||
|
buildInfo.os.isMacOS -> " -lpkl"
|
||||||
|
buildInfo.os.isWindows -> " -l:libpkl_dll.lib"
|
||||||
|
else -> " -lpkl"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
filesMatching("**/libpkl*.pc") { filter<ReplaceTokens>("tokens" to tokens) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val testNativeJava =
|
val testNativeJava =
|
||||||
@@ -428,8 +435,6 @@ val compileNativeTestDynamic =
|
|||||||
libraryFiles.from(buildInfo.targetMachine.libraryDir.map { it.file("libpkl_dll.lib") })
|
libraryFiles.from(buildInfo.targetMachine.libraryDir.map { it.file("libpkl_dll.lib") })
|
||||||
} else {
|
} else {
|
||||||
libraries.add("pkl")
|
libraries.add("pkl")
|
||||||
libraries.add("z")
|
|
||||||
libraries.add("pthread")
|
|
||||||
// Bake the library's location into the test executable so the dynamic loader can find
|
// Bake the library's location into the test executable so the dynamic loader can find
|
||||||
// libpkl.so/libpkl.dylib without needing LD_LIBRARY_PATH/DYLD_LIBRARY_PATH set at run time.
|
// libpkl.so/libpkl.dylib without needing LD_LIBRARY_PATH/DYLD_LIBRARY_PATH set at run time.
|
||||||
linkerFlags.add("-rpath")
|
linkerFlags.add("-rpath")
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
prefix=${pcfiledir}/../..
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
libdir=${exec_prefix}/lib
|
||||||
|
includedir=${prefix}/include
|
||||||
|
|
||||||
|
Name: libpkl
|
||||||
|
Description: C library for calling into Pkl's message passing API.
|
||||||
|
URL: https://pkl-lang.org/main/current/libpkl/index.html
|
||||||
|
Version: @version@
|
||||||
|
Libs: ${libdir}/@static_lib_filename@@extra_static_libs@
|
||||||
|
Cflags: -I${includedir}
|
||||||
@@ -7,5 +7,5 @@ Name: libpkl
|
|||||||
Description: C library for calling into Pkl's message passing API.
|
Description: C library for calling into Pkl's message passing API.
|
||||||
URL: https://pkl-lang.org/main/current/libpkl/index.html
|
URL: https://pkl-lang.org/main/current/libpkl/index.html
|
||||||
Version: @version@
|
Version: @version@
|
||||||
Libs: -L${libdir} -lpkl -lz -lpthread
|
Libs: -L${libdir}@extra_shared_libs@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|||||||
Reference in New Issue
Block a user