Build Make external projects from CMake
CMake ExternalProject allows building a wide variety of subprojects isolated from the main CMake project.
For GNU Make Makefile projects, it is necessary to invoke the make
command.
However, there are several programs named “make” across operating systems.
To help ensure the correct GNU Make is selected, we do:
find_program(MAKE_EXECUTABLE
NAMES gmake mingw32-make make
NAMES_PER_DIR
DOC "GNU Make")
A real-life example of CMake with Makefile ExternalProject has multiple Make invocations to build separate Make target groups, where later Make targets depend on the other Make targets being built first. We just show a snippet here for clarity, omitting definition of some of the obvious variables used.
UPDATE_DISCONNECTED true
- helps avoid CMake constantly rebuilding ExternalProject.
CONFIGURE_COMMAND ""
- since Make doesn’t have a configure step, so we must define this blank, as otherwise CMake will try to find a CMakeLists.txt in the external project code.
BUILD_COMMAND
- builds the first target(s) that are required by targets in subsequent steps. If there’s no subsequent targets, this is the only build step.
BUILD_BYPRODUCTS
- In general we point this at the “installed” files, as otherwise “ninja: error: “lib” needed by “target”, missing and no known rule to make it”. Ninja is stricter than Make about the target to source graph.
include(GNUInstallDirs)
find_program(MAKE_EXECUTABLE NAMES gmake make mingw32-make REQUIRED)
set(my_LIBRARY ${CMAKE_INSTALL_FULL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}my${CMAKE_STATIC_LIBRARY_SUFFIX})
ExternalProject_Add(my
GIT_REPOSITORY https://github.com/username/my.git
GIT_TAG main
UPDATE_DISCONNECTED true
CONFIGURE_COMMAND ""
BUILD_COMMAND ${MAKE_EXECUTABLE} -j -C <SOURCE_DIR>
INSTALL_COMMAND ${MAKE_EXECUTABLE} -j -C <SOURCE_DIR> install prefix=${CMAKE_INSTALL_PREFIX}
BUILD_BYPRODUCTS ${my_LIBRARY}
)