I have a simple C++ project which uses armadillo, which in turn needs BLAS/LAPACK. I'm compiling with gcc, so this introduces a dependency on the gfortran runtime library. When I link my code, this library is not being linked correctly.
In my source directory I have main.cpp
:
#include <armadillo>
class Triangle{
public:
arma::vec surface_normal() const;
};
arma::vec Triangle::surface_normal() const{
return arma::normalise(arma::cross(arma::vec{0.0,0.0,1.0}, arma::vec{1.0,0.0,0.0}));
}
int main(void){
Triangle triangle;
return 0;
}
and CMakeLists.txt
:
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
project(foo)
find_package(Armadillo REQUIRED)
enable_language(CXX)
add_executable(foo main.cpp)
target_include_directories(foo PUBLIC ${ARMADILLO_INCLUDE_DIRS})
target_link_libraries(foo ${ARMADILLO_LIBRARIES})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgfortran")
where I'm adding -lgfortran
as late as possible as per this question.
I'm then compiling from a build directory using
cmake -G "MinGW Makefiles" ../src
cmake --build . -- VERBOSE=1
this invokes a compile step, which runs fine, and then the linker step
C:\msys64\mingw64\bin\g++.exe -lgfortran -Wl,--whole-archive CMakeFiles\foo.dir/objects.a -Wl,--no-whole-archive -o foo.exe -Wl,--out-implib,libfoo.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles\foo.dir\linklibs.rsp
which results in the errors
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Program Files (x86)/OpenBLAS/lib/libopenblas.a(dormbr.f.obj):dormbr.f:(.text+0x3ad): undefined reference to `_gfortran_concat_string'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Program Files (x86)/OpenBLAS/lib/libopenblas.a(dormbr.f.obj):dormbr.f:(.text+0x463): undefined reference to `_gfortran_concat_string'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Program Files (x86)/OpenBLAS/lib/libopenblas.a(dormbr.f.obj):dormbr.f:(.text+0x523): undefined reference to `_gfortran_concat_string'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Program Files (x86)/OpenBLAS/lib/libopenblas.a(dormbr.f.obj):dormbr.f:(.text+0x5d9): undefined reference to `_gfortran_concat_string'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Program Files (x86)/OpenBLAS/lib/libopenblas.a(dormlq.f.obj):dormlq.f:(.text+0x2fe): undefined reference to `_gfortran_concat_string'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Program Files (x86)/OpenBLAS/lib/libopenblas.a(dormlq.f.obj):dormlq.f:(.text+0x4e4): more undefined references to `_gfortran_concat_string' follow
collect2.exe: error: ld returned 1 exit status
For reference, linklibs.rsp
contains
"C:/Program Files (x86)/OpenBLAS/lib/libopenblas.a" "C:/Program Files (x86)/OpenBLAS/lib/libopenblas.a" -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
If I manually run the linker step, and add -lgfortran
anywhere after -Wl,--whole-archive
then it completes successfully.
So my question is: how do I make CMake add -lgfortran
late enough in the linker command that it works?
Details:
- Windows 10
- gcc 11.2.0
- CMake 3.22.3
- Armadillo 10.8.2
- OpenBLAS 0.3.20