CMake Notes

Configure Clangd

CompileFlags:
  CompilationDatabase: ../build/
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=YES ...

Public VS Private VS Interface

Link Type Description
PUBLIC Everyone who depends on me is going to get this property (Transitive Dependency).
PRIVATE This property is just for me. Whoever depends on me is not going to get this (Non-Transitive Dependency).
INTERFACE I do not need this for myself. But anyone who depends on me will get this property (Transitive Dependency).

Some target properties

  • SOURCES, INTERFACE_SOURCES;
  • LINK_LIBRARIES, INTERFACE_LINK_LIBRARIES;
  • COMPILE_DEFINITIONS, INTERFACE_COMPILE_DEFINITIONS.

To diagnostics:

get_target_property(ARG1 Tutorial SOURCES)
get_target_property(ARG2 Tutorial INTERFACE_SOURCES)

get_target_property(ARG3 Tutorial INCLUDE_DIRECTORIES)
get_target_property(ARG4 Tutorial INTERFACE_INCLUDE_DIRECTORIES)

get_target_property(ARG5 Tutorial LINK_LIBRARIES)
get_target_property(ARG6 Tutorial INTERFACE_LINK_LIBRARIES)

get_target_property(ARG7 Tutorial COMPILE_DEFINITIONS)
get_target_property(ARG8 Tutorial INTERFACE_COMPILE_DEFINITIONS)
message(${ARG1}, ${ARG2},\n
  ${ARG3}, ${ARG4},\n
  ${ARG5}, ${ARG6},\n
  ${ARG7}, ${ARG8})

Pass CMake Properties into Header Files

// CMakeLists.txt
project(Tutorial VERSION 1.0)
configure_file(TutorialConfig.h.in TutorialConfig.h)
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

Add a Library / Module (And Add an OPTION to Switch)

# CMakeLists.txt
cmake_minimum_required(VERSION 3.30 FATAL_ERROR)

set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
set(CMAKE_CXX_FLAGS "-stdlib=libc++")

project(Hello CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_EXPORT_COMPILE_COMMANDS True)
set(CMAKE_CXX_MODULE_STD True)

add_executable(Hello main.cpp)

option(USE_MODULE "Whether use the form of C++20's module" YES)

add_subdirectory(mylib)
if(NOT USE_MODULE)
  target_include_directories(Hello PRIVATE "${PROJECT_SOURCE_DIR}/mylib")
else()
  target_compile_definitions(Hello PRIVATE USE_MODULE)
endif()
target_link_libraries(Hello PRIVATE Mylib)
# mylib/CMakeLists.txt
add_library(Mylib SHARED)
if(USE_MODULE)
  target_compile_definitions(Mylib PRIVATE USE_MODULE)
  target_sources(Mylib PUBLIC FILE_SET CXX_MODULES FILES mylib.cpp)
else()
  target_sources(Mylib PRIVATE mylib.cpp)
endif()
// mylib/mylib.h
#pragma once
namespace mylib { void print(); }
// mylib/mylib.cpp
#ifdef USE_MODULE
export module mylib;
import std;
export
#else
#include "mylib.h"
#include <print>
#endif
    namespace mylib {
void print() {
#ifdef USE_MODULE
  std::println(" with C++ modules!");
#else
  std::println(" without C++ modules!");
#endif
}
} // namespace mylib
// main.cpp
#ifdef USE_MODULE
import mylib;
import std;
#else
#include "mylib.h"
#include <print>
#endif
int main() { std::print("Hello"), mylib::print(); }
// CMakePresets.json
{
  "version": 9,
  "configurePresets": [
    {
      "name": "default",
      "binaryDir": "${sourceDir}/build",
      "displayName": "Default Config",
      "description": "Default build using Ninja generator",
      "generator": "Ninja",
      "cacheVariables": {
        "CMAKE_CXX_COMPILER": "/usr/bin/clang++",
        "CMAKE_EXE_LINKER_FLAGS": "-fuse-ld=lld",
        "CMAKE_AR": "/usr/bin/llvm-ar",
        "CMAKE_RANLIB": "/usr/bin/llvm-ranlib"
      }
    }
  ]
}

To validate:

$ cmake --preset=default -DUSE_MODULE=NO -B ./build && cmake --build ./build && ./build/Hello

Reference

results matching ""

    No results matching ""