Nim
Nim copied to clipboard
OpenSSL static linking on Windows
Can't static link OpenSSL on windows
Used command
nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-Lpath/to/openssl/lib --passl:-lcrypto --passl:-lssl -r tssl.nim
Solution
nim c -f -d:ssl -p:. -d:noOpenSSLHacks --dynlibOverride:ssl- --dynlibOverride:crypto- -d:sslVersion:"(" --passL:-Lpath/to/openssl/lib --passL:-Bstatic --passL:-lssl --passL:-lcrypto --passL:-Bdynamic -r tssl.nim
Additional Information
@alaviss on the discord server helped me fix this
$ nim -v
Nim Compiler Version 1.2.6 [Windows: amd64]
Compiled at 2020-07-29
Copyright (c) 2006-2020 by Andreas Rumpf
git hash: bf320ed172f74f60fd274338e82bdc9ce3520dd9
active boot switches: -d:release
someone fix this my head hurts
I didn't see this issue with choosenim though I'm providing the path to the .a files in ssl.nim instead of using -L and -l.
https://github.com/dom96/choosenim/pull/225/files
You have to actually run the binary on a system without openssl to see its effect. This issue is caused by canonDynlibName
not splitting the -
away from Windows dll names as well as stop matching at the first (
:
https://github.com/nim-lang/Nim/blob/51e3e0c7c43e82932d9bbae2e6ccc876d29b9fab/compiler/options.nim#L831-L837
And here are the dll names in openssl.nim
:
https://github.com/nim-lang/Nim/blob/3eaacac2303ab9fc1aef62208a112fae0ddd9152/lib/wrappers/openssl.nim#L37-L62
Thanks to our matching algorithm, the only way to match this for Windows is to use --dynlibOverride:crypto- --dynlibOverride:ssl- -d:sslVersion='('
. This is due to this block:
https://github.com/nim-lang/Nim/blob/3eaacac2303ab9fc1aef62208a112fae0ddd9152/lib/wrappers/openssl.nim#L55-L62
The matching algorithm cuts off at the first (
, so you guessed it, this can't be matched. The -d:sslVersion='('
is used to exploit this block:
https://github.com/nim-lang/Nim/blob/3eaacac2303ab9fc1aef62208a112fae0ddd9152/lib/wrappers/openssl.nim#L43-L46
Which would render the dll names to be: libssl-(.dll
and libcrypto-(.dll
, allowing --dynlibOverride:ssl- --dynlibOverride:crypto-
to match against them.
Good to know - I've created a fix for choosenim - https://github.com/dom96/choosenim/pull/227.
cc @dom96
Im testing on windows use msvc compile (vs2019) as nim's backend the commandline:
nim c --cc:vcc --os:windows --cpu:amd64 -d:release -d:noOpenSSLHacks --dynlibOverride:ssl- --dynlibOverride:crypto- -d:sslVersion:"(" -d:ssl -p:. --clibdir:C:\vcpkg\installed\x64-windows-static\lib\ --cincludes:C:\vcpkg\installed\x64-windows-static\include\openssl --clibdir:c:\um_lib --clibdir:c:\ucrt_lib --cincludes:c:\ucrt_includes --cincludes:c:\um_includes --cincludes:c:\shared_includes --dynlibOverride:ssl --passl:/DYNAMICBASE --passl:libcrypto.lib --passl:libssl.lib --passl:Crypt32.lib --passl:Ws2_32.lib --passl:Advapi32.lib --passl:User32.lib --passl:/link --passc:/MT test.nim
but there is another werid problem, the --cincludes:
value cannot contains space
Im using choosenim to install 1.4.0 1.2.2 1.2.0 to test, a temporary solutions maybe:
mklink /d c:\ucrt_includes "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\"
mklink /d c:\um_includes "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\"
mklink /d c:\shared_includes "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared"
mklink /d c:\um_lib "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\x64"
mklink /d c:\ucrt_lib "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64\"
@genotrance so how to use this fix ? i've installed nim using choosenim but i can't get it to work
The fix is within choosenim since it uses SSL itself - see https://github.com/dom96/choosenim/blob/master/src/choosenim.nims for the defines needed to get SSL static linked. You will need something similar in your program.
@89z that's because Nim loads openssl dynamically at runtime
Ok this worked for me with MSYS2:
nim c `
--dynlibOverride:crypto- `
--dynlibOverride:ssl- `
--passl:-lssl `
--passl:-lcrypto `
--passl:-lws2_32 `
--passl:-static `
-d:noOpenSSLHacks `
-d:ssl `
-d:sslVersion:'(' `
a.nim
As an alternative, you can avoid even using OpenSSL, and use wininet.dll
instead. That is what D does:
https://github.com/CyberShadow/ae/blob/master/sys/net/wininet.d
Solution
nim c -f -d:ssl -p:. -d:noOpenSSLHacks --dynlibOverride:ssl- --dynlibOverride:crypto- -d:sslVersion:"(" --passL:-Lpath/to/openssl/lib --passL:-Bstatic --passL:-lssl --passL:-lcrypto --passL:-Bdynamic -r tssl.nim
Thank you for presenting this solution. I still had to add --passL:-lcrypt32 --passL:-lws2_32
.