Hello everyone. I am pretty new to most of the things here, and trying to gain some understanding. Let's say I want to link to some OS native external libraries (e.g. kernel32.dll) in order to call some external procedure. I suppose this is supported by most compilers including Cranelift. How should I supply the procedure signatures and calling conventions? Am I able to compile my source code on Linux/MacOS, although my target OS is Windows? Finally, does Cranelift come with out-of-the-box support to any of the OS standard/native libraries? Thank you.
If you are using cranelift-object, calling an external function is a matter of declaring it using declare_function
with Linkage::Import
and then calling it the same way as you would call a local function. The Signature
argument you need to pass to declare_function
contains the arguments, return value and the calling convention to use. cranelift-object emits object files you need to link just like with for example a C compiler. Cranelift-object is able to create object files for other OSes than the current one, but you will need a linker capable of linking for the target OS to produce the final executable.
@bjorn3 Thank you for passing by. Excuse my questions if they seem trivial to you. Why don't Cranelift come with such a linker? Would you give an example of one?
Why don't Cranelift come with such a linker?
Few compilers come with a linker builtin. Almost all use an external one like ld, lld or mold (on Linux), ld64 (on macOS) or link.exe (on Windows).
The way compilers generally work is that they compile a source file to an object file and then you pass all object files to a linker to form the final executable or dynamic library.
Umm.. so I will still need the target environment to link. Is there a fundamental reason why this is the case? Is it that the linker needs the target environment to do its job?
You need a linker that supports the respective object file format of the target: ELF for most Unixes, Mach-O for macOS and COFF/PE for Windows. In addition the linker needs either the dynamic libraries themself or the equivalent of an import library for the respective target to known which symbols are defined in which dynamic library. And finally on all platforms except for Windows you don't actually invoke the linker directly most of the time, but a wrapper like the gcc or clang driver, which knows all configurations necessary to successfully link for a specific target.
Oh, so does Cranelift actually invoke the target linker at the end?
No, cranelift-object only emits object files, so you will have to invoke the linker yourself.
It's also worth noting that if you just need to run some code, and not build an executable or library you can use cranelift-jit
that does have a simple linker included and can call into other libraries.
Thanks a lot for your kindness. Last one for now: are the object files produced by Cranelift considered target-independent accepted by all linkers?
At the very least it is specific to a single object file format. Depending on the OS, there may or may not be a tag inside the object file itself that enforces that it is only used on that OS. You also need to make sure the the calling convention you used matches what the OS expects.
It is technically possible to use object files compiled for one target on another target with the same architecture and object file format, but I wouldn't recommend it unless you know what you are doing.
Thank you gentlemen for your generosity in knowledge sharing. Much appreciated!
Last updated: Dec 23 2024 at 12:05 UTC