From 5d85cc83e346acfba9de85d2d136a8d830c75749 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Thu, 28 Nov 2024 13:44:11 +0100 Subject: [PATCH 1/3] Ignore generated vcpkg.json --- tests/.gitignore | 3 ++- tests/vcpkg/vcpkg.json | 11 ----------- 2 files changed, 2 insertions(+), 12 deletions(-) delete mode 100644 tests/vcpkg/vcpkg.json diff --git a/tests/.gitignore b/tests/.gitignore index 21f295a..f5b621f 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,3 +1,4 @@ # These will be generated by cmkr, so no point in tracking them **/CMakeLists.txt -**/cmkr.cmake \ No newline at end of file +**/cmkr.cmake +**/vcpkg.json \ No newline at end of file diff --git a/tests/vcpkg/vcpkg.json b/tests/vcpkg/vcpkg.json deleted file mode 100644 index 8c0008a..0000000 --- a/tests/vcpkg/vcpkg.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$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": [ - "fmt" - ], - "description": "Dependencies from vcpkg", - "name": "vcpkg", - "version-string": "" -} From 83559cc5d4cc9e5e363dd1d6d8487faeae88b6a1 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Thu, 28 Nov 2024 14:23:03 +0100 Subject: [PATCH 2/3] Improve target reference documentation --- docs/cmake-toml.md | 47 ++++++++++++++++++++++++++------ docs/examples/compile-options.md | 7 +++-- tests/compile-options/cmake.toml | 7 +++-- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/docs/cmake-toml.md b/docs/cmake-toml.md index ff242d1..b2339b8 100644 --- a/docs/cmake-toml.md +++ b/docs/cmake-toml.md @@ -218,28 +218,28 @@ Table keys that match CMake variable names (`[A-Z_]+`) will be passed to the [`F [target.mytarget] condition = "mycondition" alias = "mytarget::mytarget" -type = "static" # executable, shared (DLL), static, interface, object, library, custom +type = "static" # executable, library, shared (DLL), static, interface, object, custom headers = ["src/mytarget.h"] sources = ["src/mytarget.cpp"] msvc-runtime = "" # dynamic (implicit default), static # The keys below match the target_xxx CMake commands # Keys prefixed with private- will get PRIVATE visibility -compile-definitions = [""] +compile-definitions = [""] # preprocessor define (-DFOO) private-compile-definitions = [""] -compile-features = [""] +compile-features = [""] # C++ standard version (cxx_std_20) private-compile-features = [""] -compile-options = [""] +compile-options = [""] # compiler flags private-compile-options = [""] -include-directories = [""] +include-directories = [""] # include paths/directories private-include-directories = [""] -link-directories = [""] +link-directories = [""] # library directories private-link-directories = [""] -link-libraries = [""] +link-libraries = [""] # dependencies private-link-libraries = [""] -link-options = [""] +link-options = [""] # linker flags private-link-options = [""] -precompile-headers = [""] +precompile-headers = [""] # precompiled headers private-precompile-headers = [""] cmake-before = """ @@ -258,6 +258,35 @@ CXX_STANDARD_REQUIRED = true FOLDER = "MyFolder" ``` +A table mapping the cmkr features to the relevant CMake construct and the relevant documentation pages: + +| cmkr | CMake construct | Description | +| ---- | ----- | ----------- | +| `alias` | [Alias Libraries](https://cmake.org/cmake/help/latest/command/add_library.html#alias-libraries) | Create an [alias target](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#alias-targets), used for namespacing or clarity. | +| `sources` | [`target_sources`](https://cmake.org/cmake/help/latest/command/target_sources.html) | Source files (`PRIVATE` except `interface` targets). | +| `headers` | [`target_sources`](https://cmake.org/cmake/help/latest/command/target_sources.html) | For readability (and future packaging). | +| `msvc-runtime` | [`MSVC_RUNTIME_LIBRARY`](https://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html) | The [CMP0091](https://cmake.org/cmake/help/latest/policy/CMP0091.html) policy is set automatically. | +| `compile-definitions` | [`target_compile_definitions`](https://cmake.org/cmake/help/latest/command/target_compile_definitions.html) | Adds a macro definition (define, `-DMYMACRO=XXX`). | +| `compile-features` | [`target_compile_features`](https://cmake.org/cmake/help/latest/command/target_compile_features.html) | Specifies the C++ standard version (`cxx_std_20`). | +| `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-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. | + +The default [visibility](/basics) is as follows: + +| Type | Visibility | +| ------------ | ----------- | +| `executable` | `PRIVATE` | +| `library` | `PUBLIC` | +| `shared` | `PUBLIC` | +| `static` | `PUBLIC` | +| `object` | `PUBLIC` | +| `interface` | `INTERFACE` | + ## Templates To avoid repeating yourself you can create your own target type and use it in your targets: diff --git a/docs/examples/compile-options.md b/docs/examples/compile-options.md index f219622..4c650ca 100644 --- a/docs/examples/compile-options.md +++ b/docs/examples/compile-options.md @@ -9,7 +9,7 @@ nav_order: 9 # Compiler flags -Example project that sets compiler/linker flags for various platforms. +Example project that sets compiler flags and preprocessor defines for various platforms. ```toml [project] @@ -20,11 +20,14 @@ description = "Compiler flags" type = "executable" sources = ["src/main.cpp"] msvc.compile-options = ["/W2"] +msvc.compile-definitions = ["PLATFORM=\"msvc\""] gcc.compile-options = ["-Wall"] +gcc.compile-definitions = ["PLATFORM=\"gcc\""] clang.compile-options = ["-Wall"] +clang.compile-definitions = ["PLATFORM=\"clang\""] ``` -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. +The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags and definitions 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. diff --git a/tests/compile-options/cmake.toml b/tests/compile-options/cmake.toml index af59748..205a4da 100644 --- a/tests/compile-options/cmake.toml +++ b/tests/compile-options/cmake.toml @@ -1,4 +1,4 @@ -# Example project that sets compiler/linker flags for various platforms. +# Example project that sets compiler flags and preprocessor defines for various platforms. [project] name = "compile-options" @@ -8,8 +8,11 @@ description = "Compiler flags" type = "executable" sources = ["src/main.cpp"] msvc.compile-options = ["/W2"] +msvc.compile-definitions = ["PLATFORM=\"msvc\""] gcc.compile-options = ["-Wall"] +gcc.compile-definitions = ["PLATFORM=\"gcc\""] clang.compile-options = ["-Wall"] +clang.compile-definitions = ["PLATFORM=\"clang\""] -# 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. +# The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags and definitions 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. From 78bcf2acf7ee2a203c6a34f1fecaa2788b7d9d11 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Thu, 28 Nov 2024 14:23:36 +0100 Subject: [PATCH 3/3] Add support for `[vcpkg].overlay-triplets` --- docs/cmake-toml.md | 9 +++++---- docs/examples/vcpkg.md | 9 ++++----- include/project_parser.hpp | 3 +++ src/cmake_generator.cpp | 40 ++++++++++++++++---------------------- src/project_parser.cpp | 15 +++++++++++++- tests/vcpkg/cmake.toml | 9 ++++----- 6 files changed, 47 insertions(+), 38 deletions(-) diff --git a/docs/cmake-toml.md b/docs/cmake-toml.md index b2339b8..6e4f23b 100644 --- a/docs/cmake-toml.md +++ b/docs/cmake-toml.md @@ -160,17 +160,18 @@ Variables emit a [`set`](https://cmake.org/cmake/help/latest/command/set.html) a ```toml [vcpkg] -version = "2024.03.25" -url = "https://github.com/microsoft/vcpkg/archive/refs/tags/2024.03.25.tar.gz" +version = "2024.11.16" +url = "https://github.com/microsoft/vcpkg/archive/refs/tags/2024.11.16.tar.gz" packages = ["fmt", "zlib"] overlay-ports = ["my-ports"] +overlay-triplets = ["my-triplets"] ``` -The vcpkg `version` will automatically generate the `url` from the [official repository](https://github.com/microsoft/vcpkg/releases). For a custom registry you can specify your own `url` (and omit the `version`). You can browse available packages on [vcpkg.io](https://vcpkg.io/en/packages.html). +The vcpkg `version` will automatically generate the `url` from the [official repository](https://github.com/microsoft/vcpkg/releases). For a custom registry you can specify your own `url` (and omit the `version`). You can browse available packages on [vcpkg.io](https://vcpkg.io/en/packages.html) or [vcpkg.link](https://vcpkg.link). To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`. To disable the [default features](https://learn.microsoft.com/en-us/vcpkg/concepts/default-features) you can do: `cpp-httplib[core,openssl]` -The `overlay-ports` feature allows you to embed vcpkg ports inside your project, without having to fork the main vcpkg registry or creating a custom registry. You can find more information in the relevant [documentation](https://learn.microsoft.com/en-us/vcpkg/concepts/overlay-ports). +The `overlay-ports` feature allows you to embed vcpkg ports inside your project, without having to fork the main vcpkg registry or creating a custom registry. You can find more information in the relevant [documentation](https://learn.microsoft.com/en-us/vcpkg/concepts/overlay-ports). The `overlay-triplets` feature allows you to customize triplets and change the default behavior (for example always preferring static libraries on Windows). To specify both in one go you can do `[vcpkg].overlay = "my-overlay"`. ## Packages diff --git a/docs/examples/vcpkg.md b/docs/examples/vcpkg.md index 838d66d..6a1c403 100644 --- a/docs/examples/vcpkg.md +++ b/docs/examples/vcpkg.md @@ -9,7 +9,7 @@ nav_order: 4 # Dependencies from vcpkg -Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://vcpkg.io/) and links an `example` target to it: +Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://github.com/microsoft/vcpkg) and links an `example` target to it: ```toml [project] @@ -17,13 +17,12 @@ name = "vcpkg" description = "Dependencies from vcpkg" # See https://github.com/microsoft/vcpkg/releases for vcpkg versions -# See https://vcpkg.io/en/packages.html for available packages +# See https://vcpkg.io/en/packages or https://vcpkg.link for available packages [vcpkg] -version = "2024.03.25" +version = "2024.11.16" packages = ["fmt"] -[find-package] -fmt = {} +[find-package.fmt] [target.example] type = "executable" diff --git a/include/project_parser.hpp b/include/project_parser.hpp index 4de3870..5f37142 100644 --- a/include/project_parser.hpp +++ b/include/project_parser.hpp @@ -49,7 +49,10 @@ struct Vcpkg { }; std::vector packages; + + // https://github.com/Microsoft/vcpkg-docs/blob/main/vcpkg/users/buildsystems/cmake-integration.md std::vector overlay_ports; + std::vector overlay_triplets; bool enabled() const { return !packages.empty(); diff --git a/src/cmake_generator.cpp b/src/cmake_generator.cpp index 436985c..947d7b7 100644 --- a/src/cmake_generator.cpp +++ b/src/cmake_generator.cpp @@ -861,6 +861,22 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { endl(); } + if (project.vcpkg.enabled()) { + comment("vcpkg settings"); + auto emit_overlay = [&cmd](const std::string &name, const std::vector &overlay) { + if (!overlay.empty()) { + for (const auto &directory : overlay) { + if (!fs::is_directory(directory)) { + throw std::runtime_error("[vcpkg] overlay is not a directory: " + directory); + } + } + cmd("set")(name, overlay); + } + }; + emit_overlay("VCPKG_OVERLAY_PORTS", project.vcpkg.overlay_ports); + emit_overlay("VCPKG_OVERLAY_TRIPLETS", project.vcpkg.overlay_triplets); + } + gen.conditional_includes(project.include_before); gen.conditional_cmake(project.cmake_before); @@ -996,29 +1012,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) { ofs << " ],\n"; ofs << " \"description\": \"" << escape(project.project_description) << "\",\n"; ofs << " \"name\": \"" << escape(vcpkg_escape_identifier(project.project_name)) << "\",\n"; - ofs << " \"version-string\": \"none\""; - const auto &overlay_ports = project.vcpkg.overlay_ports; - if (!overlay_ports.empty()) { - ofs << ",\n"; - // Reference: https://learn.microsoft.com/en-us/vcpkg/reference/vcpkg-json#vcpkg-configuration - ofs << " \"vcpkg-configuration\": {\n"; - ofs << " \"overlay-ports\": [\n"; - for (size_t i = 0; i < overlay_ports.size(); i++) { - const auto &directory = overlay_ports[i]; - if (!fs::is_directory(directory)) { - throw std::runtime_error("[vcpkg].overlay-ports is not a directory: " + directory); - } - ofs << " \"" << escape(directory) << "\""; - if (i > 0) { - ofs << ","; - } - ofs << "\n"; - } - ofs << " ]\n"; - ofs << " }\n"; - } else { - ofs << "\n"; - } + ofs << " \"version-string\": \"none\"\n"; ofs << "}\n"; } diff --git a/src/project_parser.cpp b/src/project_parser.cpp index 38a1b04..ec793ee 100644 --- a/src/project_parser.cpp +++ b/src/project_parser.cpp @@ -860,7 +860,20 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p vcpkg.packages.emplace_back(std::move(package)); } - v.optional("overlay-ports", vcpkg.overlay_ports); + if (v.contains("overlay")) { + std::string overlay; + v.optional("overlay", overlay); + vcpkg.overlay_triplets = vcpkg.overlay_ports = {overlay}; + if (v.contains("overlay-ports")) { + throw_key_error("[vcpkg].overlay was already specified", "overlay-ports", v.find("overlay-ports")); + } + if (v.contains("overlay-triplets")) { + throw_key_error("[vcpkg].overlay was already specified", "overlay-triplets", v.find("overlay-triplets")); + } + } else { + v.optional("overlay-ports", vcpkg.overlay_ports); + v.optional("overlay-triplets", vcpkg.overlay_triplets); + } } checker.check(conditions, true); diff --git a/tests/vcpkg/cmake.toml b/tests/vcpkg/cmake.toml index 3e573d6..382b9b5 100644 --- a/tests/vcpkg/cmake.toml +++ b/tests/vcpkg/cmake.toml @@ -1,17 +1,16 @@ -# Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://vcpkg.io/) and links an `example` target to it: +# Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://github.com/microsoft/vcpkg) and links an `example` target to it: [project] name = "vcpkg" description = "Dependencies from vcpkg" # See https://github.com/microsoft/vcpkg/releases for vcpkg versions -# See https://vcpkg.io/en/packages.html for available packages +# See https://vcpkg.io/en/packages or https://vcpkg.link for available packages [vcpkg] -version = "2024.03.25" +version = "2024.11.16" packages = ["fmt"] -[find-package] -fmt = {} +[find-package.fmt] [target.example] type = "executable"