0

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
veryreverie
  • 2,871
  • 2
  • 13
  • 26

0 Answers0