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.55k stars 1.47k forks source link

OpenSSL static linking on Windows #15220

Open vieruuuu opened 4 years ago

vieruuuu commented 4 years ago

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

genotrance commented 4 years ago

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

alaviss commented 4 years ago

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.

genotrance commented 4 years ago

Good to know - I've created a fix for choosenim - https://github.com/dom96/choosenim/pull/227.

cc @dom96

darkr4y commented 3 years ago

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\"
vieruuuu commented 3 years ago

@genotrance so how to use this fix ? i've installed nim using choosenim but i can't get it to work

genotrance commented 3 years ago

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.

ghost commented 3 years ago

@89z that's because Nim loads openssl dynamically at runtime

rockcavera commented 1 year ago

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.