mirror of
https://github.com/build-cpp/cmkr
synced 2026-06-08 13:22:55 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e650073bef | |||
| 96e44f7771 | |||
| cb9ad5cdb3 | |||
| c785b540d3 | |||
| 275b73eefa |
Generated
+1
-1
@@ -22,7 +22,7 @@ project(cmkr
|
||||
LANGUAGES
|
||||
CXX
|
||||
VERSION
|
||||
0.2.20
|
||||
0.2.21
|
||||
DESCRIPTION
|
||||
"CMakeLists generator from TOML"
|
||||
)
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ cmkr-include = false
|
||||
|
||||
[project]
|
||||
name = "cmkr"
|
||||
version = "0.2.20"
|
||||
version = "0.2.21"
|
||||
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.20" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
set(CMKR_TAG "v0.2.21" 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
|
||||
|
||||
@@ -212,6 +212,29 @@ CXX_STANDARD_REQUIRED = true
|
||||
FOLDER = "MyFolder"
|
||||
```
|
||||
|
||||
## Templates
|
||||
|
||||
To avoid repeating yourself you can create your own target type and use it in your targets:
|
||||
|
||||
```toml
|
||||
[template.example]
|
||||
condition = "MYPROJECT_BUILD_EXAMPLES"
|
||||
type = "executable"
|
||||
link-libraries = ["myproject::mylib"]
|
||||
add-function = ""
|
||||
pass-sources = false
|
||||
|
||||
# Properties from the template are merged with the ones here
|
||||
[target.myexample]
|
||||
type = "example"
|
||||
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.
|
||||
- `pass-sources`: Pass sources directly to the add function instead of using `target_sources`.
|
||||
|
||||
## Tests and installation (unfinished)
|
||||
|
||||
**Note**: The `[[test]]` and `[[install]]` are unfinished features and will likely change in a future release.
|
||||
|
||||
+28
-8
@@ -170,7 +170,6 @@ static void generate_gitfile(const char *gitfile, const std::vector<std::string>
|
||||
auto flush_line = [&line, &lines]() {
|
||||
auto itr = std::find(lines.begin(), lines.end(), line);
|
||||
if (itr != lines.end()) {
|
||||
printf("erase:%s\n", line.c_str());
|
||||
lines.erase(itr);
|
||||
}
|
||||
line.clear();
|
||||
@@ -618,7 +617,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
for (auto const &lang : project.project_languages) {
|
||||
if (known_languages.find(lang) == known_languages.end()) {
|
||||
if (project.project_allow_unknown_languages) {
|
||||
printf("Unknown language '%s' specified\n", lang.c_str());
|
||||
printf("[warning] Unknown language '%s' specified\n", lang.c_str());
|
||||
} else {
|
||||
throw std::runtime_error("Unknown language '" + lang + "' specified");
|
||||
}
|
||||
@@ -987,6 +986,9 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
auto project_root = project.root();
|
||||
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); };
|
||||
|
||||
const parser::Template *tmplate = nullptr;
|
||||
std::unique_ptr<ConditionScope> tmplate_cs{};
|
||||
|
||||
@@ -1090,7 +1092,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
auto sources = expand_cmake_paths(condition_sources, path, is_root_project);
|
||||
if (sources.empty()) {
|
||||
auto source_key = condition.empty() ? "sources" : (condition + ".sources");
|
||||
throw std::runtime_error(target.name + " " + source_key + " wildcard found 0 files");
|
||||
throw_target_error(source_key + " wildcard found 0 files");
|
||||
}
|
||||
|
||||
// Make sure there are source files for the languages used by the project
|
||||
@@ -1101,7 +1103,25 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
case parser::target_static:
|
||||
case parser::target_object:
|
||||
if (!contains_language_source(sources)) {
|
||||
throw std::runtime_error("There were no source files linked within the target " + target.name);
|
||||
std::string extensions;
|
||||
for (const auto &language : project_extensions) {
|
||||
if (!extensions.empty()) {
|
||||
extensions += " ";
|
||||
}
|
||||
extensions += language;
|
||||
}
|
||||
throw_target_error("No sources found with valid extensions (" + extensions + ")");
|
||||
}
|
||||
|
||||
// Make sure relative source files exist
|
||||
for (const auto &source : sources) {
|
||||
auto var_index = source.find("${");
|
||||
if (var_index != std::string::npos)
|
||||
continue;
|
||||
const auto &source_path = fs::path(path) / source;
|
||||
if (!fs::exists(source_path)) {
|
||||
throw_target_error("Source file does not exist " + source);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1111,7 +1131,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
if (sources_with_set) {
|
||||
// This is a sanity check to make sure the unconditional sources are first
|
||||
if (!condition.empty()) {
|
||||
throw std::runtime_error("Unreachable code, make sure unconditional sources are first");
|
||||
throw_target_error("Unreachable code, make sure unconditional sources are first");
|
||||
}
|
||||
cmd("set")(sources_var, sources);
|
||||
sources_with_set = false;
|
||||
@@ -1124,7 +1144,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
|
||||
if (tmplate != nullptr) {
|
||||
if (target_type != parser::target_template) {
|
||||
throw std::runtime_error("Unreachable code, unexpected target type for template");
|
||||
throw_target_error("Unreachable code, unexpected target type for template");
|
||||
}
|
||||
target_type = tmplate->outline.type;
|
||||
}
|
||||
@@ -1172,7 +1192,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
target_scope = "PUBLIC";
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unimplemented enum value");
|
||||
throw_target_error("Unimplemented enum value");
|
||||
}
|
||||
|
||||
// Handle custom add commands from templates.
|
||||
@@ -1253,7 +1273,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
for (const auto &propItr : properties) {
|
||||
if (propItr.first == "MSVC_RUNTIME_LIBRARY") {
|
||||
if (project_root->project_msvc_runtime == parser::msvc_last) {
|
||||
throw std::runtime_error("You cannot set [target].msvc-runtime without setting the root [project].msvc-runtime");
|
||||
throw_target_error("You cannot set msvc-runtime without setting the root [project].msvc-runtime");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user