CMake: avoid building tests by default [duplicate] - cmake

I have a small project with cmake. I build a lib and an executable. on the development machine I want also an executable that cannot be build on other machines/environments.
e.g.:
<my-lib>
| -- CMakeLists.txt
|
+ -- src/ -> build the lib/archive
| |-- lib.c
| |-- lib.h
| |-- CMakeLists.txt
|
+ -- tool -> build the tool
| |-- tool.c
| |-- CMakeLists.txt
|
+ -- tests -> build the unit tests
| |-- tests.c
| |-- CMakeLists.txt
I added CMakeLists.txt to all directories. Also an add_executable to the tests. Now the unit-test executable is build by default. But I want to exclude it from default target.
CMakeLists.txt in tests:
find_library (CUNIT_LIB cunit)
include_directories (${Cunit_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/src")
set (CMAKE_C_FLAGS "-O2 -Wall -Werror")
add_executable (unit-test tests.c)
target_link_libraries (unit-test my-lib cunit)
Has anyone a hint how to handle this? I don't want to build unit-test always!

There is a property EXCLUDE_FROM_ALL for such task.
You can write:
set_target_properties(unit-test PROPERTIES EXCLUDE_FROM_ALL TRUE)

This is very simple: protect creation of executable by introducing an option/variable.
if (DEFINED WITH_UNIT_TEST)
find_library (CUNIT_LIB cunit)
include_directories (${Cunit_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/src")
set (CMAKE_C_FLAGS "-O2 -Wall -Werror")
add_executable (unit-test tests.c)
target_link_libraries (unit-test my-lib cunit)
endif ()
Now when invoking CMake, one would have to explicitly specify -DWITH_UNIT_TEST, so that unit-test target is built, while by default it will never be build. For alternative approach, see comments.

Related

Is it possible to set output directory of EXPORT_COMPILE_COMMANDS without changing the BINARY_DIR?

CMake generates compile_commands.json in cmake build directory which means that my installation of YouCompleteMe or YCM cannot find it. For YCM to use it I need to move it from the build directory to the source or top level of the project.
Project
|- CMakeLists.txt
|- compile_commands.json (there is what i want)
|- build (this iw where i build my project)
|-- compile_commands.json (this is what i have)
|-- OtherCmakeGenerateStuff
|- src
|-- CMakeLists.txt
|-- main.cc (includes library not in project)
|-lib
|-- CMakeLists.txt
|-- math
|--- CMakeLists.txt
|--- math.cc
|--- math.hh
|-include
|-- globals.hh
|-- definitions.hh
There may be mistakes in these files as I just typed it and haven't tested it. however, my focus is on the top level CMakeLists.txt file.
CMakeLists.txt (Top level)
cmake_minimum_require(VERSION 3.8)
project(just_some_project LANGUAGES CXX VERSION 1.0)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_subdirectory(src)
add_subdirectory(lib)
include_directories(include)
src/CMakeLists.txt
cmake_minimum_require(VERSION 3.8)
project(just_some_project LANGUAGES CXX VERSION 1.0)
find_project(someotherlibrary REQUIRED)
add_executable(main main.cc)
target_include_directories(main PUBLIC math someotherlibraryfound)
lib/CMakeLists.txt (Top level)
cmake_minimum_require(VERSION 3.8)
file(GLOB Headers "*.hh")
file(GLOB Sources "*.cc")
add_library(math STATIC $Sources $Headers)

Using Taglib in CMake project without installing it

I am making a CMake project and the objective is to produce an executable, on either Windows or Unix (but not macOS), by statically linking or by directly using the source code of the third party library (Which is Taglib). I am looking into doing something as simple as that.
git clone --recurse-submodules https://github.com/MyGitAccount/MyProject.git
cd MyProject
cmake .
make
Here's are some details about my CMake project:
My project repository has a reference as a submodule to the Taglib repository.
Consider that Git, CMake and the compiler toolchain (build-essential or MinGW) are installed by default.
Project Tree Structure
ProjectName/
|-- Preload.cmake
|-- CMakeLists.txt
|-- src/
|-- CMakeLists.txt
|-- main.cpp
|-- taglib/
|-- CMakeLists.txt
|-- taglib/ (This folder is a submodule to my repository. It repository can be found here:
https://github.com/taglib/taglib)
|-- CMakeLists.txt
|-- ConfigureChecks.cmake
|-- cmake_uninstall.cmake.in
|-- config.h.cmake
|-- taglib-config.cmake
|-- taglib-config.cmd.cmake
|-- taglib.pc.cmake
|-- cmake/
|-- modules/
|-- FindCppUnit.cmake/
|-- MacroEnsureVersion.cmake/
ProjectName/Preload.cmake
if(UNIX AND NOT APPLE)
set (CMAKE_GENERATOR "Unix Makefiles" CACHE INTERNAL "" FORCE)
endif()
if(WIN32)
set (CMAKE_GENERATOR "MinGW Makefiles" CACHE INTERNAL "" FORCE)
endif()
ProjectName/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(ProjectName)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_subdirectory(taglib)
# add_subdirectory(src) # In comment for debugging purpose
ProjectName/taglib/CMakeLists.txt
set(taglib_DIR ./taglib)
find_package(taglib CONFIG)
if (Taglib_FOUND)
message("Found!")
else()
message("Not Found...")
endif()
ProjectName/src/CMakeLists.txt
file(GLOB sources "*.c" "*.cpp")
file(GLOB headers "*.h" "*.hpp")
add_executable(${CMAKE_PROJECT_NAME} ${sources} ${headers})
target_include_directories(${CMAKE_PROJECT_NAME} ${Taglib_INCLUDE_DIRS})
target_link_libraries(${CMAKE_PROJECT_NAME} ${Taglib_LIBRARIES})
Then, when running "cmake ." in "MyProject/", I obtain this error (On Windows 10).
C:\Users\UserName\Desktop\MyProject>cmake .
-- The C compiler identification is GNU 9.2.0
-- The CXX compiler identification is GNU 9.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/MinGW/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at taglib/taglib/taglib-config.cmake:4:
Parse error. Expected a command name, got unquoted argument with text "{".
Call Stack (most recent call first):
taglib/CMakeLists.txt:5 (find_package)
CMake Error at taglib/CMakeLists.txt:5 (find_package):
find_package Error reading CMake code from
"C:/Users/UserName/Desktop/MyProject/taglib/./taglib/taglib-config.cmake".
-- Configuring incomplete, errors occurred!
See also "C:/Users/UserName/Desktop/MyProject/CMakeFiles/CMakeOutput.log".
I also tried to use one of the "FindTaglib.cmake" files that I have found while googling.
I have successively placed those files in "MyProject/cmake/modules/ and set the variable "CMAKE_MODULE_PATH" but it wasn't successful.

CMake's find_package does not find library added with add_subdirectory

I'm building a test project to learn libraries zeromq with cppmq, and I want to include both libraries as subdirectories. I currently have the following structure:
|-- CMakeLists.txt
|-- deps
| |-- cppzmq-4.3.0
| | |-- CMakeLists.txt
| | `-- rest of files
| |-- zeromq-4.3.1
| | |-- CMakeLists.txt
| | `-- rest of files
`-- main.cpp
I've tried with the following CMakeLists:
cmake_minimum_required(VERSION 3.14)
project(PruebaZeroMQ)
set(CMAKE_CXX_STANDARD 11)
add_subdirectory(deps/zeromq-4.3.1)
add_subdirectory(deps/cppzmq-4.3.0)
add_executable(PruebaZeroMQ main.cpp)
target_link_libraries(PruebaZeroMQ
libzmq
cppzmq)
When I run cmake, I get the following error:
-- Detected CPPZMQ Version - 4.3.0
-- CMake libzmq package not found, trying again with pkg-config (normal install of zeromq)
CMake Error at deps/cppzmq-4.3.0/CMakeLists.txt:20 (message):
ZeroMQ was not found, neither as a CMake package nor via pkg-config
cppmq depends on zeromq, and looks like it tries to load it using find_package, so I tried to modify CMAKE_MODULE_PATH so it could find the ZeroMQConfig.cmake file, but it fails too, with the same error:
add_subdirectory(deps/zeromq-4.3.1)
list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_BINARY_DIR}/deps/zeromq-4.3.1 ")
add_subdirectory(deps/cppzmq-4.3.0)
Is there a way of achieving this? I'd rather not install the libraries system-wide.
After trying to manually find_package, CMake showed the following error message:
Add the installation prefix of "ZeroMQ" to CMAKE_PREFIX_PATH or set
"ZeroMQ_DIR" to a directory containing one of the above files.
So I tried that, using:
set(ZeroMQ_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/zeromq-4.3.1)
And it worked.

How can I set CMAKE_MODULE_PATH for doing regular and out-of-source builds in CMake?

I have a line like this in my CMakeLists.txt
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "cmake")
This is so that some custom libraries can be found with a directory tree that looks like this:
CMakeLists.txt
cmake/
|-- FindSomeLibrary.cmake
|-- FindAnotherLibrary.cmake
Normally I build simply like this:
cmake .
Which works fine. However, I want to provide a debug and release build using a script like this:
mkdir release
cd release
cmake -DCMAKE_BUILD_TYPE=Release ../
However, now it cannot find the cmake modules.
Is there a way to set CMAKE_MODULE_PATH such that it works for both in-source and out-of-source builds?
As proposed in the comments:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
and always try to set all paths relative to some CMAKE_* directory. That way you will miss many errors. ; )
As CMAKE_MODULE_PATH is a list, so it's better to use:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

How to configure cmake to get an executable not by default

I have a small project with cmake. I build a lib and an executable. on the development machine I want also an executable that cannot be build on other machines/environments.
e.g.:
<my-lib>
| -- CMakeLists.txt
|
+ -- src/ -> build the lib/archive
| |-- lib.c
| |-- lib.h
| |-- CMakeLists.txt
|
+ -- tool -> build the tool
| |-- tool.c
| |-- CMakeLists.txt
|
+ -- tests -> build the unit tests
| |-- tests.c
| |-- CMakeLists.txt
I added CMakeLists.txt to all directories. Also an add_executable to the tests. Now the unit-test executable is build by default. But I want to exclude it from default target.
CMakeLists.txt in tests:
find_library (CUNIT_LIB cunit)
include_directories (${Cunit_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/src")
set (CMAKE_C_FLAGS "-O2 -Wall -Werror")
add_executable (unit-test tests.c)
target_link_libraries (unit-test my-lib cunit)
Has anyone a hint how to handle this? I don't want to build unit-test always!
There is a property EXCLUDE_FROM_ALL for such task.
You can write:
set_target_properties(unit-test PROPERTIES EXCLUDE_FROM_ALL TRUE)
This is very simple: protect creation of executable by introducing an option/variable.
if (DEFINED WITH_UNIT_TEST)
find_library (CUNIT_LIB cunit)
include_directories (${Cunit_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/src")
set (CMAKE_C_FLAGS "-O2 -Wall -Werror")
add_executable (unit-test tests.c)
target_link_libraries (unit-test my-lib cunit)
endif ()
Now when invoking CMake, one would have to explicitly specify -DWITH_UNIT_TEST, so that unit-test target is built, while by default it will never be build. For alternative approach, see comments.