mirror of
https://github.com/build-cpp/cmkr
synced 2026-06-08 13:22:55 +00:00
Compare commits
36 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 | |||
| 08204d9847 | |||
| 2202aa8173 | |||
| d3829fb6cd | |||
| 3fb095210a | |||
| 9f99365a25 | |||
| be387141b5 | |||
| 09ded38f70 | |||
| ad90b1ad3e |
@@ -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.24
|
||||
0.2.28
|
||||
DESCRIPTION
|
||||
"CMakeLists generator from TOML"
|
||||
)
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ cmkr-include = false
|
||||
|
||||
[project]
|
||||
name = "cmkr"
|
||||
version = "0.2.24"
|
||||
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.24" 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
|
||||
|
||||
+32
-1
@@ -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:
|
||||
@@ -72,8 +98,10 @@ unix = "UNIX"
|
||||
bsd = "CMAKE_SYSTEM_NAME MATCHES \"BSD\""
|
||||
linux = "CMAKE_SYSTEM_NAME MATCHES \"Linux\""
|
||||
gcc = "CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" OR CMAKE_C_COMPILER_ID STREQUAL \"GNU\""
|
||||
clang = "(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\") OR (CMAKE_C_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\")"
|
||||
msvc = "MSVC"
|
||||
clang = "(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\") OR (CMAKE_C_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\")"
|
||||
clang-cl = "(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\") OR (CMAKE_C_COMPILER_ID MATCHES \"Clang\" AND CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\")"
|
||||
clang-any = "CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" OR CMAKE_C_COMPILER_ID MATCHES \"Clang\""
|
||||
root = "CMKR_ROOT_PROJECT"
|
||||
x64 = "CMAKE_SIZEOF_VOID_P EQUAL 8"
|
||||
x32 = "CMAKE_SIZEOF_VOID_P EQUAL 4"
|
||||
@@ -152,6 +180,7 @@ git = "https://github.com/myuser/gitcontent"
|
||||
tag = "v0.1"
|
||||
shallow = false
|
||||
system = false
|
||||
subdir = ""
|
||||
|
||||
[fetch-content.svncontent]
|
||||
condition = "mycondition"
|
||||
@@ -167,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
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
# Automatically generated from tests/compile-options/cmake.toml - DO NOT EDIT
|
||||
layout: default
|
||||
title: Compiler flags
|
||||
permalink: /examples/compile-options
|
||||
parent: Examples
|
||||
nav_order: 9
|
||||
---
|
||||
|
||||
# Compiler flags
|
||||
|
||||
Example project that sets compiler/linker flags for various platforms.
|
||||
|
||||
```toml
|
||||
[project]
|
||||
name = "compile-options"
|
||||
description = "Compiler flags"
|
||||
|
||||
[target.hello]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
msvc.compile-options = ["/W2"]
|
||||
gcc.compile-options = ["-Wall"]
|
||||
clang.compile-options = ["-Wall"]
|
||||
```
|
||||
|
||||
The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags depending on the platform. See the [targets](/cmake-toml/#targets) documentation for other things you can set.
|
||||
|
||||
_Note_: In general you only want to specify flags _required_ to compile your code without errors.
|
||||
|
||||
<sup><sub>This page was automatically generated from [tests/compile-options/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/compile-options/cmake.toml).</sub></sup>
|
||||
@@ -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 {
|
||||
|
||||
+73
-52
@@ -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) {
|
||||
@@ -562,28 +562,26 @@ struct ConditionScope {
|
||||
};
|
||||
|
||||
static bool vcpkg_valid_identifier(const std::string &name) {
|
||||
// prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default
|
||||
auto is_reserved = [](const std::string &s) {
|
||||
if (s == "prn" || s == "aux" || s == "nul" || s == "con" || s == "core" || s == "default") {
|
||||
return true;
|
||||
}
|
||||
if (s.length() == 4 && (s.compare(0, 3, "lpt") == 0 || s.compare(0, 3, "com") == 0) && (s[3] >= '1' && s[3] <= '9')) {
|
||||
return true;
|
||||
// [a-z0-9]+(-[a-z0-9]+)*
|
||||
for (size_t i = 0; i < name.length(); i++) {
|
||||
auto c = name[i];
|
||||
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (i > 0 && c == '-')) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// [a-z0-9]+(-[a-z0-9]+)*
|
||||
auto is_identifier = [](const std::string &s) {
|
||||
for (size_t i = 0; i < s.length(); i++) {
|
||||
auto c = s[i];
|
||||
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (i > 0 && c == '-')) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool vcpkg_identifier_reserved(const std::string &name) {
|
||||
// prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default
|
||||
if (name == "prn" || name == "aux" || name == "nul" || name == "con" || name == "core" || name == "default") {
|
||||
return true;
|
||||
};
|
||||
return is_identifier(name) && !is_reserved(name);
|
||||
}
|
||||
if (name.length() == 4 && (name.compare(0, 3, "lpt") == 0 || name.compare(0, 3, "com") == 0) && (name[3] >= '1' && name[3] <= '9')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string vcpkg_escape_identifier(const std::string &name) {
|
||||
@@ -600,10 +598,12 @@ static std::string vcpkg_escape_identifier(const std::string &name) {
|
||||
|
||||
escaped += std::tolower(ch);
|
||||
}
|
||||
|
||||
if (!vcpkg_valid_identifier(escaped)) {
|
||||
throw std::runtime_error("The escaped project name '" + escaped + "' is not usable with [vcpkg]");
|
||||
}
|
||||
if (vcpkg_identifier_reserved(escaped)) {
|
||||
throw std::runtime_error("The escaped project name '" + escaped + "' is a reserved name [vcpkg]");
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -847,11 +848,17 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
const auto &package = packages[i];
|
||||
const auto &features = package.features;
|
||||
if (!vcpkg_valid_identifier(package.name)) {
|
||||
throw std::runtime_error("Invalid vcpkg package name '" + package.name + "'");
|
||||
throw std::runtime_error("Invalid vcpkg package name '" + package.name + "', name is not valid");
|
||||
}
|
||||
if (vcpkg_identifier_reserved(package.name)) {
|
||||
throw std::runtime_error("Invalid vcpkg package name '" + package.name + "', name is reserved");
|
||||
}
|
||||
for (const auto &feature : features) {
|
||||
if (!vcpkg_valid_identifier(feature)) {
|
||||
throw std::runtime_error("Invalid vcpkg package feature '" + feature + "'");
|
||||
throw std::runtime_error("Invalid vcpkg package feature '" + feature + "', name is not valid");
|
||||
}
|
||||
if (vcpkg_identifier_reserved(feature)) {
|
||||
throw std::runtime_error("Invalid vcpkg package feature '" + feature + "', name is reserved");
|
||||
}
|
||||
}
|
||||
if (features.empty()) {
|
||||
@@ -894,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()) {
|
||||
@@ -929,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);
|
||||
@@ -1341,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();
|
||||
}
|
||||
@@ -1372,10 +1384,19 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the generated CMakeLists.txt output from the stringstream buffer
|
||||
auto generated_cmake = ss.str();
|
||||
|
||||
// Make sure the file ends in a single newline
|
||||
while (!generated_cmake.empty() && std::isspace(generated_cmake.back())) {
|
||||
generated_cmake.pop_back();
|
||||
}
|
||||
generated_cmake += '\n';
|
||||
|
||||
// Generate CMakeLists.txt
|
||||
auto list_path = fs::path(path) / "CMakeLists.txt";
|
||||
|
||||
auto should_regenerate = [&list_path, &ss]() {
|
||||
auto should_regenerate = [&list_path, &generated_cmake]() {
|
||||
if (!fs::exists(list_path))
|
||||
return true;
|
||||
|
||||
@@ -1385,11 +1406,11 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
|
||||
std::string data((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
||||
return data != ss.str();
|
||||
return data != generated_cmake;
|
||||
}();
|
||||
|
||||
if (should_regenerate) {
|
||||
create_file(list_path, ss.str());
|
||||
create_file(list_path, generated_cmake);
|
||||
}
|
||||
|
||||
auto generate_subdir = [path, &project](const fs::path &sub) {
|
||||
|
||||
+38
-1
@@ -265,9 +265,12 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
conditions["bsd"] = R"cmake(CMAKE_SYSTEM_NAME MATCHES "BSD")cmake";
|
||||
conditions["linux"] = conditions["lunix"] = R"cmake(CMAKE_SYSTEM_NAME MATCHES "Linux")cmake";
|
||||
conditions["gcc"] = R"cmake(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")cmake";
|
||||
conditions["msvc"] = R"cmake(MSVC)cmake";
|
||||
conditions["clang"] =
|
||||
R"cmake((CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC$") OR (CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC$"))cmake";
|
||||
conditions["msvc"] = R"cmake(MSVC)cmake";
|
||||
conditions["clang-cl"] =
|
||||
R"cmake((CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC$") OR (CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC$"))cmake";
|
||||
conditions["clang-any"] = R"cmake(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "Clang")cmake";
|
||||
conditions["root"] = R"cmake(CMKR_ROOT_PROJECT)cmake";
|
||||
conditions["x64"] = R"cmake(CMAKE_SIZEOF_VOID_P EQUAL 8)cmake";
|
||||
conditions["x32"] = R"cmake(CMAKE_SIZEOF_VOID_P EQUAL 4)cmake";
|
||||
@@ -504,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)) {
|
||||
@@ -594,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
+22
@@ -100,3 +100,25 @@ if(MSVC) # msvc
|
||||
)
|
||||
|
||||
endif()
|
||||
add_test(
|
||||
NAME
|
||||
compile-options
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_LIST_DIR}/compile-options"
|
||||
COMMAND
|
||||
"$<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()
|
||||
|
||||
@@ -52,3 +52,16 @@ name = "msvc-runtime"
|
||||
working-directory = "msvc-runtime"
|
||||
command = "$<TARGET_FILE:cmkr>"
|
||||
arguments = ["build"]
|
||||
|
||||
[[test]]
|
||||
name = "compile-options"
|
||||
working-directory = "compile-options"
|
||||
command = "$<TARGET_FILE:cmkr>"
|
||||
arguments = ["build"]
|
||||
|
||||
[[test]]
|
||||
condition = "windows"
|
||||
name = "relative-paths"
|
||||
working-directory = "relative-paths"
|
||||
command = "$<TARGET_FILE:cmkr>"
|
||||
arguments = ["build"]
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Example project that sets compiler/linker flags for various platforms.
|
||||
|
||||
[project]
|
||||
name = "compile-options"
|
||||
description = "Compiler flags"
|
||||
|
||||
[target.hello]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
msvc.compile-options = ["/W2"]
|
||||
gcc.compile-options = ["-Wall"]
|
||||
clang.compile-options = ["-Wall"]
|
||||
|
||||
# The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags depending on the platform. See the [targets](/cmake-toml/#targets) documentation for other things you can set.
|
||||
# _Note_: In general you only want to specify flags _required_ to compile your code without errors.
|
||||
@@ -0,0 +1,5 @@
|
||||
#include <cstdio>
|
||||
|
||||
int main() {
|
||||
puts("Hello from cmkr!");
|
||||
}
|
||||
@@ -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