diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index 639ef28..c70a3a7 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -164,7 +163,7 @@ struct Command { } } - std::string quote(const std::string &str) { + static std::string quote(const std::string &str) { // Don't quote arguments that don't need quoting if (str.find(' ') == std::string::npos && str.find('\"') == std::string::npos && str.find('/') == std::string::npos && str.find(';') == std::string::npos) { @@ -582,24 +581,47 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { endl(); // clang-format on - // Generate vcpkg.json - using namespace nlohmann; - json j; - j["$cmkr"] = "This file is automatically generated from cmake.toml - DO NOT EDIT"; - j["$cmkr-url"] = cmkr_url; - j["$schema"] = "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json"; - j["name"] = vcpkg_escape_identifier(project.project_name); - j["version-string"] = project.project_version; - j["dependencies"] = project.vcpkg.packages; - if (!project.project_description.empty()) { - j["description"] = project.project_description; - } - + // Generate vcpkg.json (sorry for the ugly string handling, nlohmann compiles very slowly) std::ofstream ofs("vcpkg.json", std::ios::binary); if (!ofs) { throw std::runtime_error("Failed to create a vcpkg.json manifest file!"); } - ofs << std::setw(2) << j << std::endl; + ofs << R"({ + "$cmkr": "This file is automatically generated from cmake.toml - DO NOT EDIT", + "$cmkr-url": "https://github.com/build-cpp/cmkr", + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", + "dependencies": [ +)"; + + const auto &packages = project.vcpkg.packages; + for (size_t i = 0; i < packages.size(); i++) { + const auto &package = packages[i]; + if (!vcpkg_valid_identifier(package)) { + throw std::runtime_error("Invalid vcpkg package name '" + package + "'"); + } + ofs << " \"" << package << '\"'; + if (i + 1 < packages.size()) { + ofs << ','; + } + ofs << '\n'; + } + + auto escape = [](const std::string &str) { + std::string result; + for (auto ch : str) { + if (ch == '\\' || ch == '\"') { + result += '\\'; + } + result += ch; + } + return result; + }; + + ofs << " ],\n"; + ofs << " \"description\": \"" << escape(project.project_description) << "\",\n"; + ofs << " \"name\": \"" << escape(project.project_name) << "\",\n"; + ofs << R"( "version-string": "")" << '\n'; + ofs << "}\n"; } if (!project.packages.empty()) {