-
Notifications
You must be signed in to change notification settings - Fork 21
Description
When linking a native module that includes external linkage (such as jurl
), the ldflags
(i.e libs) must be specified after the -shared
flag, else the shared object will not hold the library references in its dynamic section.
For example, when building jurl on my server.
With jpm as it is, the command line is: cc -std=c99 -I/usr/local/include/janet -I/usr/local/lib/janet -O2 -lcurl -o build/jurl/native.so build/src...o -shared -lpthread
The correct command line is: cc -std=c99 -I/usr/local/include/janet -I/usr/local/lib/janet -O2 -o build/jurl/native.so build/src...o -shared -lpthread -lcurl
Testing is trivial using readelf -d build/jurl/native.so
.
When building with jpm as it is, output starts as such:
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
When built with the correct command line, output starts as such:
0x0000000000000001 (NEEDED) Shared library: [libcurl.so.4]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
The consequence of this is that when later linking against jurl/native.so
, the former will not imply -lcurl
, and thus it will have to be inserted manually - something jpm does not do.
When linking dynamically, it's generally ok for the symbols to only become available later, so dynamic-linking-related invocations in link-cc
should likely specify ;ldflags
at the end of the command line rather than near the start.
Furthermore, this is also related to a separate issue making static linking difficult even when it is available.
When both a dynamic and a static version of a given library is accessible, most (so including gcc and clang) C compilers will default to preferring the dynamic version of the library (which is likely why jpm currently specifies static libraries for janet and static native modules using their paths rather than -l
flags).
The correct way of resolving this is passing a -static
flag in front of any -l
s that are available statically, and then a -dynamic
flag in front of any -l
s that are not.
Alternatively, jpm could take a :static
argument (on quickbin and on declare-executable) and prefix ;ldflags
with -static
when it is enabled (hard fail if any library is unavailable).
While I could try patching jpm and opening a PR at this stage (I have some rough patches around), it's probably important to see what the actual maintainers think (especially given the relatively low level of activity around the tooling and janet itself, e.g I've had #janet/1097 open for about a week; which is not an issue but pushes me in the direction of discussing first, patching later).