CMake: Project structure with unit tests
For questions 1 & 2, I would recommend making a library from your non-test files excluding main.cpp (in this case just src/sqr.cpp and src/sqr.h), and then you can avoid listing (and more importantly re-compiling) all the sources twice.
For question 3, these commands add a test called "MyTest" which invokes your executable "test" without any arguments. However, since you've added these commands to test/CMakeLists.txt and not your top-level CMakeLists.txt, you can only invoke the test from within the "test" subdirectory of your build tree (try cd test && ctest -N
). If you want the test to be runnable from your top-level build directory, you'd need to call add_test
from the top-level CMakeLists.txt. This also means you have to use the more verbose form of add_test
since your test exe isn't defined in the same CMakeLists.txt
In your case, since you're running cmake in the root folder, your build tree and your source tree are one and the same. This is known as an in-source build and isn't ideal, which leads to question 4.
The preferred method for generating the build tree is to do an out-of-source build, i.e. create a directory somewhere outside of your source tree and execute cmake from there. Even creating a "build" directory in the root of your project and executing cmake ..
would provide a clean structure which won't interfere with your source tree.
One final point is to avoid calling executables "test" (case-sensitive). For reasons why, see this answer.
To achieve these changes, I'd do the following:
CMakeLists.txt:
cmake_minimum_required (VERSION 2.8)
project (TEST)
add_subdirectory (src)
add_subdirectory (test)
enable_testing ()
add_test (NAME MyTest COMMAND Test)
src/CMakeLists.txt:
add_library (Sqr sqr.cpp sqr.h)
add_executable (demo main.cpp)
target_link_libraries (demo Sqr)
test/CMakeLists.txt:
find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
include_directories (${TEST_SOURCE_DIR}/src
${Boost_INCLUDE_DIRS}
)
add_definitions (-DBOOST_TEST_DYN_LINK)
add_executable (Test test.cpp)
target_link_libraries (Test
Sqr
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
)
CMake unit structure with many tests
This is the solution I use in my library:
FILE( GLOB log_testprograms *.cpp )
FOREACH( testsource ${log_testprograms} )
GET_FILENAME_COMPONENT( filename ${testsource} NAME_WE )
celma_add_celma_boost_testprogram( ${filename} )
ENDFOREACH()
celma_add_celma_boost_testprogram
is a macro like this:
macro( celma_add_celma_boost_testprogram filename )
add_executable( ${filename} ${filename}.cpp )
target_link_libraries( ${filename} celma ${Boost_Test_Link_Libs} )
add_test( ${filename} ${CMAKE_CURRENT_BINARY_DIR}/${filename} )
endmacro( celma_add_celma_boost_testprogram )
Celma is the name of my library, the variable Boost_Test_Link_Libs
contains the list of Boost libraries to link against, including the Boost.Test library.
Project Structure for unit testing (qtest) when using target_sources() command in sub directory
As you described, you can make a new static library target Project_Lib
. Take advantage of the fact that you parameterized the target name by using the project name (${PROJECT_NAME}
), so you actually don't have to change all of the CMakeLists.txt files in the subfolders. Just change the project name.
As I commented, simply exclude the main.cpp
file from the static library, and add it to a separate executable target instead.
In Project_Root/CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
set(SRC_DIR src)
# Change the project name, as now the static library is the primary target.
project(
Project_Lib
LANGUAGES CXX
)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Create the static library target, whose sources are populated in subdirectories.
add_library(${PROJECT_NAME} STATIC)
target_include_directories(${PROJECT_NAME} PRIVATE ${SRC_DIR})
# The only modification necessary in the subdirectories is to *exclude* the
# main.cpp file from the target_sources for the static library.
add_subdirectory(${SRC_DIR})
# Add *only* the main.cpp file to the executable target.
add_executable(Project_Exe src/main.cpp)
# Link the static library target to the executable.
target_link_libraries(Project_Exe PRIVATE ${PROJECT_NAME})
In tests/CMakeLists.txt:
...
# Link the static library to your Test executable also.
target_link_libraries(Test PRIVATE Project_Lib Qt5::Test)
How do I configure my CMake project to run all unit tests?
enable_testing()
enables add_test()
after it. So just make sure you call enable_testing()
before any add_test()
you want to enable.
CMake: How to setup unit testing of a library
add_library(DictionaryPath
...
src/WordsGraph.h
...
)
target_include_directories(DictionaryPath PUBLIC
...
PRIVATE src)
WordsGraph.h
is in src
, and you declared src
as a private include directory for DictionaryPath
.
If you don't want to do more than calling target_link_libraries
when creating a unit test, you should either move WordsGraph.h
into include
, or declare src
as a public or interface include directory.
If you don't want to move WordsGraph.h
into include
, nor declare src
as a public or interface include directory, you should add a call to target_include_directories
:
add_executable(WordsGraphTest test/WordsGraphTest.cpp)
target_link_libraries(WordsGraphTest GTest::main DictionaryPath)
target_include_directories(WordsGraphTest PRIVATE src)
add_test(NAME WordsGraphTest COMMAND WordsGraphTest)
Unit Test Output & Project Structure Advice --- CMake + Google Test Framework
- It is actually a recommended cmake practice called out-of-source build
- AFAIK it is not recommended to install recompiled googletest libraries in the system. So there should not be any problem if you compile it as shared or static library as part of your project build. I have used googletest 1.6.0 this way without problems on Windows, Linux, OSX and Android.
- I'm not sure about CTest but custom target is definitely able to run all tests for you. Here is a short solution I can suggest:
Add following lines into your top level CMakeLists.txt
(before adding any tests):
add_custom_target(test)
macro(run_test test_target)
add_custom_target(${test_target}_runtest
COMMAND ${test_target} #cmake 2.6 required
DEPENDS ${test_target}
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
add_dependencies(test ${test_target}_runtest)
endmacro()
Next for each test add a single line to append your test to the test
target:
#add_executable(mytest ${mysources})
run_test(mytest)
Related Topics
Can't Compile Easy Source in C++ and Opengl (Glfw) in Linux in Netbeans
Difference Between | and || , or & and &&
How to Find the Current Directory
What Does the Gcc Warning "Project Parameter Passing for X Changed in Gcc 7.1" Mean
Equivalent of "Using Namespace X" for Scoped Enumerations
Does Clearing a Vector Affect Its Capacity
How to Cheaply Assign C-Style Array to Std::Vector
Getting the Size of a C++ Function
How to Link Google Protobuf Libraries via Cmake on Linux
Get Signatures of Exported Functions in a Dll
Is Using Unsigned Integer Overflow Good Practice
Qdialog Exec() and Getting Result Value
Why Is a Class Allowed to Have a Static Member of Itself, But Not a Non-Static Member
When a Float Variable Goes Out of the Float Limits, What Happens
Does Boost::Bind() Copy Parameters by Reference or by Value
How to Print a String to the Console at Specific Coordinates in C++