Can I compile a dynamic lib on Linux and link on Windows?

0

I run Linux (specifically Ubuntu 20.04), and would like to know if there is a way to produce a dynamic library that could be linked against on a Windows machine. I am using GNU make and a mingw cross-compiler to attempt to do this.

Here is the simple makefile I have made for testing purposes:

CXX := x86_64-w64-mingw32-g++
CXX_FLAGS := -static-libgcc -static-libstdc++

main.exe: example.dll test_exe.o
    $(CXX) $(CXX_FLAGS) -o main.exe test_exe.o -L. -lexample

example.dll: example.o
    $(CXX) $(CXX_FLAGS) -shared -o example.dll example.o -Wl,--out-implib,libexample.a

%.o: %.cpp
    $(CXX) -c -fPIC $<

For reference: I have a file example.hpp which declares the methods that I want to be included in the library, and these methods are defined in example.cpp. test_exe.cpp contains my main function, and calls methods defined in the library. Running make generates (I believe) object files example.o and test_exe.o, followed by a dynamically linked library named example.dll and its corresponding import library named libexample.a, and then links everything together into an executable called main.exe. The produced output appears to be doing this, but I have no way of completely verifying if the output files are actually what I expect them to be.

Additionally, I have CXX_FLAGS set to statically link the c and c++ standard libraries because when I do not, I get an error saying The application was unable to start correctly (0xc000007b). I am guessing this is because by default the files expect a Linux version of the standard libraries (which would not be found on a Windows machine), and explicitly linking overrides this option? Google says this error may indicate that I have the wrong application version for my machine, so it makes sense.

The echoed commands from when I run make are:

x86_64-w64-mingw32-g++ -c -fPIC example.cpp
x86_64-w64-mingw32-g++ -static-libgcc -static-libstdc++ -shared -o example.dll example.o -Wl,--out-implib,libexample.a
x86_64-w64-mingw32-g++ -c -fPIC test_exe.cpp
x86_64-w64-mingw32-g++ -static-libgcc -static-libstdc++ -o main.exe test_exe.o -L. -lexample

When I link in Linux, everything works mostly as expected. The executable runs on Windows as long as the .dll is in the current directory, and produces an error when it is removed.

The first thing I did not expect is that the executable will run whether or not the import library libmath.a is present. I was under the assumption that I was linking against the import library which indirectly wraps the dynamic library, but this does not appear to be the case. Does anyone know what is actually happening, and why I am not linking against the import library?

My other question takes a bit more explanation. Ideally, I would like to be able to create a dynamic library on Linux, send it to a Windows machine, and link it into an arbitrary executable there. I am not entirely sure if this is possible, because Windows has to specify __declspec(dllexport) while Linux does not, but would like to know if it is. I have tried moving my dynamic and import libraries (example.dll and libexample.a), along with my library header file (example.hpp) into a directory with a new file (testapp.cpp) specifying an alternate main method.

On a Windows machine, I run g++ -c testapp.cpp to produce an object file, and then try to link. When I run g++ -o app.exe testapp.o -L. -lexample to try to generate an executable linked to the dynamic library (through the import library) I get the following error: undefined reference to 'square(int)'. square(int) is a function that is defined in the library, returning the square of an integer. I have also tried marking the function in my header file as __declspec(dllimport), which changes the error message to: undefined reference to '_imp___Z6squarei'. Is it possible on Windows to link against a .dll that did not originally specify __declspec(dllexport) for its functions (i.e. one developed in Linux)?

Build OS: Ubuntu 20.04 - version 9.3.0 of g++

Target OS: Windows 10 (tested in a virtualbox vm) - version 9.2.0 of g++

c++
c
dll
cross-compiling
.so
asked on Stack Overflow Dec 17, 2020 by Brendan Gould

1 Answer

0

I eventually got it. The command that worked was: g++ -o alt.exe testapp.o libexample.a. I am not entirely sure why this works when what I tried before did not, but it does work as expected now.

Interestingly, it still works even if I do not specify __declspec(dllimport) anywhere. I am also not sure why this works, but my best guess is that I am still using a GNU compiler, and not a windows default one.

answered on Stack Overflow Jan 4, 2021 by Brendan Gould

User contributions licensed under CC BY-SA 3.0