Skip to content

various issues with linking modes #70

@CosmicToast

Description

@CosmicToast

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 -ls that are available statically, and then a -dynamic flag in front of any -ls 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions