0

I am learning to build library with the following command

cmake -S . -B .\build\ -DCMAKE_BUILD_TYPE=Debug
cmake --build .\build\

I am getting the following errors during cmake --build .\build\

error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.obj
error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.obj 

I was referring the question at the error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.obj to solve the error error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.obj but would like to know how to implement their solution using cmake.
I referred the answer to solve the problem but it didn't solve the error.

Second problem is that I can't understand why MD_DynamicRelease is being built even though I added the option -DCMAKE_BUILD_TYPE=Debug.


Root CMakeLists.txt File

cmake_minimum_required(VERSION 3.16)

project(CppProjectTemplate VERSION 1.0.0 LANGUAGES C CXX)


set(CMAKE_CXX_STANDARD              17)
set(CMAKE_CXX_STANDARD_REQUIRED     ON)
set(CMAKE_CXX_EXTENSIONS            OFF)

set(MY_LIBRARY_NAME Library)


#Chapter 22 Starts Here --> Needs to be a cmake project else can't be used
include(FetchContent)
FetchContent_Declare(
    nlohmann_json # Must be the same name as mentioned in the main (root) cmake project file
    GIT_REPOSITORY https://github.com/nlohmann/json
    GIT_TAG v3.11.2
    GIT_SHALLOW TRUE #Won't clone recurrsively
)
FetchContent_MakeAvailable(nlohmann_json)# Must be the same name as mentioned in the main (root) cmake project file

FetchContent_Declare(
    fmt # Must be the same name as mentioned in the main (root) cmake project file
    GIT_REPOSITORY https://github.com/fmtlib/fmt
    GIT_TAG 9.1.0
    GIT_SHALLOW TRUE #Won't clone recurrsively
)
FetchContent_MakeAvailable(fmt)# Must be the same name as mentioned in the main (root) cmake project file

FetchContent_Declare(
    spdlog # Must be the same name as mentioned in the main (root) cmake project file
    GIT_REPOSITORY https://github.com/gabime/spdlog
    GIT_TAG v1.11.0
    GIT_SHALLOW TRUE #Won't clone recurrsively
)
FetchContent_MakeAvailable(spdlog)# Must be the same name as mentioned in the main (root) cmake project file

FetchContent_Declare(
    cxxopts # Must be the same name as mentioned in the main (root) cmake project file
    GIT_REPOSITORY https://github.com/jarro2783/cxxopts
    GIT_TAG v3.0.0
    GIT_SHALLOW TRUE #Won't clone recurrsively
)
FetchContent_MakeAvailable(cxxopts)# Must be the same name as mentioned in the main (root) cmake project file

FetchContent_Declare(
    Catch2 # Must be the same name as mentioned in the main (root) cmake project file
    GIT_REPOSITORY https://github.com/catchorg/Catch2
    GIT_TAG v2.13.9
    GIT_SHALLOW TRUE #Won't clone recurrsively
)
FetchContent_MakeAvailable(Catch2)# Must be the same name as mentioned in the main (root) cmake project file
# Chapter 22 Ends Here
# Enable/Disable option using -D<Option-Name>=1 or 0 e.g. -DCOMPILE_EXECUTABLE=1
option(COMPILE_EXECUTABLE "Whether to compile the executable" ON) 

add_subdirectory(src)
add_subdirectory(test)

src folder

my_lib.hh

#pragma once
#include <cstdint>
void print_hello_world(void);
std::uint32_t factorial(std::uint32_t number);

my_lib.cc

#include <iostream>
#include "my_lib.hh"
#include <nlohmann/json.hpp>
#include <fmt/format.h>
#include <spdlog/spdlog.h>
#include <cxxopts.hpp>

/**
 * @brief Print out Hello, World!!! and print the version of nlohmann-json, fmt-format, cxxopts and spdlog library
 * 
 */
void print_hello_world(void)
{
    std::cout << "Hello, World!!!" << std::endl;
    std::cout << "Json Lib Version (Inside print_hello_world) : "   
        << NLOHMANN_JSON_VERSION_MAJOR << "."
        << NLOHMANN_JSON_VERSION_MINOR << "."
        << NLOHMANN_JSON_VERSION_PATCH << std::endl;

    std::cout << "FMT Version (Inside print_hello_world) : "    
        << FMT_VERSION << std::endl;

    std::cout << "cxxopts Version (Inside print_hello_world) : "    
        << CXXOPTS__VERSION_MAJOR << "."
        << CXXOPTS__VERSION_MINOR << "."
        << CXXOPTS__VERSION_PATCH << std::endl;

    std::cout << "spdlogs Version (Inside print_hello_world) : "    
        << SPDLOG_VER_MAJOR << "."
        << SPDLOG_VER_MINOR << "."
        << SPDLOG_VER_PATCH << std::endl;
}

std::uint32_t factorial(std::uint32_t number)
{
    return number <= 1 ? number : factorial(number-1) * number;
}

src CMakeLists.txt

set(
    LIBRARY_SOURCES 
    "my_lib.cc"
    )

set(LIBRARY_HEADERS 
    "my_lib.hh")

add_library(${MY_LIBRARY_NAME} STATIC ${LIBRARY_SOURCES} ${LIBRARY_HEADERS})

target_include_directories(${MY_LIBRARY_NAME} PUBLIC 
    "./"
    "${CMAKE_BINARY_DIR}/configured_files/include"
)

target_link_libraries(${MY_LIBRARY_NAME} PUBLIC 
    nlohmann_json::nlohmann_json
    cxxopts::cxxopts
    fmt::fmt
    spdlog::spdlog
)

Test Directory

CMakeLists.txt

set(TEST_PROJECT "TestExecutable")
set(TEST_SOURCES "main.cc")
set(TEST_INCLUDE "./")

add_executable(${TEST_PROJECT} ${TEST_SOURCES})
target_include_directories(${TEST_PROJECT} PUBLIC ${TEST_INCLUDE})
target_link_libraries(${TEST_PROJECT} PUBLIC ${MY_LIBRARY_NAME} Catch2::Catch2)

main.cc

#define CATCH_CONFIG_MAIN

#include "catch.hpp"
#include "my_lib.hh"

TEST_CASE("Factorial are computed", "[Factorial]")
{
    REQUIRE(factorial(1) == 1);
    REQUIRE(factorial(2) == 2);
    REQUIRE(factorial(3) == 6);
    REQUIRE(factorial(10) == 3628800);
}
Dark Sorrow
  • 1,681
  • 14
  • 37
  • When build the project with Visual Studio generator, build type isn't known at configuration stage, when `cmake -S <..> -B <..>` is run and when `CMakeLists.txt` is processed. Setting `CMAKE_BUILD_TYPE` with such generator is at least useless and could confuse other projects which you use as subprojects. With Visual Studio build type is specified with `--config` option to `cmake --build` invocation. – Tsyvarev Jan 26 '23 at 07:52
  • @Tsyvarev, I tried the following command but still getting the same error `cmake -S . -B build\ -DCMAKE_BUILD_TYPE=Debug` and `cmake --build .\build\ --config Debug` – Dark Sorrow Jan 26 '23 at 14:12
  • Do not use `-DCMAKE_BUILD_TYPE` option at all. And make clean configuration (with empty build directory). – Tsyvarev Jan 26 '23 at 14:32
  • @Tsyvarev Tried all permutation and combinations. I'm still getting the same error. – Dark Sorrow Jan 26 '23 at 15:09
  • @DarkSorrow is this happening in the `test` project? – Milan Š. Jan 30 '23 at 09:07
  • @MilanŠ., Yes this is happening in the `test` project and especially while linking `Catch2`. – Dark Sorrow Jan 30 '23 at 10:40

1 Answers1

1

Based on your reply to my comment the issue is in this line:

target_link_libraries(${TEST_PROJECT} PUBLIC ${MY_LIBRARY_NAME} Catch2::Catch2)

I've faced similar issues and it's caused by not linking the debug library of Catch2 in DEBUG builds (but instead the release libraries). To fix this you need to use generator expressions for linking Catch2. I do not have a concrete example (it's been years since I've used Catch2), but you ideally need to link the actual Catch2 library without using the alias Catch2::Catch2 and use generator expressions to specify the debug library. e.g. you need something like:

target_link_libraries(${TEST_PROJECT} PUBLIC ${MY_LIBRARY_NAME} Catch2<$<$CMAKE_BUILD_TYPE:DEBUG>d>)

Where Catch2 is the actual library target and not the alias i.e. Catch2::Catch2. The generator expression basically expands to Catch2d when CMAKE_BUILD_TYPE == DEBUG.


EDIT: As DarkSorrow mentions in the comments below, this has resolved the issue for him

target_link_libraries(${TEST_PROJECT} PUBLIC ${MY_LIBRARY_NAME} Catch2$<$<CONFIG:Debug>:d>)
Milan Š.
  • 1,353
  • 1
  • 2
  • 11
  • I used the following command `target_link_libraries(${TEST_PROJECT} PUBLIC ${MY_LIBRARY_NAME} Catch2$<$:d>)` to build the library, – Dark Sorrow Jan 31 '23 at 15:18
  • 1
    @DarkSorrow Will put an edit to the answer to include it for other people. Glad it's fixed. – Milan Š. Jan 31 '23 at 15:20