diff --git a/include/cmake.hpp b/include/cmake.hpp index 19d6aad..a4299ff 100644 --- a/include/cmake.hpp +++ b/include/cmake.hpp @@ -33,6 +33,7 @@ struct Package { }; struct Vcpkg { + std::string url; std::vector packages; }; diff --git a/src/cmake.cpp b/src/cmake.cpp index c146423..aa7c0e0 100644 --- a/src/cmake.cpp +++ b/src/cmake.cpp @@ -192,6 +192,12 @@ CMake::CMake(const std::string &path, bool build) { get_optional(t, "link-options", target.link_options); get_optional(t, "precompile-headers", target.precompile_headers); + if (!target.headers.empty()) { + auto &sources = target.sources.nth(0).value(); + const auto &headers = target.headers.nth(0)->second; + sources.insert(sources.end(), headers.begin(), headers.end()); + } + if (t.contains("alias")) { target.alias = toml::find(t, "alias").as_string(); } @@ -251,6 +257,7 @@ CMake::CMake(const std::string &path, bool build) { if (toml.contains("vcpkg")) { const auto &v = toml::find(toml, "vcpkg"); + vcpkg.url = toml::find(v, "url").as_string(); vcpkg.packages = toml::find(v, "packages"); } diff --git a/src/gen.cpp b/src/gen.cpp index 25de5bf..911a460 100644 --- a/src/gen.cpp +++ b/src/gen.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -522,26 +523,35 @@ int generate_cmake(const char *path, bool root) { } } - if (!cmake.vcpkg.packages.empty()) { - cmd("include")("FetchContent"); - cmd("message")("STATUS", "Fetching vcpkg..."); - cmd("FetchContent_Declare")("vcpkg", "URL", "https://github.com/microsoft/vcpkg/archive/refs/tags/2021.05.12.tar.gz"); - cmd("FetchContent_MakeAvailable")("vcpkg"); - cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake"); + if (!cmake.vcpkg.packages.empty() && !cmake.vcpkg.url.empty()) { + auto vcpkg_escape_identifier = [](const std::string &name) -> std::string { + const std::regex ok("[a-z0-9]+(-[a-z0-9]+)*"); + const std::regex reserved("prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default"); + std::cmatch m; + if (!std::regex_match(name.c_str(), m, reserved) && std::regex_match(name.c_str(), m, ok)) { + return name; + } else { + // should probably throw! + return "project-name"; + } + }; using namespace nlohmann; json j; j["$schema"] = "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json"; - j["name"] = cmake.project_name; - if (cmake.project_version.empty()) - throw std::runtime_error("vcpkg manifest mode requires that the project have a version string!"); - j["version"] = cmake.project_version; + j["name"] = vcpkg_escape_identifier(cmake.project_name); + if (!cmake.project_version.empty()) + j["version"] = cmake.project_version; j["dependencies"] = cmake.vcpkg.packages; + cmd("include")("FetchContent"); + cmd("message")("STATUS", "Fetching vcpkg..."); + cmd("FetchContent_Declare")("vcpkg", "URL", cmake.vcpkg.url); + cmd("FetchContent_MakeAvailable")("vcpkg"); + cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake"); std::ofstream ofs("vcpkg.json"); if (!ofs) { throw std::runtime_error("Failed to create a vcpkg.json manifest file!"); } - ofs << std::setw(4) << j << std::endl; - ofs.close(); + ofs << std::setw(2) << j << std::endl; } if (!cmake.packages.empty()) { @@ -616,21 +626,8 @@ int generate_cmake(const char *path, bool root) { [&](const std::string &, const std::vector &includes) { inject_includes(includes); }); gen.handle_condition(target.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); }); - auto headers_var = target.name + "_HEADERS"; auto sources_var = target.name + "_SOURCES"; - if (!target.headers.empty()) { - cmd("set")(headers_var, RawArg("\"\"")).endl(); - gen.handle_condition(target.headers, [&](const std::string &condition, const std::vector &condition_headers) { - auto headers = expand_cmake_paths(condition_headers, path); - if (headers.empty()) { - auto header_key = condition.empty() ? "headers" : (condition + ".headers"); - throw std::runtime_error(target.name + " " + header_key + " wildcard found 0 files"); - } - cmd("list")("APPEND", headers_var, headers); - }); - } - bool added_toml = false; cmd("set")(sources_var, RawArg("\"\"")).endl(); gen.handle_condition(target.sources, [&](const std::string &condition, const std::vector &condition_sources) { @@ -708,10 +705,6 @@ int generate_cmake(const char *path, bool root) { // clang-format on } - if (!target.headers.empty()) { - cmd("source_group")("TREE", "${CMAKE_CURRENT_SOURCE_DIR}", "FILES", "${" + headers_var + "}").endl(); - } - if (!target.sources.empty()) { cmd("source_group")("TREE", "${CMAKE_CURRENT_SOURCE_DIR}", "FILES", "${" + sources_var + "}").endl(); }