janet-lang / spork

Various Janet utility modules - the official "Contrib" library.
MIT License
124 stars 36 forks source link

Issues with `cc.janet` on macOS #191

Closed pyrmont closed 3 months ago

pyrmont commented 3 months ago

I'm trying to use cc.janet from Spork to compile the janet-big library1 on macOS. I'm using the default /usr/bin/cc (which I think is really clang) for the compiler and /usr/bin/ld (which I think is really ld64) for the linker.

This was my first crack at the code:

(import ./deps/spork/cc)

(setdyn :visit cc/visit-execute)

# Compile Janet-Big
(cc/compile-and-link-shared "big.so"
                            "deps/janet-big/big.c"
                            "deps/janet-big/cutils.c"
                            "deps/janet-big/libbf.c")

This didn't work. After some exploring, it seems like there are four problems:

  1. -Wl,--start-group and -Wl,--end-group: ld64 doesn't recognise these options. This can be toggled off by the user calling (set :smart-libs false) but perhaps it would be better to do this automatically depending on the toolchain that is in use.

  2. -Wl,-Bstatic and -Wl,-Bdynamic: ld64 doesn't recognise these options. I can't find great documentation on this but apparently ld64 simply doesn't support distinguishing between static and dynamic libraries in the same way and static libraries should merely be absolute paths (rather than l<libname>). Again, perhaps these options could be applied depending on the toolchain in use.

  3. -Wl,rpath: ld64 appears not to recognise this option but that's not true. After some exploring (and this seems extremely poorly documented), I think the issue is that ld64 won't accept the rpath option and a =. Instead, it wants a space. To do that, the command line option for the compiler should be -Wl,rpath, (note the trailing comma) rather than -Wl,rpath=. I think this is compatible with the GNU and LLVM toolchains and so can be changed without any detrimental impact.

  4. Resolving undefined names: The creation of the shared library will fail if -undefined dynamic_lookup is not part of the command sent to the compiler. In JPM, the default macOS config sets this flag. Again, perhaps this option could be applied depending on the toolchain in use.

My knowledge of C compilation is extremely rudimentary so I'm not extremely confident in the above but if I remove the problematic options from my local version of cc.janet and add -undefined dynamic_lookup using (setdyn :lflags), I can get the library to compile.


1. This library won't actually work on macOS as-is as it relies on the header that is not available on macOS and doesn't expressly include the <math.h> for isfinite.