Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I run cmake from within cmake?

Tags:

cmake

My project depends on mariadb-connector-c and I'm trying to automate the download, build and link process with cmake.

I currently download the project into a directory, I then try to execute generate ninja files and run them but I cannot run cmake at all:

execute_process(COMMAND "cmake -GNinja ." WORKING_DIRECTORY ${mariadb-connector-c_SOURCE_DIR})

I know this doesn't work because the next step, running ninja, fails:

execute_process(COMMAND "ninja" WORKING_DIRECTORY ${mariadb-connector-c_SOURCE_DIR})

cmake runs fine in CLI, I've tried using the full path to the cmake executable and replacing the dot with the variable with the full directory (which is also a valid variable, if you're wondering.)

How can I tell cmake to run cmake on that external project?

like image 932
ruipacheco Avatar asked Jun 12 '17 12:06

ruipacheco


People also ask

How do I run a CMake program?

Running CMake from the command line From the command line, cmake can be run as an interactive question and answer session or as a non-interactive program. To run in interactive mode, just pass the option “-i” to cmake. This will cause cmake to ask you to enter a value for each value in the cache file for the project.

How do I build from source CMake?

In order to build CMake from a source tree on Windows, you must first install the latest binary version of CMake because it is used for building the source tree. Once the binary is installed, run it on CMake as you would any other project.

Do I need to run make after CMake?

Run make anywhere Once you have run cmake, you do not need to run it again unless a) you create another build directory or b) your current build directory is destroyed or horribly broken. In either of these cases, follow the steps above and run cmake in the top level build directory.


1 Answers

You can organize your project to a top-level CMakeLists.txt build your subprojects as ExternalProject.

This approach requires more work and maintenance of more CMake modules but it has its own benefits. I download Google Test as follows:

# Create download URL derived from version number.
set(GTEST_HOME https://github.com/google/googletest/archive)
set(GTEST_DOWNLOAD_URL ${GTEST_HOME}/release-${GTEST_VERSION}.tar.gz)
unset(GTEST_HOME)

# Download and build the Google Test library and add its properties to the third party arguments.
set(GTEST_ROOT ${THIRDPARTY_INSTALL_PATH}/gtest CACHE INTERNAL "")
ExternalProject_Add(gtest
    URL ${GTEST_DOWNLOAD_URL}
    CMAKE_ARGS -DBUILD_GTEST=ON -DBUILD_GMOCK=ON -DCMAKE_INSTALL_PREFIX=${GTEST_ROOT}
    INSTALL_COMMAND make install
)

list(APPEND GLOBAL_THIRDPARTY_LIB_ARGS "-DGTEST_ROOT:PATH=${GTEST_ROOT}")
unset(GTEST_DOWNLOAD_URL)
unset(GTEST_ROOT)

The code abowe is inside my ExternalGoogleTest.cmake module which is included by CMakeLists.txt of third-party libraries:

set_directory_properties(PROPERTIES EP_BASE ${CMAKE_BINARY_DIR}/ThirdParty)
get_directory_property(THIRDPARTY_BASE_PATH EP_BASE)

set(THIRDPARTY_INSTALL_PATH ${THIRDPARTY_BASE_PATH}/Install)
set(GTEST_VERSION 1.8.0)

include(ExternalProject)
include(ExternalGoogleTest)

Your own project which depends on an external library will need a CMake module to build it as ExternalProject too. It can looks like:

ExternalProject_Add(my_project
    DEPENDS gtest whatever
    SOURCE_DIR ${CMAKE_SOURCE_DIR}/lib
    CMAKE_ARGS
        ${GLOBAL_DEFAULT_ARGS}
        ${GLOBAL_THIRDPARTY_LIB_ARGS}
        -DCMAKE_INSTALL_PREFIX=${DESIRED_INSTALL_PATH}/my_project
    BUILD_COMMAND make
)

You can found more tips about this pattern here.

like image 114
Akira Avatar answered Nov 22 '22 20:11

Akira