nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.54k stars 1.47k forks source link

Can not use link.exe to link static/shared libraries on windows #19033

Open waruqi opened 3 years ago

waruqi commented 3 years ago

I set --cc:vcc to build and link nim program on windows 10, but I cannot pass --passL:-libpath:xxx to nim to link library.

>nim c --cc:vcc -d:release --nimcache:build\.gens\test\windows\x64\release\nimcache --passL:-libpath:build\windows\x64\release --passL:-lfoo -o:build\windows\x64\release\test.exe src\main.nim
Hint: used config file 'C:\Program Files\nim-1.6.0\config\nim.cfg' [Conf]
Hint: used config file 'C:\Program Files\nim-1.6.0\config\config.nims' [Conf]
.........................................................
Hint:  [Link]
cl : Command line warning D9002 : ignoring unknown option '-libpath:build\windows\x64\release'
cl : Command line warning D9002 : ignoring unknown option '-lfoo'
@mmain.nim.c.obj : error LNK2019: unresolved external symbol foo referenced in function NimMainInner
Z:\personal\xmake\tests\projects\nim\static_library\build\windows\x64\release\test.exe : fatal error LNK1120: 1 unresolved externals
Error: execution of an external program failed: 'vccexe.exe  --platform:amd64 /FeZ:\personal\xmake\tests\projects\nim\static_library\build\windows\x64\release\test.exe  Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_digitsutils.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_assertions.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_dollars.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_io.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_system.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\@mmain.nim.c.obj  /nologo   -libpath:build\windows\x64\release -lfoo  '

-libpath: and -lfoo seems to be passed into cl.exe and cl.exe ignored them.

and nim cannot use link.exe to link them. it always call vccexe.exe to link objects and libraries.

verbose output

nim c --cc:vcc -d:release --nimcache:build\.gens\test\windows\x64\release\nimcache --passL:-libpath:build\windows\x64\release --passL:-lfoo -o:build\windows\x64\release\test.exe --verbosity:3 src\main.nim
C:\Program Files\nim-1.6.0\config\nim.cfg(51, 1) Hint: added path: 'C:\Users\ruki\.nimble\pkgs\' [Path]
  nimblepath="$home/.nimble/pkgs/"
  ^
D:\a\nightlies\nightlies\nim-1.6.0\compiler\nimblecmd.nim(139, 12) compiler msg initiated here [MsgOrigin]
Hint: used config file 'C:\Program Files\nim-1.6.0\config\nim.cfg' [Conf]
D:\a\nightlies\nightlies\nim-1.6.0\compiler\nimconf.nim(297, 17) compiler msg initiated here [MsgOrigin]
Hint: used config file 'C:\Program Files\nim-1.6.0\config\config.nims' [Conf]
D:\a\nightlies\nightlies\nim-1.6.0\compiler\nimconf.nim(297, 17) compiler msg initiated here [MsgOrigin]
.........................................................
Z:\personal\xmake\tests\projects\nim\static_library\src\main.nim(1, 1) Hint: (module: 28, symId: 0, typeId: 2, sealed: false) [ProcessingStmt]
  proc foo(n: int): int {.cdecl, importc}
  ^
D:\a\nightlies\nightlies\nim-1.6.0\compiler\passaux.nim(29, 10) compiler msg initiated here [MsgOrigin]
Z:\personal\xmake\tests\projects\nim\static_library\src\main.nim(3, 6) Hint: (module: 28, symId: 2, typeId: 3, sealed: false) [ProcessingStmt]
  echo foo(2)
       ^
D:\a\nightlies\nightlies\nim-1.6.0\compiler\passaux.nim(29, 10) compiler msg initiated here [MsgOrigin]
Hint: (module: 28, symId: 2, typeId: 6, sealed: false) [ProcessingStmt]
D:\a\nightlies\nightlies\nim-1.6.0\compiler\passaux.nim(29, 10) compiler msg initiated here [MsgOrigin]
Hint: vccexe.exe  --platform:amd64 /FeZ:\personal\xmake\tests\projects\nim\static_library\build\windows\x64\release\test.exe  Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_digitsutils.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_assertions.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_dollars.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_io.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\stdlib_system.nim.c.obj Z:\personal\xmake\tests\projects\nim\static_library\build\.gens\test\windows\x64\release\nimcache\@mmain.nim.c.obj  /nologo   -libpath:build\windows\x64\release -lfoo   [Link]
D:\a\nightlies\nightlies\nim-1.6.0\compiler\extccomp.nim(398, 13) compiler msg initiated here [MsgOrigin]
cl : Command line warning D9002 : ignoring unknown option '-libpath:build\windows\x64\release'
cl : Command line warning D9002 : ignoring unknown option '-lfoo'
@mmain.nim.c.obj : error LNK2019: unresolved external symbol foo referenced in function NimMainInner
Z:\personal\xmake\tests\projects\nim\static_library\build\windows\x64\release\test.exe : fatal error LNK1120: 1 unresolved externals
$ nim -v
Nim Compiler Version 1.6
# make sure to include the git hash if not using a tagged release
waruqi commented 3 years ago

related problem: https://forum.nim-lang.org/t/341 https://github.com/nim-lang/Nim/issues/8098

geekrelief commented 3 years ago

Relevant doc: https://docs.microsoft.com/en-us/cpp/build/reference/cl-invokes-the-linker?view=msvc-160

waruqi commented 3 years ago

https://docs.microsoft.com/en-us/cpp/build/reference/cl-invokes-the-linker?view=msvc-160

Thanks, I use --passL:-link --passL:-libpath:dir --passL:foo.lib to solve this problem.

nim c --cc:vcc -d:release --nimcache:build\.gens\test\windows\x64\release\nimcache --passL:-link --passL:-libpath:build\windows\x64\release --passL:foo.lib -o:build\windows\x64\release\test.exe src\main.nim

I can finally let xmake support building nim projects on windows, thank you very much. @geekrelief

$ xmake -v
[ 33%]: linking.release foo.lib
"C:\\Program Files\\nim-1.6.0\\bin\\nim" c --cc:vcc -d:release --nimcache:build\.gens\foo\windows\x64\release\nimcache --app:staticlib --noMain --passC:-DNimMain=NimMain_2D68A01A --passC:-DNimMainInne
r=NimMainInner_2D68A01A --passC:-DNimMainModule=NimMainModule_2D68A01A --passC:-DPreMain=PreMain_2D68A01A --passC:-DPreMainInner=PreMainInner_2D68A01A -o:build\windows\x64\release\foo.lib src\foo.nim
[ 66%]: linking.release test.exe
"C:\\Program Files\\nim-1.6.0\\bin\\nim" c --cc:vcc -d:release --nimcache:build\.gens\test\windows\x64\release\nimcache --passL:-link --passL:-libpath:build\windows\x64\release --passL:foo.lib -o:buil
d\windows\x64\release\test.exe src\main.nim
[100%]: build ok!

However, I think nim should be able to handle link flags better and pass them automatically to link.exe instead of cl.exe

geekrelief commented 2 years ago

FYI, I tested this on Windows 10, nim devel (1.7.1) with Visual Studio 2019, and I was able to compile with a single passL with /link as the first option passed. The order of passL doesn't matter, i.e. passC doesn't have to come before passL. For example in nimble I call:

exec &"nim c --passL:\"/link /libpath:samples /libpath:samples/plugins\" {settings.join(\" \")} {nimFilePath}"

where settings is a seq[string] containing other options like: @["--passC:\"/wd4311 /wd4312 /wd4103 /wd4133 /wd4028\" ", "--app:lib", "--gc:arc", "-d:danger", "--nomain:on"]

waruqi commented 2 years ago

ok, thanks.