mirror of
https://github.com/build-cpp/cmkr
synced 2026-06-08 13:22:55 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f4b376e42 | |||
| fcbf937c49 | |||
| e609c8a48f | |||
| 735898dbac | |||
| f7126b0158 | |||
| b6702714eb | |||
| efa4f716c2 | |||
| 76b7b8e778 | |||
| 501b26ced5 | |||
| 5bc36275ad | |||
| 35c837a181 | |||
| 710dfa4963 | |||
| c49ee6bafe | |||
| 368273bab2 | |||
| b1249af365 | |||
| ea2ff31b5a | |||
| a32eb66df4 | |||
| 9b85833240 | |||
| ccb3d0b9ef | |||
| 49cdab39bd | |||
| e318139314 | |||
| 0f2a9a55fb | |||
| 38cec2d5d1 | |||
| 3caf593438 | |||
| c94dbd6416 | |||
| a1eaf601c6 |
@@ -13,6 +13,7 @@ AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
|
||||
@@ -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.41
|
||||
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.41"
|
||||
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.41" 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.
|
||||
|
||||
+18
-12
@@ -171,7 +171,9 @@ The vcpkg `version` will automatically generate the `url` from the [official rep
|
||||
|
||||
To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`. To disable the [default features](https://learn.microsoft.com/en-us/vcpkg/concepts/default-features) you can do: `cpp-httplib[core,openssl]`
|
||||
|
||||
The `overlay-ports` feature allows you to embed vcpkg ports inside your project, without having to fork the main vcpkg registry or creating a custom registry. You can find more information in the relevant [documentation](https://learn.microsoft.com/en-us/vcpkg/concepts/overlay-ports). The `overlay-triplets` feature allows you to customize triplets and change the default behavior (for example always preferring static libraries on Windows). To specify both in one go you can do `[vcpkg].overlay = "my-overlay"`.
|
||||
The `overlay-ports` feature allows you to embed vcpkg ports inside your project, without having to fork the main vcpkg registry or creating a custom registry. You can find more information in the relevant [documentation](https://learn.microsoft.com/en-us/vcpkg/concepts/overlay-ports). The `overlay-triplets` feature allows you to customize triplets and change the default behavior (for example always preferring static libraries on Windows). To specify both in one go you can do `[vcpkg].overlay = "vcpkg-overlay"`.
|
||||
|
||||
For a concrete example of all the features, take a look at the [vcpkg_template](https://github.com/build-cpp/vcpkg_template) repository.
|
||||
|
||||
## Packages
|
||||
|
||||
@@ -189,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.
|
||||
@@ -272,7 +276,7 @@ A table mapping the cmkr features to the relevant CMake construct and the releva
|
||||
| `compile-options` | [`target_compile_options`](https://cmake.org/cmake/help/latest/command/target_compile_options.html) | Adds compiler flags. |
|
||||
| `include-directories` | [`target_include_directories`](https://cmake.org/cmake/help/latest/command/target_include_directories.html) | Adds include directories. |
|
||||
| `link-directories` | [`target_link_directories`](https://cmake.org/cmake/help/latest/command/target_link_directories.html) | Adds library directories. |
|
||||
| `link-libraries` | [`target_link_libraries`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) | Adds library dependencies. |
|
||||
| `link-libraries` | [`target_link_libraries`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) | Adds library dependencies. Use `::mylib` to make sure a target exists. |
|
||||
| `link-options` | [`target_link_options`](https://cmake.org/cmake/help/latest/command/target_link_options.html) | Adds linker flags. |
|
||||
| `precompile-headers` | [`target_precompile_headers`](https://cmake.org/cmake/help/latest/command/target_precompile_headers.html) | Specifies precompiled headers. |
|
||||
| `properties` | [`set_target_properties`](https://cmake.org/cmake/help/latest/command/set_target_properties.html) | See [properties on targets](https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#properties-on-targets) for more information. |
|
||||
@@ -298,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
|
||||
@@ -309,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;
|
||||
};
|
||||
|
||||
|
||||
+54
-15
@@ -289,6 +289,10 @@ struct RawArg {
|
||||
}
|
||||
|
||||
std::string arg;
|
||||
|
||||
bool empty() const {
|
||||
return arg.empty();
|
||||
}
|
||||
};
|
||||
|
||||
// Credit: JustMagic
|
||||
@@ -406,7 +410,7 @@ struct Command {
|
||||
}
|
||||
|
||||
bool print_arg(const RawArg &arg) {
|
||||
if (arg.arg.empty()) {
|
||||
if (arg.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -558,11 +562,15 @@ struct Generator {
|
||||
}
|
||||
|
||||
void conditional_includes(const parser::ConditionVector &include) {
|
||||
handle_condition(include, [this](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
|
||||
handle_condition(include, [this](const std::string &, const std::vector<std::string> &includes) {
|
||||
inject_includes(includes);
|
||||
});
|
||||
}
|
||||
|
||||
void conditional_cmake(const parser::Condition<std::string> &cmake) {
|
||||
handle_condition(cmake, [this](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
|
||||
handle_condition(cmake, [this](const std::string &, const std::string &cmake) {
|
||||
inject_cmake(cmake);
|
||||
});
|
||||
}
|
||||
|
||||
bool if_condition(const std::string &condition) {
|
||||
@@ -719,9 +727,15 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
|
||||
// Helper lambdas for more convenient CMake generation
|
||||
auto &ss = gen.ss;
|
||||
auto cmd = [&gen](const std::string &command) { return gen.cmd(command); };
|
||||
auto comment = [&gen](const std::string &comment) { return gen.comment(comment); };
|
||||
auto endl = [&gen]() { gen.endl(); };
|
||||
auto cmd = [&gen](const std::string &command) {
|
||||
return gen.cmd(command);
|
||||
};
|
||||
auto comment = [&gen](const std::string &comment) {
|
||||
return gen.comment(comment);
|
||||
};
|
||||
auto endl = [&gen]() {
|
||||
gen.endl();
|
||||
};
|
||||
|
||||
std::string cmkr_url = "https://github.com/build-cpp/cmkr";
|
||||
comment("This file is automatically generated from cmake.toml - DO NOT EDIT");
|
||||
@@ -1145,7 +1159,9 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
for (size_t i = 0; i < project.targets.size(); i++) {
|
||||
const auto &target = project.targets[i];
|
||||
|
||||
auto throw_target_error = [&target](const std::string &message) { throw std::runtime_error("[target." + target.name + "] " + message); };
|
||||
auto throw_target_error = [&target](const std::string &message) {
|
||||
throw std::runtime_error("[target." + target.name + "] " + message);
|
||||
};
|
||||
|
||||
const parser::Template *tmplate = nullptr;
|
||||
std::unique_ptr<ConditionScope> tmplate_cs{};
|
||||
@@ -1356,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 + "}");
|
||||
@@ -1384,8 +1399,29 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
|
||||
auto target_cmd = [&](const char *command, const parser::ConditionVector &cargs, const std::string &scope) {
|
||||
gen.handle_condition(cargs,
|
||||
[&](const std::string &, const std::vector<std::string> &args) { cmd(command)(target.name, scope, args); });
|
||||
gen.handle_condition(cargs, [&](const std::string &, const std::vector<std::string> &args) {
|
||||
cmd(command)(target.name, scope, args);
|
||||
});
|
||||
};
|
||||
|
||||
auto link_libraries = [&](const parser::ConditionVector &cargs, const std::string &scope) {
|
||||
gen.handle_condition(cargs, [&](const std::string &, const std::vector<std::string> &args) {
|
||||
std::vector<std::string> targs;
|
||||
for (const std::string &arg : args) {
|
||||
if (arg.find("::") == 0) {
|
||||
auto library = arg.substr(2);
|
||||
// clang-format off
|
||||
cmd("if")("NOT", "TARGET", library);
|
||||
cmd("message")("FATAL_ERROR", "Target \"" + library + "\" referenced by \"" + target.name + "\" does not exist!");
|
||||
cmd("endif")().endl();
|
||||
// clang-format on
|
||||
targs.push_back(std::move(library));
|
||||
} else {
|
||||
targs.push_back(arg);
|
||||
}
|
||||
}
|
||||
cmd("target_link_libraries")(target.name, scope, targs);
|
||||
});
|
||||
};
|
||||
|
||||
auto gen_target_cmds = [&](const parser::Target &t) {
|
||||
@@ -1404,8 +1440,8 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
target_cmd("target_link_directories", t.link_directories, target_scope);
|
||||
target_cmd("target_link_directories", t.private_link_directories, "PRIVATE");
|
||||
|
||||
target_cmd("target_link_libraries", t.link_libraries, target_scope);
|
||||
target_cmd("target_link_libraries", t.private_link_libraries, "PRIVATE");
|
||||
link_libraries(t.link_libraries, target_scope);
|
||||
link_libraries(t.private_link_libraries, "PRIVATE");
|
||||
|
||||
target_cmd("target_link_options", t.link_options, target_scope);
|
||||
target_cmd("target_link_options", t.private_link_options, "PRIVATE");
|
||||
@@ -1428,14 +1464,17 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
|
||||
gen.handle_condition(props, [&](const std::string &, const tsl::ordered_map<std::string, std::string> &properties) {
|
||||
tsl::ordered_map<std::string, RawArg> raw_properties;
|
||||
for (const auto &propItr : properties) {
|
||||
if (propItr.first == "MSVC_RUNTIME_LIBRARY") {
|
||||
if (project_root->project_msvc_runtime == parser::msvc_last) {
|
||||
throw_target_error("You cannot set msvc-runtime without setting the root [project].msvc-runtime");
|
||||
}
|
||||
}
|
||||
// NOTE: We need to make sure that empty strings do not get omitted
|
||||
raw_properties.emplace(propItr.first, Command::quote(propItr.second));
|
||||
}
|
||||
cmd("set_target_properties")(target.name, "PROPERTIES", properties);
|
||||
cmd("set_target_properties")(target.name, "PROPERTIES", raw_properties);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+13
-9
@@ -656,22 +656,25 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
// Add support for relative paths for (private-)link-libraries
|
||||
const auto fix_relative_paths = [&name, &path](ConditionVector &libraries, const char *key) {
|
||||
for (const auto &library_entries : libraries) {
|
||||
for (auto &library_path : libraries[library_entries.first]) {
|
||||
for (auto &library : libraries[library_entries.first]) {
|
||||
// Skip processing paths with potential CMake macros in them (this check isn't perfect)
|
||||
// https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#variable-references
|
||||
if ((library_path.find("${") != std::string::npos || library_path.find("$ENV{") != std::string::npos ||
|
||||
library_path.find("$CACHE{") != std::string::npos) &&
|
||||
library_path.find('}') != std::string::npos) {
|
||||
if ((library.find("${") != std::string::npos || library.find("$ENV{") != std::string::npos ||
|
||||
library.find("$CACHE{") != std::string::npos) &&
|
||||
library.find('}') != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fs::exists(fs::path(path) / library_path)) {
|
||||
// If the file path is relative, prepend ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
library_path.insert(0, "${CMAKE_CURRENT_SOURCE_DIR}/");
|
||||
} else if (library_path.find_first_of(R"(\/)") != std::string::npos) {
|
||||
auto library_path = fs::path(path) / library;
|
||||
if (fs::exists(library_path)) {
|
||||
if (!fs::is_directory(library_path)) {
|
||||
// If the file path is relative (and not a directory), prepend ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
library.insert(0, "${CMAKE_CURRENT_SOURCE_DIR}/");
|
||||
}
|
||||
} else if (library.find_first_of(R"(\/)") != std::string::npos) {
|
||||
// Error if the path contains a directory separator and the file doesn't exist
|
||||
throw std::runtime_error("Attempted to link against a library file that doesn't exist for target \"" + name + "\" in \"" +
|
||||
key + "\": " + library_path);
|
||||
key + "\": " + library);
|
||||
} else {
|
||||
// NOTE: We cannot check if system libraries exist, so we leave them as-is
|
||||
}
|
||||
@@ -782,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