mirror of
https://github.com/build-cpp/cmkr
synced 2026-06-08 13:22:55 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f4b376e42 | |||
| fcbf937c49 | |||
| e609c8a48f | |||
| 735898dbac | |||
| f7126b0158 | |||
| b6702714eb | |||
| efa4f716c2 | |||
| 76b7b8e778 | |||
| 501b26ced5 | |||
| 5bc36275ad | |||
| 35c837a181 | |||
| 710dfa4963 | |||
| c49ee6bafe | |||
| 368273bab2 |
@@ -10,19 +10,16 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-2022, macos-latest, ubuntu-20.04]
|
||||
os: [windows-2022, macos-latest, ubuntu-22.04]
|
||||
env:
|
||||
BUILD_TYPE: 'Release'
|
||||
CMAKE_GENERATOR: 'Ninja'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Ninja
|
||||
uses: seanmiddleditch/gha-setup-ninja@6263846cf3c17009dfc81604efabae16044fc074 # master
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Visual Studio Development Environment
|
||||
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
|
||||
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.1
|
||||
|
||||
- name: Tag cmkr.cmake
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
@@ -45,27 +42,27 @@ jobs:
|
||||
ctest -C ${{ env.BUILD_TYPE }} --verbose
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ github.event.repository.name }}-${{ matrix.os }}
|
||||
path: install/bin/*
|
||||
|
||||
- name: Get lowercase OS name
|
||||
id: osname
|
||||
uses: ASzc/change-string-case-action@07c1e24a97f0951e13f88870b99c058fcf0b14cf # v5
|
||||
uses: ASzc/change-string-case-action@ccb130a4e483d3e86287289183704dc9bf53e77e # master 2024-04-05
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
string: ${{ runner.os }}
|
||||
|
||||
- name: Compress artifacts
|
||||
uses: vimtor/action-zip@26a249fb00d43ca98dad77a4b3838025fc226aa1 # v1.1
|
||||
uses: vimtor/action-zip@1379ea20d4c5705669ba81fd626dd01b1c738f26 # v1.2
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
files: install/bin/
|
||||
dest: ${{ github.event.repository.name }}-${{ steps.osname.outputs.lowercase }}.zip
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
prerelease: ${{ !startsWith(github.ref, 'refs/tags/v') || contains(github.ref, '-pre') }}
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: clang-format
|
||||
id: clang-format
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run editorconfig-checker
|
||||
uses: editorconfig-checker/action-editorconfig-checker@d4fca16fc71adef10fbe101903b654449fa9570c # master 2022-03-15
|
||||
uses: editorconfig-checker/action-editorconfig-checker@27dd658c2b1282c7f1f4dc242cdf0f6d8af728ab # master 2025-05-30
|
||||
|
||||
Generated
+1
-1
@@ -22,7 +22,7 @@ project(cmkr
|
||||
LANGUAGES
|
||||
CXX
|
||||
VERSION
|
||||
0.2.44
|
||||
0.2.45
|
||||
DESCRIPTION
|
||||
"CMakeLists generator from TOML"
|
||||
)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# cmkr
|
||||
|
||||
[](https://deepwiki.com/build-cpp/cmkr)
|
||||
|
||||
`cmkr`, pronounced "cmaker", is a modern build system based on [CMake](https://cmake.org/) and [TOML](https://toml.io).
|
||||
|
||||
`cmkr` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example:
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ cmkr-include = false
|
||||
|
||||
[project]
|
||||
name = "cmkr"
|
||||
version = "0.2.44"
|
||||
version = "0.2.45"
|
||||
description = "CMakeLists generator from TOML"
|
||||
languages = ["CXX"]
|
||||
include-after = [
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ include_guard()
|
||||
|
||||
# Change these defaults to point to your infrastructure if desired
|
||||
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
|
||||
set(CMKR_TAG "v0.2.44" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
set(CMKR_TAG "v0.2.45" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
|
||||
|
||||
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
|
||||
|
||||
+80
-13
@@ -6,7 +6,7 @@ nav_order: 1
|
||||
|
||||
# Basics
|
||||
|
||||
To effectively use cmkr it helps to understand the basic concepts of CMake.
|
||||
To effectively use cmkr it helps to understand the basic concepts of CMake. This page serves as an introduction to CMake for beginners. Links to the CMake documentation are included for reference.
|
||||
|
||||
## Projects
|
||||
|
||||
@@ -16,25 +16,41 @@ A CMake **project** is a collection of targets. In the context of libraries the
|
||||
|
||||
## Targets
|
||||
|
||||
The basic unit of CMake is called a **target**. A target (also referred to as [binary target](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#binary-targets) in the CMake documentation) corresponds to an executable or library you can build. There are also [pseudo targets](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#pseudo-targets), but we ignore them for now.
|
||||
The basic unit of CMake is called a **target**. A target (also referred to as [binary target](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#binary-targets) in the CMake documentation) corresponds to an executable or static/dynamic library you can build.
|
||||
|
||||
<sub>Visual Studio: a **target** corresponds to a _project_.</sub>
|
||||
|
||||
Most important target types:
|
||||
|
||||
|Type|Purpose|
|
||||
|-|-|
|
||||
|Executable|Program you run on your computer (`.exe`)|
|
||||
|Static library|Library code _compiled into_ the final executable (`.lib`, `.a`)|
|
||||
|Dynamic library|Library code loaded at runtime (`.dll`, `.so`, `.dylib`)|
|
||||
|Interface|Used for organizational purposes (common flags/includes/libraries)|
|
||||
|
||||
There are also other [pseudo targets](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#pseudo-targets), but they are not important for now.
|
||||
|
||||
## Target Properties
|
||||
|
||||
Targets have a collection of **properties** that describe how to build them.
|
||||
Targets have a collection of **properties** that describe how the compiler builds them.
|
||||
|
||||
Examples of properties:
|
||||
The most commonly-used properties:
|
||||
|
||||
- _Sources_: the `*.cpp` files used to build the target.
|
||||
- _Compile options_: Command line flags for the compiler.
|
||||
- _Link libraries_: The **dependencies** required to build this target.
|
||||
- [_Sources_](https://cmake.org/cmake/help/latest/command/target_sources.html): the `*.cpp` files used to build the target.
|
||||
- [_Include directories_](https://cmake.org/cmake/help/latest/command/target_include_directories.html): Paths to directories the compiler will search when doing `#include`.
|
||||
- [_Compile definitions_](https://cmake.org/cmake/help/latest/command/target_compile_definitions.html): Preprocessor macro definitions used for compilation (`-DMYOPTION`).
|
||||
- [_Compile options_](https://cmake.org/cmake/help/latest/command/target_compile_options.html): Command line flags for the compiler (platform/compiler specific).
|
||||
- [_Compile features_](https://cmake.org/cmake/help/latest/command/target_compile_features.html): C/C++ standard version to build with.
|
||||
- [_Link libraries_](https://cmake.org/cmake/help/latest/command/target_link_libraries.html): The **dependencies** required to build this target.
|
||||
- [_Link options_](https://cmake.org/cmake/help/latest/command/target_link_options.html): Command line flags for the linker (platform/linker specific).
|
||||
|
||||
<sub>See the [CMake documentation](https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#properties-on-targets) for an exhaustive list of target properties.</sub>
|
||||
|
||||
**Important**: The term **link** has a slightly different meaning in CMake than you might expect. In addition to adding a library to the command line of the linker, CMake also propagates properties of the target you link to.
|
||||
**Important**: The term **link** has a slightly different meaning in CMake than you might expect. In addition to adding a library to the command line, CMake also (transitively) propagates properties of the target you link to based on their _visibility_.
|
||||
|
||||
<sub>You can think of **linking** as _depending on_.</sub>
|
||||
You should think of **linking** in CMake as _depending on_.
|
||||
{:.info}
|
||||
|
||||
The propagation of properties depends on their **visibility**:
|
||||
|
||||
@@ -44,7 +60,7 @@ The propagation of properties depends on their **visibility**:
|
||||
|
||||
In practice you default to **private**, unless consumers of your library _require_ the property to build their target. In that case you use **public**.
|
||||
|
||||
### Example
|
||||
## Example
|
||||
|
||||
The most intuitive example is with _include directories_. Imagine there are two targets:
|
||||
|
||||
@@ -67,10 +83,61 @@ name = "DataProcessor"
|
||||
type = "static"
|
||||
sources = ["StringUtils/src/stringutils.cpp"]
|
||||
headers = ["StringUtils/include/stringutils.hpp"]
|
||||
include-directories = ["StringUtils/include"]
|
||||
include-directories = ["StringUtils/include"] # public (default for libraries)
|
||||
|
||||
[target.DataProcessor]
|
||||
type = "executable"
|
||||
sources = ["DataProcessor/src/main.cpp"]
|
||||
link-libraries = ["StringUtils"]
|
||||
```
|
||||
link-libraries = ["StringUtils"] # private (default for executables)
|
||||
```
|
||||
|
||||
The generated `CMakeLists.txt` (simplified) looks like this:
|
||||
|
||||
```cmake
|
||||
project(DataProcessor)
|
||||
|
||||
# Target: StringUtils
|
||||
add_library(StringUtils STATIC
|
||||
"StringUtils/include/stringutils.hpp"
|
||||
"StringUtils/src/stringutils.cpp"
|
||||
)
|
||||
target_include_directories(StringUtils PUBLIC
|
||||
"StringUtils/include"
|
||||
)
|
||||
|
||||
# Target: DataProcessor
|
||||
add_executable(DataProcessor
|
||||
"DataProcessor/src/main.cpp"
|
||||
)
|
||||
target_link_libraries(DataProcessor PRIVATE
|
||||
StringUtils
|
||||
)
|
||||
```
|
||||
|
||||
## CMake Phases
|
||||
|
||||
CMake works in three phases:
|
||||
1. **Configure**: Execute `CMakeLists.txt` (find dependencies, create targets, OS/compiler-specific conditions, etc).
|
||||
2. **Generate**: Generate build files (propagates target properties and handles [_generator expressions_](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html)).
|
||||
3. **Build**: Execute the compiler to produce executables/libraries.
|
||||
|
||||
CMake keeps generated files separate from your source in a **build directory**. You specify a [**generator**](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) (Visual Studio/Ninja) and [**build type**](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations) (Debug/Release) during configuration.
|
||||
|
||||
```bash
|
||||
# Configure project and generate build files in build directory
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
# Build the project
|
||||
cmake --build build --config Release
|
||||
```
|
||||
|
||||
We specify both `CMAKE_BUILD_TYPE` and `--config` to be compatible with generators that support multiple configurations at once ((like Visual Studio/Xcode/Ninja Multi-Config).
|
||||
{:.info}
|
||||
|
||||
**Build Types**:
|
||||
- `Debug`: No optimization, debug symbols
|
||||
- `Release`: Full optimization, no debug symbols
|
||||
- `RelWithDebInfo`: Medium optimizations, debug symbols
|
||||
- `MinSizeRel`: Optimize for size, no debug symbols
|
||||
|
||||
**Generators**: CMake auto-detects (Makefiles on Linux/macOS, Visual Studio on Windows), but you can specify explicitly with `-G` during the _configure_ step.
|
||||
|
||||
+14
-10
@@ -191,26 +191,28 @@ components = ["mycomponent"]
|
||||
**Note**: The `[fetch-content]` feature is unpolished and will likely change in a future release.
|
||||
|
||||
```toml
|
||||
# Include CMake project from git
|
||||
[fetch-content.gitcontent]
|
||||
condition = "mycondition"
|
||||
git = "https://github.com/myuser/gitcontent"
|
||||
tag = "v0.1"
|
||||
shallow = false
|
||||
shallow = false # shallow clone (--depth 1)
|
||||
system = false
|
||||
subdir = ""
|
||||
subdir = "" # folder containing CMakeLists.txt
|
||||
|
||||
# Include a CMake project from a URL
|
||||
[fetch-content.urlcontent]
|
||||
condition = "mycondition"
|
||||
url = "https://content-host.com/urlcontent.zip"
|
||||
# Other supported algorithms:
|
||||
# md5, sha1, sha224, sha256, sha384, sha512, sha3_224, sha3_256, sha3_384, sha3_512
|
||||
hash = "SHA1 502a4e25b8b209889c99c7fa0732102682c2e4ff"
|
||||
sha1 = "502a4e25b8b209889c99c7fa0732102682c2e4ff"
|
||||
|
||||
[fetch-content.svncontent]
|
||||
condition = "mycondition"
|
||||
svn = "https://svn-host.com/url"
|
||||
rev = "svn_rev"
|
||||
|
||||
[fetch-content.urlcontent]
|
||||
condition = "mycondition"
|
||||
url = "https://content-host.com/urlcontent.zip"
|
||||
# These are equivalent, supported algorithms:
|
||||
# md5, sha1, sha224, sha256, sha384, sha512, sha3_224, sha3_256, sha3_384, sha3_512
|
||||
hash = "SHA1 502a4e25b8b209889c99c7fa0732102682c2e4ff"
|
||||
sha1 = "502a4e25b8b209889c99c7fa0732102682c2e4ff"
|
||||
```
|
||||
|
||||
Table keys that match CMake variable names (`[A-Z_]+`) will be passed to the [`FetchContent_Declare`](https://cmake.org/cmake/help/latest/module/FetchContent.html#command:fetchcontent_declare) command.
|
||||
@@ -300,6 +302,7 @@ condition = "MYPROJECT_BUILD_EXAMPLES"
|
||||
type = "executable"
|
||||
link-libraries = ["myproject::mylib"]
|
||||
add-function = ""
|
||||
add-arguments = ["myoption"]
|
||||
pass-sources = false
|
||||
|
||||
# Properties from the template are merged with the ones here
|
||||
@@ -311,6 +314,7 @@ sources = ["src/myexample.cpp"]
|
||||
The properties declared on a `template` are the same as the ones you use for targets. The only exceptions are:
|
||||
|
||||
- `add-function`: Specifies a custom add function. Projects like [pybind11](https://pybind11.readthedocs.io/en/stable/cmake/index.html#new-findpython-mode) have their own `add_xxx` function, which you can specify here.
|
||||
- `add-arguments`: Arguments to pass to the `add-function` before the list of sources. See [cmake_parse_arguments](https://cmake.org/cmake/help/latest/command/cmake_parse_arguments.html) for more details.
|
||||
- `pass-sources`: Pass sources directly to the add function instead of using `target_sources`.
|
||||
|
||||
## Tests and installation (unfinished)
|
||||
|
||||
@@ -16,8 +16,9 @@ Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) from [GitHub](https://github.com)
|
||||
name = "fetch-content"
|
||||
description = "Fetching from git"
|
||||
|
||||
[fetch-content]
|
||||
fmt = { git = "https://github.com/fmtlib/fmt", tag = "7.1.3" }
|
||||
[fetch-content.fmt]
|
||||
git = "https://github.com/fmtlib/fmt"
|
||||
tag = "7.1.3"
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
|
||||
@@ -118,6 +118,7 @@ struct Target {
|
||||
struct Template {
|
||||
Target outline;
|
||||
std::string add_function;
|
||||
std::vector<std::string> add_arguments;
|
||||
bool pass_sources_to_add_function = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -1372,12 +1372,11 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
// Handle custom add commands from templates.
|
||||
if (tmplate != nullptr && !tmplate->add_function.empty()) {
|
||||
add_command = tmplate->add_function;
|
||||
target_type_string = ""; // TODO: let templates supply options to the add_command here?
|
||||
|
||||
if (tmplate->pass_sources_to_add_function) {
|
||||
cmd(add_command)(target.name, target_type_string, "${" + sources_var + "}");
|
||||
cmd(add_command)(target.name, tmplate->add_arguments, "${" + sources_var + "}");
|
||||
} else {
|
||||
cmd(add_command)(target.name, target_type_string).endl();
|
||||
cmd(add_command)(target.name, tmplate->add_arguments).endl();
|
||||
if (has_sources) {
|
||||
cmd("target_sources")(target.name, target_type == parser::target_interface ? "INTERFACE" : "PRIVATE",
|
||||
"${" + sources_var + "}");
|
||||
|
||||
@@ -785,6 +785,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
tmplate.outline = parse_target(name, t, true);
|
||||
|
||||
t.optional("add-function", tmplate.add_function);
|
||||
t.optional("add-arguments", tmplate.add_arguments);
|
||||
t.optional("pass-sources-to-add-function", tmplate.pass_sources_to_add_function);
|
||||
t.optional("pass-sources", tmplate.pass_sources_to_add_function);
|
||||
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
name = "fetch-content"
|
||||
description = "Fetching from git"
|
||||
|
||||
[fetch-content]
|
||||
fmt = { git = "https://github.com/fmtlib/fmt", tag = "7.1.3" }
|
||||
[fetch-content.fmt]
|
||||
git = "https://github.com/fmtlib/fmt"
|
||||
tag = "7.1.3"
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
|
||||
Reference in New Issue
Block a user