Nim icon indicating copy to clipboard operation
Nim copied to clipboard

OpenSSL static linking on Windows

Open vieruuuu opened this issue 4 years ago • 8 comments

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

vieruuuu avatar Aug 23 '20 12:08 vieruuuu

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

genotrance avatar Oct 09 '20 00:10 genotrance

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.

alaviss avatar Oct 09 '20 02:10 alaviss

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

cc @dom96

genotrance avatar Oct 09 '20 03:10 genotrance

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\"

darkr4y avatar Nov 27 '20 10:11 darkr4y

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

vieruuuu avatar Dec 17 '20 16:12 vieruuuu

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.

genotrance avatar Dec 17 '20 17:12 genotrance

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

ghost avatar Mar 20 '21 23:03 ghost

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

89z avatar Mar 20 '21 23:03 89z

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.

rockcavera avatar Jan 20 '23 17:01 rockcavera