Jay1
May 23, 2023, 8:10pm
1
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.
--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.
Jay1
May 23, 2023, 8:59pm
3
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.
Exactly. If -shared
produces a file that exports something on Linux that is also by sheer coincidence rather than by design.
Jay1
May 23, 2023, 9:26pm
5
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!
Jay1
May 23, 2023, 9:28pm
6
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!”);
}
Jay1
May 23, 2023, 9:39pm
7
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!