Reputation: 1644
I need to build a FORTRAN DLL on Windows using gfortran such that it can be called by C++ with Visual Studio 2013.
I've got a sample DLL building with MSYS2, but I can't figure out how to get a LIB file for Visual Studio.
Searching online has produced mostly results about how to make a LIB file with Visual Studio, and how to create a LIB file from only a DLL and a header file. But I don't want to do the nasty stuff involved in the latter, and I don't think I need to, since I'm the one building the DLL. I just want to build the DLL and get my LIB file with it.
One exception is this SO question, however the answer is not clear to me. It seems like he's doing something similar to other solutions I've found for creating a LIB file after the DLL already exists... but I can't believe this is the optimal solution.
Part of the reason I'm not satisfied with creating it after-the-fact is that I want to put this into a process so other developers can use the code after me -- it's not just a one-time-build sort of thing. I don't want to have to give them a list of complicated instructions.
Do you know how to do this or have any suggestions for how to go about it?
Here's my poorly written example Makefile. I can post the rest of the code if requested.
Makefile: (My editor replaced tabs with spaces)
FC=gfortran -g
CC=g++ -g
DLL_SRC_DIR=.
BUILD_DIR=build
all:
$(FC) -c $(DLL_SRC_DIR)/fdll.f90 -o $(BUILD_DIR)/fdll.o
$(CC) -c -DBUILDING_C_DLL $(DLL_SRC_DIR)/cdll.cpp -o $(BUILD_DIR)/cdll.o
$(CC) -shared -o $(BUILD_DIR)/cdll.dll $(BUILD_DIR)/cdll.o $(BUILD_DIR)/fdll.o -Wl,--out-implib,$(BUILD_DIR)/libcdll.a -lgfortran
clean:
rm -f $(BUILD_DIR)/*
Edit: Thanks to IanH, here's my new Makefile!
FC=gfortran -g
CC=g++ -g
DLL_SRC_DIR=.
BUILD_DIR=build
all:
$(FC) -c $(DLL_SRC_DIR)/fdll.f90 -o $(BUILD_DIR)/fdll.o
$(CC) -c -DBUILDING_C_DLL $(DLL_SRC_DIR)/cdll.cpp -o $(BUILD_DIR)/cdll.o
$(CC) -shared -o $(BUILD_DIR)/libcdll.dll $(BUILD_DIR)/cdll.o $(BUILD_DIR)/fdll.o -Wl,--out-implib,$(BUILD_DIR)/libcdll.a,--output-def,$(BUILD_DIR)/libcdll.def -lgfortran
/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio\ 12.0/VC/BIN/lib /MACHINE:x86 /DEF:$(BUILD_DIR)\\libcdll.def /OUT:$(BUILD_DIR)\\libcdll.lib
clean:
rm -f $(BUILD_DIR)/*
Upvotes: 1
Views: 1410
Reputation: 21431
The gcc linker can be instructed to output a module definition file (.def extension) that describes all the exports from the DLL.
This def file can then be turned into an import library (a form of .lib file) by the Microsoft Library Manager and then that static library can be consumed by the other windows oriented tools.
Change your link line to be something like:
$(CC) -shared -o $(BUILD_DIR)/cdll.dll $(BUILD_DIR)/cdll.o \
$(BUILD_DIR)/fdll.o \
-Wl,--out-implib,$(BUILD_DIR)/libcdll.a,--output-def,$(BUILD_DIR)/libcdll.def \
-lgfortran
and add a new line to generate the static library such as:
LIB.EXE /MACHINE:x64 /DEF:$(BUILD_DIR)\libcdll.def /OUT:$(BUILD_DIR)\libcdll.lib
Change x64
to the appropriate machine type if you are not compiling for x64. Expect confusion if BUILD_DIR
contains spaces or similar.
The static library can then be supplied to invocations of the cl.exe Microsoft compiler driver.
Note that particular care needs to be taken when using executable modules (DLL's, EXE's) that have different runtime libraries within the one process.
Upvotes: 2