toolchain swapping combined with FetchContent feature

Hi all.

I’m new in cmake so maybe my question sound kinda dummy.

I’m dealing with a 3rd part dependencies. For those dependencies I use the fetchContent to deal with the them. Each depenency have a code similar to this

message("Adding library A...")
include(FetchContent)
FetchContent_Declare(librarya
        GIT_REPOSITORY "https://gitpath/dependency_a.git"
        GIT_TAG "main"
)

FetchContent_GetProperties(librarya)
if(NOT librarya_POPULATED)
    message("not found, downloading...")
    FetchContent_Populate(librarya)
    add_subdirectory(${librarya_SOURCE_DIR} ${librarya_BINARY_DIR})
endif()
message("Lib found, adding...")
FetchContent_MakeAvailable(librarya)

set(LIBRARYA_INCLUDE_DIRS ${librarya_SOURCE_DIR}/include)
include_directories(${LIBRARYA_INCLUDE_DIRS})

Now my problems come when I try to swap between toolchains. Until now we never use more than a simple toolchain with gcc (I never set by myself I just have the CC and CXX set into $ENV) , but now we need also intel compilator, and swap depending on the machine to run. When I try to set the icpx and icx I have a problem each time the FetchContent_Populate run thow and error because they remove the actual toolchain and cannot find the new compilers.

I found that this MR https://gitlab.kitware.com/cmake/cmake/-/merge_requests/8248/diffs talk about remove the cache because we need to download.

I’m not pretty sure at this point where I need to upload the the toolchain file, as well how dynamically select witch toolchain use based on the parent project toolchain.

I can send a MR to the libraries teams, to include changes changes into the library, so I find kind of “bad practice” to hardcode into the CMakeList.txt after I populate.

 file(READ ${gtest_SOURCE_DIR}/CMakeLists.txt gtest_CMakeLists)
    # I want to avoid this kind of practice
    string(FIND "${gtest_CMakeLists}" "CMAKE_POLICY(SET CMP0048 NEW)" CMP0048_FOUND)
    if(CMP0048_FOUND EQUAL -1)
        message(STATUS "INTEL compiter Not found, adding it to the GoogleTest CMakeLists.txt")
        string(REGEX REPLACE "project\\( googletest-distribution \\)" "SET(CMAKE_CXX_COMPILER /opt/intel.... )\nproject( googletest-distribution )" gtest_CMakeLists "${gtest_CMakeLists}")
        file(WRITE ${gtest_SOURCE_DIR}/CMakeLists.txt "${gtest_CMakeLists}")
    else()
        message(STATUS "Intel compiler found")
    endif()

I wan to avoid this as much as possible (since in most of the libraries I can push commits)

Thanks in advice to everyone,

Best regards,
Alberto Merino.

How or what do you “swap”? If you change the compiler details for an existing build directory, you should either clear that build directory completely, or add --fresh to your cmake command line to discard any cached information about the toolchain from the previous run.

FetchContent itself doesn’t enable any languages for its sub-build. If you’re getting errors about a compiler being missing, that would like be coming from the main project, not FetchContent or its sub-build. I suspect your problem is not clearing the details from a previous run, as explained just above.

While we’re here, I also point out that your example shouldn’t be calling FetchContent_GetProperties() or FetchCotnent_Populate(). Calling just FetchContent_MakeAvailable() is what you need, and are indeed doing. You’ve essentially mixed both the old and new pattern. All you need is this:

include(FetchContent)
FetchContent_Declare(librarya
        GIT_REPOSITORY "https://gitpath/dependency_a.git"
        GIT_TAG "main"
)
FetchContent_MakeAvailable(librarya)

Also note that GIT_TAG main is not recommended. Using a branch name means you’re tracking a floating commit, which means your builds are not repeatable over time. You should really be using a git commit hash or a git tag, which means your build should be repeatable. It will also mean your local build doesn’t have to contact the remote server every time you run CMake, it will only do that if it doesn’t already have the requested commit or tag checked out.

2 Likes

Hello Craig, thanks for your fast response.

First of all thanks for your feedback about how I deal with the FetchContent. I already fix and use only the MakeAvailable.

Also look that the problem was a cache issue, so thanks I was able to compile everything .