├── .gitignore ├── CMakeLists.txt ├── CTestConfig.cmake ├── LICENSE ├── README.md ├── cmake ├── FindGit.cmake ├── config.h.in ├── git_revision.cmake ├── googletest-download.cmake ├── googletest.cmake ├── packaging.cmake └── safeguards.cmake ├── src ├── CMakeLists.txt ├── example.cpp ├── example.h ├── generate.py ├── main.cpp ├── mylib.cpp └── mylib.h └── test ├── CMakeLists.txt ├── example_add.cpp ├── example_subtract.cpp └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # stop if cmake version below 3.5 2 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR) 3 | 4 | # project name and supported languages 5 | project(example Fortran C CXX) 6 | 7 | # guard against in-source builds and bad build-type strings 8 | include(cmake/safeguards.cmake) 9 | 10 | # detect operating system and host processor 11 | message(STATUS "We are on a ${CMAKE_SYSTEM_NAME} system") 12 | message(STATUS "The host processor is ${CMAKE_HOST_SYSTEM_PROCESSOR}") 13 | 14 | # place binaries and libraries according to GNU standards 15 | include(GNUInstallDirs) 16 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) 17 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) 18 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 19 | 20 | # example how to set c++ compiler flags for GNU 21 | if(CMAKE_CXX_COMPILER_ID MATCHES GNU) 22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas -Wno-sign-compare -Woverloaded-virtual -Wwrite-strings -Wno-unused") 23 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") 24 | set(CMAKE_CXX_FLAGS_RELEASE "-O3") 25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") 26 | endif() 27 | 28 | # get git hash 29 | include(cmake/git_revision.cmake) 30 | 31 | # project version 32 | set(VERSION_MAJOR 1) 33 | set(VERSION_MINOR 0) 34 | set(VERSION_PATCH 0) 35 | 36 | # configure header file 37 | configure_file( 38 | ${PROJECT_SOURCE_DIR}/cmake/config.h.in 39 | ${PROJECT_BINARY_DIR}/config.h 40 | ) 41 | 42 | add_subdirectory(src) 43 | 44 | # set cdash buildname 45 | set(BUILDNAME 46 | "${CMAKE_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}-${CMAKE_Fortran_COMPILER_ID}-${cmake_build_type_tolower}" 47 | CACHE STRING 48 | "Name of build on the dashboard" 49 | ) 50 | 51 | # allow to report to a cdash dashboard 52 | include(CTest) 53 | 54 | # fetch googletest 55 | include(cmake/googletest.cmake) 56 | fetch_googletest( 57 | ${PROJECT_SOURCE_DIR}/cmake 58 | ${PROJECT_BINARY_DIR}/googletest 59 | ) 60 | 61 | # enable testing 62 | enable_testing() 63 | 64 | # define tests 65 | add_subdirectory(test) 66 | 67 | # cpack 68 | include(cmake/packaging.cmake) 69 | -------------------------------------------------------------------------------- /CTestConfig.cmake: -------------------------------------------------------------------------------- 1 | set(CTEST_PROJECT_NAME "cmake-example") 2 | set(CTEST_NIGHTLY_START_TIME "00:00:00 CEST") 3 | set(CTEST_DROP_METHOD "http") 4 | set(CTEST_DROP_SITE "my.cdash.org") 5 | set(CTEST_DROP_LOCATION "/submit.php?project=cmake-example") 6 | set(CTEST_DROP_SITE_CDASH TRUE) 7 | set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS 200) 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2018 by Radovan Bast. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of cmake-example nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License](https://img.shields.io/badge/license-%20BSD--3-blue.svg)](../master/LICENSE) 2 | 3 | 4 | # CMake example 5 | 6 | Example project which demonstrates various CMake features. 7 | 8 | - [CDash testing dashboard](http://my.cdash.org/index.php?project=cmake-example) (probably empty but you can submit your test result to it) 9 | 10 | 11 | ## How to build this demo 12 | 13 | ``` 14 | cmake -H. -Bbuild -DCMAKE_INSTALL_PREFIX:PATH=/tmp/foo 15 | cd build 16 | cmake --build . 17 | ctest 18 | cmake --build . --target install 19 | ``` 20 | -------------------------------------------------------------------------------- /cmake/FindGit.cmake: -------------------------------------------------------------------------------- 1 | find_program( 2 | GIT_EXECUTABLE 3 | NAMES git 4 | DOC "git command line client" 5 | ) 6 | mark_as_advanced(GIT_EXECUTABLE) 7 | 8 | include(FindPackageHandleStandardArgs) 9 | find_package_handle_standard_args(Git DEFAULT_MSG GIT_EXECUTABLE) 10 | -------------------------------------------------------------------------------- /cmake/config.h.in: -------------------------------------------------------------------------------- 1 | #define VERSION_MAJOR @VERSION_MAJOR@ 2 | #define VERSION_MINOR @VERSION_MINOR@ 3 | #define VERSION_PATCH @VERSION_PATCH@ 4 | 5 | const char *GIT_REVISION = "@GIT_REVISION@"; 6 | -------------------------------------------------------------------------------- /cmake/git_revision.cmake: -------------------------------------------------------------------------------- 1 | find_package(Git) 2 | 3 | if(GIT_FOUND) 4 | execute_process( 5 | COMMAND ${GIT_EXECUTABLE} rev-list --max-count=1 HEAD 6 | OUTPUT_VARIABLE GIT_REVISION 7 | ERROR_QUIET 8 | ) 9 | if(NOT ${GIT_REVISION} STREQUAL "") 10 | string(STRIP ${GIT_REVISION} GIT_REVISION) 11 | endif() 12 | execute_process( 13 | COMMAND ${GIT_EXECUTABLE} status -s 14 | OUTPUT_VARIABLE GIT_CHANGES 15 | ERROR_QUIET 16 | ) 17 | if(NOT ${GIT_CHANGES} STREQUAL "") 18 | string(APPEND GIT_REVISION "-:UNCOMMITTED CHANGES") 19 | message("There are uncommited changes adjust .gitignore or commit: ${GIT_CHANGES}") 20 | endif() 21 | message(STATUS "Current git revision is ${GIT_REVISION}") 22 | else() 23 | set(GIT_REVISION "unknown") 24 | endif() 25 | -------------------------------------------------------------------------------- /cmake/googletest-download.cmake: -------------------------------------------------------------------------------- 1 | # code copied from https://crascit.com/2015/07/25/cmake-gtest/ 2 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR) 3 | 4 | project(googletest-download NONE) 5 | 6 | include(ExternalProject) 7 | 8 | ExternalProject_Add( 9 | googletest 10 | SOURCE_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-src" 11 | BINARY_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-build" 12 | GIT_REPOSITORY 13 | https://github.com/google/googletest.git 14 | GIT_TAG 15 | release-1.8.0 16 | CONFIGURE_COMMAND "" 17 | BUILD_COMMAND "" 18 | INSTALL_COMMAND "" 19 | TEST_COMMAND "" 20 | ) 21 | -------------------------------------------------------------------------------- /cmake/googletest.cmake: -------------------------------------------------------------------------------- 1 | # the following code to fetch googletest 2 | # is inspired by and adapted after https://crascit.com/2015/07/25/cmake-gtest/ 3 | # download and unpack googletest at configure time 4 | 5 | macro(fetch_googletest _download_module_path _download_root) 6 | set(GOOGLETEST_DOWNLOAD_ROOT ${_download_root}) 7 | configure_file( 8 | ${_download_module_path}/googletest-download.cmake 9 | ${_download_root}/CMakeLists.txt 10 | @ONLY 11 | ) 12 | unset(GOOGLETEST_DOWNLOAD_ROOT) 13 | 14 | execute_process( 15 | COMMAND 16 | "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" . 17 | WORKING_DIRECTORY 18 | ${_download_root} 19 | ) 20 | execute_process( 21 | COMMAND 22 | "${CMAKE_COMMAND}" --build . 23 | WORKING_DIRECTORY 24 | ${_download_root} 25 | ) 26 | 27 | # adds the targers: gtest, gtest_main, gmock, gmock_main 28 | add_subdirectory( 29 | ${_download_root}/googletest-src 30 | ${_download_root}/googletest-build 31 | ) 32 | endmacro() 33 | -------------------------------------------------------------------------------- /cmake/packaging.cmake: -------------------------------------------------------------------------------- 1 | include(InstallRequiredSystemLibraries) 2 | 3 | set(CPACK_PACKAGE_CONTACT "Kilgore Trout") 4 | 5 | include(CPack) 6 | -------------------------------------------------------------------------------- /cmake/safeguards.cmake: -------------------------------------------------------------------------------- 1 | # Provides safeguards against in-source builds and bad build types. 2 | # 3 | # Variables used:: 4 | # 5 | # PROJECT_SOURCE_DIR 6 | # PROJECT_BINARY_DIR 7 | # CMAKE_BUILD_TYPE 8 | 9 | if(NOT CMAKE_BUILD_TYPE) 10 | set(CMAKE_BUILD_TYPE "Release") 11 | endif() 12 | 13 | if(${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR}) 14 | message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there.") 15 | endif() 16 | 17 | string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_tolower) 18 | string(TOUPPER "${CMAKE_BUILD_TYPE}" cmake_build_type_toupper) 19 | 20 | if(NOT cmake_build_type_tolower STREQUAL "debug" AND 21 | NOT cmake_build_type_tolower STREQUAL "release" AND 22 | NOT cmake_build_type_tolower STREQUAL "minsizerel" AND 23 | NOT cmake_build_type_tolower STREQUAL "relwithdebinfo") 24 | message(FATAL_ERROR "Unknown build type \"${CMAKE_BUILD_TYPE}\". Allowed values are Debug, Release, RelWithDebInfo, and MinSizeRel (case-insensitive).") 25 | endif() 26 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # find python 2 | find_package(PythonInterp) 3 | if(NOT PYTHONINTERP_FOUND) 4 | message(FATAL_ERROR "ERROR: Python interpreter not found. Cannot continue - sorry.") 5 | endif() 6 | 7 | # generate the file 8 | add_custom_target( 9 | generate_file 10 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generate.py > ${PROJECT_BINARY_DIR}/mylib_generated.cpp 11 | ) 12 | 13 | # mark the file as generated 14 | set_source_files_properties(${PROJECT_BINARY_DIR}/mylib_generated.cpp PROPERTIES GENERATED 1) 15 | 16 | # static library 17 | add_library(mylib_static STATIC mylib.cpp ${PROJECT_BINARY_DIR}/mylib_generated.cpp) 18 | add_dependencies(mylib_static generate_file) 19 | target_include_directories( 20 | mylib_static 21 | PRIVATE 22 | ${CMAKE_CURRENT_LIST_DIR} 23 | ) 24 | 25 | # shared library 26 | add_library(mylib_shared SHARED mylib.cpp) 27 | 28 | # compile main executable 29 | add_executable(main.x main.cpp) 30 | target_include_directories( 31 | main.x 32 | PRIVATE 33 | ${PROJECT_BINARY_DIR} 34 | ) 35 | 36 | # link library 37 | target_link_libraries(main.x mylib_static) 38 | 39 | # library that holds sources to test 40 | add_library(example "") 41 | target_sources( 42 | example 43 | PRIVATE 44 | example.cpp 45 | PUBLIC 46 | ${CMAKE_CURRENT_LIST_DIR}/example.h 47 | ) 48 | target_include_directories( 49 | example 50 | PUBLIC 51 | ${CMAKE_CURRENT_LIST_DIR} 52 | ) 53 | 54 | # install binary 55 | install(TARGETS main.x DESTINATION cmake-example/bin) 56 | 57 | # install libs 58 | install(TARGETS mylib_shared DESTINATION cmake-example/lib) 59 | install(TARGETS mylib_static DESTINATION cmake-example/lib) 60 | 61 | # install headers 62 | install(FILES ${PROJECT_SOURCE_DIR}/src/mylib.h DESTINATION cmake-example/include) 63 | -------------------------------------------------------------------------------- /src/example.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "example.h" 3 | 4 | double add_numbers(const double f1, const double f2) 5 | { 6 | return f1 + f2; 7 | } 8 | 9 | double subtract_numbers(const double f1, const double f2) 10 | { 11 | return f1 - f2; 12 | } 13 | 14 | double multiply_numbers(const double f1, const double f2) 15 | { 16 | return f1*f2; 17 | } 18 | -------------------------------------------------------------------------------- /src/example.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | double add_numbers(const double f1, const double f2); 4 | 5 | double subtract_numbers(const double f1, const double f2); 6 | 7 | double multiply_numbers(const double f1, const double f2); 8 | -------------------------------------------------------------------------------- /src/generate.py: -------------------------------------------------------------------------------- 1 | source = r'''#include 2 | #include "mylib.h" 3 | 4 | void do_something_else() 5 | { 6 | printf("something else\n"); 7 | }''' 8 | 9 | print(source) 10 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "mylib.h" 4 | #include "config.h" 5 | 6 | int main(int argc, char** argv) 7 | { 8 | printf("program version: %i.%i.%i\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); 9 | printf("git hash: %s\n", GIT_REVISION); 10 | 11 | do_something(); 12 | do_something_else(); // generated 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/mylib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mylib.h" 3 | 4 | void do_something() 5 | { 6 | printf("something\n"); 7 | } 8 | -------------------------------------------------------------------------------- /src/mylib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void do_something(); 4 | void do_something_else(); 5 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable( 2 | unit_tests 3 | example_add.cpp 4 | example_subtract.cpp 5 | ) 6 | 7 | target_link_libraries( 8 | unit_tests 9 | gtest_main 10 | example 11 | ) 12 | 13 | add_test( 14 | NAME 15 | unit 16 | COMMAND 17 | ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/unit_tests 18 | ) 19 | -------------------------------------------------------------------------------- /test/example_add.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "example.h" 3 | 4 | TEST(example, add) 5 | { 6 | double res; 7 | res = add_numbers(1.0, 2.0); 8 | ASSERT_NEAR(res, 3.0, 1.0e-11); 9 | } 10 | -------------------------------------------------------------------------------- /test/example_subtract.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "example.h" 3 | 4 | TEST(example, subtract) 5 | { 6 | double res; 7 | res = subtract_numbers(1.0, 2.0); 8 | ASSERT_NEAR(res, -1.0, 1.0e-11); 9 | } 10 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | int main(int argc, char** argv) 4 | { 5 | ::testing::InitGoogleTest(&argc, argv); 6 | return RUN_ALL_TESTS(); 7 | } 8 | --------------------------------------------------------------------------------