I want to make a builder project that checks out sub-modules and builds them as a group, and I would like to build them in a single pass.
builder
submod1
submod2 #depends on submod1
submod3 #depends on submod2
For testing I downloaded ZeroMQ and cppzmq as submodules and built both with the cppzmq/demo to confirm they are linkable. I chose them because cppzmq checks for libzmq as a target but the demo only links with a find_package.
cmake_minimum_required(VERSION 3.10)
project(ZMQ_builder)
option(BUILD_TESTS "No tests" OFF)
option(CPPZMQ_BUILD_TESTS "No tests" OFF)
option(BUILD_STATIC "ninja can only build static or shared" OFF)
option(BUILD_SHARED "ninja can only build static or shared" ON)
add_subdirectory(libzmq)
set_property(TARGET libzmq PROPERTY CXX_STANDARD 17)
if (NOT TARGET libzmq AND NOT TARGET libzmq-static)
message(WARNING "libzmq and libzmq-static don't exist after being created")
endif()
if(NOT TARGET ZeroMQ)
message(status "ZeroMQ needs an alias") #prints this
add_library(ZeroMQ ALIAS libzmq)
endif()
if(NOT TARGET ZeroMQ)
message(WARNING "ZeroMQ Target Still doesn't exist")
endif()
if(NOT ZeroMQ_FOUND)
message(WARNING "ZeroMQ marked as not found") #prints this warning
find_package(ZeroMQ)
#set(ZeroMQ_FOUND true)
endif()
add_subdirectory(cppzmq)
find_package(cppzmq) #dies here
add_subdirectory(cppzmq/demo)
which outputs
ZeroMQ marked as not found .../builder\CMakeLists.txt 28
CMake Warning at ...\builder\CMakeLists.txt:29 (find_package):
By not providing "FindZeroMQ.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "ZeroMQ", but
CMake did not find one.
Could not find a package configuration file provided by "ZeroMQ" with any
of the following names:
ZeroMQConfig.cmake
zeromq-config.cmake
Add the installation prefix of "ZeroMQ" to CMAKE_PREFIX_PATH or set
"ZeroMQ_DIR" to a directory containing one of the above files. If "ZeroMQ"
provides a separate development package or SDK, be sure it has been
installed. ...\builder\CMakeLists.txt 29
ZeroMQ was NOT found! .../builder/build/cppzmq/cppzmqConfig.cmake 53
So the find call ignored the ZeroMQ alias Target (add_library(ZeroMQ ALIAS libzmq)
) and also missed ".../builder/build/libzmq/ZeroMQConfig.cmake" despite finding "../builder/build/cppzmq/cppzmqConfig.cmake"
I don't understand why find_package is ignoring the ZeroMQ target that's already in the build? and also why the build can find cppzmqConfig.cmake but not ZeroMQConfig.cmake despite both existing?
find_package() doesn't actually look at the global targets list, it has its own targets list that only prevents other find calls from refetching
instead of creating an alias target call find_package_handle_standard_args in a Find<>.cmake module for each class
so for this case a Findcppzmq.cmake
include(FindPackageHandleStandardArgs)
find_package(ZeroMQ REQUIRED)
if(TARGET cppzmq)
find_package_handle_standard_args(cppzmq
REQUIRED_VARS cppzmq_BINARY_DIR)
endif()
and a FindZeroMQ.cmake
include(FindPackageHandleStandardArgs)
if(TARGET ZeroMQ)
find_package_handle_standard_args(ZeroMQ
REQUIRED_VARS ZeroMQ_BINARY_DIR)
endif()
alternatively if all the repos in the builder project are seperate you can instead use ExternalProject_Add so that projects will be generated in order at build time. Making an effective package.
cmake_minimum_required(VERSION 3.16)
project(ExternalBuilder)
include(ExternalProject)
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_LIST_DIR}/install)
set(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX})
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
ExternalProject_Add(
ZeroMQ
GIT_REPOSITORY https://github.com/zeromq/libzmq.git
GIT_TAG v4.3.2
CMAKE_ARGS -DCMAKE_MODULE_PATH:PATH=${CMAKE_INSTALL_PREFIX} -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} -DBUILD_TESTS=OFF -DBUILD_STATIC=OFF
)
ExternalProject_Add(
cppzmq
DEPENDS ZeroMQ
GIT_REPOSITORY https://github.com/zeromq/cppzmq.git
GIT_TAG v4.7.1
CMAKE_ARGS -DCMAKE_MODULE_PATH:PATH=${CMAKE_INSTALL_PREFIX} -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} -DCPPZMQ_BUILD_TESTS=OFF
)
ExternalProject_Add(
zmqProject
DEPENDS ZeroMQ
...
)