When executing cmake to generate ctest inputs, how can I directly specify the destination directory for the cmake-generated CTestTestfile.cmake? Specifically, my test suite is an independent cmake project. I currently add it to the main cmake project with include(), but the more appropriate method is to use add_subdirectory(). However, add_subdirectory() installs CTestTestfile.cmake in the subproject's directory in the build directory, but I need it in build/ for ctest to find it.
I set up the test macros in a file CTestList.cmake which lives in the test_project. This file is included in the build in test_project/CMakeLists.txt:
include(CTest)
include(${CMAKE_CURRENT_LIST_DIR}/CTestList.cmake)
With include():
project/
|-- CMakeLists.txt
|-- src/
|-- test_project/
`-- build/
|-- CTestTestfile.cmake
`-- test_project/
With add_subdirectory():
project/
|-- CMakeLists.txt
|-- src/
|-- test_project/
`-- build/
`-- test_project/
`-- CTestTestfile.cmake
The include and the add_subdirectory commands of CMake are very different.
While the include command works like #include of C and C++ – loads the content of included file into the file where it appears –, the add_subdirectory adds a subdirectory to the build. This means that when you use the add_subdirectory the variables inside the subdirectory's CMakeLists.txt will be the part of a different scope and the value of CMAKE_CURRENT_BINARY_DIR variable will be different too. Just add the following line to the test_project/CMakeLists.txt and try either to include it or add it by add_subdirectory:
message(STATUS "The files will be generated into: " ${CMAKE_CURRENT_BINARY_DIR})
The enable_testing enables testing for current directory and below. So, when you used the add_subdirecory instead of include the current directory meant build/test_project/ – as explained above.
To make sure the CTestTestfile.cmake will be created in build directory too, simply add an extra enable_testing command to the top-level CMakeLists.txt.
Related
I am trying to use splint on moderately large project which uses cmake for build.
Project contains hundreds of source file scattered over large directory structure. I am not finding any info for using splint with cmake.
directory structure is like
|-- CMakeLists.txt
|-- dir1
|-- CMakeLists.txt
|-- src
'-- file1.c
|-- include
'-- file1.h
|-- dir2
|-- CMakeLists.txt
|-- src
'-- file2.c
|-- include
'-- file2.h
Thanks.
Let me Google it for you. For "cmake splint" Google gives this link as 2nd result.
You can use it in your project if license permits, or just use it as reference when writing your own module. It is very simple, all it does is call splint executable with needed flags on requested sources using cmake's add_custom_target command.
I have a directory layout like the following
projectA/
|-- CMakeLists.txt
|-- src/
|-- main.cpp
projectB/
|-- CMakeLists.txt
|-- src/
|-- file1.cpp
|-- file1.hpp
|-- file2.hpp
|-- main.cpp
|-- third_party/
|-- include
|-- lib1
I can build my code (separately) for projectA and projectB just fine, i.e. both projects run by itself, independet of each other.
Now, in projectA I need to use code that exists in projectB (specifically file1.cpp, file1.hpp, file2.hpp and the third party libs).
It seems bad practice to me to just copy the necessary files from projectB/src, paste it into the src directory of projectA and adjust the CMakeLists.txt in projectA accordingly (by partially merging projectB/CMakeLists.txt and projectA/CMakeLists.txt).
Is there a nice way I can use CMake to (and now I'm not sure about the right terminology) include the project defined by projectB/CMakeLists.txt in projectA/CMakeLists.txt. The idea is that everything concerning projectB to run independently is stated in projectB/CMakeLists.txt and shouldn't I be able to access this information when I want to use it in projectA?
This is probably a common question, nevertheless I did not find anything helpful online, might also be due to not having the right terminology at hand.
You have to decide the level of encapsulation you need.
Package: If dependency ProjectB can run independently and you only ever need it for its compiled library, then use CMake's packaging system, i.e. export(TARGETS) or export(EXPORT) or export(PACKAGE) or install(EXPORT).
add_subdirectory: If dependency ProjectB also has build target information you need, e.g. compile defines, flags and other dependencies, then you can just make a top-level CMakeLists and use add_subdirectory()
include: If dependency ProjectB only has sub-target properties you need, including sources, you could include() the CMakeLists.txt, but this is really designed for sub directories and where you do not want to change the existing current directory for CMake processing
Interface library: If your third party libraries are not header-only, then they should probably be independent packages, otherwise assuming they are not huge like Boost, you can just copy them to ProjectA. Boost-like dependencies should almost always be kept external to projects
Hardcode paths: You could hardcode paths to the individual files of projectB, but this is brittle without making it a subdirectory of projectA, which in turn would offer better solutions, as above
Refactor to third library: If none of the above fits, you could refactor out the specific files as a separate library and use the standard packaging mechanism to depend on it for both ProjectA and ProjectB.
You can use ExternalProject module
https://cmake.org/cmake/help/v3.7/module/ExternalProject.html
Suppose, projectB is library. Then:
project("A")
include(ExternalProject)
ExternalProject_Add(b_lib
SOURCE_DIR "${B_SOURCE_DIR}"
BINARY_DIR "${B_BUILD_DIR}"
CMAKE_ARGS "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-DCMAKE_INSTALL_PREFIX=${B_INSTALL_DIR}"
"-DARBITRARY_VAR=some_value")
add_executable(a_exe src/main.cpp)
target_include_directories(a_exe PRIVATE "${B_INSTALL_DIR}")
target_link_libraries(a_exe "${B_INSTALL_DIR}/b_lib")
I have a simple project with one shared library called A and one executable called B linking A. I make a Visual Studio 2017 build just outside my sources so that the build directory and the source directory have both the same parent directory. This is fine.
But when I build my Visual Studio 2017 solution, many undesired directories appear under parent directory as well; one for each target that did run (A, B, INSTALL, etc.) that contains the build log for that target. I don't want those polluting log directories or it would be OK if they would appear under my build directory along Visual Studio 2017 stuff if they can't be avoided. Anyone knows how to handle this?
CMake version: 3.8.1
EDIT
The last 3 directories are those that are unwanted:
Parent directory
|-- build-vc15-x64 directory
|-- VS 2017 related stuff
|-- sources directory
|-- CMakeLists.txt
|-- libA sources directory
|-- stuff for libA
|-- execB sources directory
|-- stuff for execB
|-- unexpected directory here when building libA in solution in build-vc15-x64 (contains build log file of libA)
|-- unexpected directory here when building execB in solution in build-vc-15-x64 (contains build log file of execB)
|-- x64 (contains build log file of target INSTALL)
Use out-of-source builds, in other words, your build and your source directory should be different directories. Additionally, you have to call CMake and build just within your build directory, not in the parent directory. CMake creates a bunch of auxiliary files and directory right where it is called.
There is no point calling CMake in the common parent directory of source and build dir.
I have a small project with this structure:
myproject/
mylib/
include/
src/
myprog/
include/
src/
I added a CmakeLists.txt file into myproject and added the subdirectory mylib and myprog. The subdirectories got a CMakeLists, too. Now, when I run cmake, both modules are built correctly, unless I want to use mylib in myprogram. I've found solutions where the global CmakeLists defines an include_directories. But I would prefer to define this in mylib such that mylib/include is added to the project' include path. I would like a project of submodules where each submodule defines it's sources and includes and the project's CMakeLists only connects the modules together. How can I do that? Is that what I try to achieve recommanded? (cmake newbie)
You want target_include_directories. See http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
I have a project with about 600 directories, containing the source for about a dozen libraries and several dozen programs. Some of the programs depend upon a C++ header file that is generated from a text file.
How do I cleanly tell CMake how to include that path to the generated header file into the include path for those source files which require it?
Or alternatively, how can I force the generated file to be installed into a known location before CMake attempts to compile those programs? (This idea is based on the current Makefile system, which generates the header and installs it into the /include directory where all source files can find it.)
Or is there some other alternative?
-- EDIT: added "toy" example --
This example does not work. I need a way to tell prog1 and prog2 where to find home.h.
My tree:
.
|-- prog1/
| |-- CMakeLists.txt
| `-- prog1.cpp
|-- prog2/
| |-- CMakeLists.txt
| `-- prog2.cpp
`-- share/
`-- dict/
|-- CMakeLists.txt
`-- gen.sh*
In share/dict:
cmake_minimum_required(VERSION 2.8.4)
project(dict)
set(SRC foo.c)
set(HEADERS foo.h home.h)
add_custom_target(home
ALL
DEPENDS ${CMAKE_INSTALL_PREFIX}/include/home.h
)
add_custom_command(
OUTPUT ${CMAKE_INSTALL_PREFIX}/include/home.h
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/gen.sh gen.sh
COMMAND gen.sh ${CMAKE_INSTALL_PREFIX}
)
add_library(dict ${SRC})
install(TARGETS dict DESTINATION lib)
install(FILES ${HEADERS} DESTINATION include)
In prog1 (and similarly in prog2):
cmake_minimum_required(VERSION 2.8.4)
project(prog1)
add_executable(prog1 prog1.cpp)
target_link_libraries(prog1 dict)
install(TARGETS prog1 DESTINATION bin)
After
add_library(dict ${SRC})
add
target_include_directories(dict
# The location of the headers before installation
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
# The location of the headers after installation
$<INSTALL_INTERFACE:include>
)
and read the link I already provided in the comment.
Outputting generated files into out-of-source build directory is an intended way to do it.
Use CMAKE_BINARY_DIR and CMAKE_CURRENT_BINARY_DIR as output prefix and as target_include_directories() argument.