Hi, I'm trying to use Nim with a toolchain whose docs say I should use a command like below to link the final application:
clang
-nostartfiles
-Wl,--gc-sections
-Wl,-pie
-Wl,--start-group
/path/to/crt.o
<OBJECT FILES>
<STATIC LIBS>
-Wl,--end-group
-Wl,--start-group
<SHARED LIBS>
-Wl,--end-group
/path/to/crtend.o
-o <OUTPUT FILE>
The exact ordering of the arguments passed to the linker seems to be important, especially that crt.o goes first, crtend.o goes last, and that the static and shared libs stuff are enclosed in their own groups with -Wl,--start-group and -Wl,--end-group.
Does anyone know any strategies I could use to make this work?
Hi, Maybe you've already solved this, but you can do the following
# only compile (translate)
$ nim c -c application.nim
# cd nimcache
$ cd $XDG_CACHE_HOME/nim/$projectname(_r|_d) or ~/.cache/nim/$projectname(_r|_d)
# nim only compiles (translates) the required header files by specifying the location of the header files
$ clang -I ~/.choosenim/toolchains/nim-1.6.10/lib -c *.c
# I have not tried this, but use clang's lld to link with an object file created with the desired options
$ ld.lld -Wl,--start-group /path/to/crt.o <OBJECT FILES> <STATIC LIBS> -Wl,--end-group /path/to/crtend.o -o <OUTPUT FILE>
I'm not sure why the toolchain you plan to use specifies the order of the links in detail, but maybe lld is supposed to do this as I recall, since it usually does not reference symbols repeatedly (To speed up the process?).
-( archives -) or --start-group archives --end-group > The archives should be a list of archive files. They may be either explicit file names, or -l options. > The specified archives are searched repeatedly until no new undefined references are created. Normally, an archive is searched only once in the order that it is specified on the command line. If a symbol in that archive is needed to resolve an undefined symbol referred to by an object in an archive that appears later on the command line, the linker would not be able to resolve that reference. By grouping the archives, they all be searched repeatedly until all possible references are resolved. > Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between two or more archives.
I didn't try it all the way through, so sorry if I'm wrong.
Thanks for the reply. Approximately, I think it will work and link in the correct order, but I am very sorry to have to abandon this, because I found it to be quite time consuming to try it with my skills.
Here is what I found out
If a static library depends on another library, but the other library again depends on the former library, there is a cycle. You can resolve this by enclosing the cyclically dependent libraries by -( and -), such as -( -la -lb -) (you may need to escape the parens, such as -( and -)).
The quote above seems to be about the gcc linker, And I often see the following statements in Nim's sources
when defined(xxx):
{.passl: "-lm".}
This probably indicates the possibility of adding a link in the order of Nim dependencies before the external toolchain (.a, .so) for that Nim source dependency
I doubt that they really need to be linked in order, since it is probably just name resolution of symbols, but even if they are linked in order, the means to verify that the contents of the generated binaries are so is a bit difficult with my skills. With Nim, it is likely to work as expected because it works straightforwardly with the C processing system, but even if it works, it is by chance unless specified as a specification, and it would be a burden on the Nim core developer with incremental compilation, incremental linking, etc. It may be better to write a Makefile that does the above.
Sorry for all the speculation.
Thanks so much for your help! This has been really useful if only to know what my options are.
I doubt that they really need to be linked in order, since it is probably just name resolution of symbols
Yes you're right, it seems that the order shown in the example is simply best practise and the only possibly 'important' thing is that /path/to/crtend.o should go at the end. Luckily when I'm setting clang.options.linker in nimscript configuration, or using --passL, the specified options are indeed appended, so there's no problem here yet. (but I haven't checked what order they come in if you set both...)
If I do run into trouble, then it seems that using Nim to generate the sources and then feeding them to a custom Makefile would indeed be the best solution.