CMake with protobuf file in subdirectory - c++

I have seen a lot of similar questions and answers, but until now it seems not so obvious to get it working. I am quite new to CMake and until now everything was easy except the integration with protocol buffers.
I have a project with subdirectories, where each subdirectory has its own CMakeLists.txt
One of the subdirectory contains a .proto file. If the PROTOBUF_GENERATE_CPP macro is executed it generates the sources and the headers files. This macro is invoked from the CMakeLists.txt in the subdirectory containing the .proto file.
It seems however the make file is not invoked because no sources are added to the target. I can not add the sources to the target, because the files do not exist, they exist after generation, so this results in an error when CMake runs.
Setting the file properties to generated seems also not to help. In general, before the build process starts the macro should have been run to generated the source files.
How to do this, any working examples ?
Example:
./src/externals/protodef (from other repository, only contains .proto files)
./src/generated (supposed for the generated c and header files by protoc)
CMakeLists-1 (project root)
cmake_minimum_required (VERSION 2.6)
PROJECT (prototest)
ADD_SUBDIRECTORY("${PROJECT_SOURCE_DIR}/src/externals/protodef")
ADD_SUBDIRECTORY("${PROJECT_SOURCE_DIR}/src")
SET_SOURCE_FILES_PROPERTIES(${PROTO_SOURCES} ${PROTO_HEADERS} PROPERTIES GENERATED TRUE)
ADD_EXECUTABLE(prototest ${PROTO_SOURCES} ${SOURCE} )
TARGET_LINK_LIBRARIES(prototest ${EXTERNAL_LIBS} )
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
CMakeLists-2 (src)
SET(SOURCE ${SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
PARENT_SCOPE
)
CMakeLists-3 (src/externals/protodef)
SET(PROTOBUF_PATH "D:/protobuf-3.0.0/" )
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${PROTOBUF_PATH}")
# Changing PROTO_SRCS and PROTO_HDRS does not work for setting the location
# of the generated files.
# Those variable are ignored by CMake for compiling the proto files.
# Using a dedicated CMakeLists.txt and settng CURRENT_BINARY dir is a
# workaround to get them where we want.
SET(GENERATED_DIR ${PROJECT_SOURCE_DIR}/src/generated )
SET(CMAKE_CURRENT_BINARY_DIR ${GENERATED_DIR} )
INCLUDE(FindProtobuf)
FIND_PACKAGE(Protobuf REQUIRED)
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS${CMAKE_CURRENT_SOURCE_DIR}/test1.proto)
SET( EXTERNAL_LIBS ${PROTOBUF_PATH}/lib/libprotobuf.a PARENT_SCOPE)
# Propagate sources to the parant project
SET(PROTO_SOURCES ${PROTO_SRCS}
PARENT_SCOPE
)
SET(PROTO_HEADERS ${PROTO_HDRS}
PARENT_SCOPE
)

First generate the protobuf files, then add them to a CMake target.
CMakeLists (src) :
# Generate h/cpp proto files (./src/externals/protodef) into ./src/generated folder
PROTOBUF_GENERATE_CPP(...)
# Process subdir
ADD_SUBDIRECTORY(generated)
It seems that PROTOBUF_GENERATE_CPP can only be used in the same subdirectory. A possible workaround is to invoke protoc directly instead :
FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/externals/protodef PROTOMODEL_PATH)
FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/generated PROTOBINDING_PATH)
FILE(GLOB DATAMODEL_PROTOS "${CMAKE_CURRENT_SOURCE_DIR}/externals/protodef/*.proto")
FOREACH(proto ${DATAMODEL_PROTOS})
FILE(TO_NATIVE_PATH ${proto} proto_native)
EXECUTE_PROCESS(COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --proto_path=${PROTOMODEL_PATH} --cpp_out=${PROTOBINDING_PATH} ${proto_native}
RESULT_VARIABLE rv)
# Optional, but that can show the user if something have gone wrong with the proto generation
IF(${rv})
MESSAGE("Generation of data model returned ${rv} for proto ${proto_native}")
ENDIF()
ENDFOREACH(proto)
CMakeLists (src/generated) :
## List generated sources files
FILE(GLOB HDRS "*.h")
FILE(GLOB SRCS "*.cc")
ADD_LIBRARY(protoBinding ${HDRS} ${SRCS})
# ${PROTOBUF_LIBRARIES} should be defined by FIND_PACKAGE(Protobuf REQUIRED)
TARGET_LINK_LIBRARIES(protoBinding ${PROTOBUF_LIBRARIES})
This way CMake will first generate the header/source files, and only then add the generated files to a CMake target.
You can then use protoBinding target to link the generated files to an other target (e.g at the end of src's CMakeLists.txt) :
ADD_LIBRARY(myModel ${myFiles})
TARGET_LINK_LIBRARIES(myModel protoBinding)

Related

CMake how to collect auto generated source and header files

To put a bit of context first, I'm trying to decouple a repo that includes protobuf definitions as well as proto-using entities. I want to create a repo with only protobuf definitions and scripts that export the resulting classes in different languages, to be imported by other projects that use them.
Generating protobuf classes in c++ is actually quite simple (few lines of python script), but after that it gets tricky. You end up with an unorganized set of source files. I want to use CMake to collect all of the files and generate the library. The file structure should look something like this:
/root
/proto-package-1
foo.pb.h
foo.pb.cc
/proto-package-2
/proto-package-3
bar.pb.h
bar.pb.cc
bazz.pb.h
bazz.pb.cc
I'm a bit of a noob in CMake but I've read that it is good practice to explicitly list all the source files in the CMakeLists.txt file. But I'd like to make the generation of this c++ library to be fully automatic. Would that be a good reason to violate this rule? And what CMake commands can help me out?
cmake_minimum_required (VERSION 3.5)
project ("CMakeProject1")
set(TARGET_NAME CMakeProject1)
# Include sub-projects.
include_directories(${CMAKE_SOURCE_DIR})
add_library(${TARGET_NAME} STATIC
${CMAKE_SOURCE_DIR}/root/proto-package-1/foo.pb.h
${CMAKE_SOURCE_DIR}/root/proto-package-1/foo.pb.cc
//This is not going to cut it. Cannot add a proto and auto-generate.
)
You can also generate them in the cmake and create a list of generated files
# Get list of .proto files
file(GLOB_RECURSE proto_files RELATIVE ${PROJECT_SOURCE_DIR} "*.proto")
## Get Protobuf include dirs
get_target_property(protobuf_dirs protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
foreach(dir IN LISTS protobuf_dirs)
if ("${dir}" MATCHES "BUILD_INTERFACE")
message(STATUS "Adding proto path: ${dir}")
list(APPEND PROTO_DIRS "--proto_path=${dir}")
endif()
endforeach()
# Generate Protobuf cpp sources
set(PROTO_HDRS)
set(PROTO_SRCS)
foreach(PROTO_FILE IN LISTS proto_files)
#message(STATUS "protoc proto(cc): ${PROTO_FILE}")
get_filename_component(PROTO_DIR ${PROTO_FILE} DIRECTORY)
get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE)
set(PROTO_HDR ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.h)
set(PROTO_SRC ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.cc)
#message(STATUS "protoc hdr: ${PROTO_HDR}")
#message(STATUS "protoc src: ${PROTO_SRC}")
add_custom_command(
OUTPUT ${PROTO_SRC} ${PROTO_HDR}
COMMAND protobuf::protoc
"--proto_path=${PROJECT_SOURCE_DIR}"
${PROTO_DIRS}
"--cpp_out=${PROJECT_BINARY_DIR}"
${PROTO_FILE}
DEPENDS ${PROTO_FILE} protobuf::protoc
COMMENT "Generate C++ protocol buffer for ${PROTO_FILE}"
VERBATIM)
list(APPEND PROTO_HDRS ${PROTO_HDR})
list(APPEND PROTO_SRCS ${PROTO_SRC})
endforeach()
# [optional] Create a library of all generated C++ files
add_library(${PROJECT_NAME}_proto ${PROTO_SRCS} ${PROTO_HDRS})
set_target_properties(${PROJECT_NAME}_proto PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_STANDARD 11)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_STANDARD_REQUIRED ON)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_EXTENSIONS OFF)
target_include_directories(${PROJECT_NAME}_proto PRIVATE
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
$<TARGET_PROPERTY:protobuf::libprotobuf,INTERFACE_INCLUDE_DIRECTORIES>
)
target_link_libraries(${PROJECT_NAME}_proto PRIVATE protobuf::libprotobuf)
ref: https://github.com/google/or-tools/blob/a0a56698ba8fd07b7f84aee4fc45d891a8cd9828/cmake/cpp.cmake#L234-L294
I believe you can use an internal function of the FindProtobuf package to generate static libraries containing protobuf implementations:
find_package(Protobuf 3.12 REQUIRED)
add_library(protopackage1 STATIC proto-package-1/foo.proto)
protobuf_generate(LANGUAGE cpp TARGET protopackage1)
You can pass extra arguments to protobuf_generate but you will have to figure out how protobuf_generate_cpp passes them.

How to properly use file GLOB?

I'm trying to use GLOB_RECURSE to specify my sources and headers files. Currently, my CMakeLists.txt for a static library is:
project(LinearSystemLib)
file(GLOB_RECURSE ${PROJECT_NAME}_headers ${PROJECT_SOURCE_DIR}/*.h)
file(GLOB_RECURSE ${PROJECT_NAME}_sources ${PROJECT_SOURCE_DIR}/*.cpp)
add_library(
${PROJECT_NAME} STATIC ${${PROJECT_NAME}_headers}
${${PROJECT_NAME}_sources}
)
install(
TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION libs
ARCHIVE DESTINATION archives
)
The library directory looks like this:
LinearSystemLib
CMakeLists.txt
source
LinearSystemLib.cpp
include
LinearSystemLib.h
When I run command cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug (in the build directory) everything goes ok. Yet, command make it displays the following:
/home/felipe/Documents/Dados/SINMEC/Eclipse/LinearSystemLib/source/LinearSystemLib.cpp:1:29: fatal error: LinearSystemLib.h: No such file or directory
Is my CMakeLists wrong? I don't want to set specify the sources and headers files by name. I'm not finding information about glob_recurse easily.
I can make it work by listing the sources and headers files by name. However, it MUST be done with the glob_recurse or with glob.
I solved my problem, here's what LinearSystemLib directory looks like:
LinearSystemLib
CMakeLists.txt
source
LinearSystemLib.cpp
include
LinearSystemLib.h
The CMakeLists.txt contains:
project(LinearSystemLib)
#INCLUDE DIRECTORIES
include_directories(${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/include)
#SEARCH FOR .CPP AND .H FILES
file(GLOB ${PROJECT_NAME}_headers ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/include/*.h)
file(GLOB ${PROJECT_NAME}_sources ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/source/*.cpp)
#ADD LIBRARY
add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_sources})
#DEFINE OUTPUT LOCATION
install(
TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION static_libs
)
You don't actually NEED to add the .h/.hpp files using GLOB. I did it because otherwise, Visual Studio (or CodeBlocks) wouldn't create a "Header Files" folder on the project menu.
I wasn't properly specifying the path where GLOB would find the files.
${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/source/
You need to add
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})
so the correct -I argument is added to your compilation step. Use make VERBOSE=1 to see exactly what commands make is executing.

Cmake managed C++

I have cli wrapper function which i am trying to configure in cmake. After i generate the project with cmake the generated .proj file does not have the property of clr support is set to no common languaage runtime support. below is my cmake file
# This is the root ITK CMakeLists file.
cmake_minimum_required(VERSION 2.8.9)
if(COMMAND CMAKE_POLICY)
cmake_policy(SET CMP0003 NEW)
endif()
set_target_properties(${TargetName} PROPERTIES COMPILE_FLAGS "/clr")
SET(LINK_LIBRARIES
D:\\2016\\RandomSlicing\\Processing\\lib\\obliquePlane.lib
)
# The header files
SET(HEADERS
ObliquePlaneWrapper.h
obliquePlane.h
)
# The implementation files
SET(SOURCES
ObliquePlaneWrapper.cpp
)
# Find ITK.
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
# Add this as include directory
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}
${SOURCE_PATH}
${VXL_INCLUDE_DIRS}
)
# Main library
#ADD_EXECUTABLE(obliquePlane ${HEADERS} ${SOURCES})
ADD_LIBRARY(ObliquePlaneWrapper SHARED ${HEADERS} ${SOURCES})
TARGET_LINK_LIBRARIES(ObliquePlaneWrapper ${LINK_LIBRARIES} ${ITK_LIBRARIES})
I manually set this property in the All_build project and the corresponding .proj file. When i build the project it is searching for the ObliquePlaneWrapper.dll which it should be generating. Is this a problem because of some flag not set for common language runtime support
You can manually supply Compile Flags to specific sources to be compiled with specific flags. This includes \CLR for Visual C++. See example here.
https://cmake.org/pipermail/cmake/2011-April/043773.html

how do i build libraries in subdirectories using cmake?

My code is organized like this:
cpp
main.cpp (calls code from dataStructures/ and common/)
CMakeLists.txt (topmost CMakeLists file)
build
common
CMakeLists.txt (should be responsible for building common shared library)
include
utils.h
src
utils.cpp
build
dataStructures
CMakeLists.txt (build dataStructures shared library - dependent on common library)
include
dsLinkedList.h
src
dsLinkedList.cpp
build
build\ directories contain the built target. The actual code can be seen here: https://github.com/brainydexter/PublicCode/tree/master/cpp
As of now, CMakeLists.txt in each of the subdirectories build their own shared libraries. Topmost CMakeLists file then references the libraries and paths like this
Topmost CMakeLists.txt
cmake_minimum_required(VERSION 3.2.2)
project(cpp)
#For the shared library:
set ( PROJECT_LINK_LIBS libcppDS.dylib libcppCommon.dylib)
link_directories( dataStructures/build )
link_directories( common/build )
#Bring the headers, into the project
include_directories(common/include)
include_directories(dataStructures/include)
#Can manually add the sources using the set command as follows:
set(MAINEXEC main.cpp)
add_executable(testDS ${MAINEXEC})
target_link_libraries(testDS ${PROJECT_LINK_LIBS} )
How can I change the topmost CMakeLists.txt to go into subdirectories (common and dataStructures) and build their targets if they haven't been built, without me having to manually build the individual libraries ?
CMakeLists for common :
cmake_minimum_required(VERSION 3.2.2)
project(cpp_common)
set(CMAKE_BUILD_TYPE Release)
#Bring the headers, such as Student.h into the project
include_directories(include)
#However, the file(GLOB...) allows for wildcard additions:
file(GLOB SOURCES "src/*.cpp")
#Generate the shared library from the sources
add_library(cppCommon SHARED ${SOURCES})
dataStructures :
cmake_minimum_required(VERSION 3.2.2)
project(cpp_dataStructures)
set(CMAKE_BUILD_TYPE Release)
#For the shared library:
set ( PROJECT_LINK_LIBS libcppCommon.dylib )
link_directories( ../common/build )
#Bring the headers, such as Student.h into the project
include_directories(include)
include_directories(../common/include/)
#However, the file(GLOB...) allows for wildcard additions:
file(GLOB SOURCES "src/*.cpp")
#Generate the shared library from the sources
add_library(cppDS SHARED ${SOURCES})
Update:
This pull request helped me understand the correct way of doing this:
https://github.com/brainydexter/PublicCode/pull/1
and commitId: 4b4f1d3d24b5d82f78da3cbffe423754d8c39ec0 on my git
You are only missing a simple thing: add_subdirectory.
From the documentation:
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
Add a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.txt and code files are located. If it is a relative path it will be evaluated with respect to the current directory (the typical usage), but it may also be an absolute path. The binary_dir specifies the directory in which to place the output files. If it is a relative path it will be evaluated with respect to the current output directory, but it may also be an absolute path.
http://www.cmake.org/cmake/help/v3.0/command/add_subdirectory.html
It does exactly what you need.

How can I link static libraries defined in CMake subprojects to targets in other subprojects?

I have a large, modular CMake project.
Some modules are static libraries, some are executables that may or may not use some of these libraries. I already have a system of requirement/dependency checking in place that would stop cmake and tell the user if he's trying to build an executable but not the library that it requires.
The project compiles fine as is. I would like to split this into subprojects, i.e. set project(${module_name}) for each of the modules' CMakeLists.txt. Unfortunately, as soon as I insert this line into the apppropriate macro, I immediately get linker errors, i.e. the executables can no longer see the symbols defined in the static libraries.
The c++ command (I happen to be using gcc 4.8) that is invoked on the executables is unchanged, so something else must be different. How can I fix this and retain the subproject structure?
EDIT: per #Gerald's comment, additional information.
Project folder structure:
root
|
|-bin
|-lib
|-cmake(various CMake scripts, added to module path)
|-third_party
|-...
|-CMakeLists.txt
|-modules(top-level module directory, expanded)
|
|-CMakeLists.txt
|-exec_module_a
|-exec_module_b
|-... (other exec modules)
|-lib_module_a
|-lib_module_b
|- ... (other lib modules)
|-lib_module_N (expanded)
|
|-CMakeLists.txt
|-include/root/module_N (various include files)
|-src (various source files)
|-tests
Structure of a typical leaf-level CMakeLists.txt (same but one arg. to root_add_subproject for both lib and exec modules):
include(RootUtils)
set(module_name ${EXEC_MODULE_A})
#---------------------------CHECK REQUIREMENTS---------------------------------#
root_check_module_requirements(module_name
BUILD_${LIB_MODULE_A}
BUILD_${LIB_MODULE_G}
#...
WITH_QT
WITH_THIRD_PARTY_BLAH1
WITH_THIRD_PARTY_BLAH2
#...
)
#---------------------------ADD SOURCES AND TARGET-----------------------------#
root_add_subproject(${module_name} executable qt_on)
#---------------------------ADD INCLUDES---------------------------------------#
target_include_directories(${TARGET_NAME} PUBLIC
#third-party includes
${THIRD_PARTY_BLAH1_INCLUDE_DIRS}
${THIRD_PARTY_BLAH1_INCLUDE_DIRS}
#...
#module includes
"${MODULES_DIR}/${LIB_MODULE_A}/include"
"${MODULES_DIR}/${LIB_MODULE_B}/include"
#...
)
#---------------------------LINK LIBRARIES-------------------------------------#
target_link_libraries(${TARGET_NAME} PUBLIC
#third-party libraries
${QT5_TARGETS}
${THIRD_PARTY_BLAH1_LIBRARIES}
${THIRD_PARTY_BLAH2_LIBRARIES}
#...
#module libraries
${LIB_MODULE_A}
${LIB_MODULE_B}
#...
)
if(UNIX)
#... link third-party dependencies conditional on platform
endif()
#---------------------------ADD TESTS------------------------------------------#
#SET(BUILD_TESTS FALSE)#comment out to build the local unit tests
root_add_tests(${module_name})
#==============================================================================#
The relevant script in RootUtils.cmake looks like this:
macro(augmentarium_add_subproject module_name proj_type qt_on)
if(${qt_on} STREQUAL "qt_on" OR ${qt_on} STREQUAL "YES" OR ${qt_on} STREQUAL "TRUE")
set(QT_ON TRUE)
else()
set(QT_ON FALSE)
endif()
#---------------------------DEFINE SUBPROJECT----------------------------------#
#TODO: fix problems with macro (figure out how to set up library as a subproject w/o destroying linking capability)
#project(${module_name}) # <------- THIS is the line that causes linker errors
set(TARGET_NAME ${module_name})
string(TOUPPER "${TARGET_NAME}" TARGET_NAME_UPPER)
if(QT_ON)
set(CMAKE_AUTOMOC ON)
endif()
#---------------------------DEFINE SOURCE FILES--------------------------------#
include_directories(include)
SET(${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR include/${PROJECT_NAME}/${TARGET_NAME})
file(GLOB ${TARGET_NAME_UPPER}_CMAKELISTS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
file(GLOB ${TARGET_NAME_UPPER}_SOURCES src/*.cpp)
file(GLOB ${TARGET_NAME_UPPER}_HEADERS src/*.h src/*.h.in src/*.hpp src/*.tpp
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.h
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.h.in
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.hpp
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.tpp)
file(GLOB ${TARGET_NAME_UPPER}_TEST_SOURCES tests/*.cpp)
if(QT_ON)
file(GLOB_RECURSE MOC_${TARGET_NAME_UPPER}_SOURCES moc_*.cpp *_automoc.cpp qrc_*.cpp)
#remove generated moc files
foreach(FILE_NAME ${MOC_${TARGET_NAME_UPPER}_SOURCES})
list(REMOVE_ITEM ${TARGET_NAME_UPPER}_SOURCES ${FILE_NAME})
endforeach()
endif(QT_ON)
if(QT_ON)
#---------------------------ADD UI FILES---------------------------------------#
file(GLOB ${TARGET_NAME_UPPER}_UI src/*.ui)
if(BUILD_${TARGET_NAME})
#this macro doesn't get defined unless QtWidgets is found
qt5_wrap_ui(${TARGET_NAME_UPPER}_UI_HEADERS ${${TARGET_NAME_UPPER}_UI})
endif()
#---------------------------ADD RESOUCE FILES----------------------------------#
file(GLOB ${TARGET_NAME_UPPER}_RESOURCE_FILES *.qrc)
if(BUILD_${TARGET_NAME})
#this macro doesn't get defined unless QtWidgets is found
qt5_add_resources(${TARGET_NAME_UPPER}_GENERATED_RESOURCES ${${TARGET_NAME_UPPER}_RESOURCE_FILES})
endif()
endif(QT_ON)
#..........................organize source/header files........................#
source_group("Source Files" FILES ${${TARGET_NAME_UPPER}_SOURCES})
source_group("Header Files" FILES ${${TARGET_NAME_UPPER}_HEADERS})
if(QT_ON)
source_group("Resource Files" FILES ${${TARGET_NAME_UPPER}_RESOURCE_FILES})
source_group("UI Files" FILES ${${TARGET_NAME_UPPER}_UI})
source_group("Generated Files" FILES ${${TARGET_NAME_UPPER}_GENERATED_RESOURCES} ${${TARGET_NAME_UPPER}_UI_HEADERS})
endif()
#---------------------------ADD TARGET-----------------------------------------#
set(ALL_${TARGET_NAME_UPPER}_FILES
${${TARGET_NAME_UPPER}_CMAKELISTS}
${${TARGET_NAME_UPPER}_SOURCES}
${${TARGET_NAME_UPPER}_HEADERS}
${${TARGET_NAME_UPPER}_RESOURCE_FILES}
${${TARGET_NAME_UPPER}_UI}
${${TARGET_NAME_UPPER}_GENERATED_RESOURCES}
)
if(${proj_type} STREQUAL "executable")
add_executable(${TARGET_NAME} ${ALL_${TARGET_NAME_UPPER}_FILES})
elseif(${proj_type} STREQUAL "library")
add_library(${TARGET_NAME} STATIC ${ALL_${TARGET_NAME_UPPER}_FILES})
else()
add_custom_target(${TARGET_NAME} ${ALL_${TARGET_NAME_UPPER}_FILES})
endif()
endmacro()
If that's still not enough, here's how the subprojects are included in the module-level CMakeLists.txt:
foreach (MODULE_NAME ${MODULES})
add_subdirectory (${MODULE_NAME})
endforeach()
CMake version used: 3.1.3
How do you manage dependencies between libs with CMake? This should be done using TARGET_LINK_LIBRARIES(myexe mylib1 mylib2)