Linking to shared library built within my project works under linux but not Windows

I have fairly complex code called Xyce that builds statically under mac/linux and windows with CMake just fine.

When I switch to building with shared libraries, the main target “Xyce” will depend on the dynamic library libxyce.so, libxyce.dylib or xyce.dll depending on the OS.

Under Mac Os and Liniux this works fine. My final “Xyce” binary correctly, dynamically links to the appropriate dynamic library.

Under Windows, my CMake build system correctly makes "xyce.dll’ and “xyce.dll.manifext” but the linking of the final executable fails because “Xyce” is trying to link to “xyce.lib”.

The only properties I set on Xyce in regards to XyceLib in my Cmake code is:

target_link_libraries(Xyce XyceLib)

I’m befuddled. Any suggestions on what to look for would be appreciated.

Here’s what the link like looks like when I’m linking Xyce.C with xyce-shared.dll. I tried changing the name of the target shared library to see if that would help but it didn’t:

FAILED: src/Xyce.exe
cmd.exe /C "cd . && “C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe” -E vs_link_exe --intdir=src\CMakeFiles\Xyce.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100220~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100220~1.0\x64\mt.exe --manifests – C:\PROGRA~2\Intel\oneAPI\compiler\latest\windows\bin\icx.exe /nologo src\CMakeFiles\Xyce.dir\Xyce.C.obj /Qoption,link,/machine:x64 /INCREMENTAL:NO /Qoption,link,/subsystem:console src\xyce-share.lib …

According to the link like it’s trying to link to “xyce-share.lib” and not “xyce-share.dll”

Thanks,
Rich

How exactly does it fail? Does it output any error messages? I see it says “FAILED” in your command line fragment, but there is usually also an error message with some details.

What you described so far looks correct - that is how stuff works with DLLs on Windows: it links with xyce.lib when you build the project, and for running the application you’ll need to have xyce.dll available somewhere in PATH (usually in the same folder with the executable).

Also, just in case, for making DLLs one needs to export symbols in a certain manner. Do you have that in your library? You could also do -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=1, but that’s usually not recommended.

1 Like

Good question. How it fails is that “xyce.lib” is never created in the build process.

I thought that on Windows the final executable would be linked to “xyce.dll” but “xyce.lib” appears on the call to the linker. What you are suggesting is that the final executable will link to “xyce.lib” but then depend on “xyce.dll” at runtime.

That suggests that my build setup is not producing the needed “xyce.lib” file. Would “xyce.lib” be an interface library in this case and NOT the full static library?

Thanks
rich

I think your last paragraph is key. Right now I’m not doing anything to export symbols in a Windows build. I’ll look into doing this properly as exporting the entire project’s worth would be too much.

Thanks!
Rich

And while you are at: you can and should also do that on Linux in general to achieve a clean ABI.

Yes, the .lib file is basically an index of “these symbols exist in a DLL named foo.lib”. The linker uses this and injects a “load foo.dll” note into the library or executable that is being created. Note that the linker also creates this .lib file, but it will not do so if there are no exported symbols in the generated file (usually a .dll). A missing .lib file means that your .dll is not actually exporting any symbols for use by other libraries or executables.

No, it’s just part of a shared library intended for the linker to use.

Thanks! It works for me, it fix my issue on Windows