mirror of
https://github.com/build-cpp/cmkr
synced 2026-06-08 13:22:55 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1249af365 | |||
| ea2ff31b5a | |||
| a32eb66df4 | |||
| 9b85833240 | |||
| ccb3d0b9ef | |||
| 49cdab39bd | |||
| e318139314 | |||
| 0f2a9a55fb | |||
| 38cec2d5d1 | |||
| 3caf593438 | |||
| c94dbd6416 | |||
| a1eaf601c6 | |||
| 10320c8e55 | |||
| 45e12c8d98 | |||
| e12ebc060d | |||
| c6e3fc159f | |||
| dc6f306d9c | |||
| e08bd5a311 | |||
| 068977e2f5 |
@@ -13,6 +13,7 @@ AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
|
||||
Generated
+2
-2
@@ -1,7 +1,7 @@
|
||||
# This file is automatically generated from cmake.toml - DO NOT EDIT
|
||||
# See https://github.com/build-cpp/cmkr for more information
|
||||
|
||||
cmake_minimum_required(VERSION 2.8...3.8)
|
||||
cmake_minimum_required(VERSION 2.8...3.31)
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
||||
message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
|
||||
@@ -22,7 +22,7 @@ project(cmkr
|
||||
LANGUAGES
|
||||
CXX
|
||||
VERSION
|
||||
0.2.39
|
||||
0.2.44
|
||||
DESCRIPTION
|
||||
"CMakeLists generator from TOML"
|
||||
)
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
[cmake]
|
||||
version = "2.8...3.8"
|
||||
version = "2.8...3.31"
|
||||
cmkr-include = false
|
||||
|
||||
[project]
|
||||
name = "cmkr"
|
||||
version = "0.2.39"
|
||||
version = "0.2.44"
|
||||
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.39" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
set(CMKR_TAG "v0.2.44" 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
|
||||
|
||||
+4
-2
@@ -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
|
||||
|
||||
@@ -272,7 +274,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. |
|
||||
|
||||
+62
-21
@@ -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");
|
||||
@@ -865,12 +879,17 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
comment("vcpkg settings");
|
||||
auto emit_overlay = [&cmd](const std::string &name, const std::vector<std::string> &overlay) {
|
||||
if (!overlay.empty()) {
|
||||
std::vector<std::string> set_args;
|
||||
for (const auto &directory : overlay) {
|
||||
if (!fs::path(directory).is_relative()) {
|
||||
throw std::runtime_error("[vcpkg] overlay is not a relative path: " + directory);
|
||||
}
|
||||
if (!fs::is_directory(directory)) {
|
||||
throw std::runtime_error("[vcpkg] overlay is not a directory: " + directory);
|
||||
}
|
||||
set_args.emplace_back("${CMAKE_CURRENT_SOURCE_DIR}/" + directory);
|
||||
}
|
||||
cmd("set")(name, overlay);
|
||||
cmd("set")(name, set_args);
|
||||
}
|
||||
};
|
||||
emit_overlay("VCPKG_OVERLAY_PORTS", project.vcpkg.overlay_ports);
|
||||
@@ -938,15 +957,11 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
cmd("endif")();
|
||||
cmd("message")("STATUS", "Fetching vcpkg (" + version_name + ")...");
|
||||
cmd("FetchContent_Declare")("vcpkg", vcpkg_args);
|
||||
// Not using FetchContent_MakeAvailable here in case vcpkg adds CMakeLists.txt
|
||||
cmd("FetchContent_GetProperties")("vcpkg");
|
||||
cmd("if")("NOT", "vcpkg_POPULATED");
|
||||
cmd("FetchContent_Populate")("vcpkg");
|
||||
cmd("if")("CMAKE_HOST_SYSTEM_NAME", "STREQUAL", "Darwin", "AND", "CMAKE_OSX_ARCHITECTURES", "STREQUAL", RawArg("\"\""));
|
||||
cmd("set")("CMAKE_OSX_ARCHITECTURES", "${CMAKE_HOST_SYSTEM_PROCESSOR}", "CACHE", "STRING", RawArg("\"\""), "FORCE");
|
||||
cmd("endif")();
|
||||
cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake");
|
||||
cmd("FetchContent_MakeAvailable")("vcpkg").endl();
|
||||
cmd("if")("CMAKE_HOST_SYSTEM_NAME", "STREQUAL", "Darwin", "AND", "CMAKE_OSX_ARCHITECTURES", "STREQUAL", RawArg("\"\""));
|
||||
cmd("set")("CMAKE_OSX_ARCHITECTURES", "${CMAKE_HOST_SYSTEM_PROCESSOR}", "CACHE", "STRING", RawArg("\"\""), "FORCE");
|
||||
cmd("endif")();
|
||||
cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake");
|
||||
cmd("endif")();
|
||||
endl();
|
||||
// clang-format on
|
||||
@@ -1144,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{};
|
||||
@@ -1383,8 +1400,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) {
|
||||
@@ -1403,8 +1441,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");
|
||||
@@ -1427,14 +1465,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+12
-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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user