0

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.

Fungor
  • 15
  • 3
  • what's in `main.cpp`? Have you used the correct macros? https://github.com/catchorg/Catch2/blob/v2.x/docs/own-main.md#top – Alan Birtles May 06 '23 at 19:30
  • is this the most minimal example you could devise to reproduce this problem? ([mre]) (I think not- like- first of all, you've got a bunch of other libraries in here that probably aren't necessary to reproduce the problem) – starball May 06 '23 at 19:48
  • @AlanBirtles I am not using my own main() for Catch2. My main.cpp is built in executable, which is the end target for my project (other lib_x are just supporting it). Tests are just like this: `TEST_CASE("Testing class X") { // code }` – Fungor May 06 '23 at 19:56
  • @user I agree that information about rang and zlib is in some way excessive. The reason why I provided it is to show that apart from Catch2 the rest of my dependencies are working. – Fungor May 06 '23 at 20:01
  • You'll either need to either provide your own main or use the catch macros to define one for you – Alan Birtles May 07 '23 at 07:27
  • @AlanBirtles I am sorry, I do not understand what do you mean. I followed starting guide from Catch2 repository, I made my tests the way I described above and they even worked, when I used FetchContent instead of Conan 2.0. Each library has number of .cpp files that are used to built targets like "lib-x-test" which are executables. Clearly, my problem is related to how I install Catch2 and not how I use it. Sorry for possible misunderstanding. – Fungor May 07 '23 at 07:46
  • If you provide a [mre] your question would be much easier to answer – Alan Birtles May 07 '23 at 07:47
  • @AlanBirtles I edited my question with recreated issue on much smaller scale. Hope it will be reproducible enough. – Fungor May 07 '23 at 08:42
  • Does this help? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Jesper Juhl May 07 '23 at 10:41
  • @JesperJuhl I appreciate the response, but not too much. I'm familiar with concepts of linking, I understand the basic reasons for linkage errors but here solution is unknown to me, – Fungor May 07 '23 at 11:21
  • I don't know whether it's related, but this way of injecting conan toolchain and hardcoding CMAKE_BUILD_TYPE is totally wrong. You should follow conan tutorials: https://docs.conan.io/2/tutorial/consuming_packages/build_simple_cmake_project.html. – SpacePotatoes May 07 '23 at 14:30
  • @SpacePotatoes Fair point, if someone will want to inject toolchain file like this it needs to be either set() before project() or in command line args. Still not the source of the problem though. – Fungor May 07 '23 at 16:31

1 Answers1

2

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.

user16217248
  • 3,119
  • 19
  • 19
  • 37
SpacePotatoes
  • 659
  • 5
  • 11
  • Well, that's it. Thanks for assistance! Can you elaborate how exactly I have failed in my example? – Fungor May 07 '23 at 18:29
  • 1
    If using CMake>=3.23, it is also possible and convenient to use the generated CMake presets for a shorter command line, lik e``cmake --presets conan-release`` – drodri May 07 '23 at 22:17
  • One of the failures is trying to set the toolchain in the CMakeLists.txt as ``set(CMAKE_TOOLCHAIN_FILE "build/conan_toolchain.cmake")``. This is not possible, it has to be passed in the command line to be effective when the ``project()`` call happens. – drodri May 07 '23 at 22:19
  • @drodri Thanks, I edited answer with his information. – Fungor May 08 '23 at 07:32