There is a natural problem with ExternalProject_Add:
ExternalProject_Add executes commands only on build.
Hence, download will not happen at the configure stage of your project which makes it difficult to use find_package
, because the files cannot be found during your first configure run.
Take this CMakeLists.txt:
cmake_minimum_required(VERSION 3.21)
project(untitled)
set(CMAKE_CXX_STANDARD 17)
add_executable(untitled main.cpp)
include(ExternalProject)
ExternalProject_Add(
casadi-3.5.5
URL https://github.com/casadi/casadi/releases/download/3.5.5/casadi-linux-py39-v3.5.5-64bit.tar.gz
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
PREFIX ${CMAKE_BINARY_DIR}/external/casadi)
find_package(casadi HINTS ${CMAKE_BINARY_DIR}/external/casadi/src/casadi-3.5.5/casadi)
target_link_libraries(untitled casadi)
In order to use it you have to do the following:
- Configure your project
mkdir build
cd build
cmake ..
- Build (download) casadi-3.5.5
cmake --build . --target casadi-3.5.5
- Reconfigure your project, because now
find_package
will find the needed files
cmake ..
- Build your targets
cmake --build .
If you want a one step build, there are ways to get around this problem
Here is an example for the second option, which might be better since FetchContent doesn't have the full functionality of ExternalProject.
#include <casadi/casadi.hpp>
int main()
{
casadi_printf("This works!");
return 0;
}
cmake_minimum_required(VERSION 3.20)
project(untitled)
set(CMAKE_CXX_STANDARD 17)
# some default target
add_executable(untitled main.cpp)
# Configure and build external project
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/external)
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/external
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/external
)
execute_process(
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/external
)
# find and link externals
find_package(casadi REQUIRED HINTS ${CMAKE_BINARY_DIR}/external/external/casadi/src/casadi-3.5.5/casadi)
target_link_libraries(untitled casadi)
cmake_minimum_required(VERSION 3.20)
project(external)
include(ExternalProject)
ExternalProject_Add(
casadi-3.5.5
URL https://github.com/casadi/casadi/releases/download/3.5.5/casadi-linux-py39-v3.5.5-64bit.tar.gz
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
PREFIX ${CMAKE_BINARY_DIR}/external/casadi)
The point is to have another cmake project under external/CMakeLists.txt
, which gets configured and build via execute_process
calls from the main cmake project. Do note, that you can now have find_package(casadi REQUIRED ...)
at configure stage, because the download will happen just before.