dependency on default CMake target [duplicate] - makefile

In my project, I have about 250 projects with one main project that uses most of the projects. It's important that all projects are up to date when the main project is run. So basically, Visual Studio should check for all 250 projects for changes when MainProject is compiled (and run). My CMakeLists.txt files look like this.
Root/CMakeLists.txt
....
add_subdirectory (MainProject)
add_subdirectory (ProjectA)
add_subdirectory (ProjectB)
add_subdirectory (ProjectC)
add_subdirectory (ProjectD)
....
Root/MainProject/CMakeLists.txt
....
add_executable (MainProject a.cpp b.cpp)
add_dependencies (MainProject ProjectA ProjectB ...)
....
Root/ProjectA/CMakeLists.txt
....
add_executable (ProjectA a.cpp b.cpp)
....
Obviously this is a very simplified example, but hopefully the idea is there. Basically, in order to make Visual Studio to check for dependencies for all 250 projects or so, I have to add all the other projects in the main project as dependencies. Now this is not an elegant solution at all, as add_dependencies in MainProject has a LOT of dependencies in it. It works, but is there anything more elegant for this problem?

Turning my comments into an answer
At the moment (as per CMake version 3.5.x), there is - as far as I know - no global target list provided by CMake itself (e.g. as a global property).
Edit: It is now implemented: Global BUILDSYSTEM_TARGETS property was released with CMake 3.7
Posible Solutions
In your case - going by the assumption that you don't want to modify all 250 sub-project's CMakeLists.txt files - overwriting add_executable(), add_library() and add_custom_target() would do the trick:
cmake_minimum_required(VERSION 2.8)
project(DependsAllTest)
macro(add_library _target)
_add_library(${_target} ${ARGN})
set_property(GLOBAL APPEND PROPERTY GlobalTargetList ${_target})
endmacro()
macro(add_executable _target)
_add_executable(${_target} ${ARGN})
set_property(GLOBAL APPEND PROPERTY GlobalTargetList ${_target})
endmacro()
macro(add_custom_target _target)
_add_custom_target(${_target} ${ARGN})
set_property(GLOBAL APPEND PROPERTY GlobalTargetList ${_target})
endmacro()
add_subdirectory(MainProject)
add_subdirectory(ProjectA)
add_subdirectory(ProjectB)
add_subdirectory(ProjectC)
add_subdirectory(ProjectD)
get_property(_allTargets GLOBAL PROPERTY GlobalTargetList)
message(STATUS "GlobalTargetList: ${_allTargets}")
add_dependencies(MainProject ${_allTargets})
Sure enough, if you would do this from scratch I would - as #Lindydancer has suggested - use your own versions of those commands to allow global customizations.
If you go by the prerequisite that MainProject is always first, you could simplify this a little:
cmake_minimum_required(VERSION 2.8)
project(DependsAllTest2)
macro(add_library _target)
_add_library(${_target} ${ARGN})
add_dependencies(MainProject ${_target})
endmacro()
macro(add_executable _target)
_add_executable(${_target} ${ARGN})
add_dependencies(MainProject ${_target})
endmacro()
macro(add_custom_target _target)
_add_custom_target(${_target} ${ARGN})
add_dependencies(MainProject ${_target})
endmacro()
add_subdirectory(MainProject)
add_subdirectory(ProjectA)
add_subdirectory(ProjectB)
add_subdirectory(ProjectC)
add_subdirectory(ProjectD)
References
CMake: Getting a list of all targets?
What is the name of CMake's default build target?

Related

Visual Studio 15 2017 and cmake release builds

I am try to convert our visual studio builds to use cmake. For the most part it's working; the debug build works like a champ! But when I try to create a "release" build, a "Debug" directory is created inside the build/release directory.
C:\repos\source\build\Release\Debug>ls
dep1.dll dep1.ilk dep1.pdb test.pdb dep2.pdb
dep1.exp dep1.lib test.lib dep2.lib
Why is the compiler creating a Debug directory inside the release directory? It looks bad, I don't want there to be any confusion between debug and release! Putting a "Debug" directory inside the release directory looks "hacky" to me.
The first dependency and test library are built successfully but the libraries and test executables are dumped inside "release/Debug" directory, not inside the "build/release" directory. Because upper level dependencies are linking inside the "build/release", I expect to find all build artifacts in the "build/release" directory.
In my CMakeLists.txt, I set the CMAKE_LIBRARY_OUTPUT_DIRECTORY to build/Release. This is created and used, but like I said earlier, a Debug directory is created and is used to put all built targets. See snippet of proj1.cmake
function(SET_OUTPUT_DIRECTORIES build_path build_type)
MESSAGE ( "SET_OUTPUT_DIRECTORIES: building as ${build_type}")
if( build_type STREQUAL "Debug" )
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${build_path}/${build_type} PARENT_SCOPE)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${build_path}/${build_type} PARENT_SCOPE)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${build_path}/${build_type} PARENT_SCOPE)
SET(VS_INTERMEDIATE_DIRECTORY_DEBUG} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} )
elseif( build_type STREQUAL "Release" )
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${build_path}/${build_type} PARENT_SCOPE)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${build_path}/${build_type} PARENT_SCOPE)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${build_path}/${build_type} PARENT_SCOPE)
SET(VS_INTERMEDIATE_DIRECTORY_RELEASE} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} )
endif()
endfunction( SET_OUTPUT_DIRECTORIES )
function(SET_OUTPUT_DIRECTORIES_1 build_path build_type)
MESSAGE ( "SET_OUTPUT_DIRECTORIES: building as ${build_type}")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${build_path}/${build_type} PARENT_SCOPE)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${build_path}/${build_type} PARENT_SCOPE)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${build_path}/${build_type} PARENT_SCOPE)
SET(CONFIG_DIR ${build_path}/${build_type} PARENT_SCOPE)
endfunction( SET_OUTPUT_DIRECTORIES )
Snippets of CMakeLists.txt
SET_OUTPUT_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_BUILD_TYPE})
SET_OUTPUT_DIRECTORIES_1(${CMAKE_BINARY_DIR} ${CMAKE_BUILD_TYPE})
# Executable we want cmake to build
add_executable(proj1 ${SRC} ${HDR} )
ADD_DEPENDENCIES( proj1 dep1 dep4)
TARGET_LINK_LIBRARIES( proj1 ${dep1} ${dep2} ${dep3} ${dep4} )
SET_TARGET_PROPERTIES( proj1 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
TARGET_LINK_LIBRARIES( proj1 debug ${LIBD} optimized ${LIB} )
TARGET_LINK_LIBRARIES(proj1 debug ${Boost_FILESYSTEM_LIBRARY_DEBUG} optimized ${Boost_FILESYSTEM_LIBRARY_RELEASE})
TARGET_LINK_LIBRARIES( proj1 debug ${Boost_DATE_TIME_LIBRARY_DEBUG} optimized ${Boost_DATE_TIME_LIBRARY_RELEASE} )
TARGET_LINK_LIBRARIES( proj1 debug ${Boost_SYSTEM_LIBRARY_DEBUG} optimized ${Boost_SYSTEM_LIBRARY_RELEASE} )
TARGET_LINK_LIBRARIES( proj1 debug ${Boost_THREAD_LIBRARY_DEBUG} optimized ${Boost_THREAD_LIBRARY_RELEASE} )
TARGET_LINK_LIBRARIES( proj1 debug ${Boost_CHRONO_LIBRARY_DEBUG} optimized ${Boost_CHRONO_LIBRARY_RELEASE} )
TARGET_LINK_LIBRARIES( proj1 debug ${Boost_REGEX_LIBRARY_DEBUG} optimized ${Boost_REGEX_LIBRARY_RELEASE} )
Has anyone ever experienced this? I googled stuff for cmake and visual studio, and set vs_intermediate_directory_release to the same path as cmake_library_output_directory. But it doesn't do anything different; It still creates this debug directory inside the build/release directory.
Is this something we cannot change via cmake? Why is this so hard to do, I've been banging my head against this problem for a really long time...any help is help! Thanks in advance.

msvc not generate moc file with CMake automoc

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(source_files
a.cpp
b.cpp
...
)
set(header_files
a.hpp
b.hpp
...
)
set(Qt_libs
Qt5::Core
Qt5::Gui
Qt5::Widget
...
)
add_library(demo SHARED ${header_files} ${source_files})
target_link_libraries(demo ${Qt_libs} ...)
set_properties(TARGET demo PROPERTY FOLDER "somewhere")
install(...)
I have a sample CMakeLists.txt shows above.
The most weird thing is, it won't generate those moc files until I manually modified (like adding a empty line to the file) those header files (where Q_OBJECT presents).
The situation not happen every time. But, once it happens, clean build nor deleting whole project file won't help.
I'm using qt 5.11, CMake 3.7, Visual Studio 2015.
You are setting the global setting with set() which could be overwritten.
Please use set_target_properties, for example
project(exampleProj)
add_executable(exampleProj main.cpp)
set_target_properties(exampleProj
PROPERTIES
CMAKE_INCLUDE_CURRENT_DIR ON
CMAKE_AUTOMOC ON)

Making all projects in CMake Visual Studio depend on one project

In my project, I have about 250 projects with one main project that uses most of the projects. It's important that all projects are up to date when the main project is run. So basically, Visual Studio should check for all 250 projects for changes when MainProject is compiled (and run). My CMakeLists.txt files look like this.
Root/CMakeLists.txt
....
add_subdirectory (MainProject)
add_subdirectory (ProjectA)
add_subdirectory (ProjectB)
add_subdirectory (ProjectC)
add_subdirectory (ProjectD)
....
Root/MainProject/CMakeLists.txt
....
add_executable (MainProject a.cpp b.cpp)
add_dependencies (MainProject ProjectA ProjectB ...)
....
Root/ProjectA/CMakeLists.txt
....
add_executable (ProjectA a.cpp b.cpp)
....
Obviously this is a very simplified example, but hopefully the idea is there. Basically, in order to make Visual Studio to check for dependencies for all 250 projects or so, I have to add all the other projects in the main project as dependencies. Now this is not an elegant solution at all, as add_dependencies in MainProject has a LOT of dependencies in it. It works, but is there anything more elegant for this problem?
Turning my comments into an answer
At the moment (as per CMake version 3.5.x), there is - as far as I know - no global target list provided by CMake itself (e.g. as a global property).
Edit: It is now implemented: Global BUILDSYSTEM_TARGETS property was released with CMake 3.7
Posible Solutions
In your case - going by the assumption that you don't want to modify all 250 sub-project's CMakeLists.txt files - overwriting add_executable(), add_library() and add_custom_target() would do the trick:
cmake_minimum_required(VERSION 2.8)
project(DependsAllTest)
macro(add_library _target)
_add_library(${_target} ${ARGN})
set_property(GLOBAL APPEND PROPERTY GlobalTargetList ${_target})
endmacro()
macro(add_executable _target)
_add_executable(${_target} ${ARGN})
set_property(GLOBAL APPEND PROPERTY GlobalTargetList ${_target})
endmacro()
macro(add_custom_target _target)
_add_custom_target(${_target} ${ARGN})
set_property(GLOBAL APPEND PROPERTY GlobalTargetList ${_target})
endmacro()
add_subdirectory(MainProject)
add_subdirectory(ProjectA)
add_subdirectory(ProjectB)
add_subdirectory(ProjectC)
add_subdirectory(ProjectD)
get_property(_allTargets GLOBAL PROPERTY GlobalTargetList)
message(STATUS "GlobalTargetList: ${_allTargets}")
add_dependencies(MainProject ${_allTargets})
Sure enough, if you would do this from scratch I would - as #Lindydancer has suggested - use your own versions of those commands to allow global customizations.
If you go by the prerequisite that MainProject is always first, you could simplify this a little:
cmake_minimum_required(VERSION 2.8)
project(DependsAllTest2)
macro(add_library _target)
_add_library(${_target} ${ARGN})
add_dependencies(MainProject ${_target})
endmacro()
macro(add_executable _target)
_add_executable(${_target} ${ARGN})
add_dependencies(MainProject ${_target})
endmacro()
macro(add_custom_target _target)
_add_custom_target(${_target} ${ARGN})
add_dependencies(MainProject ${_target})
endmacro()
add_subdirectory(MainProject)
add_subdirectory(ProjectA)
add_subdirectory(ProjectB)
add_subdirectory(ProjectC)
add_subdirectory(ProjectD)
References
CMake: Getting a list of all targets?
What is the name of CMake's default build target?

CMake: How to show headers in "Header files" in Visual Studio project?

I have created a simple library project in C++ and added CMake file to automatically generate a Visual Studio project. My small project contains only 2 files:
include/
testproject/
testproject.h
src/
testproject.cpp
CMakeLists.txt
Header file now in External Dependencies (screenshot). How to display it in the section "Headers"? (or any other. Just not "External Dependencies")
CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(PROJECTNAME testproject)
PROJECT(${PROJECTNAME})
FILE(GLOB MY_HEADERS "include/*.h")
FILE(GLOB MY_SOURCES "src/*.cpp")
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
ADD_LIBRARY(
${PROJECTNAME} STATIC
${MY_HEADERS} ${MY_SOURCES}
)
Note: If change dirs struct to
include/
testproject.h
src/
testproject.cpp
CMakeLists.txt
result will be like on a screenshot. Header file in "Header files". But I need in previous project structure
Use GLOB_RECURSE:
GLOB_RECURSE will generate a list similar to the regular GLOB, except it will traverse all the subdirectories of the matched directory and match the files. Subdirectories that are symlinks are only traversed if FOLLOW_SYMLINKS is given or cmake policy CMP0009 is not set to NEW. See cmake –help-policy CMP0009 for more information.
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(PROJECTNAME testproject)
PROJECT(${PROJECTNAME})
FILE(GLOB_RECURSE MY_HEADERS "include/*.h")
FILE(GLOB MY_SOURCES "src/*.cpp")
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
ADD_LIBRARY(
${PROJECTNAME} STATIC
${MY_HEADERS} ${MY_SOURCES}
)

Disabling a Visual Studio project for building using cmake

I'm generating a VS2010 solution with a few projects (currently 4, will be up to 10-20 in the end). I only want one of them to build; the rest should be disabled. I can do this manually by going into the configuration manager and unchecking the boxes I don't want, but obviously this isn't a good solution.
Is there something I can add to the CMakeLists.txt file for a project that will cause it to do this? Searching through the docs, google and SO yielded nothing.
Update: Here is my root CMakeLists.txt in case that helps:
cmake_minimum_required(VERSION 2.8)
add_definitions(-DCOMPILER_MSVC)
project (PDEngine)
set(LINKER_LANGUAGE CXX)
add_subdirectory (units/platform)
add_subdirectory (units/render_api)
add_subdirectory (units/memory)
add_subdirectory (units/game)
set(custom_exe "${CMAKE_CURRENT_BINARY_DIR}/units/Platform/Debug/Platform.lib2")
add_custom_command(OUTPUT ${custom_exe}
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/local/msvc/bam.bat -j $ENV{NUMBER_OF_PROCESSORS}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/local/msvc/bam.bat
)
#add_custom_command(OUTPUT ${custom_exe_clean}
#COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/local/msvc/bam.bat -c
#DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/local/msvc/bam.bat
#)
add_custom_target(bam ALL DEPENDS ${custom_exe})
#add_custom_target(bamclean ALL DEPENDS ${custom_exe_clean}})
(The bam.bat stuff is based off of the answer I got here: How do I configure CMake to make the VS solution use a specific build commandline? )
And here's the CMakeLists.txt for the "platform" project:
cmake_minimum_required (VERSION 2.8)
project (Platform)
set (COMPILER_MSVC 1)
include_directories(${Platform_SOURCE_DIR}/include)
file(GLOB Project_HEADERS ${Platform_SOURCE_DIR}/include/platform/*.h)
source_group("Headers" FILES ${Project_HEADERS})
add_library(Platform STATIC EXCLUDE_FROM_ALL src/*.cpp ${Project_HEADERS})
So if what you want to do is not build something by default, you can remove it from the "ALL" target (which shows up in Visual Studio as ALL_BUILD). The way you do this is with the target property EXCLUDE_FROM_ALL, or by passing EXCLUDE_FROM_ALL to add_executable and add_library. (Custom targets default to EXCLUDE_FROM_ALL, so there, to do the reverse, you add ALL to the arguments to add_custom_target).
Then, all your targets will show up, but when clicking "build solution", only the ones you want will build. Others can be built by right clicking them and choosing "Build", like the built-in INSTALL project/target.
There is a EXCLUDE_FROM_DEFAULT_BUILD target property for that purpose.
See https://stackoverflow.com/a/14911387/594456.

Resources