mirror of
https://github.com/build-cpp/cmkr
synced 2026-06-08 13:22:55 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1072cb44e2 | |||
| 926fc15fa2 | |||
| e2c929adb0 | |||
| 0dec7ca4d5 | |||
| 45e346b4a3 | |||
| 7165986190 | |||
| be0ef6d615 | |||
| d607b9028c | |||
| 099b14552c | |||
| 771c80a41a | |||
| 58c7de1d60 | |||
| a61e4bb999 | |||
| 47aaeaf8ce | |||
| 62609a0088 | |||
| e0d8a085db | |||
| 56da4144ae | |||
| 9388b3f29d | |||
| 079644cfeb | |||
| a7ca9f04c0 | |||
| 339c2aac94 | |||
| c573c9a76d | |||
| b24a0a2fdc | |||
| 854e8817c4 | |||
| 1c2947b2fc | |||
| 19e61aa1aa | |||
| bfa1e1fe0d | |||
| 56bd78f7ad | |||
| 4362b3547f |
@@ -10,7 +10,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-2022, macos-11, ubuntu-20.04]
|
||||
os: [windows-2022, macos-latest, ubuntu-20.04]
|
||||
env:
|
||||
BUILD_TYPE: 'Release'
|
||||
CMAKE_GENERATOR: 'Ninja'
|
||||
|
||||
Generated
+1
-1
@@ -22,7 +22,7 @@ project(cmkr
|
||||
LANGUAGES
|
||||
CXX
|
||||
VERSION
|
||||
0.2.25
|
||||
0.2.28
|
||||
DESCRIPTION
|
||||
"CMakeLists generator from TOML"
|
||||
)
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ cmkr-include = false
|
||||
|
||||
[project]
|
||||
name = "cmkr"
|
||||
version = "0.2.25"
|
||||
version = "0.2.28"
|
||||
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.25" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
set(CMKR_TAG "v0.2.28" 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
|
||||
|
||||
@@ -39,6 +39,32 @@ include-before = ["cmake/before-project.cmake"]
|
||||
include-after = ["cmake/after-project.cmake"]
|
||||
```
|
||||
|
||||
### Languages
|
||||
|
||||
Supported languages are (see [`enable_language`](https://cmake.org/cmake/help/latest/command/enable_language.html) for more information):
|
||||
|
||||
- `C`
|
||||
- `CXX` → C++
|
||||
- `CSharp` → C#
|
||||
- `CUDA`
|
||||
- `OBJC` → Objective-C
|
||||
- `OBJCXX` → Objective-C++
|
||||
- `Fortran`
|
||||
- `HIP`
|
||||
- `ISPC`
|
||||
- `Swift`
|
||||
- `ASM`
|
||||
- `ASM_MASM` → [Microsoft Macro Assembler (MASM)](https://learn.microsoft.com/en-US/cpp/assembler/masm/masm-for-x64-ml64-exe)
|
||||
- `ASM_NASM` → [Netwide Assembler (NASM)](https://www.nasm.us)
|
||||
- `ASM_MARMASM` [Microsoft ARM Assembler](https://learn.microsoft.com/en-us/cpp/assembler/arm/arm-assembler-command-line-reference)
|
||||
- `ASM-ATT`
|
||||
- `Java` (undocumented)
|
||||
- `RC` (undocumented)
|
||||
|
||||
After a language is enabled, adding sources files with the corresponding extension to your target will automatically use the appropriate compiler/assembler for it.
|
||||
|
||||
_Note_: It is generally discouraged to disable the `C` language, unless you are absolutely sure it is not used. Sometimes projects added with `fetch-content` implicitly require it and the error messages can be extremely confusing.
|
||||
|
||||
## Conditions
|
||||
|
||||
You can specify your own conditions and use them in any `condition` field:
|
||||
@@ -154,6 +180,7 @@ git = "https://github.com/myuser/gitcontent"
|
||||
tag = "v0.1"
|
||||
shallow = false
|
||||
system = false
|
||||
subdir = ""
|
||||
|
||||
[fetch-content.svncontent]
|
||||
condition = "mycondition"
|
||||
@@ -169,6 +196,8 @@ 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.
|
||||
|
||||
## Targets
|
||||
|
||||
```toml
|
||||
|
||||
@@ -19,7 +19,7 @@ description = "Dependencies from vcpkg"
|
||||
# See https://github.com/microsoft/vcpkg/releases for vcpkg versions
|
||||
# See https://vcpkg.io/en/packages.html for available packages
|
||||
[vcpkg]
|
||||
version = "2022.11.14"
|
||||
version = "2024.03.25"
|
||||
packages = ["fmt"]
|
||||
|
||||
[find-package]
|
||||
|
||||
@@ -156,6 +156,7 @@ struct Content {
|
||||
ConditionVector include_before;
|
||||
ConditionVector include_after;
|
||||
bool system;
|
||||
std::string subdir;
|
||||
};
|
||||
|
||||
enum MsvcRuntimeType {
|
||||
|
||||
+33
-27
@@ -215,7 +215,7 @@ void generate_project(const std::string &type) {
|
||||
generate_gitfile(".gitattributes", {"/**/CMakeLists.txt linguist-generated", "/**/cmkr.cmake linguist-vendored"});
|
||||
|
||||
// Generate .gitignore with reasonable defaults for CMake
|
||||
generate_gitfile(".gitignore", {"build*/", "cmake-build*/", ".idea/", ".vscode/"});
|
||||
generate_gitfile(".gitignore", {"build*/", "cmake-build*/", "CMakerLists.txt", "CMakeLists.txt.user"});
|
||||
|
||||
tsl::ordered_map<std::string, std::string> variables = {
|
||||
{"@name", name},
|
||||
@@ -493,7 +493,7 @@ struct Generator {
|
||||
throw std::runtime_error("Detected additional \" at the end of cmake block");
|
||||
}
|
||||
auto cmake_lf = tolf(cmake);
|
||||
while (cmake_lf.back() == '\n')
|
||||
while (!cmake_lf.empty() && cmake_lf.back() == '\n')
|
||||
cmake_lf.pop_back();
|
||||
bool did_indent = false;
|
||||
for (char ch : cmake_lf) {
|
||||
@@ -814,19 +814,20 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
cmd("if")("CMKR_ROOT_PROJECT", "AND", "NOT", "CMKR_DISABLE_VCPKG");
|
||||
cmd("include")("FetchContent");
|
||||
comment("Fix warnings about DOWNLOAD_EXTRACT_TIMESTAMP");
|
||||
// clang-format off
|
||||
cmd("if")("POLICY", "CMP0135");
|
||||
cmd("cmake_policy")("SET", "CMP0135", "NEW");
|
||||
cmd("endif")();
|
||||
// clang-format on
|
||||
cmd("message")("STATUS", "Fetching vcpkg (" + version_name + ")...");
|
||||
cmd("FetchContent_Declare")("vcpkg", "URL", url);
|
||||
// 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("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake");
|
||||
cmd("endif")();
|
||||
cmd("message")("STATUS", "Fetching vcpkg (" + version_name + ")...");
|
||||
cmd("FetchContent_Declare")("vcpkg", "URL", url);
|
||||
// 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("endif")();
|
||||
cmd("endif")();
|
||||
endl();
|
||||
// clang-format on
|
||||
@@ -900,6 +901,20 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
ofs << "}\n";
|
||||
}
|
||||
|
||||
if (!project.packages.empty()) {
|
||||
comment("Packages");
|
||||
for (const auto &dep : project.packages) {
|
||||
auto version = dep.version;
|
||||
if (version == "*")
|
||||
version.clear();
|
||||
auto required = dep.required ? "REQUIRED" : "";
|
||||
auto config = dep.config ? "CONFIG" : "";
|
||||
auto components = std::make_pair("COMPONENTS", dep.components);
|
||||
ConditionScope cs(gen, dep.condition);
|
||||
cmd("find_package")(dep.name, version, required, config, components).endl();
|
||||
}
|
||||
}
|
||||
|
||||
if (!project.contents.empty()) {
|
||||
cmd("include")("FetchContent").endl();
|
||||
if (!project.root()->vcpkg.enabled()) {
|
||||
@@ -935,20 +950,6 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!project.packages.empty()) {
|
||||
comment("Packages");
|
||||
for (const auto &dep : project.packages) {
|
||||
auto version = dep.version;
|
||||
if (version == "*")
|
||||
version.clear();
|
||||
auto required = dep.required ? "REQUIRED" : "";
|
||||
auto config = dep.config ? "CONFIG" : "";
|
||||
auto components = std::make_pair("COMPONENTS", dep.components);
|
||||
ConditionScope cs(gen, dep.condition);
|
||||
cmd("find_package")(dep.name, version, required, config, components).endl();
|
||||
}
|
||||
}
|
||||
|
||||
auto add_subdir = [&](const std::string &dir) {
|
||||
// clang-format off
|
||||
comment("Subdirectory: " + dir);
|
||||
@@ -1347,7 +1348,12 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
auto working_directory = std::make_pair("WORKING_DIRECTORY", dir);
|
||||
auto command = std::make_pair("COMMAND", test.command);
|
||||
auto arguments = std::make_pair("", test.arguments);
|
||||
|
||||
// Transform the provided arguments into raw arguments to prevent them from being quoted when the generator runs
|
||||
std::vector<RawArg> raw_arguments{};
|
||||
for (const auto &argument : test.arguments)
|
||||
raw_arguments.emplace_back(argument);
|
||||
auto arguments = std::make_pair("", raw_arguments);
|
||||
ConditionScope cs(gen, test.condition);
|
||||
cmd("add_test")(name, configurations, working_directory, command, arguments).endl();
|
||||
}
|
||||
|
||||
@@ -507,6 +507,8 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
value = algo + "=" + value;
|
||||
} else if (key == "hash") {
|
||||
key = "URL_HASH";
|
||||
} else if (key == "subdir") {
|
||||
key = "SOURCE_SUBDIR";
|
||||
} else if (is_cmake_arg(key)) {
|
||||
// allow passthrough of ExternalProject options
|
||||
} else if (!c.visisted(key)) {
|
||||
@@ -597,6 +599,38 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
t.optional("link-libraries", target.link_libraries);
|
||||
t.optional("private-link-libraries", target.private_link_libraries);
|
||||
|
||||
// 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]) {
|
||||
// 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) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip paths that don't contain backwards or forwards slashes
|
||||
if (library_path.find_first_of(R"(\/)") == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the new file path exists, otherwise emit an error
|
||||
const auto expected_library_file_path = fs::path{path} / library_path;
|
||||
if (!fs::exists(expected_library_file_path)) {
|
||||
throw std::runtime_error("Attempted to link against a library file that doesn't exist for target \"" + name + "\" in \"" +
|
||||
key + "\": " + library_path);
|
||||
}
|
||||
|
||||
// Prepend ${CMAKE_CURRENT_SOURCE_DIR} to the path
|
||||
library_path.insert(0, "${CMAKE_CURRENT_SOURCE_DIR}/");
|
||||
}
|
||||
}
|
||||
};
|
||||
fix_relative_paths(target.link_libraries, "link-libraries");
|
||||
fix_relative_paths(target.private_link_libraries, "private-link-libraries");
|
||||
|
||||
t.optional("link-options", target.link_options);
|
||||
t.optional("private-link-options", target.private_link_options);
|
||||
|
||||
|
||||
Generated
+13
@@ -109,3 +109,16 @@ add_test(
|
||||
"$<TARGET_FILE:cmkr>"
|
||||
build
|
||||
)
|
||||
|
||||
if(WIN32) # windows
|
||||
add_test(
|
||||
NAME
|
||||
relative-paths
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_LIST_DIR}/relative-paths"
|
||||
COMMAND
|
||||
"$<TARGET_FILE:cmkr>"
|
||||
build
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
+8
-1
@@ -57,4 +57,11 @@ arguments = ["build"]
|
||||
name = "compile-options"
|
||||
working-directory = "compile-options"
|
||||
command = "$<TARGET_FILE:cmkr>"
|
||||
arguments = ["build"]
|
||||
arguments = ["build"]
|
||||
|
||||
[[test]]
|
||||
condition = "windows"
|
||||
name = "relative-paths"
|
||||
working-directory = "relative-paths"
|
||||
command = "$<TARGET_FILE:cmkr>"
|
||||
arguments = ["build"]
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[project]
|
||||
name = "relative-paths"
|
||||
|
||||
[target.test-library]
|
||||
type = "static"
|
||||
sources = ["src/library-code.cpp"]
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
windows.link-libraries = ["libs/test-library-x64-Release.lib"]
|
||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
// Created by Anthony Printup on 9/18/2023.
|
||||
#include <cstdio>
|
||||
|
||||
extern "C" void library_function() {
|
||||
std::puts("Hello from library_function!");
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Created by Anthony Printup on 9/18/2023.
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef WIN32
|
||||
extern "C" void library_function();
|
||||
#endif
|
||||
int main() {
|
||||
puts("Hello from cmkr(relative-paths)!");
|
||||
#ifdef WIN32
|
||||
library_function();
|
||||
#endif
|
||||
}
|
||||
@@ -7,7 +7,7 @@ description = "Dependencies from vcpkg"
|
||||
# See https://github.com/microsoft/vcpkg/releases for vcpkg versions
|
||||
# See https://vcpkg.io/en/packages.html for available packages
|
||||
[vcpkg]
|
||||
version = "2022.11.14"
|
||||
version = "2024.03.25"
|
||||
packages = ["fmt"]
|
||||
|
||||
[find-package]
|
||||
|
||||
Reference in New Issue
Block a user