I cant test my library due to missing dependencies when I include it in CMake.

I have the main CMake file for my project that looks like this:

cmake_minimum_required(VERSION 3.19...3.25 FATAL_ERROR)

project(
        Turingforge
        VERSION 0.1.0
        LANGUAGES CXX C
)

#add_compile_options(-Wundef -Wcast-align -Wchar-subscripts -Wnon-virtual-dtor -Wunused-local-typedefs -Wpointer-arith
#        -Wwrite-strings -Wformat-security -Wlogical-op -Wenum-conversion -Wdouble-promotion -Wconversion -Wshadow
#        -Wno-psabi -Wno-variadic-macros -Wno-long-long -fno-check-new -fno-common -fstrict-aliasing)

#Make sure that custom modules are found
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake)

# Only do these if this is the main project, and not if it is included through add_subdirectory
if(PROJECT_IS_TOP_LEVEL)
  set(CMAKE_CXX_STANDARD 20)
  set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

  # Ensure -std=c++xx instead of -std=g++xx
  set(CMAKE_CXX_EXTENSIONS OFF)

  set_property(GLOBAL PROPERTY USE_FOLDERS ON)

  # Testing only available if this is the main app
  # Note this needs to be done in the main CMakeLists
  # since it calls enable_testing, which must be in the
  # main CMakeLists.
  include(CTest)

  # Docs only available if this is the main app
  find_package(Doxygen)
  if(Doxygen_FOUND)
    add_subdirectory(docs)
  else()
    message(STATUS "Doxygen not found, not building docs")
  endif()
endif()

##############################################
# Add subdirectories
add_subdirectory(src)

# The executable code is here
#add_subdirectory(apps)

set(BUILD_TESTING ON)
# Testing only available if this is the main app
# Emergency override TURINGFORGE_CMAKE_BUILD_TESTING provided as well
if ((PROJECT_IS_TOP_LEVEL OR TURINGFORGE_CMAKE_BUILD_TESTING) AND BUILD_TESTING)
  enable_testing()
  add_subdirectory(tests)
endif()

Inside src/ I have another CMake file that builds my library:

##############################################
# Find/Install system dependencies
include(FetchContent)
include(ExternalProject)

# Formatting library
FetchContent_Declare(
        fmtlib
        GIT_REPOSITORY https://github.com/fmtlib/fmt.git
        GIT_TAG 10.1.1)
set(FMT_INSTALL ON)
# Adds fmt::fmt
FetchContent_MakeAvailable(fmtlib)

# Eigen
FetchContent_Declare(
        Eigen
        GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
        GIT_TAG 3.4.0
        GIT_SHALLOW TRUE
        GIT_PROGRESS TRUE)
set(EIGEN_BUILD_DOC OFF)
set(BUILD_TESTING OFF)
set(EIGEN_BUILD_PKGCONFIG OFF)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
FetchContent_MakeAvailable(Eigen)

find_package (Eigen3 3.4 REQUIRED NO_MODULE)

# Fast float
FetchContent_Declare(
        fast_float
        GIT_REPOSITORY https://github.com/fastfloat/fast_float.git
        GIT_TAG tags/v6.0.0
        GIT_SHALLOW TRUE)
set(FASTFLOAT_INSTALL OFF)
# Adds fast_float
FetchContent_MakeAvailable(fast_float)

# Fast unordered map and set
FetchContent_Declare(
        unordered_dense
        GIT_REPOSITORY https://github.com/martinus/unordered_dense.git
        GIT_TAG tags/v4.3.1
        GIT_SHALLOW TRUE)
# Adds unordered_dense::unordered_dense
FetchContent_MakeAvailable(unordered_dense)

# SIMD vector operations
FetchContent_Declare(
        vectorclass
        GIT_REPOSITORY https://github.com/vectorclass/version2.git
        GIT_TAG tags/v2.02.01
        GIT_SHALLOW 1)
FetchContent_MakeAvailable(vectorclass)

# Fast hash Functions
FetchContent_Declare(
        xxhash
        GIT_REPOSITORY https://github.com/Cyan4973/xxHash.git
        GIT_TAG tags/v0.8.2
        GIT_SHALLOW TRUE)
set(XXHASH_BUNDLED_MODE ON)
set(XXH_INLINE_ALL ON)
# Adds xxhash
FetchContent_MakeAvailable(xxHash)
file(GLOB XXHASH_SOURCES ${xxhash_SOURCE_DIR}/*.c)
list(REMOVE_ITEM XXHASH_SOURCES ${xxhash_SOURCE_DIR}/xxhsum.c)
list(REMOVE_ITEM XXHASH_SOURCES ${xxhash_SOURCE_DIR}/xxh_x86dispatch.c)
add_library(xxhash STATIC ${XXHASH_SOURCES})
target_include_directories(xxhash PUBLIC ${xxhash_SOURCE_DIR})

##############################################
# Create target and set properties

file(GLOB_RECURSE HEADER_LIST CONFIGURE_DEPENDS
        "${PROJECT_SOURCE_DIR}/include/turing_forge/*/*.hpp"
        "${PROJECT_SOURCE_DIR}/include/vstat/*.hpp"
        "${PROJECT_SOURCE_DIR}/include/csv/*.hpp"
)

file(GLOB_RECURSE SRC_LIST CONFIGURE_DEPENDS
        "${PROJECT_SOURCE_DIR}/src/*/*.cpp"
)

add_library(turingforge
        ${SRC_LIST}
        ${HEADER_LIST}
)

#Add an alias so that library can be used inside the build tree, e.g. when testing
add_library(Turingforge::turingforge ALIAS turingforge)

#Set target properties
target_include_directories(turingforge
        PUBLIC
            $<INSTALL_INTERFACE:include>
            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
            ${PROJECT_SOURCE_DIR}/include
        PRIVATE
            ${vectorclass_SOURCE_DIR}
)

target_compile_features(turingforge PRIVATE cxx_auto_type)
target_compile_options(turingforge PRIVATE
        $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:-Wall -Wextra -pedantic -Werror>)

target_link_libraries(turingforge
        PUBLIC
            fmt::fmt Eigen3::Eigen unordered_dense::unordered_dense
        PRIVATE
            xxhash vectorclass fast_float
)

##############################################
# Installation instructions

# TODO: fix libraries not being in any export set
option(TURINGFORGE_INSTALL "Enable install" OFF)
set(TURINGFORGE_INSTALL OFF)

if (TURINGFORGE_INSTALL)
    include(GNUInstallDirs)
    set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/Turingforge)

    install(TARGETS turingforge
            EXPORT turingforge-targets
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    )

    # This is required so that the exported target has the name Turingforge and not turingforge
    set_target_properties(turingforge PROPERTIES EXPORT_NAME Turingforge)

    install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

    # Export the targets to a script
    install(EXPORT turingforge-targets
            FILE
                TuringforgeTargets.cmake
            NAMESPACE
                Turingforge::
            DESTINATION
                ${INSTALL_CONFIGDIR}
    )

    # Create a ConfigVersion.cmake file
    include(CMakePackageConfigHelpers)
    write_basic_package_version_file(
            ${CMAKE_CURRENT_BINARY_DIR}/TuringforgeConfigVersion.cmake
            VERSION ${PROJECT_VERSION}
            COMPATIBILITY AnyNewerVersion
    )

    configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/../cmake/TuringforgeConfig.cmake.in
            ${CMAKE_CURRENT_BINARY_DIR}/TuringforgeConfig.cmake
            INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
    )

    # Install the config, configversion and custom find modules if any
    install(FILES
            ${CMAKE_CURRENT_BINARY_DIR}/TuringforgeConfig.cmake
            ${CMAKE_CURRENT_BINARY_DIR}/TuringforgeConfigVersion.cmake
            DESTINATION ${INSTALL_CONFIGDIR}
    )

    ##############################################
    ## Exporting from the build tree
    #configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/SOMECUSTOM.cmake
    #        ${CMAKE_CURRENT_BINARY_DIR}/SOMECUSTOM.cmake
    #        COPYONLY)

    export(EXPORT turingforge-targets
            FILE ${CMAKE_CURRENT_BINARY_DIR}/TuringforgeTargets.cmake
            NAMESPACE Turingforge::)

    # Register package in the User Package Registry
    export(PACKAGE Turingforge)

    # Make sure IDEs put the headers in a nice place
    source_group(
            TREE "${PROJECT_SOURCE_DIR}/include"
            PREFIX "Header Files"
            FILES ${HEADER_LIST}
    )
endif()

and finally I try to run tests built by this CMake file inside tests/:

# Testing library
FetchContent_Declare(
  catch
  GIT_REPOSITORY https://github.com/catchorg/Catch2.git
  GIT_TAG v3.5.0)
# Adds Catch2::Catch2
FetchContent_MakeAvailable(catch)

list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)

set(TEST_SOURCES
        test_evaluation.cpp
        test_expression.cpp
)

string(REPLACE ".cpp" "" BASENAMES "${TEST_SOURCES}")
set(TARGETS ${BASENAMES})

foreach(name ${TARGETS})
    add_executable(${name} ${name}.cpp)
    target_link_libraries(${name} turingforge Catch2::Catch2WithMain)
    target_compile_features(${name} PRIVATE cxx_std_20)
endforeach()

include(ParseAndAddCatchTests)
ParseAndAddCatchTests(${TARGETS})

When I try to run a test I get:

FAILED: tests/test_expression 
: && /usr/bin/c++ -g  tests/CMakeFiles/test_expression.dir/test_expression.cpp.o -o tests/test_expression  src/libturingforge.a  _deps/catch-build/src/libCatch2Maind.a  _deps/fmtlib-build/libfmtd.a  -lvectorclass  src/libxxhash.a  _deps/catch-build/src/libCatch2d.a && :
/usr/bin/ld: cannot find -lvectorclass: No such file or directory
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

I think I am not building vectorclass correctly and as such it is not found here. I’m not sure though and I was wondering if someone can identify the reason behind the error.

Additionally, if I set TURINGFORGE_INSTALL I get the following errors:

CMake Error in src/CMakeLists.txt:
 Target "turingforge" INTERFACE_INCLUDE_DIRECTORIES property contains path:

   "/home/user/Downloads/research/SymbolicRegression/deletmeee/include"

 which is prefixed in the source directory.


CMake Error: install(EXPORT "turingforge-targets" ...) includes target "turingforge" which requires target "unordered_dense" that is not in any export set.
CMake Error: install(EXPORT "turingforge-targets" ...) includes target "turingforge" which requires target "xxhash" that is not in any export set.
CMake Error: install(EXPORT "turingforge-targets" ...) includes target "turingforge" which requires target "fast_float" that is not in any export set.
CMake Error in src/CMakeLists.txt:
 export called with target "turingforge" which requires target
 "unordered_dense" that is not in any export set.


CMake Error in src/CMakeLists.txt:
 export called with target "turingforge" which requires target "xxhash" that
 is not in any export set.


CMake Error in src/CMakeLists.txt:
 export called with target "turingforge" which requires target "fast_float"
 that is not in any export set.

How can I include the needed targets on the export set?

You can’t use a git repo like that, which is NOT prepared for CMake as build system!
Even more, is must be prepared to use in a superbuild project like yours!

I see!
Additionally, when it comes to the superbuild thing you mentioned. I did follow some tutorials, but I feel with the number of dependencies that I have, I am not doing it correctly, for example as I mention above, the entire ‘install’ part does not work. Do you have any advice on cleaning refactoring?

one possible solution would be to create a file cmake/Findvectorclass.cmake

# Read the documentation of FetchContent first!
# https://cmake.org/cmake/help/latest/module/FetchContent.html

include(FetchContent)

FetchContent_Declare(
  vectorclass
  GIT_REPOSITORY https://github.com/vectorclass/version2.git
  GIT_TAG tags/v2.02.01
  GIT_SHALLOW YES
)

# Note that here we manually do what FetchContent_MakeAvailable() would do,
# except to ensure that the dependency can also get what it needs,
# we add custom logic between the FetchContent_Populate() and add_subdirectory() calls.

FetchContent_GetProperties(vectorclass)
if(NOT vectorclass_POPULATED)
  FetchContent_Populate(vectorclass)

  # Because we are in a find module, we are solely responsible for resolution.
  # Setting this *_FOUND variable to a truthy value will signal to the calling
  # find_package() command that we were successful.
  # More relevant info regarding find modules and what variables they use can be
  # found in the documentation of find_package() and
  # https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html

  # NOT needed: add_subdirectory("${vectorclass_SOURCE_DIR}" "${vectorclass_BINARY_DIR}")

  set(vectorclass_FOUND 1)

  include(GNUInstallDirs)

  #
  # add vectorclass as header only lib
  #
  set(_PROJECT_NAME vectorclass)
  add_library(${_PROJECT_NAME} INTERFACE)
  target_include_directories(${_PROJECT_NAME} INTERFACE $<BUILD_INTERFACE:${vectorclass_SOURCE_DIR}>)
  add_library(${_PROJECT_NAME}::${_PROJECT_NAME} ALIAS ${_PROJECT_NAME})

  if(CMAKE_SKIP_INSTALL_RULES)
    return()
  endif()

  # install (if required)
  target_include_directories(${_PROJECT_NAME} INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
  install(TARGETS ${_PROJECT_NAME} EXPORT ${_PROJECT_NAME}-config)
  install(EXPORT ${_PROJECT_NAME}-config NAMESPACE ${_PROJECT_NAME}::
          DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${_PROJECT_NAME}
  )
  install(DIRECTORY ${vectorclass_SOURCE_DIR}/
          DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${_PROJECT_NAME}
          FILES_MATCHING
          PATTERN "*.h"
          PATTERN ".git" EXCLUDE
  )

endif()

and use it like this

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
find_package(vectorclass MODULE REQUIRED)