FrostyTigerXP
FrostyTigerXP

Reputation: 81

How to download and compile external library only once with CMake?

I am using the Unity testing library in my project. Ideally, I would like to automatically download the source code from GitHub and put it in the external/ directory, build the library once, regardless of how many different CMake configurations I have (one Debug and one Release CMake configuration), and link the library with my application.

I have tried to use FetchContent, ExternalProject, and add_subdirectory but none of these seem to work quite right.

The issues I am currently facing right now are:

This is my project structure:

project/             <-- Project root
|-- bin/             <-- Application executable
|-- build/           <-- CMake build files
|   |-- _deps/       <-- Where Unity is built
|-- doc/             <-- Documentation from Doxygen
|-- include/         <-- Unity header files
|-- lib/             <-- Unity library file
|-- module/          <-- Application source code
|-- CMakeLists.txt   <-- CMake configuration file

This is my CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)
project(Project VERSION 1.0.0)
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/include)
add_subdirectory(module)

# Add Unity testing framework from GitHub
include(FetchContent)
FetchContent_Declare(
  unity
  GIT_REPOSITORY https://github.com/ThrowTheSwitch/Unity.git
  GIT_TAG        v2.5.1
)
FetchContent_MakeAvailable(unity)
FetchContent_GetProperties(unity)
if (NOT unity_POPULATED)
  FetchContent_Populate(unity)
  add_subdirectory(${unity_SOURCE_DIR} ${unity_BINARY_DIR})
endif()

enable_testing()
add_subdirectory(tests)

I really have no idea how to accomplish this. I looked at this other question and this link but it didn't seem to do everything I wanted it to do. Any help is appreciated.

Upvotes: 3

Views: 2918

Answers (1)

FrostyTigerXP
FrostyTigerXP

Reputation: 81

I was able to make it work using ExternalProject. This is what my CMakeLists.txt looks like now:

include(ExternalProject)
set(UNITY unity_project)
ExternalProject_Add(
    unity_project
    GIT_REPOSITORY https://github.com/ThrowTheSwitch/Unity.git
    GIT_TAG cf949f45ca6d172a177b00da21310607b97bc7a7
    PREFIX ${PROJECT_SOURCE_DIR}/external/${UNITY}
    CONFIGURE_COMMAND cmake ../${UNITY}
    BUILD_COMMAND cmake --build .
    INSTALL_COMMAND cmake --install . --prefix ${PROJECT_SOURCE_DIR}
    UPDATE_COMMAND ""
)
add_library(unity STATIC IMPORTED)
set_property(TARGET unity PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/lib/libunity.a)
add_dependencies(unity unity_project)

The first issue was solved by the line:

PREFIX ${PROJECT_SOURCE_DIR}/external/${UNITY}

The second issue was solved by the line:

UPDATE_COMMAND ""

The third issue was solved by the line:

INSTALL_COMMAND cmake --install . --prefix ${PROJECT_SOURCE_DIR}

Upvotes: 3

Related Questions