Search code examples
c++cmakeconancatch2

Problem linking to Catch2 library installed with Conan 2.0 in CMake


I recreated my issue on smaller project. Let's assume there are these files (also build directory):

├── add.hpp
├── add-test.cpp
├── CMakeLists.txt
└── conanfile.txt

add.hpp:

inline int add(int a, int b) { return a + b; }

add-test.cpp:

#include <catch2/catch_all.hpp>
#include "add.hpp"

TEST_CASE("testing add") {
    REQUIRE(add(1, 1) == 2);
}

conanfile.txt:

[requires]
catch2/3.3.1

[generators]
CMakeDeps
CMakeToolchain

I use the following CMake script to build all of this:

cmake_minimum_required(VERSION 3.5)

project(add LANGUAGES CXX VERSION 0.0.0)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(CMAKE_TOOLCHAIN_FILE "build/conan_toolchain.cmake")
# Required to be set.
set(CMAKE_BUILD_TYPE "Debug")
# CMake can't find Conan packages without these two lines
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})

find_package(Catch2 REQUIRED)

include_directories(${Catch2_INCLUDE_DIR})

add_executable(add-test add-test.cpp)

target_link_libraries(add-test Catch2::Catch2WithMain)

Conan profile is:

[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=12.2
os=Linux

I use the following commands to build my project (Assuming build/ is empty):

conan install . --output-folder=build --build=missing
cd build
cmake ..
cmake --build .

CMake configuration and Conan install go fine, then when building I get a swarm of linker errors, all are connected with Catch2. Some of them are like this:

/usr/bin/ld: CMakeFiles/add-test.dir/add-test.cpp.o: in function `Catch::BinaryExpr<int, int>::~BinaryExpr()':
/home/fungor/.conan2/p/catchff10ed8b5da5a/p/include/catch2/internal/catch_decomposer.hpp:73: undefined reference to `Catch::ITransientExpression::~ITransientExpression()'
/usr/bin/ld: CMakeFiles/add-test.dir/add-test.cpp.o:(.data.rel.ro._ZTIN5Catch10BinaryExprIiiEE[_ZTIN5Catch10BinaryExprIiiEE]+0x10): undefined reference to `typeinfo for Catch::ITransientExpression'
/usr/bin/ld: CMakeFiles/add-test.dir/add-test.cpp.o: in function `Catch::BinaryExpr<int, int>::streamReconstructedExpression(std::ostream&) const':
/home/fungor/.conan2/p/catchff10ed8b5da5a/p/include/catch2/internal/catch_decomposer.hpp:80: undefined reference to `Catch::formatReconstructedExpression(std::ostream&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Catch::StringRef, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
... (a bunch more of these undefined references)

What am I doing wrong?

I tried:

  • clearing Conan cache, rebuilding packages
  • different Conan profiles: different CPP standards, build configs.

I just need Catch2 to work with my project.

this seems similar to mine, but in my case libstdc++ is already set to ...++11

EDIT 1: Stripped question to be more minimal.

EDIT 2: Recreated my problem on smaller scale.

EDIT 3: Included information about conanfile.txt and corrected CMake script.


Solution

  • To begin with, change your CMakeLists:

    cmake_minimum_required(VERSION 3.8)
    project(add LANGUAGES CXX VERSION 0.0.0)
    
    find_package(Catch2 REQUIRED)
    
    add_executable(add-test add-test.cpp)
    target_link_libraries(add-test PRIVATE Catch2::Catch2WithMain)
    target_compile_features(add-test PRIVATE cxx_std_17)
    

    And the way you call conan & cmake:

    conan install . -of build-debug -s build_type=Debug -b missing 
    cmake -S . -B build-debug -DCMAKE_TOOLCHAIN_FILE=build-debug/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug
    cmake --build build-debug
    

    Always try to set CMake toolchain file in command line arguments. Another way is to set variable CMAKE_TOOLCHAIN_FILE before project() call in CMakeLists. The last one is not a good practice anyway.