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++
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.
User contributions licensed under CC BY-SA 3.0