I'm a beginner to CMake and have been modifying a CMake script (see below) and it was compiling fine. However, I am now following this article to add Google Test:
https://raymii.org/s/tutorials/Cpp_project_setup_with_cmake_and_unit_tests.html
but I have a lot of problems. I don't think i've done this properly.
I'm currently getting undefined references to Boost source code when linking the unit test:
[ 98%] Linking CXX executable helloworld_test
cd /bla/bla/HelloWorld/build/test && /usr/bin/cmake -E cmake_link_script CMakeFiles/helloworld_test.dir/link.txt --verbose=1
/usr/bin/c++ -Wall -Wextra -pedantic -march=native -O2 -g -DNDEBUG -fsanitize=address CMakeFiles/helloworld_test.dir/AComponentTest.cpp.o CMakeFiles/helloworld_test.dir/main.cpp.o -o helloworld_test ../libhelloworld.a ../lib/libgtest.a /usr/lib/x86_64-linux-gnu/libssl.a /usr/lib/x86_64-linux-gnu/libcrypto.a -ldl
/usr/bin/ld: ../libhelloworld.a(AComponent.cpp.o): in function `ix::AComponent::onConnected()':
/bla/bla/HelloWorld/src/AComponent.cpp:152: undefined reference to `boost::json::serialize[abi:cxx11](boost::json::value const&)'
/usr/bin/ld: /bla/bla/HelloWorld/src/AComponent.cpp:153: undefined reference to `boost::json::value::~value()'
/usr/bin/ld: /bla/bla/HelloWorld/src/AComponent.cpp:144: undefined reference to `boost::json::value::value(std::initializer_list<boost::json::value_ref>, boost::json::storage_ptr)'
/usr/bin/ld: /bla/bla/HelloWorld/src/AComponent.cpp:146: undefined reference to `boost::json::operator<<(std::ostream&, boost::json::value const&)'
/usr/bin/ld: /bla/bla/HelloWorld/src/AComponent.cpp:153: undefined reference to `boost::json::value::~value()'
However, weirdly I didn't need to reference Boost in the CMake before adding the unit tests, so I'm not sure why that worked but fails now i'm building the tests? I'm really confused.
This is my CMake:
cmake_minimum_required(VERSION 3.20)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
project(helloworld C CXX)
set (CMAKE_CXX_STANDARD 20)
set (CMAKE_BUILD_TYPE Release)
set (BUILD_MAIN TRUE)
set (BUILD_SHARED_LIBS FALSE)
set (OPENSSL_USE_STATIC_LIBS TRUE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set( HELLOWORLD_HEADERS helloworld/File1.h helloworld/File2.h )
set( HELLOWORLD_SOURCES helloworld/File1.cpp helloworld/File2.cpp )
# Static library
add_library( helloworld ${HELLOWORLD_SOURCES} ${HELLOWORLD_HEADERS} )
# OpenSSL
if (NOT OPENSSL_FOUND)
find_package(OpenSSL REQUIRED)
endif()
add_definitions(${OPENSSL_DEFINITIONS})
target_include_directories(helloworld PUBLIC $<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>)
target_link_libraries(helloworld PRIVATE ${OPENSSL_LIBRARIES})
set( HELLOWORLD_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR})
include(GNUInstallDirs)
target_include_directories(helloworld PUBLIC
$<BUILD_INTERFACE:${HELLOWORLD_INCLUDE_DIRS}/>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/helloworld>
)
set_target_properties(helloworld PROPERTIES PUBLIC_HEADER "${HELLOWORLD_HEADERS}")
add_library(helloworld::helloworld ALIAS helloworld)
include_directories(/bla/bla/helloworld/lib/googletest/googletest/include/)
add_subdirectory(test)
add_subdirectory(lib/googletest)
add_executable(main main.cpp)
target_link_libraries(main helloworld)
My folder structure looks like this:
HelloWorld
|---CMakeList.txt
|---main.cpp
|---build
|---lib
| |---googletest
| |---googletest
| |---include
| |---gtest
| | <all the google test code>
|---src
| |---CMakeList.txt
| <lots of code>
|---tst
| |---CMakeList.txt
| |---main.cpp
| |---AComponentTest.cpp
As per the article, my tst/CMakeList.txt
is this:
set(BINARY ${CMAKE_PROJECT_NAME}_test)
file(GLOB_RECURSE TEST_SOURCES LIST_DIRECTORIES false *.h *.cpp)
set(SOURCES ${TEST_SOURCES})
add_executable(${BINARY} ${TEST_SOURCES})
add_test(NAME ${BINARY} COMMAND ${BINARY})
target_link_libraries(${BINARY} PUBLIC ${CMAKE_PROJECT_NAME} gtest)
and these are the only additional lines I added to helloworld/CMakeList.txt
:
include_directories(/bla/bla/helloworld/lib/googletest/googletest/include/)
add_subdirectory(test)
add_subdirectory(lib/googletest)
(if I comment-out these lines, it builds fine)
My test is very simple:
#include "gtest/gtest.h"
#include <src/AComponent.h>
TEST(blaTest, test1)
{
const char* config_path = "";
AComponent a(config_path, true);
EXPECT_EQ(false, false);
}