Skip to content

Commit 69d844a

Browse files
committed
Refactor msvc-static to msvc-runtime
1 parent af9a117 commit 69d844a

File tree

10 files changed

+154
-59
lines changed

10 files changed

+154
-59
lines changed

docs/examples/msvc-runtime.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
# Automatically generated from tests/msvc-runtime/cmake.toml - DO NOT EDIT
3+
layout: default
4+
title: Static MSVC runtime
5+
permalink: /examples/msvc-runtime
6+
parent: Examples
7+
nav_order: 8
8+
---
9+
10+
# Static MSVC runtime
11+
12+
13+
14+
```toml
15+
[project]
16+
name = "msvc-runtime"
17+
description = "Static MSVC runtime"
18+
msvc-runtime = "static"
19+
20+
# This target will compile with a static runtime
21+
[target.static-runtime]
22+
type = "executable"
23+
sources = ["src/main.cpp"]
24+
25+
# This target overrides the [project].msvc-runtime
26+
[target.dynamic-runtime]
27+
type = "executable"
28+
sources = ["src/main.cpp"]
29+
msvc-runtime = "dynamic"
30+
```
31+
32+
33+
34+
<sup><sub>This page was automatically generated from [tests/msvc-runtime/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/msvc-runtime/cmake.toml).</sub></sup>

docs/examples/msvc-static.md

Lines changed: 0 additions & 27 deletions
This file was deleted.

include/project_parser.hpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ struct Target {
102102
Condition<std::string> cmake_after;
103103
ConditionVector include_before;
104104
ConditionVector include_after;
105-
106-
bool allow_msvc_static = false;
107105
};
108106

109107
struct Template {
@@ -153,7 +151,17 @@ struct Content {
153151
ConditionVector include_after;
154152
};
155153

154+
enum MsvcRuntimeType {
155+
msvc_dynamic,
156+
msvc_static,
157+
msvc_last,
158+
};
159+
160+
extern const char *msvcRuntimeTypeNames[msvc_last];
161+
156162
struct Project {
163+
const Project *parent;
164+
157165
// This is the CMake version required to use all cmkr versions.
158166
std::string cmake_version = "3.15";
159167
std::string cmkr_include = "cmkr.cmake";
@@ -171,6 +179,7 @@ struct Project {
171179
std::string project_version;
172180
std::string project_description;
173181
std::vector<std::string> project_languages;
182+
MsvcRuntimeType project_msvc_runtime = msvc_last;
174183
Condition<std::string> cmake_before;
175184
Condition<std::string> cmake_after;
176185
ConditionVector include_before;
@@ -188,6 +197,7 @@ struct Project {
188197
std::vector<Subdir> subdirs;
189198

190199
Project(const Project *parent, const std::string &path, bool build);
200+
const Project *root() const;
191201
};
192202

193203
bool is_root_path(const std::string &path);

src/cmake_generator.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -523,10 +523,12 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
523523

524524
if (root_project) {
525525
cmd("cmake_minimum_required")("VERSION", project.cmake_version).endl();
526-
// clang-format off
527-
cmd("if")("POLICY", "CMP0091");
528-
cmd("cmake_policy")("SET", "CMP0091", "NEW");
529-
cmd("endif")().endl();
526+
527+
if (project.project_msvc_runtime != parser::msvc_last) {
528+
comment("Enable support for MSVC_RUNTIME_LIBRARY");
529+
cmd("cmake_policy")("SET", "CMP0091", "NEW").endl();
530+
}
531+
530532
// clang-format on
531533
if (!project.allow_in_tree) {
532534
// clang-format off
@@ -810,6 +812,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
810812
}
811813

812814
if (!project.targets.empty()) {
815+
auto root_project = project.root();
813816
for (size_t i = 0; i < project.targets.size(); i++) {
814817
if (i > 0) {
815818
endl();
@@ -1018,6 +1021,13 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
10181021
}
10191022

10201023
gen.handle_condition(props, [&](const std::string &, const tsl::ordered_map<std::string, std::string> &properties) {
1024+
for (const auto &propItr : properties) {
1025+
if (propItr.first == "MSVC_RUNTIME_LIBRARY") {
1026+
if (root_project->project_msvc_runtime == parser::msvc_last) {
1027+
throw std::runtime_error("You cannot set [target].msvc-runtime without setting the root [project].msvc-runtime");
1028+
}
1029+
}
1030+
}
10211031
cmd("set_target_properties")(target.name, "PROPERTIES", properties);
10221032
});
10231033
}
@@ -1030,10 +1040,6 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
10301040
gen.conditional_cmake(tmplate->outline.cmake_after);
10311041
}
10321042

1033-
if (target.allow_msvc_static && !target.name.empty()) {
1034-
cmd("set_property")("TARGET", target.name, "PROPERTY", "MSVC_RUNTIME_LIBRARY", "MultiThreaded$<$<CONFIG:Debug>:Debug>");
1035-
}
1036-
10371043
cmd("unset")("CMKR_TARGET");
10381044
cmd("unset")("CMKR_SOURCES");
10391045
}

src/project_parser.cpp

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ static TargetType parse_targetType(const std::string &name) {
2121
return target_last;
2222
}
2323

24+
const char *msvcRuntimeTypeNames[msvc_last] = {"dynamic", "static"};
25+
26+
static MsvcRuntimeType parse_msvcRuntimeType(const std::string &name) {
27+
for (int i = 0; i < msvc_last; i++) {
28+
if (name == msvcRuntimeTypeNames[i]) {
29+
return static_cast<MsvcRuntimeType>(i);
30+
}
31+
}
32+
return msvc_last;
33+
}
34+
2435
using TomlBasicValue = toml::basic_value<toml::discard_comments, tsl::ordered_map, std::vector>;
2536

2637
static std::string format_key_error(const std::string &error, const toml::key &ky, const TomlBasicValue &value) {
@@ -192,7 +203,7 @@ class TomlCheckerRoot {
192203
}
193204
};
194205

195-
Project::Project(const Project *parent, const std::string &path, bool build) {
206+
Project::Project(const Project *parent, const std::string &path, bool build) : parent(parent) {
196207
const auto toml_path = fs::path(path) / "cmake.toml";
197208
if (!fs::exists(toml_path)) {
198209
throw std::runtime_error("File not found '" + toml_path.string() + "'");
@@ -276,6 +287,21 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
276287
project.optional("include-before", include_before);
277288
project.optional("include-after", include_after);
278289
project.optional("subdirs", project_subdirs);
290+
291+
std::string msvc_runtime;
292+
project.optional("msvc-runtime", msvc_runtime);
293+
if (!msvc_runtime.empty()) {
294+
project_msvc_runtime = parse_msvcRuntimeType(msvc_runtime);
295+
if (project_msvc_runtime == msvc_last) {
296+
std::string error = "Unknown runtime '" + msvc_runtime + "'\n";
297+
error += "Available types:\n";
298+
for (std::string type_name : msvcRuntimeTypeNames) {
299+
error += " - " + type_name + "\n";
300+
}
301+
error.pop_back(); // Remove last newline
302+
throw std::runtime_error(format_key_error(error, msvc_runtime, project.find("msvc-runtime")));
303+
}
304+
}
279305
}
280306

281307
if (checker.contains("subdir")) {
@@ -523,7 +549,33 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
523549
t.optional("precompile-headers", target.precompile_headers);
524550
t.optional("private-precompile-headers", target.private_precompile_headers);
525551

526-
t.optional("msvc-static", target.allow_msvc_static);
552+
Condition<std::string> msvc_runtime;
553+
t.optional("msvc-runtime", msvc_runtime);
554+
for (const auto &condItr : msvc_runtime) {
555+
switch (parse_msvcRuntimeType(condItr.second)) {
556+
case msvc_dynamic:
557+
target.properties[condItr.first]["MSVC_RUNTIME_LIBRARY"] = "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL";
558+
break;
559+
case msvc_static:
560+
target.properties[condItr.first]["MSVC_RUNTIME_LIBRARY"] = "MultiThreaded$<$<CONFIG:Debug>:Debug>";
561+
break;
562+
default: {
563+
std::string error = "Unknown runtime '" + condItr.second + "'\n";
564+
error += "Available types:\n";
565+
for (std::string type_name : msvcRuntimeTypeNames) {
566+
error += " - " + type_name + "\n";
567+
}
568+
error.pop_back(); // Remove last newline
569+
const TomlBasicValue *report;
570+
if (condItr.first.empty()) {
571+
report = &t.find("msvc-runtime");
572+
} else {
573+
report = &t.find(condItr.first).as_table().find("msvc-runtime").value();
574+
}
575+
throw std::runtime_error(format_key_error(error, condItr.second, *report));
576+
}
577+
}
578+
}
527579

528580
t.optional("condition", target.condition);
529581
t.optional("alias", target.alias);
@@ -666,6 +718,13 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
666718
checker.check(conditions, true);
667719
}
668720

721+
const Project *Project::root() const {
722+
auto root = this;
723+
while (root->parent != nullptr)
724+
root = root->parent;
725+
return root;
726+
}
727+
669728
bool is_root_path(const std::string &path) {
670729
const auto toml_path = fs::path(path) / "cmake.toml";
671730
if (!fs::exists(toml_path)) {

tests/CMakeLists.txt

Lines changed: 11 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/cmake.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,10 @@ name = "templates"
4545
working-directory = "templates"
4646
command = "$<TARGET_FILE:cmkr>"
4747
arguments = ["build"]
48+
49+
[[test]]
50+
condition = "msvc"
51+
name = "msvc-runtime"
52+
working-directory = "msvc-runtime"
53+
command = "$<TARGET_FILE:cmkr>"
54+
arguments = ["build"]

tests/msvc-runtime/cmake.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[project]
2+
name = "msvc-runtime"
3+
description = "Static MSVC runtime"
4+
msvc-runtime = "static"
5+
6+
# This target will compile with a static runtime
7+
[target.static-runtime]
8+
type = "executable"
9+
sources = ["src/main.cpp"]
10+
11+
# This target overrides the [project].msvc-runtime
12+
[target.dynamic-runtime]
13+
type = "executable"
14+
sources = ["src/main.cpp"]
15+
msvc-runtime = "dynamic"
File renamed without changes.

tests/msvc-static/cmake.toml

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)