├── .gitlab ├── issue_templates │ ├── Bug.md │ ├── Feature.md │ └── Research.md └── merge_request_templates │ └── Merge_Request.md ├── README.md ├── executable ├── CMakeLists.txt └── src │ └── main.cpp └── library ├── CMakeLists.txt ├── ModuleA ├── CMakeLists.txt ├── include │ └── A.hpp └── src │ └── A.cpp ├── ModuleB ├── CMakeLists.txt ├── include │ └── B.hpp └── src │ └── B.cpp ├── cmake_modules └── Config.cmake.in └── tests └── CMakeLists.txt /.gitlab/issue_templates/Bug.md: -------------------------------------------------------------------------------- 1 | ### Summary 2 | 3 | (Summarize the bug encountered concisely) 4 | 5 | ### Steps to reproduce 6 | 7 | (How one can reproduce the issue - this is very important) 8 | 9 | ### Dev environment 10 | 11 | * OS: (Linux, Windows, MacOS) 12 | * CMake version: (cmake --version) 13 | * Compiler: (gcc/clang/... & version) 14 | * Build type: (debug/release) 15 | * Commit: (current commit or tag) 16 | * (Any related repository commit/tag e.g fw4spl-deps, fw4spl, fw4spl-ar ...) 17 | 18 | 19 | ### What is the current *bug* behavior? 20 | 21 | (What actually happens) 22 | 23 | ### What is the expected *correct* behavior? 24 | 25 | (What you should see instead) 26 | 27 | ### Relevant logs and/or screenshots 28 | 29 | (Paste any relevant logs - please use code blocks (```) to format console output, 30 | logs, and code as it's very hard to read otherwise.) 31 | 32 | ### Possible fixes 33 | 34 | (If you can, link to the line of code that might be responsible for the problem) 35 | 36 | /label ~"Type:bugfix" 37 | -------------------------------------------------------------------------------- /.gitlab/issue_templates/Feature.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | (Include problem, use cases, benefits, and/or goals) 4 | 5 | ### Proposal 6 | 7 | ### Links / references 8 | 9 | ### Documentation blurb 10 | 11 | (Write the start of the documentation of this feature here, include: 12 | 13 | 1. Why should someone use it; what's the underlying problem. 14 | 2. What is the solution. 15 | 3. How does someone use this 16 | 17 | During implementation, this can then be copied and used as a starter for the documentation.) 18 | 19 | /label ~"Type:feature" 20 | -------------------------------------------------------------------------------- /.gitlab/issue_templates/Research.md: -------------------------------------------------------------------------------- 1 | # Goal and general information 2 | 3 | _Brief description of the goal of this algorithm research task._ 4 | 5 | # Specification 6 | 7 | _Specifications include functional, performance, language and data. The algorithms should focus on solving a specific problem with well-defined interfaces._ 8 | 9 | # Background 10 | 11 | _Background check to see what algorithms exist for solving the problem. Do they meet our needs? Have better new algorithms been published?_ 12 | 13 | # Data 14 | 15 | _Collection of data required for testing (or training in the case of learning-based algorithms). Formatting of data so that it can be inputted to the algorithm._ 16 | 17 | # Evaluation 18 | 19 | _Evaluation framework is used to test the algorithm for correctness and meeting performance specification._ 20 | 21 | # Baseline 22 | 23 | _Existing algorithm selection, implementation and evaluation._ 24 | 25 | # Prototyping 26 | 27 | _The main algorithm research cycle: evaluate performance, make improvements, repeat._ 28 | 29 | # Integration 30 | 31 | _Integration of algorithm code into production system._ 32 | 33 | # Communication 34 | 35 | _Communicate how the algorithm works (internal and/or article publication)._ 36 | 37 | /label ~"Type:research" 38 | -------------------------------------------------------------------------------- /.gitlab/merge_request_templates/Merge_Request.md: -------------------------------------------------------------------------------- 1 | ## What does this MR do? 2 | 3 | (Briefly describe what this MR is about) 4 | 5 | ## How to test it? 6 | 7 | (Describe how to test this feature step by step) 8 | 9 | ## Data 10 | 11 | (link to the needed data) 12 | 13 | ## Some results 14 | 15 | (Some interesting results, screenshot, perfs, ...) 16 | 17 | ## Additional tests to run 18 | 19 | (If you need some specific test e.g Windows compilation...) 20 | 21 | - [ ] Build on Windows 22 | - [ ] ... 23 | 24 | ## Associated Issues/Merge Requests 25 | 26 | - Issues 27 | - Fixes repo#number 28 | - [ ] depends on repo#number 29 | 30 | - Merge requests 31 | - See also repo!number 32 | - [ ] depends on repo!number 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # modern_cmake 2 | 3 | Tutorial/Example to deal with modern cmake. 4 | This tutorial assume that you already know how to write a CMakeLists.txt 5 | 6 | ## Introduction 7 | 8 | This repository contains samples to deals with modern cmake (imported targets, etc...). 9 | The repository is splitted into two differents parts: 10 | 11 | * A library called `ModernCMake` 12 | * An executable called `sampleExec` 13 | 14 | ## ModernCMake library 15 | 16 | ### General 17 | 18 | The library contains some dummy C++ code (that's not the point) to show how to make a library in a modern-cmake-way. 19 | Please read comments in each CMakeLists.txt for detailled informations about each instruction. 20 | 21 | Here's the basic structure of the project: 22 | 23 | ``` 24 | |library 25 | | CMakeLists.txt 26 | | ModuleA 27 | | CMakeLists.txt 28 | | src/A.cpp 29 | | include/A.hpp 30 | | ModuleB 31 | | CMakeLists.txt 32 | | src/B.cpp 33 | | include/B.cpp 34 | |cmake_modules 35 | | config.cmake.in 36 | ``` 37 | 38 | The concept here is to build two libraries (libA & libB), libA depends on std::thread "library" [(an imported target provided by CMake)](https://cmake.org/cmake/help/v3.16/module/FindThreads.html), and libB depends on libA. The example shows you how to made thoses dependencies transitives. 39 | 40 | After that you can build `sampleExec` to link against ModernCMake library in a modern-way. 41 | 42 | ### How to build it 43 | 44 | To build `ModernCMake` libraries 45 | 46 | `$ cmake path/to/modern_cmake/src/library -G Ninja -DCMAKE_BUILD_TYPE=[Release or Debug] -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/path/to/install/dir` 47 | 48 | To install it please run: 49 | 50 | `$ ninja install` 51 | 52 | ### Modern CMake concepts 53 | 54 | I'm pretty bad in preambles so... 55 | 56 | Credits from Pablo Arias from the article ["It's time to do CMake Right"](https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/). 57 | 58 | > Enough preambles. Does this look familiar to you? 59 | 60 | ```cmake 61 | find_package(Boost 1.55 COMPONENTS asio) 62 | list(APPEND INCLUDE_DIRS ${BOOST_INCLUDE_DIRS}) 63 | list(APPEND LIBRARIES ${BOOST_LIBRARIES}) 64 | 65 | include_directories(${INCLUDE_DIRS}) 66 | link_libraries(${LIBRARIES}) 67 | ``` 68 | 69 | >Don’t. Just don’t. This is wrong in so many dimensions. You are just blindly throwing stuff into a pot of include directories and compiler flags. There is no structure. There is no transparency. Not to mention that functions like include_directories work at the directory level and apply to all entities defined in scope. 70 | 71 | >And this isn’t even the real problem, what do you do with transitive dependencies? What about the order of linking? Yes, you need to take care about that yourself. The moment you need to deal with the dependencies of your dependencies is the moment your life needs to be reevaluated. 72 | 73 | I try here to explain a few basic concepts that you should keep in mind when creating a library with CMake using the ModernCMake library as an example. 74 | 75 | Let's start with the project 76 | 77 | ```cmake 78 | cmake_minimum_required(VERSION 3.5) 79 | # Project Name Version & main Languages 80 | project(ModernCMake VERSION 1.0.0 LANGUAGES CXX) 81 | ``` 82 | 83 | Nothing fancy here, the project is defined by a NAME a VERSION and the main LANGUAGES. 84 | 85 | Note that CMake generates `${PROJECT_NAME}` , `${PROJECT_VERSION}`. 86 | 87 | #### Imported Targets 88 | 89 | Find your required external libraries, here I will use `std::thread` and CMake made a nice [imported target](https://cmake.org/cmake/help/v3.16/module/FindThreads.html) to use it. 90 | 91 | ```cmake 92 | # Create an imported target Threads::Threads 93 | find_package(Threads QUIET REQUIRED) 94 | ``` 95 | 96 | Let's create the first library **A** (a really inspired name) 97 | 98 | ```cmake 99 | # Creation of A library (don't GLOB) 100 | add_library(A 101 | include/A.hpp 102 | src/A.cpp 103 | ) 104 | 105 | ``` 106 | 107 | Please avoid globbing expression, it is much more readable if all necessary files are written in the `add_library`. 108 | 109 | Let's define some property on **A** target, why not start with includes ? 110 | 111 | #### Use generator-expressions 112 | 113 | ```cmake 114 | # Use Generators expression to deals with folders (includes may not be at the same place between build and install). 115 | target_include_directories( 116 | A 117 | PUBLIC 118 | $ 119 | $ 120 | ) 121 | ``` 122 | 123 | Here I use what cmake called [generator-expressions](https://cmake.org/cmake/help/v3.16/manual/cmake-generator-expressions.7.html). Includes directory may be different between build and install, so with generators I can tell to the target where to find headers. You can also provide more complex mechanism with PRIVATE headers, etc... 124 | 125 | #### Please export your Targets 126 | 127 | Last but not the least is the export of our target. We want to do this in a nice way so that users will only to call somehting like this: 128 | 129 | ```cmake 130 | findPackage(ModernCMake QUIET COMPONENTS ModernCMake::A REQUIRED) 131 | ``` 132 | 133 | and to link the desired target to their library/application. 134 | 135 | ```cmake 136 | target_link_libraries( TARGET PUBLIC ModernCMake::A) 137 | ``` 138 | 139 | **AND THAT'S IT**, we don't want to link with additionnal library or includes 1000 directories, because exported targets are transitives (they forwards theirs needed requirements) and also exports the public headers. 140 | 141 | If you need **A** library, you only **want** to link against **A**. The last think the user want to do is to dig into your library to find which library is missing... 142 | 143 | In CMake, installed targets are registered to exports using the **EXPORT** argument. Exports are therefore just a set of targets that can be exported and installed. Here we just told CMake to install our library and to register the target in the export file. 144 | 145 | _in Module/A/CMakeLists.txt_ 146 | 147 | ```cmake 148 | ... 149 | # Install A library, the EXPORT is required to export your library as a COMPONENTS (ModernCMake::A) 150 | install(TARGETS A 151 | EXPORT ${MC_TARGETS_EXPORT_NAME} 152 | RUNTIME DESTINATION ${RUNTIME_DESTINATION} 153 | LIBRARY DESTINATION ${LIBRARY_DESTINATION} 154 | ARCHIVE DESTINATION ${ARCHIVE_DESTINATION} 155 | ``` 156 | 157 | If you look into the main CMakeLists.txt you will see 158 | 159 | ```cmake 160 | # Set standard installation directories 161 | set(RUNTIME_DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) #DLL 162 | set(LIBRARY_DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) # Libraries (.so, .lib, .dylib) 163 | set(ARCHIVE_DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) # Archives files (if needed) 164 | set(INCLUDES_DESTINATION ${CMAKE_INSTALL_PREFIX}/headers) # Install headers in a headers directory 165 | set(INCLUDES_INSTALL_DIR ${INCLUDES_DESTINATION}/ModernCMake) #Add a ModernCmake directory after headers/ 166 | 167 | # Generate cmake configuration scripts (MC = ModernCMake) 168 | # Where to generate cmake files (build dir) 169 | set(MC_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") 170 | # Name of cmake config files 171 | set(MC_VERSION_CONFIG "${MC_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") 172 | set(MC_PROJECT_CONFIG "${MC_GENERATED_DIR}/${PROJECT_NAME}Config.cmake") 173 | # Name of CMake Targets file (ModernCMakeTargets.cmake) 174 | set(MC_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") 175 | # Where to install cmake "Targets" files 176 | set(MC_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") 177 | # Set a namespace before targets (each target will be prefixed by ModernCMake::) 178 | set(MC_NAMESPACE "${PROJECT_NAME}::") 179 | # Version (redondant here we can use ${PROJECT_VERSION}) 180 | set(MC_VERSION 1.0.0) 181 | 182 | # Generate basic config version files 183 | include(CMakePackageConfigHelpers) 184 | # This is a cmake function that create basic ProjectconfigVersion.cmake files. 185 | write_basic_package_version_file( 186 | "${MC_VERSION_CONFIG}" VERSION ${MC_VERSION} COMPATIBILITY SameMajorVersion 187 | ) 188 | # Configure the config.cmake.in 189 | configure_file("${ModernCMake_SOURCE_DIR}/cmake_modules/Config.cmake.in" "${MC_PROJECT_CONFIG}" @ONLY) 190 | 191 | # Install cmake config files 192 | install( 193 | FILES "${MC_PROJECT_CONFIG}" "${MC_VERSION_CONFIG}" 194 | DESTINATION "${MC_CONFIG_INSTALL_DIR}") 195 | 196 | # Install cmake targets files 197 | install( 198 | EXPORT "${MC_TARGETS_EXPORT_NAME}" 199 | NAMESPACE "${MC_NAMESPACE}" 200 | DESTINATION "${MC_CONFIG_INSTALL_DIR}") 201 | ``` 202 | 203 | While the two first blocks are only setting some filenames or paths, the interesting part is the end. CMake provide a function to generate [a basic configVersion file](https://cmake.org/cmake/help/v3.16/module/CMakePackageConfigHelpers.html#command:write_basic_package_version_file). 204 | 205 | 206 | 207 | The interesting part are the generated cmake files. When the library is installed you will see some additionnal files installed by CMAKE in `your/install/dir/lib/cmake/ModernCMake`. 208 | 209 | This files are realy the basis of doing cmake right, while when writting `find_package(myPackage)`CMake will first looking for `myPackageConfig.cmake` ! So you don't have any excuses to not provide Config Files. 210 | 211 | Let's take a look in the install folder of ModernCMake, you can see that config files are installed in `path/to/the/install/dir/lib/cmake/ModernCMake/` , you will see 4 files: 212 | 213 | * `ModernCMakeConfig.cmake`: the basic config file (here provided by us) 214 | * `ModernCMakeConfigVersion.cmake`: the generated config file by cmake, it contains some code to check if version are compatible (required version vs provided version). 215 | * `ModernCMakeTargets.cmake`: our exported targets see below. 216 | * `ModernCMakeTargets-_[release/debug]_.cmake`: additionnal informations of our targets for specific build (debug, release, ...). 217 | 218 | The most important part are in the `ModernCMakeTargets.cmake` 219 | 220 | ```cmake 221 | # Create imported target ModernCMake::A 222 | add_library(ModernCMake::A SHARED IMPORTED) 223 | 224 | set_target_properties(ModernCMake::A PROPERTIES 225 | INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/headers" 226 | INTERFACE_LINK_LIBRARIES "Threads::Threads" 227 | ) 228 | 229 | # Create imported target ModernCMake::B 230 | add_library(ModernCMake::B SHARED IMPORTED) 231 | 232 | set_target_properties(ModernCMake::B PROPERTIES 233 | INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/headers" 234 | INTERFACE_LINK_LIBRARIES "ModernCMake::A" 235 | ) 236 | ``` 237 | 238 | You can see that each of our targets exports their own includes dirs and link libraries. As a result if you write an application or a library that use for example `ModernCMake::B`, it will automaticaly forward the link to `ModernCMake::A` and therefore the link to `Threads::Threads` ! 239 | 240 | Let's verify this. 241 | 242 | ## A sample to rules them all 243 | 244 | Let's build an application that uses ModernCMake library. 245 | 246 | the executable folder contain a CMakeLists.txt and a main.cpp 247 | 248 | To build it launch (from a build directory): 249 | 250 | `$ cmake ../../../src/modern_cmake/executable -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/Path/to/a/install/directory/` 251 | 252 | CMake will ask you to set the `ModernCMake_DIR`. You will need to set it to the `install/dir/of/ModernCMake/lib/cmake/ModernCMake`, so that cmake find the config files, remember ? 253 | 254 | after that run `ninja`, and magic of cmake should happend. 255 | 256 | A quick look to the `./sampleExec` shared libraries (ldd or otools), and you will see that both ModernCMake::A & B are linked. 257 | 258 | Yeah no suprise, but if we look at the CMakeLists.txt of sampleExec you will that 259 | 260 | ```cmake 261 | # Project Name Version & main Languages. 262 | project(sampleExec VERSION 1.0.0 LANGUAGES CXX) 263 | 264 | set(CMAKE_CXX_STANDARD 11) 265 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 266 | 267 | # Find the B Component of ModernCMake. 268 | find_package(ModernCMake QUIET COMPONENTS ModernCMake::B) 269 | 270 | add_executable(${PROJECT_NAME} src/main.cpp) 271 | 272 | target_link_libraries(${PROJECT_NAME} PUBLIC ModernCMake::B) 273 | ``` 274 | 275 | We only ask cmake to find `ModernCMake::B` and to link `ModernCMake::B` to `sampleExec`. But since B needs A and thanks to our nice exported targets cmake find everyting, that's **transitivity baby** ! 276 | 277 | You can also launch `sampleExec` to see that we use both libraries: 278 | 279 | ```shell 280 | $ ./sampleExec 281 | [sampleExec]: Hello world ! 282 | [ModernCMake::B]: Call ModernCMake::A 283 | [ModernCMake::A]: Lanch process... 284 | Value: 10 285 | ``` 286 | 287 | ## More Ressources 288 | 289 | * https://cliutils.gitlab.io/modern-cmake/ 290 | * https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/ 291 | * https://gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1 292 | * https://rix0r.nl/blog/2015/08/13/cmake-guide/ 293 | * https://www.youtube.com/watch?v=y7ndUhdQuU8&feature=youtu.be -------------------------------------------------------------------------------- /executable/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | # Project Name Version & main Languages. 3 | project(sampleExec VERSION 1.0.0 LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | # Find the B Component of ModernCMake. 9 | find_package(ModernCMake QUIET COMPONENTS ModernCMake::B) 10 | 11 | add_executable(${PROJECT_NAME} src/main.cpp) 12 | 13 | target_link_libraries(${PROJECT_NAME} PUBLIC ModernCMake::B) -------------------------------------------------------------------------------- /executable/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main(void) 6 | { 7 | std::cout<<"[sampleExec]: Hello world !"<CallFoo(); 12 | 13 | delete foobar; 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /library/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | # Project Name Version & main Languages 3 | project(ModernCMake VERSION 1.0.0 LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | # Create an imported target Threads::Threads 9 | find_package(Threads QUIET REQUIRED) 10 | 11 | # Set standard installation directories 12 | set(RUNTIME_DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) #DLL 13 | set(LIBRARY_DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) # Libraries (.so, .lib, .dylib) 14 | set(ARCHIVE_DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) # Archives files (if needed) 15 | set(INCLUDES_DESTINATION ${CMAKE_INSTALL_PREFIX}/headers) # Install headers in a headers directory 16 | set(INCLUDES_INSTALL_DIR ${INCLUDES_DESTINATION}/ModernCMake) #Add a ModernCmake directory after headers/ 17 | 18 | # Generate cmake configuration scripts (MC = ModernCMake) 19 | # Where to generate cmake files (build dir) 20 | set(MC_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") 21 | # Name of cmake config files 22 | set(MC_VERSION_CONFIG "${MC_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") 23 | set(MC_PROJECT_CONFIG "${MC_GENERATED_DIR}/${PROJECT_NAME}Config.cmake") 24 | # Name of CMake Targets file (ModernCMakeTargets.cmake) 25 | set(MC_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") 26 | # Where to install cmake "Targets" files 27 | set(MC_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") 28 | # Set a namespace before targets (each target will be prefixed by ModernCMake::) 29 | set(MC_NAMESPACE "${PROJECT_NAME}::") 30 | # Version (redondant here we can use ${PROJECT_VERSION}) 31 | set(MC_VERSION 1.0.0) 32 | 33 | # Generate basic config version files 34 | include(CMakePackageConfigHelpers) 35 | # This is a cmake function that create basic ProjectconfigVersion.cmake files. 36 | write_basic_package_version_file( 37 | "${MC_VERSION_CONFIG}" VERSION ${MC_VERSION} COMPATIBILITY SameMajorVersion 38 | ) 39 | # Configure the config.cmake.in 40 | configure_file("${ModernCMake_SOURCE_DIR}/cmake_modules/Config.cmake.in" "${MC_PROJECT_CONFIG}" @ONLY) 41 | 42 | # Install cmake config files 43 | install( 44 | FILES "${MC_PROJECT_CONFIG}" "${MC_VERSION_CONFIG}" 45 | DESTINATION "${MC_CONFIG_INSTALL_DIR}") 46 | 47 | # Install cmake targets files 48 | install( 49 | EXPORT "${MC_TARGETS_EXPORT_NAME}" 50 | NAMESPACE "${MC_NAMESPACE}" 51 | DESTINATION "${MC_CONFIG_INSTALL_DIR}") 52 | 53 | 54 | # Add subdirectories 55 | add_subdirectory(ModuleA) 56 | add_subdirectory(ModuleB) -------------------------------------------------------------------------------- /library/ModuleA/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Creation of A library (don't GLOB) 2 | add_library(A 3 | include/A.hpp 4 | src/A.cpp 5 | ) 6 | 7 | # Use Generators expression to deals with folders (includes may not be at the same place between build and install). 8 | target_include_directories( 9 | A 10 | PUBLIC 11 | $ 12 | $ 13 | ) 14 | 15 | # Linking A with Thread::Thread library. Will populate the INTERFACE_LINK_LIBRARIES 16 | target_link_libraries(A PUBLIC Threads::Threads) 17 | 18 | # Install A library, the EXPORT is required to export your library as a COMPONENTS (ModernCMake::A) 19 | install(TARGETS A 20 | EXPORT ${MC_TARGETS_EXPORT_NAME} 21 | RUNTIME DESTINATION ${RUNTIME_DESTINATION} 22 | LIBRARY DESTINATION ${LIBRARY_DESTINATION} 23 | ARCHIVE DESTINATION ${ARCHIVE_DESTINATION} 24 | ) 25 | 26 | install(FILES include/A.hpp DESTINATION ${INCLUDES_INSTALL_DIR}) -------------------------------------------------------------------------------- /library/ModuleA/include/A.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace ModernCMake 6 | { 7 | class A 8 | { 9 | public: 10 | /// Constructor 11 | A(); 12 | /// Destructor 13 | virtual ~A(); 14 | /// Foo 15 | void foo(); 16 | /// Bar 17 | void bar(); 18 | 19 | private: 20 | /// value 21 | int m_value {0}; 22 | /// thread 23 | std::thread m_thread; 24 | }; 25 | 26 | } //namespace ModernCMake -------------------------------------------------------------------------------- /library/ModuleA/src/A.cpp: -------------------------------------------------------------------------------- 1 | #include "A.hpp" 2 | 3 | #include 4 | 5 | namespace ModernCMake 6 | { 7 | 8 | A::A() 9 | { 10 | 11 | } 12 | 13 | A::~A() 14 | { 15 | 16 | } 17 | 18 | void A::foo() 19 | { 20 | std::cout<<"[ModernCMake::A]: Lanch process..."< 11 | $ 12 | ) 13 | 14 | # Linking A with Thread::Thread library. 15 | target_link_libraries(B PUBLIC A) 16 | 17 | install(TARGETS B 18 | EXPORT ${MC_TARGETS_EXPORT_NAME} 19 | RUNTIME DESTINATION ${RUNTIME_DESTINATION} 20 | LIBRARY DESTINATION ${LIBRARY_DESTINATION} 21 | ARCHIVE DESTINATION ${ARCHIVE_DESTINATION} 22 | ) 23 | 24 | install(FILES include/B.hpp DESTINATION ${INCLUDES_INSTALL_DIR}) -------------------------------------------------------------------------------- /library/ModuleB/include/B.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "A.hpp" 4 | #include 5 | 6 | namespace ModernCMake 7 | { 8 | 9 | class B 10 | { 11 | public: 12 | 13 | B(); 14 | virtual ~B(); 15 | 16 | void CallFoo(); 17 | 18 | private: 19 | 20 | std::shared_ptr m_aPtr; 21 | 22 | 23 | }; 24 | } // namespace ModernCMake -------------------------------------------------------------------------------- /library/ModuleB/src/B.cpp: -------------------------------------------------------------------------------- 1 | #include "B.hpp" 2 | 3 | #include 4 | 5 | namespace ModernCMake 6 | { 7 | 8 | B::B() 9 | { 10 | m_aPtr = std::make_shared(); 11 | } 12 | 13 | B::~B() 14 | { 15 | m_aPtr.reset(); 16 | } 17 | 18 | void B::CallFoo() 19 | { 20 | std::cout<<"[ModernCMake::B]: Call ModernCMake::A"<foo(); 22 | } 23 | 24 | } //ModernCMake -------------------------------------------------------------------------------- /library/cmake_modules/Config.cmake.in: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | 3 | # Put here the required dependencies of your library 4 | 5 | find_dependency(Threads) 6 | 7 | #find_dependency(Eigen3) 8 | #find_dependency(OpenGL) 9 | 10 | include("${CMAKE_CURRENT_LIST_DIR}/@MC_TARGETS_EXPORT_NAME@.cmake") 11 | -------------------------------------------------------------------------------- /library/tests/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IRCAD/modern-cmake-tutorial/c6fb104101f2dec51d5f3d0c63978b2d40bbf926/library/tests/CMakeLists.txt --------------------------------------------------------------------------------