# Compiling Crystal shared libary on Windows

**URL:** <https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700>\
**Category:** Help & Support\
**Created:** [May 23, 2023, 8:10pm UTC](https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700 "2023-05-23T20:10:30Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jay1](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jay1/32/1486_2.png) [@Jay1](https://forum.crystal-lang.org/u/Jay1)\
**Post date:** [May 23, 2023, 8:10pm UTC](https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700/1 "2023-05-23T20:10:30Z")

</div>

I can compile a shared library for use in C using an example from stack overflow (questions/32916684) on Linux.

For the life of me I can’t do the same on Windows using the Windows Crystal implementation and MSVC 2022 (cl.exe).

Anyone any ideas if this is possible?

The command on Linux is:

crystal build --single-module --link-flags=“-shared” -o liblogger.so

none of the cl.exe flags work in place of “-shared” though, and the various other approaches I tried.

---

<div class="post-metadata">

**Author:** ![HertzDevil](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hertzdevil/32/1023_2.png) [@HertzDevil](https://forum.crystal-lang.org/u/HertzDevil)\
**Post date:** [May 23, 2023, 8:28pm UTC](https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700/2 "2023-05-23T20:28:26Z")

</div>

`--link-flags=/DLL -o logger.dll`

However, as you might have noticed, the Crystal runtime is not really prepared for use as a shared library yet. Additionally, currently this will build a DLL that links to the Microsoft C runtime statically (i.e. `/MT`), which is discouraged.

---

<div class="post-metadata">

**Author:** ![Jay1](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jay1/32/1486_2.png) [@Jay1](https://forum.crystal-lang.org/u/Jay1)\
**Post date:** [May 23, 2023, 8:59pm UTC](https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700/3 "2023-05-23T20:59:40Z")

</div>

It does produce a DLL, I tried this flag earlier. A dumpbin /EXPORTS liblogger.dll shows no exported functions strangely.

A lib file is also not produced which can be linked against it. There doesn’t seem to be any compiler flags for crystal build to pass “/LD” to get a lib file.

---

<div class="post-metadata">

**Author:** ![HertzDevil](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hertzdevil/32/1023_2.png) [@HertzDevil](https://forum.crystal-lang.org/u/HertzDevil)\
**Post date:** [May 23, 2023, 9:18pm UTC](https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700/4 "2023-05-23T21:18:03Z")

</div>

Exactly. If `-shared` produces a file that exports something on Linux that is also by sheer coincidence rather than by design.

---

<div class="post-metadata">

**Author:** ![Jay1](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jay1/32/1486_2.png) [@Jay1](https://forum.crystal-lang.org/u/Jay1)\
**Post date:** [May 23, 2023, 9:26pm UTC](https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700/5 "2023-05-23T21:26:07Z")

</div>

Fixed it. If I use --verbose I can see the command it is running with cl.exe - I can then modify that and add /LD and /DEF:liblogger.def on the end. I had to create a def file manually. I got the functions to use in the def file from nm liblogger.obj | grep crystal\_ in WSL.

Complete command is:

C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.36.32532\bin\Hostx64\x64\cl.exe" /nologo /LD liblogger.obj /link “/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.36.32532\atlmfc\lib\x64” “/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.36.32532\lib\x64” “/LIBPATH:C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22000.0\ucrt\x64” “/LIBPATH:C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22000.0\um\x64” /DEBUG:FULL /PDBALTPATH:%\_PDB% /INCREMENTAL:NO /STACK:0x800000 /LIBPATH:C:\Users\jools\scoop\apps\crystal\current\lib pcre2-8.lib gc.lib libcmt.lib iconv.lib advapi32.lib Kernel32.lib shell32.lib ole32.lib WS2\_32.lib kernel32.lib legacy\_stdio\_definitions.lib DbgHelp.lib libucrt.lib /DEF:liblogger.def

Churns out:  
Creating library liblogger.lib and object liblogger.exp

Then:  
C:\Users\jools\tmp\crystal\>main.exe  
Hello world!

---

<div class="post-metadata">

**Author:** ![Jay1](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jay1/32/1486_2.png) [@Jay1](https://forum.crystal-lang.org/u/Jay1)\
**Post date:** [May 23, 2023, 9:28pm UTC](https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700/6 "2023-05-23T21:28:10Z")

</div>

And for anyone else:

C:\Users\jools\tmp\crystal\>more liblogger.def  
LIBRARY liblogger  
EXPORTS  
\_\_crystal\_main  
\_\_crystal\_malloc  
\_\_crystal\_malloc64  
\_\_crystal\_malloc\_atomic  
\_\_crystal\_malloc\_atomic64  
\_\_crystal\_once  
\_\_crystal\_once\_init  
\_\_crystal\_raise  
\_\_crystal\_raise\_overflow  
\_\_crystal\_raise\_string  
\_\_crystal\_realloc  
\_\_crystal\_realloc64  
crystal\_init  
crystal\_log

C:\Users\jools\tmp\crystal\>more logger.cr  
fun init = crystal\_init : Void

GC.init

LibCrystalMain.\_\_crystal\_main(0, Pointer(Pointer(UInt8)).null)  
end

fun log = crystal\_log(text: UInt8\*): Void  
puts String.new(text)  
end

C:\Users\jools\tmp\crystal\>more logger.h  
#ifndef \_CRYSTAL\_LOGGER\_H  
#define \_CRYSTAL\_LOGGER\_H

void crystal\_init(void);  
void crystal\_log(char\* text);  
#endif

C:\Users\jools\tmp\crystal\>more main.c  
#include “logger.h”

int main(void) {  
crystal\_init();  
crystal\_log(“Hello world!”);  
}

---

<div class="post-metadata">

**Author:** ![Jay1](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jay1/32/1486_2.png) [@Jay1](https://forum.crystal-lang.org/u/Jay1)\
**Post date:** [May 23, 2023, 9:39pm UTC](https://forum.crystal-lang.org/t/compiling-crystal-shared-libary-on-windows/5700/7 "2023-05-23T21:39:43Z")

</div>

A complete run:

crystal build logger.cr --single-module --emit obj --verbose

mv logger.obj liblogger.obj

Copy command and remove /ENTRY:wmainCRTStartup ; add /LD and /DEF:liblogger.def ; to get:

“C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.36.32532\bin\Hostx64\x64\cl.exe” /nologo /LD liblogger.obj /link “/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.36.32532\atlmfc\lib\x64” “/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.36.32532\lib\x64” “/LIBPATH:C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22000.0\ucrt\x64” “/LIBPATH:C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22000.0\um\x64” /DEBUG:FULL /PDBALTPATH:%\_PDB% /INCREMENTAL:NO /STACK:0x800000 /LIBPATH:C:\Users\jools\scoop\apps\crystal\current\lib pcre2-8.lib gc.lib libcmt.lib iconv.lib advapi32.lib Kernel32.lib shell32.lib ole32.lib WS2\_32.lib kernel32.lib legacy\_stdio\_definitions.lib DbgHelp.lib libucrt.lib /DEF:liblogger.def

cl main.c /link liblogger.lib

C:\Users\jools\tmp\crystal\>main.exe  
Hello world!
