diff --git a/.clang-format b/.clang-format index 09ec46b..39a0dad 100644 --- a/.clang-format +++ b/.clang-format @@ -13,6 +13,7 @@ AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false +AllowShortLambdasOnASingleLine: None AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false diff --git a/docs/cmake-toml.md b/docs/cmake-toml.md index 6e4f23b..eebbf49 100644 --- a/docs/cmake-toml.md +++ b/docs/cmake-toml.md @@ -272,7 +272,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. | diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index 8153038..793f3a8 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -558,11 +558,15 @@ struct Generator { } void conditional_includes(const parser::ConditionVector &include) { - handle_condition(include, [this](const std::string &, const std::vector &includes) { inject_includes(includes); }); + handle_condition(include, [this](const std::string &, const std::vector &includes) { + inject_includes(includes); + }); } void conditional_cmake(const parser::Condition &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 +723,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"); @@ -1145,7 +1155,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 tmplate_cs{}; @@ -1384,8 +1396,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 &args) { cmd(command)(target.name, scope, args); }); + gen.handle_condition(cargs, [&](const std::string &, const std::vector &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 &args) { + std::vector 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) { @@ -1404,8 +1437,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");