mirror of
https://github.com/microsoft/vcpkg.git
synced 2024-11-24 01:59:00 +08:00
[vcpkg manifest] Add documentation! (#13488)
* [vcpkg docs] add docs for manifest files These are just for the maintainer docs, not user docs. * [vcpkg] EBNF-ify platform expression parsing this modifies nothing about what strings are accepted or rejected, it just moves stuff around. also adds tests. * [vcpkg docs] add manifest mode example * [wip] docs for augustin also fix tabs * [vcpkg manifest] switch to using maps for features * Apply suggestions from code review * un-experimentize format-manifest * flesh out the user manifest mode docs * CRs * billy CRs * final personal pass-thru
This commit is contained in:
parent
76362dd2b2
commit
0fec1340eb
51
README.md
51
README.md
@ -274,56 +274,6 @@ This will still allow people to not use vcpkg,
|
||||
by passing the `CMAKE_TOOLCHAIN_FILE` directly,
|
||||
but it will make the configure-build step slightly easier.
|
||||
|
||||
## Quick Start: Manifests
|
||||
|
||||
So, you want to look at what the future of vcpkg is going to be like!
|
||||
We really appreciate it 😄. First, though, a warning:
|
||||
manifest support in vcpkg is still in beta! Mostly, it should just work,
|
||||
but there are no guarantees and it's likely you'll hit at least a bug or two
|
||||
while you're using vcpkg in this mode. Additionally,
|
||||
we will likely break behavior before stabilizing, so be forewarned.
|
||||
Please [open issues][contributing:submit-issue] if you hit any bugs!
|
||||
|
||||
First, install vcpkg as normal for [Windows](#quick-start-windows) or
|
||||
[Unix](#quick-start-unix).
|
||||
You may wish to install vcpkg in a central place,
|
||||
as the installed directory exists locally,
|
||||
and it's fine to run multiple vcpkg commands from the same
|
||||
vcpkg directory at the same time.
|
||||
|
||||
Then, we must turn on the `manifests` vcpkg feature flag by adding
|
||||
`manifests` to the comma-separated `--feature-flags` option,
|
||||
or by adding it to the comma-separated `VCPKG_FEATURE_FLAGS`
|
||||
environment variable.
|
||||
|
||||
You may also want to add vcpkg to the `PATH`.
|
||||
|
||||
Then, all one has to do is create a manifest;
|
||||
create a file called `vcpkg.json`, and type the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "<name of your project>",
|
||||
"version-string": "<version of your project>",
|
||||
"dependencies": [
|
||||
"abseil",
|
||||
"boost"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The libraries will be installed into the `vcpkg_installed`
|
||||
directory, in the same directory as your `vcpkg.json`.
|
||||
If you can use the regular CMake toolchain,
|
||||
or the Visual Studio/MSBuild integration,
|
||||
it will install the dependencies automatically,
|
||||
although you will need to set `VcpkgManifestEnabled` to `On` for MSBuild.
|
||||
If you wish to install your dependencies without using either CMake or MSBuild,
|
||||
you may use a simple `vcpkg install --feature-flags=manifests`
|
||||
|
||||
For more information, check out the [manifest][getting-started:manifest-spec]
|
||||
specification.
|
||||
|
||||
[getting-started:using-a-package]: docs/examples/installing-and-using-packages.md
|
||||
[getting-started:integration]: docs/users/integration.md
|
||||
[getting-started:git]: https://git-scm.com/downloads
|
||||
@ -333,7 +283,6 @@ specification.
|
||||
[getting-started:macos-brew]: #installing-gcc-on-macos
|
||||
[getting-started:macos-gcc]: #installing-gcc-on-macos
|
||||
[getting-started:visual-studio]: https://visualstudio.microsoft.com/
|
||||
[getting-started:manifest-spec]: docs/specifications/manifests.md
|
||||
|
||||
# Tab-Completion/Auto-Completion
|
||||
|
||||
|
199
docs/examples/manifest-mode-cmake.md
Normal file
199
docs/examples/manifest-mode-cmake.md
Normal file
@ -0,0 +1,199 @@
|
||||
# Manifest Mode: CMake Example
|
||||
|
||||
We would like to add vcpkg manifest support to an existing cmake project!
|
||||
Let's create a simple project that prints the fibonacci sequence up to a certain number,
|
||||
using some common dependencies.
|
||||
|
||||
## Initial Layout
|
||||
|
||||
Let's create the following file layout:
|
||||
|
||||
```no-highlight
|
||||
fibo/
|
||||
src/
|
||||
main.cxx
|
||||
CMakeLists.txt
|
||||
```
|
||||
|
||||
And we wish to use [fmt](https://github.com/fmtlib/fmt), [range-v3](https://github.com/ericniebler/range-v3),
|
||||
and [cxxopts](https://github.com/jarro2783/cxxopts).
|
||||
|
||||
Let's write our `CMakeLists.txt` first:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(fibo CXX)
|
||||
|
||||
find_package(fmt REQUIRED)
|
||||
find_package(range-v3 REQUIRED)
|
||||
find_package(cxxopts REQUIRED)
|
||||
|
||||
add_executable(fibo src/main.cxx)
|
||||
|
||||
target_link_libraries(fibo
|
||||
PRIVATE
|
||||
fmt::fmt
|
||||
range-v3::range-v3
|
||||
cxxopts::cxxopts)
|
||||
```
|
||||
|
||||
And then we should add `main.cxx`:
|
||||
|
||||
```cxx
|
||||
#include <cxxopts.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <range/v3/view.hpp>
|
||||
|
||||
namespace view = ranges::view;
|
||||
|
||||
int fib(int x) {
|
||||
int a = 0, b = 1;
|
||||
|
||||
for (int it : view::repeat(0) | view::take(x)) {
|
||||
(void)it;
|
||||
int tmp = a;
|
||||
a += b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
cxxopts::Options options("fibo", "Print the fibonacci sequence up to a value 'n'");
|
||||
options.add_options()
|
||||
("n,value", "The value to print to", cxxopts::value<int>()->default_value("10"));
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
auto n = result["value"].as<int>();
|
||||
|
||||
for (int x : view::iota(1) | view::take(n)) {
|
||||
fmt::print("fib({}) = {}\n", x, fib(x));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is a simple project of course, but it should give us a clean project to start with.
|
||||
Let's try it out!
|
||||
|
||||
Let's assume you have `fmt`, `range-v3`, and `cxxopts` installed with vcpkg classic mode;
|
||||
then, you can just do a simple:
|
||||
|
||||
```cmd
|
||||
D:\src\fibo> cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=D:\src\vcpkg\scripts\buildsystems\vcpkg.cmake
|
||||
-- Building for: Visual Studio 16 2019
|
||||
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19041.
|
||||
-- The CXX compiler identification is MSVC 19.27.29111.0
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/bin/Hostx64/x64/cl.exe - skipped
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: D:/src/fibo/build
|
||||
D:\src\fibo> cmake --build build
|
||||
Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET Framework
|
||||
Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Checking Build System
|
||||
Building Custom Rule D:/src/fibo/CMakeLists.txt
|
||||
main.cxx
|
||||
The contents of <span> are available only with C++20 or later.
|
||||
fibo.vcxproj -> D:\src\fibo\build\Debug\fibo.exe
|
||||
Building Custom Rule D:/src/fibo/CMakeLists.txt
|
||||
```
|
||||
|
||||
And now we can try out the `fibo` binary!
|
||||
|
||||
```cmd
|
||||
D:\src\fibo> .\build\Debug\fibo.exe -n 7
|
||||
fib(1) = 1
|
||||
fib(2) = 1
|
||||
fib(3) = 2
|
||||
fib(4) = 3
|
||||
fib(5) = 5
|
||||
fib(6) = 8
|
||||
fib(7) = 13
|
||||
```
|
||||
|
||||
it works!
|
||||
|
||||
## Converting to Manifest Mode
|
||||
|
||||
We now wish to use manifest mode, so all of our dependencies are managed for us! Let's write a `vcpkg.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "fibo",
|
||||
"version-string": "0.1.0",
|
||||
"dependencies": [
|
||||
"cxxopts",
|
||||
"fmt",
|
||||
"range-v3"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Let's delete the build directory and rerun the build:
|
||||
|
||||
```cmd
|
||||
D:\src\fibo> rmdir /S /Q build
|
||||
D:\src\fibo> cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=D:\src\vcpkg\scripts\buildsystems\vcpkg.cmake
|
||||
-- Running vcpkg install
|
||||
Detecting compiler hash for triplet x64-windows...
|
||||
The following packages will be built and installed:
|
||||
cxxopts[core]:x64-windows
|
||||
fmt[core]:x64-windows
|
||||
range-v3[core]:x64-windows
|
||||
Starting package 1/3: cxxopts:x64-windows
|
||||
Building package cxxopts[core]:x64-windows...
|
||||
Using cached binary package: C:\Users\me\AppData\Local\vcpkg/archives\d2\d2d1e5302cdfefef2fd090d8eda84cc0c1fbe6f1.zip
|
||||
Building package cxxopts[core]:x64-windows... done
|
||||
Installing package cxxopts[core]:x64-windows...
|
||||
Installing package cxxopts[core]:x64-windows... done
|
||||
Elapsed time for package cxxopts:x64-windows: 50.64 ms
|
||||
Starting package 2/3: fmt:x64-windows
|
||||
Building package fmt[core]:x64-windows...
|
||||
Using cached binary package: C:\Users\me\AppData\Local\vcpkg/archives\bf\bf00d5214e912d71414b545b241f54ef87fdf6e5.zip
|
||||
Building package fmt[core]:x64-windows... done
|
||||
Installing package fmt[core]:x64-windows...
|
||||
Installing package fmt[core]:x64-windows... done
|
||||
Elapsed time for package fmt:x64-windows: 225 ms
|
||||
Starting package 3/3: range-v3:x64-windows
|
||||
Building package range-v3[core]:x64-windows...
|
||||
Using cached binary package: C:\Users\me\AppData\Local\vcpkg/archives\fe\fe2cdedef6953bf954e8ddca471bf3cc8d9b06d7.zip
|
||||
Building package range-v3[core]:x64-windows... done
|
||||
Installing package range-v3[core]:x64-windows...
|
||||
Installing package range-v3[core]:x64-windows... done
|
||||
Elapsed time for package range-v3:x64-windows: 1.466 s
|
||||
|
||||
Total elapsed time: 1.742 s
|
||||
|
||||
-- Running vcpkg install - done
|
||||
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19041.
|
||||
-- The CXX compiler identification is MSVC 19.27.29111.0
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/bin/Hostx64/x64/cl.exe - skipped
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: D:/src/fibo/build
|
||||
D:\src\fibo> cmake --build build
|
||||
Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET Framework
|
||||
Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Checking Build System
|
||||
Building Custom Rule D:/src/fibo/CMakeLists.txt
|
||||
main.cxx
|
||||
The contents of <span> are available only with C++20 or later.
|
||||
fibo.vcxproj -> D:\src\fibo\build\Debug\fibo.exe
|
||||
Building Custom Rule D:/src/fibo/CMakeLists.txt
|
||||
```
|
||||
|
||||
You can see that with just a _single file_, we've changed over to manifests without _any_ trouble.
|
||||
The build system doesn't change _at all_! We just add a `vcpkg.json` file, delete the build directory,
|
||||
and reconfigure. And we're done!
|
@ -1,18 +1,23 @@
|
||||
## Packaging Github Repos Example: libogg
|
||||
### Create the CONTROL file
|
||||
The `CONTROL` file is a simple set of fields describing the package's metadata.
|
||||
### Create the manifest file
|
||||
The manifest file (called `vcpkg.json`) is a json file describing the package's metadata.
|
||||
|
||||
*For libogg, we'll create the file `ports\libogg\CONTROL` with the following contents:*
|
||||
```no-highlight
|
||||
Source: libogg
|
||||
Version: 1.3.3
|
||||
Description: Ogg is a multimedia container format, and the native file and stream format for the Xiph.org multimedia codecs.
|
||||
For libogg, we'll create the file `ports/libogg/vcpkg.json` with the following content:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "libogg",
|
||||
"version-string": "1.3.3",
|
||||
"description": "Ogg is a multimedia container format, and the native file and stream format for the Xiph.org multimedia codecs."
|
||||
}
|
||||
```
|
||||
|
||||
You can format the manifest file to our specifications with `vcpkg format-manifest ports/libogg/vcpkg.json`.
|
||||
|
||||
### Create the portfile
|
||||
`portfile.cmake` describes how to build and install the package. First we download the project from Github with [`vcpkg_from_github`](../maintainers/vcpkg_from_github.md):
|
||||
|
||||
```no-highlight
|
||||
```cmake
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO xiph/ogg
|
||||
@ -26,7 +31,7 @@ The important parts to update are `REPO` for the GitHub repository path, `REF` f
|
||||
|
||||
Finally, we configure the project with CMake, install the package, and copy over the license file:
|
||||
|
||||
```no-highlight
|
||||
```cmake
|
||||
vcpkg_configure_cmake(
|
||||
SOURCE_PATH ${SOURCE_PATH}
|
||||
PREFER_NINJA
|
||||
@ -40,14 +45,14 @@ Check the documentation for [`vcpkg_configure_cmake`](../maintainers/vcpkg_confi
|
||||
Now you can run `vcpkg install libogg` to build and install the package.
|
||||
|
||||
### Suggested example portfiles
|
||||
In the `ports\` directory are many libraries that can be used as examples, including many that are not based on CMake.
|
||||
In the `ports/` directory are many libraries that can be used as examples, including many that are not based on CMake.
|
||||
|
||||
- Header only libraries
|
||||
- rapidjson
|
||||
- range-v3
|
||||
- rapidjson
|
||||
- range-v3
|
||||
- MSBuild-based
|
||||
- cppunit
|
||||
- mpg123
|
||||
- cppunit
|
||||
- mpg123
|
||||
- Non-CMake, custom buildsystem
|
||||
- openssl
|
||||
- ffmpeg
|
||||
- openssl
|
||||
- ffmpeg
|
||||
|
@ -13,21 +13,23 @@ Finally, if the server's name for the archive is not very descriptive (such as d
|
||||
|
||||
*`zlib1211.zip` is a fine name, so no change needed.*
|
||||
|
||||
All this information can then be passed into the `create` command, which will download the sources and bootstrap the packaging process inside `ports\<packagename>`.
|
||||
All this information can then be passed into the `create` command, which will download the sources and bootstrap the packaging process inside `ports/<packagename>`.
|
||||
|
||||
```no-highlight
|
||||
PS D:\src\vcpkg> .\vcpkg create zlib2 http://zlib.net/zlib-1.2.11.tar.gz zlib1211.tar.gz
|
||||
-- Generated portfile: D:/src/vcpkg/ports/zlib2/portfile.cmake
|
||||
```
|
||||
|
||||
### Create the CONTROL file
|
||||
In addition to the generated `ports\<package>\portfile.cmake`, we also need a `ports\<package>\CONTROL` file. This file is a simple set of fields describing the package's metadata.
|
||||
### Create the manifest file
|
||||
In addition to the generated `ports/<package>/portfile.cmake`, we also need a `ports/<package>/vcpkg.json` file. This file is a simple set of fields describing the package's metadata.
|
||||
|
||||
*For zlib2, we'll create the file `ports\zlib2\CONTROL` with the following contents:*
|
||||
```no-highlight
|
||||
Source: zlib2
|
||||
Version: 1.2.11
|
||||
Description: A Massively Spiffy Yet Delicately Unobtrusive Compression Library
|
||||
*For zlib2, we'll create the file `ports/zlib2/vcpkg.json` with the following contents:*
|
||||
```json
|
||||
{
|
||||
"name": "zlib2",
|
||||
"version-string": "1.2.11",
|
||||
"description": "A Massively Spiffy Yet Delicately Unobtrusive Compression Library"
|
||||
}
|
||||
```
|
||||
|
||||
### Tweak the generated portfile
|
||||
@ -62,7 +64,7 @@ Found 3 error(s). Please correct the portfile:
|
||||
At this point, it is a matter of reading the error messages and log files while steadily improving the quality of the portfile. Zlib required providing a discrete copy of the LICENSE to copy into the package, suppressing the build and installation of executables and headers, and removing the static libraries after they were installed.
|
||||
|
||||
### Suggested example portfiles
|
||||
In the `ports\` directory are many libraries that can be used as examples, including many that are not based on CMake.
|
||||
In the `ports/` directory are many libraries that can be used as examples, including many that are not based on CMake.
|
||||
|
||||
- Header only libraries
|
||||
- rapidjson
|
||||
|
@ -163,9 +163,9 @@ To be completely sure this works from scratch, we need to remove the package and
|
||||
PS D:\src\vcpkg> vcpkg remove libpng:x64-uwp
|
||||
Package libpng:x64-uwp was successfully removed
|
||||
```
|
||||
and complete delete the building directory: D:\src\vcpkg\buildtrees\libpng
|
||||
|
||||
Now we try a fresh, from scratch install.
|
||||
|
||||
```no-highlight
|
||||
PS D:\src\vcpkg> vcpkg install libpng:x64-uwp
|
||||
Computing installation plan...
|
||||
@ -173,36 +173,48 @@ The following packages will be built and installed:
|
||||
libpng[core]:x64-uwp
|
||||
Starting package 1/1: libpng:x64-uwp
|
||||
Building package libpng[core]:x64-uwp...
|
||||
-- Using cached C:/src/vcpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
|
||||
-- Cleaning sources at C:/src/vcpkg/buildtrees/libpng/src/v1.6.37-c993153cdf.clean. Pass --editable to vcpkg to reuse sources.
|
||||
-- Extracting source C:/src/vcpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
|
||||
-- Applying patch use-abort-on-all-platforms.patch
|
||||
-- Using source at C:/src/vcpkg/buildtrees/libpng/src/v1.6.37-c993153cdf.clean
|
||||
Could not locate cached archive: C:\Users\me\AppData\Local\vcpkg/archives\f4\f44b54f818f78b9a4ccd34b3666f566f94286850.zip
|
||||
-- Using cached D:/src/vcpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
|
||||
-- Extracting source D:/src/vcpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
|
||||
-- Applying patch use_abort.patch
|
||||
-- Applying patch cmake.patch
|
||||
-- Applying patch pkgconfig.patch
|
||||
-- Applying patch pkgconfig.2.patch
|
||||
-- Using source at D:/src/vcpkg/buildtrees/libpng/src/v1.6.37-10db9f58e4.clean
|
||||
-- Configuring x64-uwp
|
||||
-- Building x64-uwp-dbg
|
||||
-- Building x64-uwp-rel
|
||||
-- Installing: C:/src/vcpkg/packages/libpng_x64-uwp/share/libpng/copyright
|
||||
-- Fixing pkgconfig file: D:/src/vcpkg/packages/libpng_x64-uwp/lib/pkgconfig/libpng.pc
|
||||
-- Fixing pkgconfig file: D:/src/vcpkg/packages/libpng_x64-uwp/lib/pkgconfig/libpng16.pc
|
||||
-- Fixing pkgconfig file: D:/src/vcpkg/packages/libpng_x64-uwp/debug/lib/pkgconfig/libpng.pc
|
||||
-- Fixing pkgconfig file: D:/src/vcpkg/packages/libpng_x64-uwp/debug/lib/pkgconfig/libpng16.pc
|
||||
-- Installing: D:/src/vcpkg/packages/libpng_x64-uwp/share/libpng/copyright
|
||||
-- Performing post-build validation
|
||||
-- Performing post-build validation done
|
||||
Stored binary cache: C:\Users\me\AppData\Local\vcpkg/archives\f4\f44b54f818f78b9a4ccd34b3666f566f94286850.zip
|
||||
Building package libpng[core]:x64-uwp... done
|
||||
Installing package libpng[core]:x64-uwp...
|
||||
Installing package libpng[core]:x64-uwp... done
|
||||
Elapsed time for package libpng:x64-uwp: 15.31 s
|
||||
Elapsed time for package libpng:x64-uwp: 11.94 s
|
||||
|
||||
Total elapsed time: 15.35 s
|
||||
Total elapsed time: 11.95 s
|
||||
|
||||
The package libpng:x64-uwp provides CMake targets:
|
||||
|
||||
find_package(libpng CONFIG REQUIRED)
|
||||
target_link_libraries(main PRIVATE png)
|
||||
|
||||
```
|
||||
|
||||
Finally, to fully commit and publish the changes, we need to bump the internal release number and add the patch file to source control, then make a Pull Request!
|
||||
Finally, to fully commit and publish the changes, we need to bump the port version in `vcpkg.json`,
|
||||
and add the patch file to source control, then make a Pull Request!
|
||||
|
||||
```no-highlight
|
||||
# ports\libpng\CONTROL
|
||||
Source: libpng
|
||||
Version: 1.6.37-1
|
||||
Build-Depends: zlib
|
||||
```json
|
||||
{
|
||||
"name": "libpng",
|
||||
"version": "1.6.37",
|
||||
"port-version": 1,
|
||||
"dependencies": [
|
||||
"zlib"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
@ -15,10 +15,12 @@ Vcpkg helps you manage C and C++ libraries on Windows, Linux and MacOS. This too
|
||||
- [Triplet files](users/triplets.md)
|
||||
- [Configuration and Environment](users/config-environment.md)
|
||||
- [Usage with Android](users/android.md)
|
||||
- [Using a manifest file to declare your dependencies](users/top-level-manifest.md)
|
||||
|
||||
### Maintainer help
|
||||
|
||||
- [Control files](maintainers/control-files.md)
|
||||
- [Control files](maintainers/control-files.md) - in general, one should use manifest files instead
|
||||
- [Manifest files](maintainers/manifest-files.md)
|
||||
- [Portfile functions](maintainers/portfile-functions.md)
|
||||
- [Maintainer Guidelines](maintainers/maintainer-guide.md)
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
# CONTROL files
|
||||
|
||||
CONTROL files are retained for backwards compatibility with earlier versions of vcpkg;
|
||||
all new features are added only to vcpkg.json, and we recommend using vcpkg.json for any newly authored port.
|
||||
|
||||
The `CONTROL` file contains metadata about the port. The syntax is based on [the Debian `control` format][debian] although we only support the subset of fields documented here.
|
||||
|
||||
Field names are case-sensitive and start the line without leading whitespace. Paragraphs are separated by one or more empty lines.
|
||||
|
@ -128,25 +128,32 @@ A lib is considered conflicting if it does any of the following:
|
||||
|
||||
Conflicting libs are typically by design and not considered a defect. Because some build systems link against everything in the lib directory, these should be moved into a subdirectory named `manual-link`.
|
||||
|
||||
## Manifests and CONTROL files
|
||||
|
||||
When adding a new port, use the new manifest syntax for defining a port;
|
||||
you may also change over to manifests when modifying an existing port.
|
||||
You may do so easily by running the `vcpkg format-manifest` command, which will convert existing CONTROL
|
||||
files into manifest files. Do not convert CONTROL files that have not been modified.
|
||||
|
||||
## Versioning
|
||||
|
||||
### Follow common conventions for the `Version:` field
|
||||
### Follow common conventions for the `"version"` field
|
||||
|
||||
See our [CONTROL files document](control-files.md#version) for a full explanation of our conventions.
|
||||
See our [manifest files document](manifest-files.md#version-fields) for a full explanation of our conventions.
|
||||
|
||||
### Update the `Version:` field in the `CONTROL` file of any modified ports
|
||||
### Update the `"port-version"` field in the manifest file of any modified ports
|
||||
|
||||
Vcpkg uses this field to determine whether a given port is out-of-date and should be changed whenever the port's behavior changes.
|
||||
|
||||
Our convention for this field is to append a `-N` to the upstream version when changes need to be made.
|
||||
Our convention is to use the `"port-version"` field for changes to the port that don't change the upstream version, and to reset the `"port-version"` back to zero when an update to the upstream version is made.
|
||||
|
||||
For Example:
|
||||
|
||||
- Zlib's package version is currently `1.2.1`.
|
||||
- Zlib's package version is currently `1.2.1`, with no explicit `"port-version"` (equivalent to a `"port-version"` of `0`).
|
||||
- You've discovered that the wrong copyright file has been deployed, and fixed that in the portfile.
|
||||
- You should update the `Version:` field in the control file to `1.2.1-1`.
|
||||
- You should update the `"port-version"` field in the manifest file to `1`.
|
||||
|
||||
See our [CONTROL files document](control-files.md#version) for a full explanation of our conventions.
|
||||
See our [manifest files document](manifest-files.md#port-version) for a full explanation of our conventions.
|
||||
|
||||
## Patching
|
||||
|
||||
@ -212,7 +219,7 @@ Finally, DLL files on Windows should never be renamed post-build because it brea
|
||||
|
||||
### Vcpkg internal code
|
||||
|
||||
We require the c/c++ code inside vcpkg to follow the clang-format, if you change them. Please perform the following steps after modification:
|
||||
We require the C++ code inside vcpkg to follow the clang-format, if you change them. Please perform the following steps after modification:
|
||||
|
||||
- Use Visual Studio:
|
||||
1. Configure your [clang-format tools](https://devblogs.microsoft.com/cppblog/clangformat-support-in-visual-studio-2017-15-7-preview-1/).
|
||||
@ -226,15 +233,13 @@ We require the c/c++ code inside vcpkg to follow the clang-format, if you change
|
||||
> LLVM_PATH/bin/clang-format.exe -style=file -i changed_file.cpp
|
||||
```
|
||||
|
||||
### Manifest
|
||||
### Manifests
|
||||
|
||||
We require that the manifest file needs to be formatted, perform the following steps to solve this issue:
|
||||
We require that the manifest file be formatted. Use the following command to format all manifest files:
|
||||
|
||||
1. Format all changed manifest files.
|
||||
```cmd
|
||||
> vcpkg x-format-manifest --all
|
||||
> vcpkg format-manifest --all
|
||||
```
|
||||
2. Commit changes to your branch.
|
||||
|
||||
## Useful implementation notes
|
||||
|
||||
|
420
docs/maintainers/manifest-files.md
Normal file
420
docs/maintainers/manifest-files.md
Normal file
@ -0,0 +1,420 @@
|
||||
# Manifest files - `vcpkg.json`
|
||||
|
||||
The `vcpkg.json` file contains metadata about the port.
|
||||
It's a JSON file, and replaces the existing CONTROL file metadata structure.
|
||||
It must have a top level object, and all fields are case sensitive.
|
||||
|
||||
## Examples:
|
||||
|
||||
The most important fields in a manifest, the ones which are required for all ports,
|
||||
are the `"name"` field, and a version field (for now, just `"version-string"`).
|
||||
There's more information about these fields below.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "ace",
|
||||
"version-string": "6.5.5"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "vtk",
|
||||
"version-string": "8.2.0",
|
||||
"port-version": 2,
|
||||
"description": "Software system for 3D computer graphics, image processing, and visualization",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "atlmfc",
|
||||
"platform": "windows"
|
||||
},
|
||||
"double-conversion",
|
||||
"eigen3",
|
||||
"expat",
|
||||
"freetype",
|
||||
"glew",
|
||||
"hdf5",
|
||||
"jsoncpp",
|
||||
"libharu",
|
||||
"libjpeg-turbo",
|
||||
"libpng",
|
||||
"libtheora",
|
||||
"libxml2",
|
||||
"lz4",
|
||||
"netcdf-c",
|
||||
"proj4",
|
||||
"pugixml",
|
||||
"sqlite3",
|
||||
"tiff",
|
||||
"zlib"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
### `"name"`
|
||||
The name of the port.
|
||||
|
||||
When adding new ports be aware that the name may conflict with other projects that are not a part of vcpkg. For example `json` conflicts with too many other projects so you should add a scope to the name such as `taocpp-json` to make it unique. Verify there are no conflicts on a search engine as well as on other package collections.
|
||||
|
||||
Package collections to check for conflicts:
|
||||
|
||||
+ [Repology](https://repology.org/projects/)
|
||||
+ [Debian packages](https://www.debian.org/distrib/packages)
|
||||
+ [Packages search](https://pkgs.org/)
|
||||
|
||||
A name must be an identifier: i.e., it must only consist of lowercase ascii alphabetic characters,
|
||||
numbers, and hyphens, and it must not begin nor end with a hyphen.
|
||||
|
||||
### Version fields
|
||||
|
||||
The library version. There is currently only one kind of version, a `"version-string"` -
|
||||
however, more version kinds will be added later. Additionally,
|
||||
`"port-version"` is used to differentiate between port changes that don't change the underlying library version.
|
||||
|
||||
#### `"version-string"`
|
||||
|
||||
This field is an ascii string, and may contain alphanumeric characters, `.`, `_`, or `-`. No attempt at ordering versions is made; all versions are treated as byte strings and are only evaluated for equality.
|
||||
|
||||
For tagged-release ports, we follow the following convention:
|
||||
|
||||
1. If the library follows a scheme like `va.b.c`, we remove the leading `v`. In this case, it becomes `a.b.c`.
|
||||
2. If the library includes its own name in the version like `curl-7_65_1`, we remove the leading name: `7_65_1`
|
||||
3. If the library is versioned by dates, format the resulting version string just like the upstream library;
|
||||
for example, Abseil formats their dates `lts_2020_02_25`, so the `"version-string"` should be `"lts_2020_02_25"`.
|
||||
|
||||
For rolling-release ports, we use the date that the _commit was accessed by you_, formatted as `YYYY-MM-DD`. Stated another way: if someone had a time machine and went to that date, they would see this commit as the latest master.
|
||||
|
||||
For example, given:
|
||||
1. The latest commit was made on 2019-04-19
|
||||
2. The current version string is `2019-02-14`
|
||||
3. Today's date is 2019-06-01.
|
||||
|
||||
Then if you update the source version today, you should give it version `2019-06-01`.
|
||||
|
||||
#### `"port-version"`
|
||||
|
||||
The version of the port, aside from the library version.
|
||||
|
||||
This field is a non-negative integer.
|
||||
It allows one to version the port file separately from the version of the underlying library;
|
||||
if you make a change to a port, without changing the underlying version of the library,
|
||||
you should increment this field by one (starting at `0`, which is equivalent to no `"port-version"` field).
|
||||
When the version of the underlying library is upgraded,
|
||||
this field should be set back to `0` (i.e., delete the `"port-version"` field).
|
||||
|
||||
#### Examples:
|
||||
```json
|
||||
{
|
||||
"version": "1.0.5",
|
||||
"port-version": 2
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "2019-03-21"
|
||||
}
|
||||
```
|
||||
|
||||
### `"description"`
|
||||
|
||||
A description of the library.
|
||||
|
||||
This field can either be a single string, which should be a summary of the library,
|
||||
or can be an array, with the first line being a summary and the remaining lines being the detailed description -
|
||||
one string per line.
|
||||
|
||||
#### Examples:
|
||||
```json
|
||||
{
|
||||
"description": "C++ header-only JSON library"
|
||||
}
|
||||
```
|
||||
```json
|
||||
{
|
||||
"description": [
|
||||
"Mosquitto is an open source message broker that implements the MQ Telemetry Transport protocol versions 3.1 and 3.1.1.",
|
||||
"MQTT provides a lightweight method of carrying out messaging using a publish/subscribe model."
|
||||
"This makes it suitable for 'machine to machine' messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers like the Arduino."
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `"homepage"`
|
||||
|
||||
The URL of the homepage for the library where a user is able to find additional documentation or the original source code.
|
||||
|
||||
### `"documentation"`
|
||||
|
||||
The URL where a user would be able to find official documentation for the library. Optional.
|
||||
|
||||
### `"maintainers"`
|
||||
|
||||
A list of strings that define the set of maintainers of a package.
|
||||
It's recommended that these take the form of `Givenname Surname <email>`,
|
||||
but this field is not checked for consistency.
|
||||
|
||||
Optional.
|
||||
|
||||
#### Example:
|
||||
```json
|
||||
{
|
||||
"homepage": "https://github.com/microsoft/vcpkg"
|
||||
}
|
||||
```
|
||||
|
||||
### `"dependencies"`
|
||||
|
||||
An array of ports the library has a dependency on.
|
||||
|
||||
vcpkg does not distinguish between build-only dependencies and runtime dependencies.
|
||||
The complete list of dependencies needed to successfully use the library should be specified.
|
||||
|
||||
For example: websocketpp is a header only library, and thus does not require any dependencies at install time.
|
||||
However, downstream users need boost and openssl to make use of the library.
|
||||
Therefore, websocketpp lists boost and openssl as dependencies.
|
||||
|
||||
Each dependency may be either an identifier, or an object.
|
||||
For many dependencies, just listing the name of the library should be fine;
|
||||
however, if one needs to add extra information to that dependency, one may use the dependency object.
|
||||
For a dependency object, the `"name"` field is used to designate the library;
|
||||
for example the dependency object `{ "name": "zlib" }` is equivalent to just writing `"zlib"`.
|
||||
|
||||
If the port is dependent on optional features of another library,
|
||||
those can be specified using the `"features"` field of the dependency object.
|
||||
If the port does not require any features from the dependency,
|
||||
this should be specifed with the `"default-features"` fields set to `false`.
|
||||
|
||||
Dependencies can also be filtered based on the target triplet to support differing requirements.
|
||||
These filters use the same syntax as the `"supports"` field below,
|
||||
and are specified in the `"platform"` field.
|
||||
|
||||
#### Example:
|
||||
```json
|
||||
{
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "curl",
|
||||
"default-features": false,
|
||||
"features": [
|
||||
"winssl"
|
||||
],
|
||||
"platform": "windows"
|
||||
},
|
||||
{
|
||||
"name": "curl",
|
||||
"default-features": false,
|
||||
"features": [
|
||||
"openssl"
|
||||
],
|
||||
"platform": "!windows"
|
||||
},
|
||||
"rapidjson"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `"features"`
|
||||
|
||||
Multiple optional features can be specified in manifest files, in the `"features"` object field.
|
||||
This field is a map from the feature name, to the feature's information.
|
||||
Each one must have a `"description"` field, and may also optionally have a `"dependencies"` field.
|
||||
|
||||
A feature's name must be an identifier -
|
||||
in other words, lowercase alphabetic characters, digits, and hyphens,
|
||||
neither starting nor ending with a hyphen.
|
||||
|
||||
A feature's `"description"` is a description of the feature,
|
||||
and is the same kind of thing as the port `"description"` field.
|
||||
|
||||
A feature's `"dependencies"` field contains the list of extra dependencies required to build and use this feature;
|
||||
this field isn't required if the feature doesn't require any extra dependencies.
|
||||
On installation the dependencies from all selected features are combined to produce the full dependency list for the build.
|
||||
|
||||
#### Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "vtk",
|
||||
"version-string": "8.2.0",
|
||||
"port-version": 2,
|
||||
"description": "Software system for 3D computer graphics, image processing, and visualization",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "atlmfc",
|
||||
"platform": "windows"
|
||||
},
|
||||
"double-conversion",
|
||||
"eigen3",
|
||||
"expat",
|
||||
"freetype",
|
||||
"glew",
|
||||
"hdf5",
|
||||
"jsoncpp",
|
||||
"libharu",
|
||||
"libjpeg-turbo",
|
||||
"libpng",
|
||||
"libtheora",
|
||||
"libxml2",
|
||||
"lz4",
|
||||
"netcdf-c",
|
||||
"proj4",
|
||||
"pugixml",
|
||||
"sqlite3",
|
||||
"tiff",
|
||||
"zlib"
|
||||
],
|
||||
"features": {
|
||||
"mpi": {
|
||||
"description": "MPI functionality for VTK",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "hdf5",
|
||||
"features": [
|
||||
"parallel"
|
||||
]
|
||||
},
|
||||
"mpi"
|
||||
]
|
||||
},
|
||||
"openvr": {
|
||||
"description": "OpenVR functionality for VTK",
|
||||
"dependencies": [
|
||||
"openvr",
|
||||
"sdl2"
|
||||
]
|
||||
},
|
||||
"python": {
|
||||
"description": "Python functionality for VTK",
|
||||
"dependencies": [
|
||||
"python3"
|
||||
]
|
||||
},
|
||||
"qt": {
|
||||
"description": "Qt functionality for VTK",
|
||||
"dependencies": [
|
||||
"qt5"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `"default-features"`
|
||||
|
||||
An array of feature names that the library uses by default, if nothing else is specified.
|
||||
|
||||
#### Example:
|
||||
```json
|
||||
{
|
||||
"default-features": [
|
||||
"kinesis"
|
||||
],
|
||||
"features": {
|
||||
"dynamodb": {
|
||||
"description": "Build dynamodb support",
|
||||
"dependencies": [
|
||||
"dynamodb"
|
||||
]
|
||||
},
|
||||
"kinesis": {
|
||||
"description": "build kinesis support"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `"supports"`
|
||||
|
||||
A string, formatted as a platform expression,
|
||||
that evaluates to true when the port should build successfully for a triplet.
|
||||
|
||||
This field is used in the CI testing to skip ports,
|
||||
and warns users in advance that a given install tree is not expected to succeed.
|
||||
Therefore, this field should be used optimistically;
|
||||
in cases where a port is expected to succeed 10% of the time, it should still be marked "supported".
|
||||
|
||||
The grammar for this top-level platform expression, in [EBNF], is as follows:
|
||||
|
||||
```ebnf
|
||||
whitespace-character =
|
||||
| ? U+0009 "CHARACTER TABULATION" ?
|
||||
| ? U+000A "LINE FEED" ?
|
||||
| ? U+000D "CARRIAGE RETURN" ?
|
||||
| ? U+0020 "SPACE" ? ;
|
||||
optional-whitespace = { whitespace-character } ;
|
||||
|
||||
lowercase-alpha =
|
||||
| "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m"
|
||||
| "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" ;
|
||||
digit =
|
||||
| "0" | "1" | "2" | "3" | "4"
|
||||
| "5" | "6" | "7" | "8" | "9" ;
|
||||
identifier-character =
|
||||
| lowercase-alpha
|
||||
| digit ;
|
||||
|
||||
platform-expression =
|
||||
| platform-expression-not
|
||||
| platform-expression-and
|
||||
| platform-expression-or ;
|
||||
|
||||
platform-expression-identifier =
|
||||
| identifier-character, { identifier-character }, optional-whitespace ;
|
||||
|
||||
platform-expression-simple =
|
||||
| platform-expression-identifier
|
||||
| "(", optional-whitespace, platform-expression, ")", optional-whitespace ;
|
||||
|
||||
platform-expression-not =
|
||||
| platform-expression-simple
|
||||
| "!", optional-whitespace, platform-expression-simple ;
|
||||
|
||||
platform-expression-and =
|
||||
| platform-expression-not, { "&", optional-whitespace, platform-expression-not } ;
|
||||
|
||||
platform-expression-or =
|
||||
| platform-expression-not, { "|", optional-whitespace, platform-expression-not } ;
|
||||
|
||||
top-level-platform-expression = optional-whitespace, platform-expression ;
|
||||
```
|
||||
|
||||
Basically, there are four kinds of expressions -- identifiers, negations, ands, and ors.
|
||||
Negations may only negate an identifier or a grouped expression.
|
||||
Ands and ors are a list of `&` or `|` separated identifiers, negated expressions, and grouped expressions.
|
||||
One may not mix `&` and `|` without parentheses for grouping.
|
||||
|
||||
These predefined identifier expressions are computed from standard triplet settings:
|
||||
- `x64` - `VCPKG_TARGET_ARCHITECTURE` == `"x64"`
|
||||
- `x86` - `VCPKG_TARGET_ARCHITECTURE` == `"x86"`
|
||||
- `arm` - `VCPKG_TARGET_ARCHITECTURE` == `"arm"` or `VCPKG_TARGET_ARCHITECTURE` == `"arm64"`
|
||||
- `arm64` - `VCPKG_TARGET_ARCHITECTURE` == `"arm64"`
|
||||
- `windows` - `VCPKG_CMAKE_SYSTEM_NAME` == `""` or `VCPKG_CMAKE_SYSTEM_NAME` == `"WindowsStore"`
|
||||
- `uwp` - `VCPKG_CMAKE_SYSTEM_NAME` == `"WindowsStore"`
|
||||
- `linux` - `VCPKG_CMAKE_SYSTEM_NAME` == `"Linux"`
|
||||
- `osx` - `VCPKG_CMAKE_SYSTEM_NAME` == `"Darwin"`
|
||||
- `android` - `VCPKG_CMAKE_SYSTEM_NAME` == `"Android"`
|
||||
- `static` - `VCPKG_LIBRARY_LINKAGE` == `"static"`
|
||||
- `wasm32` - `VCPKG_TARGET_ARCHITECTURE` == `"wasm32"`
|
||||
- `emscripten` - `VCPKG_CMAKE_SYSTEM_NAME` == `"Emscripten"`
|
||||
|
||||
These predefined identifier expressions can be overridden in the triplet file,
|
||||
via the [`VCPKG_DEP_INFO_OVERRIDE_VARS`](../users/triplets.md) option,
|
||||
and new identifier expressions can be added via the same mechanism.
|
||||
|
||||
This field is optional and defaults to true.
|
||||
|
||||
> Implementers' Note: these terms are computed from the triplet via the `vcpkg_get_dep_info` mechanism.
|
||||
|
||||
[EBNF]: https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form
|
||||
|
||||
#### Example:
|
||||
```json
|
||||
{
|
||||
"supports": "!uwp & !(arm & !arm64)"
|
||||
}
|
||||
```
|
||||
|
||||
This means "doesn't support uwp, nor arm32 (but does support arm64)".
|
@ -1,6 +1,6 @@
|
||||
Vcpkg PR Checklist
|
||||
=====================
|
||||
Revision: 0
|
||||
Revision: 1
|
||||
|
||||
## Overview
|
||||
This document provides an annotated checklist which vcpkg team members use to apply the "reviewed" label on incoming pull requests. If a pull request violates any of these points, we may ask contributors to make necessary changes before we can merge the changeset.
|
||||
@ -10,87 +10,87 @@ Feel free to create an issue or pull request if you feel that this checklist can
|
||||
## Checklist
|
||||
You can link any of these checklist items in a GitHub comment by copying the link address attached to each item code.
|
||||
|
||||
<details id=c000001>
|
||||
<summary><a href=#c000001>c000001</a>: No deprecated helper functions are used</summary>
|
||||
<details id="c000001">
|
||||
<summary><a href="#c000001">c000001</a>: No deprecated helper functions are used</summary>
|
||||
|
||||
See our [Maintainer Guidelines and Policies](maintainer-guide.md#Avoid-deprecated-helper-functions) for more information.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000002>
|
||||
<summary><a href=#c000002>c000002</a>: Control Version field is updated</summary>
|
||||
<details id="c000002">
|
||||
<summary><a href="#c000002">c000002</a>: `"port-version"` field is updated</summary>
|
||||
|
||||
See our [Maintainer Guidelines and Policies](maintainer-guide.md#versioning) for more information.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000003>
|
||||
<summary><a href=#c000003>c000003</a>: New ports contain a Description field written in English</summary>
|
||||
<details id="c000003">
|
||||
<summary><a href="#c000003">c000003</a>: New ports contain a `"description"` field written in English</summary>
|
||||
|
||||
A description only one or a few sentences long is helpful. Consider using the library's official description from their `README.md` or similar if possible. Automatic translations are acceptable and we are happy to clean up translations to English for our contributors.
|
||||
|
||||
See our [CONTROL file documentation](https://github.com/grdowns/vcpkg/blob/pr-checklist/docs/maintainers/control-files.md#description) for more information.
|
||||
See our [manifest file documentation](manifest-files.md#description) for more information.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000004>
|
||||
<summary><a href=#c000004>c000004</a>: No unnecessary comments are present in the changeset</summary>
|
||||
<details id="c000004">
|
||||
<summary><a href="#c000004">c000004</a>: No unnecessary comments are present in the changeset</summary>
|
||||
|
||||
See our [Maintainer Guidelines and Policies](maintainer-guide.md#Avoid-excessive-comments-in-portfiles) for more information.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000005>
|
||||
<summary><a href=#c000005>c000005</a>: Downloaded archives are versioned if available</summary
|
||||
<details id="c000005">
|
||||
<summary><a href="#c000005">c000005</a>: Downloaded archives are versioned if available</summary
|
||||
|
||||
To ensure archive content does not change, archives downloaded preferably have an associated version tag that can be incremented alongside the port version.
|
||||
To ensure archive content does not change, archives downloaded preferably have an associated version tag that can be incremented alongside the port's `"version"`.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000006>
|
||||
<summary><a href=#c000006>c000006</a>: New ports pass CI checks for triplets that the library officially supports</summary>
|
||||
<details id="c000006">
|
||||
<summary><a href="#c000006">c000006</a>: New ports pass CI checks for triplets that the library officially supports</summary>
|
||||
|
||||
To ensure vcpkg ports are of a high quality, we ask that incoming ports support the official platforms for the library in question.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000007>
|
||||
<summary><a href=#c000007>c000007</a>: Patches fix issues that are vcpkg-specific only</summary>
|
||||
<details id="c000007">
|
||||
<summary><a href="#c000007">c000007</a>: Patches fix issues that are vcpkg-specific only</summary>
|
||||
|
||||
If possible, patches to the library source code should be upstreamed to the library's official repository. Opening up a pull request on the library's repository will help to improve the library for everyone, not just vcpkg users.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000008>
|
||||
<summary><a href=#c000008>c000008</a>: New ports download source code from the official source if available</summary>
|
||||
<details id="c000008">
|
||||
<summary><a href="#c000008">c000008</a>: New ports download source code from the official source if available</summary>
|
||||
|
||||
To respect library authors and keep code secure, please have ports download source code from the official source. We may make exceptions if the original source code is not available and there is substantial community interest in maintaining the library in question.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000009>
|
||||
<summary><a href=#c000010>c000010</a>: Ports and port features are named correctly</summary>
|
||||
<details id="c000009">
|
||||
<summary><a href="#c000009">c000009</a>: Ports and port features are named correctly</summary>
|
||||
|
||||
For user accessibility, we prefer names of ports and port features to be intuitive and close to their counterparts in official sources and other package managers. If you are unsure about the naming of a port or port feature, we recommend checking repology.org, packages.ubuntu.com, or searching for additional information using a search engine. We can also help our contributors with this, so feel free to ask for naming suggestions if you are unsure.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000010>
|
||||
<summary><a href=#c000011>c000011</a>: Library targets are exported when appropriate</summary>
|
||||
<details id="c000010">
|
||||
<summary><a href="#c000010">c000010</a>: Library targets are exported when appropriate</summary>
|
||||
|
||||
To provide users with a seamless build system integration, please be sure to export and provide a means of finding the library targets intended to be used downstream. Targets not meant to be exported should be be marked private and not exported.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000011>
|
||||
<summary><a href=#c000012>c000012</a>: Ports do not use applications which modify the user's system</summary>
|
||||
<details id="c000011">
|
||||
<summary><a href="#c000011">c000011</a>: Ports do not use applications which modify the user's system</summary>
|
||||
|
||||
Ports should uphold vcpkg's contract of not modifying the user's system by avoiding applications which do so. Examples of these applications are `sudo`, `apt`, `brew`, or `pip`. Please use an alternative to these types of programs wherever possible.
|
||||
|
||||
</details>
|
||||
|
||||
<details id=c000012>
|
||||
<summary><a href=#c000013>c000013</a>: Ports with system dependencies include an information message during installation</summary>
|
||||
<details id="c000012">
|
||||
<summary><a href="#c000012">c000012</a>: Ports with system dependencies include an information message during installation</summary>
|
||||
|
||||
Some ports have library and tool dependencies that do not exist within vcpkg. For these missing dependencies, we ask that contributors add a message to the top of the port's `portfile.cmake` stating the missing dependencies and how to acquire them. We ask that the message is displayed before any major work is done to ensure that users can "early out" of the installation process as soon as possible in case they are missing the dependency.
|
||||
|
||||
@ -104,3 +104,12 @@ These can be installed on Ubuntu systems via sudo apt install autoconf libtool"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details id="c000013">
|
||||
<summary><a href="#c000013">c000013</a>: Manifest files are used instead of CONTROL files for new ports</summary>
|
||||
|
||||
Many existing ports use the CONTROL file syntax; while this syntax will be supported for some time to come,
|
||||
new ports should not use these. Any newly added port _must_ use the manifest files.
|
||||
|
||||
We also recommend, when significant modifications are made to ports, that one switches to manifest files;
|
||||
however, this is not required. You may find `vcpkg format-manifest` useful.
|
||||
|
259
docs/users/manifests.md
Normal file
259
docs/users/manifests.md
Normal file
@ -0,0 +1,259 @@
|
||||
# Manifest Mode
|
||||
|
||||
vcpkg has two modes of operation - classic mode and manifest mode.
|
||||
|
||||
In classic mode, vcpkg produces an "installed" tree,
|
||||
whose contents are changed by explicit calls to `vcpkg install` or `vcpkg remove`.
|
||||
The installed tree is intended for consumption by any number of projects:
|
||||
for example, installing a bunch of libraries and then using those libraries from Visual Studio,
|
||||
without additional configuration.
|
||||
Because the installed tree is not associated with an individual project,
|
||||
it's similar to tools like `brew` or `apt`,
|
||||
except that the installed tree is vcpkg-installation-local,
|
||||
rather than global to a system or user.
|
||||
|
||||
In manifest mode, an installed tree is associated with a particular project rather than the vcpkg installation.
|
||||
The set of installed ports is controlled by editing the project's "manifest file",
|
||||
and the installed tree is placed in the project directory or build directory.
|
||||
This mode acts more similarly to language package managers like Cargo, or npm.
|
||||
We recommend using this manifest mode whenever possible,
|
||||
because it allows one to encode a project's dependencies explicitly in a project file,
|
||||
rather than in the documentation, making your project much easier to consume.
|
||||
|
||||
Manifest mode is in beta, but one can use it from the CMake integration,
|
||||
which will be stable when used via things like `find_package`.
|
||||
This is the recommended way to use manifest mode.
|
||||
|
||||
In this document, we have basic information on [Writing a Manifest](#writing-a-manifest),
|
||||
the [vcpkg Command Line Interface](#command-line-interface),
|
||||
and a little more information on [CMake](#cmake-integration) integration.
|
||||
|
||||
Check out the [manifest cmake example](../examples/manifest-mode-cmake.md) for an example project using CMake and manifest mode.
|
||||
|
||||
## Writing a Manifest
|
||||
|
||||
A manifest is a JSON-formatted file which lies at the root of your project.
|
||||
It contains all the information a person needs to know to get dependencies for your project,
|
||||
as well as all the metadata about your project that a person who depends on you might be interested in.
|
||||
|
||||
Every manifest is named `vcpkg.json`, and has a top level object. It is a strict JSON file,
|
||||
and can't contain things like comments or trailing commas - however,
|
||||
you can use field names that start with `$` to write your comments.
|
||||
|
||||
All of the fields that `vcpkg.json` supports are as follows; the most important ones are [`"name"`](#name),
|
||||
the [version fields](#version-fields), and [`"dependencies"`](#dependencies):
|
||||
|
||||
### `"name"`
|
||||
|
||||
This is the name of your project! It must be formatted in a way that vcpkg understands - in other words,
|
||||
it must be lowercase alphabetic characters, digits, and hyphens, and it must not start nor end with a hyphen.
|
||||
For example, `Boost.Asio` might be given the name `boost-asio`.
|
||||
|
||||
This is a required field.
|
||||
|
||||
### Version fields
|
||||
|
||||
There is, at this point, only one version field - `"version-string"`. However, more will be added in the future.
|
||||
You must have one (and only one) version field. There are different reasons to use each version field:
|
||||
|
||||
* `"version-string"` - used for packages that don't have orderable versions. This is pretty uncommon,
|
||||
but since we don't have any versioning constraints yet, this is the only one that you can use.
|
||||
|
||||
Additionally, the `"port-version"` field is used by registries of packages,
|
||||
as a way to version "the package gotten from `vcpkg install`" differently from the upstream package version.
|
||||
You shouldn't need to worry about this at all.
|
||||
|
||||
### `"description"`
|
||||
|
||||
This is where you describe your project. Give it a good description to help in searching for it!
|
||||
This can be a single string, or it can be an array of strings;
|
||||
in the latter case, the first string is treated as a summary,
|
||||
while the remaining strings are treated as the full description.
|
||||
|
||||
### `"dependencies"`
|
||||
|
||||
This field lists all the dependencies you'll need to build your library (as well as any your dependents might need,
|
||||
if they were to use you). It's an array of strings and objects:
|
||||
|
||||
* A string dependency (e.g., `"dependencies": [ "zlib" ]`) is the simplest way one can depend on a library;
|
||||
it means you don't depend on a single version, and don't need to write down any more information.
|
||||
* On the other hand, an object dependency (e.g., `"dependencies": [ { "name": "zlib" } ]`)
|
||||
allows you to add that extra information.
|
||||
|
||||
An object dependency can have the following fields:
|
||||
|
||||
#### `"name"`
|
||||
|
||||
The name of the dependency. This follows the same restrictions as the [`"name"`](#name) property for a project.
|
||||
|
||||
#### `"features"` and `"default-features"`
|
||||
|
||||
`"features"` is an array of feature names which tell you the set of features that the
|
||||
dependencies need to have at a minimum,
|
||||
while `"default-features"` is a boolean that tells vcpkg whether or not to
|
||||
install the features the package author thinks should be "most common for most people to use".
|
||||
|
||||
For example, `ffmpeg` is a library which supports many, many audio and video codecs;
|
||||
however, for your specific project, you may only need mp3 encoding.
|
||||
Then, you might just ask for:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "ffmpeg",
|
||||
"default-features": false,
|
||||
"features": [ "mp3lame" ]
|
||||
}
|
||||
```
|
||||
|
||||
#### `"platform"`
|
||||
|
||||
The `"platform"` field defines the platforms where the dependency should be installed - for example,
|
||||
you might need to use sha256, and so you use platform primitives on Windows, but `picosha2` on non-Windows platforms.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "picosha2",
|
||||
"platform": "!windows"
|
||||
}
|
||||
```
|
||||
|
||||
This is a string field which takes boolean expressions of the form `<identifier>`,
|
||||
`!expression`, `expression { & expression & expression...}`, and `expression { | expression | expression...}`,
|
||||
along with parentheses to denote precedence.
|
||||
For example, a dependency that's only installed on the Windows OS, for the ARM64 architecture,
|
||||
and on Linux on x64, would be written `(windows & arm64) | (linux & x64)`.
|
||||
|
||||
The common identifiers are:
|
||||
|
||||
- The operating system: `windows`, `uwp`, `linux`, `osx` (includes macOS), `android`, `emscripten`
|
||||
- The architecture: `x86`, `x64`, `wasm32`, `arm64`, `arm` (includes both arm32 and arm64 due to backwards compatibility)
|
||||
|
||||
although one can define their own.
|
||||
|
||||
#### Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "arrow",
|
||||
"default-features": false,
|
||||
"features": [ "json" ]
|
||||
},
|
||||
"boost-asio",
|
||||
"openssl",
|
||||
{
|
||||
"name": "picosha2",
|
||||
"platform": "!windows"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `"supports"`
|
||||
|
||||
If your project doesn't support common platforms, you can tell your users this with the `"supports"` field.
|
||||
It uses the same platform expressions as [`"platform"`](#platform), from dependencies, as well as the
|
||||
`"supports"` field of features.
|
||||
For example, if your library doesn't support linux, you might write `{ "supports": "!linux" }`.
|
||||
|
||||
|
||||
### `"features"` and `"default-features"`
|
||||
|
||||
The `"features"` field defines _your_ project's optional features, that others may either depend on or not.
|
||||
It's an object, where the keys are the names of the features, and the values are objects describing the feature.
|
||||
`"description"` is required,
|
||||
and acts exactly like the [`"description"`](#description) field on the global package,
|
||||
and `"dependencies"` are optional,
|
||||
and again act exactly like the [`"dependencies"`](#dependencies) field on the global package.
|
||||
There's also the `"supports"` field,
|
||||
which again acts exactly like the [`"supports"`](#supports) field on the global package.
|
||||
|
||||
You also have control over which features are default, if a person doesn't ask for anything specific,
|
||||
and that's the `"default-features"` field, which is an array of feature names.
|
||||
|
||||
#### Example:
|
||||
|
||||
```
|
||||
{
|
||||
"name": "libdb",
|
||||
"description": [
|
||||
"An example database library.",
|
||||
"Optionally uses one of CBOR, JSON, or CSV as a backend."
|
||||
],
|
||||
"default-features": [ "cbor", "csv", "json" ],
|
||||
"features": {
|
||||
"cbor": {
|
||||
"description": "The CBOR backend",
|
||||
"dependencies": [
|
||||
{
|
||||
"$explanation": [
|
||||
"This is currently how you tell vcpkg that the cbor feature depends on the json feature of this package",
|
||||
"We're looking into making this easier"
|
||||
],
|
||||
"name": "libdb",
|
||||
"default-features": false,
|
||||
"features": [ "json" ]
|
||||
}
|
||||
]
|
||||
},
|
||||
"csv": {
|
||||
"description": "The CSV backend",
|
||||
"dependencies": [
|
||||
"fast-cpp-csv-parser"
|
||||
]
|
||||
},
|
||||
"gui": {
|
||||
"description": "The GUI libdb database viewer.",
|
||||
"supports": "windows | osx"
|
||||
}
|
||||
"json": {
|
||||
"description": "The JSON backend",
|
||||
"dependencies": [
|
||||
"jsoncons"
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Command Line Interface
|
||||
|
||||
The command line interface around the new manifest mode is pretty simple.
|
||||
There's only one command that one really needs to worry about, `vcpkg install`,
|
||||
although `vcpkg search` is still useful.
|
||||
Since manifest mode is still in beta, you'll need to pass a feature flag: `manifests`.
|
||||
There are a few ways to pass this feature flag:
|
||||
|
||||
* `--feature-flag` option: On any vcpkg command, you can pass `--feature-flag=manifests`
|
||||
* `VCPKG_FEATURE_FLAGS` environment variable: one can set the environment variable `VCPKG_FEATURE_FLAGS` to
|
||||
`manifests`.
|
||||
|
||||
### `vcpkg install`
|
||||
|
||||
Once one has written a manifest file,
|
||||
they can run `vcpkg install` in any subdirectory of the directory containing `vcpkg.json`.
|
||||
It will install all of the dependencies for the default triplet into
|
||||
`<directory containing vcpkg.json>/vcpkg_installed`.
|
||||
If you want to switch the triplet (for example, this is very common on windows, where the default triplet is x86-windows, not x64-windows),
|
||||
you can pass it with the `--triplet` option: `vcpkg install --triplet x64-windows` (or whatever).
|
||||
Then, vcpkg will install all the dependencies, and you're ready to go!
|
||||
|
||||
## CMake Integration
|
||||
|
||||
The CMake integration acts exactly like the existing CMake integration.
|
||||
One passes the toolchain file, located at `[vcpkg root]/scripts/buildsystems/vcpkg.cmake`,
|
||||
to the CMake invocation via the `CMAKE_TOOLCHAIN_FILE` variable.
|
||||
Then, CMake will install all dependencies into the build directory, and you're good!
|
||||
It ends up that you only have to run CMake, and vcpkg is called only as part of the build process.
|
||||
Unlike bare vcpkg, the feature flag is not required,
|
||||
since the CMake integration won't break as long as you depending on the exact naming of vcpkg's installed directory.
|
||||
|
||||
### Example:
|
||||
|
||||
```
|
||||
> cmake -B builddir -S . -DCMAKE_TOOLCHAIN_FILE=[vcpkg root]/scripts/buildsystems/vcpkg.cmake
|
||||
> cmake --build builddir
|
||||
```
|
||||
|
||||
with a `vcpkg.json` in the same directory as `CMakeLists.txt` should Just Work!
|
@ -93,7 +93,7 @@ Replaces the default computed list of triplet "Supports" terms.
|
||||
|
||||
This option (if set) will override the default set of terms used for qualified dependency resolution and "Supports" field evaluation.
|
||||
|
||||
See the [`Supports`](../maintainers/control-files.md#Supports) control file field documentation for more details.
|
||||
See the [`"supports"`](../maintainers/manifest-files.md#supports) manifest file field documentation for more details.
|
||||
|
||||
> Implementers' Note: this list is extracted via the `vcpkg_get_dep_info` mechanism.
|
||||
|
||||
|
@ -9,10 +9,9 @@
|
||||
"Abseil is not meant to be a competitor to the standard library; we've just found that many of these utilities serve a purpose within our code base, and we now want to provide those resources to the C++ community as a whole."
|
||||
],
|
||||
"homepage": "https://github.com/abseil/abseil-cpp",
|
||||
"features": [
|
||||
{
|
||||
"name": "cxx17",
|
||||
"features": {
|
||||
"cxx17": {
|
||||
"description": "Enable compiler C++17."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -10,18 +10,15 @@
|
||||
"logging",
|
||||
"tls"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "jit",
|
||||
"features": {
|
||||
"jit": {
|
||||
"description": "Default feature. Enables jit pipeline compilation. Not supported for ARM and UWP."
|
||||
},
|
||||
{
|
||||
"name": "logging",
|
||||
"logging": {
|
||||
"description": "Default feature. Enables logging."
|
||||
},
|
||||
{
|
||||
"name": "tls",
|
||||
"tls": {
|
||||
"description": "Default feature. Enables use of thread_local feature. Disable for platforms where thread local storage is expensive or not supported."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -32,24 +32,21 @@
|
||||
"qt5-base",
|
||||
"suitesparse"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "cuda",
|
||||
"features": {
|
||||
"cuda": {
|
||||
"description": "CUDA support for current compute architecture of this machine.",
|
||||
"dependencies": [
|
||||
"cuda"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "cuda-redist",
|
||||
"cuda-redist": {
|
||||
"description": "Redistributable CUDA support for common supported compute architectures.",
|
||||
"dependencies": [
|
||||
"cuda"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tests",
|
||||
"tests": {
|
||||
"description": "Enable TESTS."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,9 @@
|
||||
"homepage": "https://github.com/google/cpu_features",
|
||||
"license": "Apache-2.0",
|
||||
"supports": "!(arm | uwp)",
|
||||
"features": [
|
||||
{
|
||||
"name": "tools",
|
||||
"features": {
|
||||
"tools": {
|
||||
"description": "list_cpu_features command line tool"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,9 @@
|
||||
"version-string": "1.50.1",
|
||||
"description": "GeographicLib, a C++ library for performing geographic conversions",
|
||||
"homepage": "https://geographiclib.sourceforge.io",
|
||||
"features": [
|
||||
{
|
||||
"name": "tools",
|
||||
"features": {
|
||||
"tools": {
|
||||
"description": "The GeographicLib tools"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,8 @@
|
||||
"default-features": [
|
||||
"external-libs"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "external-libs",
|
||||
"features": {
|
||||
"external-libs": {
|
||||
"description": "Default feature. Enables Ogg Vorbis, FLAC and Ogg Opus formats support.",
|
||||
"dependencies": [
|
||||
"libflac",
|
||||
@ -18,5 +17,5 @@
|
||||
"opus"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -13,14 +13,13 @@
|
||||
"boost-random",
|
||||
"boost-type-traits"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "python",
|
||||
"features": {
|
||||
"python": {
|
||||
"description": "Interacting with python with pybind11 interface",
|
||||
"dependencies": [
|
||||
"boost-python",
|
||||
"pybind11"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -17,25 +17,21 @@
|
||||
"zlib",
|
||||
"zziplib"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "csharp",
|
||||
"features": {
|
||||
"csharp": {
|
||||
"description": "Build csharp bindings"
|
||||
},
|
||||
{
|
||||
"name": "d3d9",
|
||||
"d3d9": {
|
||||
"description": "Build Direct3D9 RenderSystem"
|
||||
},
|
||||
{
|
||||
"name": "java",
|
||||
"java": {
|
||||
"description": "Build Java (JNI) bindings"
|
||||
},
|
||||
{
|
||||
"name": "python",
|
||||
"python": {
|
||||
"description": "Build Python bindings",
|
||||
"dependencies": [
|
||||
"python3"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ if (-not (Test-Path "$Root/vcpkg.exe"))
|
||||
}
|
||||
}
|
||||
|
||||
& "$Root/vcpkg.exe" 'x-format-manifest' '--all'
|
||||
& "$Root/vcpkg.exe" 'format-manifest' '--all'
|
||||
if (-not $?)
|
||||
{
|
||||
Write-Error "Failed formatting manifests; are they well-formed?"
|
||||
|
@ -474,6 +474,20 @@ namespace vcpkg::Json
|
||||
return visit_value(value, visitor);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Optional<Type> visit_map_field(StringView key, const Value& value, IDeserializer<Type>& visitor)
|
||||
{
|
||||
m_path.push_back(key);
|
||||
auto res = internal_visit(value, visitor);
|
||||
m_path.pop_back();
|
||||
return std::move(res);
|
||||
}
|
||||
template<class Type>
|
||||
Optional<Type> visit_map_field(StringView key, const Value& value, IDeserializer<Type>&& visitor)
|
||||
{
|
||||
return visit_map_field(key, value, visitor);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Optional<std::vector<Type>> array_elements(const Array& arr, IDeserializer<Type>& visitor)
|
||||
{
|
||||
|
@ -76,24 +76,7 @@ namespace vcpkg::PlatformExpression
|
||||
Allow,
|
||||
};
|
||||
|
||||
// platform expression parses the following :
|
||||
// <platform-expression>:
|
||||
// <platform-expression.not>
|
||||
// <platform-expression.and>
|
||||
// <platform-expression.or>
|
||||
// <platform-expression.simple>:
|
||||
// ( <platform-expression> )
|
||||
// <platform-expression.identifier>
|
||||
// <platform-expression.identifier>:
|
||||
// A lowercase alpha-numeric string
|
||||
// <platform-expression.not>:
|
||||
// <platform-expression.simple>
|
||||
// ! <platform-expression.simple>
|
||||
// <platform-expression.and>
|
||||
// <platform-expression.not>
|
||||
// <platform-expression.and> & <platform-expression.not>
|
||||
// <platform-expression.or>
|
||||
// <platform-expression.not>
|
||||
// <platform-expression.or> | <platform-expression.not>
|
||||
// platform expression parses a platform expression; the EBNF of such is defined in
|
||||
// /docs/maintainers/manifest-files.md#supports
|
||||
ExpectedS<Expr> parse_platform_expression(StringView expression, MultipleBinaryOperators multiple_binary_operators);
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ TEST_CASE ("get_available_paths_commands works", "[commands]")
|
||||
"autocomplete",
|
||||
"hash",
|
||||
"fetch",
|
||||
"format-manifest",
|
||||
"x-ci-clean",
|
||||
"x-history",
|
||||
"x-package-info",
|
||||
"x-vsinstances",
|
||||
"x-format-manifest",
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,7 @@ TEST_CASE ("SourceParagraph manifest empty supports", "[manifests]")
|
||||
|
||||
TEST_CASE ("Serialize all the ports", "[manifests]")
|
||||
{
|
||||
std::vector<std::string> args_list = {"x-format-manifest"};
|
||||
std::vector<std::string> args_list = {"format-manifest"};
|
||||
auto& fs = Files::get_real_filesystem();
|
||||
auto args = VcpkgCmdArguments::create_from_arg_sequence(args_list.data(), args_list.data() + args_list.size());
|
||||
VcpkgPaths paths{fs, args};
|
||||
|
80
toolsrc/src/vcpkg-test/platform-expression.cpp
Normal file
80
toolsrc/src/vcpkg-test/platform-expression.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <vcpkg/platform-expression.h>
|
||||
|
||||
using vcpkg::StringView;
|
||||
using namespace vcpkg::PlatformExpression;
|
||||
|
||||
static vcpkg::ExpectedS<Expr> parse_expr(StringView s)
|
||||
{
|
||||
return parse_platform_expression(s, MultipleBinaryOperators::Deny);
|
||||
}
|
||||
|
||||
TEST_CASE ("platform-expression-identifier", "[platform-expression]")
|
||||
{
|
||||
auto m_expr = parse_expr("windows");
|
||||
REQUIRE(m_expr);
|
||||
auto& expr = *m_expr.get();
|
||||
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
|
||||
CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
|
||||
CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Darwin"}}));
|
||||
}
|
||||
|
||||
TEST_CASE ("platform-expression-not", "[platform-expression]")
|
||||
{
|
||||
auto m_expr = parse_expr("!windows");
|
||||
REQUIRE(m_expr);
|
||||
auto& expr = *m_expr.get();
|
||||
|
||||
CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
|
||||
CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Darwin"}}));
|
||||
}
|
||||
|
||||
TEST_CASE ("platform-expression-and", "[platform-expression]")
|
||||
{
|
||||
auto m_expr = parse_expr("!windows & !arm");
|
||||
REQUIRE(m_expr);
|
||||
auto& expr = *m_expr.get();
|
||||
|
||||
CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
|
||||
CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
|
||||
CHECK_FALSE(expr.evaluate({
|
||||
{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"},
|
||||
{"VCPKG_TARGET_ARCHITECTURE", "arm"},
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_CASE ("platform-expression-or", "[platform-expression]")
|
||||
{
|
||||
auto m_expr = parse_expr("!windows | arm");
|
||||
REQUIRE(m_expr);
|
||||
auto& expr = *m_expr.get();
|
||||
|
||||
CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}, {"VCPKG_TARGET_ARCHITECTURE", "arm"}}));
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
|
||||
}
|
||||
|
||||
TEST_CASE ("weird platform-expressions whitespace", "[platform-expression]")
|
||||
{
|
||||
auto m_expr = parse_expr(" ! \t windows \n| arm \r");
|
||||
REQUIRE(m_expr);
|
||||
auto& expr = *m_expr.get();
|
||||
|
||||
CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}, {"VCPKG_TARGET_ARCHITECTURE", "arm"}}));
|
||||
CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
|
||||
}
|
||||
|
||||
TEST_CASE ("no mixing &, | in platform expressions", "[platform-expression]")
|
||||
{
|
||||
auto m_expr = parse_expr("windows & arm | linux");
|
||||
CHECK_FALSE(m_expr);
|
||||
m_expr = parse_expr("windows | !arm & linux");
|
||||
CHECK_FALSE(m_expr);
|
||||
}
|
@ -93,7 +93,7 @@ namespace vcpkg::Commands
|
||||
{"x-package-info", &info},
|
||||
{"x-history", &porthistory},
|
||||
{"x-vsinstances", &vsinstances},
|
||||
{"x-format-manifest", &format_manifest},
|
||||
{"format-manifest", &format_manifest},
|
||||
};
|
||||
return t;
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ namespace vcpkg::Commands::FormatManifest
|
||||
};
|
||||
|
||||
const CommandStructure COMMAND_STRUCTURE = {
|
||||
create_example_string(R"###(x-format-manifest --all)###"),
|
||||
create_example_string(R"###(format-manifest --all)###"),
|
||||
0,
|
||||
SIZE_MAX,
|
||||
{FORMAT_SWITCHES, {}, {}},
|
||||
@ -204,7 +204,7 @@ namespace vcpkg::Commands::FormatManifest
|
||||
|
||||
if (!format_all && convert_control)
|
||||
{
|
||||
System::print2(System::Color::warning, R"(x-format-manifest was passed '--convert-control' without '--all'.
|
||||
System::print2(System::Color::warning, R"(format-manifest was passed '--convert-control' without '--all'.
|
||||
This doesn't do anything:
|
||||
we will automatically convert all control files passed explicitly.)");
|
||||
}
|
||||
|
@ -106,10 +106,10 @@ namespace vcpkg::PlatformExpression
|
||||
return multiple_binary_operators == MultipleBinaryOperators::Allow;
|
||||
}
|
||||
|
||||
// top-level-platform-expression = optional-whitespace, platform-expression
|
||||
PlatformExpression::Expr parse()
|
||||
{
|
||||
skip_whitespace();
|
||||
|
||||
auto res = expr();
|
||||
|
||||
if (!at_eof())
|
||||
@ -121,64 +121,71 @@ namespace vcpkg::PlatformExpression
|
||||
}
|
||||
|
||||
private:
|
||||
// <platform-expression.and>
|
||||
// <platform-expression.not>
|
||||
// <platform-expression.and> & <platform-expression.not>
|
||||
// <platform-expression.or>
|
||||
// <platform-expression.not>
|
||||
// <platform-expression.or> | <platform-expression.not>
|
||||
|
||||
// identifier-character =
|
||||
// | lowercase-alpha
|
||||
// | digit ;
|
||||
static bool is_identifier_char(char32_t ch) { return is_lower_alpha(ch) || is_ascii_digit(ch); }
|
||||
|
||||
// <platform-expression>:
|
||||
// <platform-expression.not>
|
||||
// <platform-expression.and>
|
||||
// <platform-expression.or>
|
||||
// platform-expression =
|
||||
// | platform-expression-not
|
||||
// | platform-expression-and
|
||||
// | platform-expression-or ;
|
||||
std::unique_ptr<ExprImpl> expr()
|
||||
{
|
||||
// this is the common prefix of all the variants
|
||||
// platform-expression-not,
|
||||
auto result = expr_not();
|
||||
|
||||
switch (cur())
|
||||
{
|
||||
case '|':
|
||||
{
|
||||
// { "|", optional-whitespace, platform-expression-not }
|
||||
return expr_binary<'|', '&'>(std::make_unique<ExprImpl>(ExprKind::op_or, std::move(result)));
|
||||
}
|
||||
case '&':
|
||||
{
|
||||
// { "&", optional-whitespace, platform-expression-not }
|
||||
return expr_binary<'&', '|'>(std::make_unique<ExprImpl>(ExprKind::op_and, std::move(result)));
|
||||
}
|
||||
default: return result;
|
||||
}
|
||||
}
|
||||
|
||||
// <platform-expression.simple>:
|
||||
// ( <platform-expression> )
|
||||
// <platform-expression.identifier>
|
||||
// platform-expression-simple =
|
||||
// | platform-expression-identifier
|
||||
// | "(", optional-whitespace, platform-expression, ")", optional-whitespace ;
|
||||
std::unique_ptr<ExprImpl> expr_simple()
|
||||
{
|
||||
if (cur() == '(')
|
||||
{
|
||||
// "(",
|
||||
next();
|
||||
// optional-whitespace,
|
||||
skip_whitespace();
|
||||
// platform-expression,
|
||||
auto result = expr();
|
||||
if (cur() != ')')
|
||||
{
|
||||
add_error("missing closing )");
|
||||
return result;
|
||||
}
|
||||
// ")",
|
||||
next();
|
||||
// optional-whitespace
|
||||
skip_whitespace();
|
||||
return result;
|
||||
}
|
||||
|
||||
// platform-expression-identifier
|
||||
return expr_identifier();
|
||||
}
|
||||
|
||||
// <platform-expression.identifier>:
|
||||
// A lowercase alpha-numeric string
|
||||
// platform-expression-identifier =
|
||||
// | identifier-character, { identifier-character }, optional-whitespace ;
|
||||
std::unique_ptr<ExprImpl> expr_identifier()
|
||||
{
|
||||
// identifier-character, { identifier-character },
|
||||
std::string name = match_zero_or_more(is_identifier_char).to_string();
|
||||
|
||||
if (name.empty())
|
||||
@ -186,25 +193,39 @@ namespace vcpkg::PlatformExpression
|
||||
add_error("unexpected character in logic expression");
|
||||
}
|
||||
|
||||
// optional-whitespace
|
||||
skip_whitespace();
|
||||
|
||||
return std::make_unique<ExprImpl>(ExprKind::identifier, std::move(name));
|
||||
}
|
||||
|
||||
// <platform-expression.not>:
|
||||
// <platform-expression.simple>
|
||||
// ! <platform-expression.simple>
|
||||
// platform-expression-not =
|
||||
// | platform-expression-simple
|
||||
// | "!", optional-whitespace, platform-expression-simple ;
|
||||
std::unique_ptr<ExprImpl> expr_not()
|
||||
{
|
||||
if (cur() == '!')
|
||||
{
|
||||
// "!",
|
||||
next();
|
||||
// optional-whitespace,
|
||||
skip_whitespace();
|
||||
// platform-expression-simple
|
||||
return std::make_unique<ExprImpl>(ExprKind::op_not, expr_simple());
|
||||
}
|
||||
|
||||
// platform-expression-simple
|
||||
return expr_simple();
|
||||
}
|
||||
|
||||
// platform-expression-and =
|
||||
// | platform-expression-not, { "&", optional-whitespace, platform-expression-not } ;
|
||||
//
|
||||
// platform-expression-or =
|
||||
// | platform-expression-not, { "|", optional-whitespace, platform-expression-not } ;
|
||||
//
|
||||
// already taken care of by the caller: platform-expression-not
|
||||
// so we start at either "&" or "|"
|
||||
template<char oper, char other>
|
||||
std::unique_ptr<ExprImpl> expr_binary(std::unique_ptr<ExprImpl>&& seed)
|
||||
{
|
||||
@ -213,10 +234,13 @@ namespace vcpkg::PlatformExpression
|
||||
// Support chains of the operator to avoid breaking backwards compatibility
|
||||
do
|
||||
{
|
||||
// "&" or "|",
|
||||
next();
|
||||
} while (allow_multiple_binary_operators() && cur() == oper);
|
||||
|
||||
// optional-whitespace,
|
||||
skip_whitespace();
|
||||
// platform-expression-not, (go back to start of repetition)
|
||||
seed->exprs.push_back(expr_not());
|
||||
} while (cur() == oper);
|
||||
|
||||
@ -225,7 +249,6 @@ namespace vcpkg::PlatformExpression
|
||||
add_error("mixing & and | is not allowed; use () to specify order of operations");
|
||||
}
|
||||
|
||||
skip_whitespace();
|
||||
return std::move(seed);
|
||||
}
|
||||
};
|
||||
|
@ -447,6 +447,11 @@ namespace vcpkg
|
||||
constexpr StringLiteral DependencyDeserializer::DEFAULT_FEATURES;
|
||||
constexpr StringLiteral DependencyDeserializer::PLATFORM;
|
||||
|
||||
// reasoning for these two distinct types -- FeatureDeserializer and ArrayFeatureDeserializer:
|
||||
// `"features"` may be defined in one of two ways:
|
||||
// - An array of feature objects, which contains the `"name"` field
|
||||
// - An object mapping feature names to feature objects, which do not contain the `"name"` field
|
||||
// `ArrayFeatureDeserializer` is used for the former, `FeatureDeserializer` is used for the latter.
|
||||
struct FeatureDeserializer : Json::IDeserializer<std::unique_ptr<FeatureParagraph>>
|
||||
{
|
||||
virtual StringView type_name() const override { return "a feature"; }
|
||||
@ -457,7 +462,7 @@ namespace vcpkg
|
||||
|
||||
virtual Span<const StringView> valid_fields() const override
|
||||
{
|
||||
static const StringView t[] = {NAME, DESCRIPTION, DEPENDENCIES};
|
||||
static const StringView t[] = {DESCRIPTION, DEPENDENCIES};
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -465,6 +470,7 @@ namespace vcpkg
|
||||
const Json::Object& obj) override
|
||||
{
|
||||
auto feature = std::make_unique<FeatureParagraph>();
|
||||
feature->name = std::move(name);
|
||||
|
||||
for (const auto& el : obj)
|
||||
{
|
||||
@ -474,8 +480,7 @@ namespace vcpkg
|
||||
}
|
||||
}
|
||||
|
||||
r.required_object_field(type_name(), obj, NAME, feature->name, Json::IdentifierDeserializer{});
|
||||
r.required_object_field(type_name(), obj, DESCRIPTION, feature->description, Json::ParagraphDeserializer{});
|
||||
r.required_object_field("a feature", obj, DESCRIPTION, feature->description, Json::ParagraphDeserializer{});
|
||||
r.optional_object_field(
|
||||
obj,
|
||||
DEPENDENCIES,
|
||||
@ -484,12 +489,85 @@ namespace vcpkg
|
||||
|
||||
return std::move(feature);
|
||||
}
|
||||
|
||||
FeatureDeserializer() = default;
|
||||
FeatureDeserializer(std::string&& s) : name(std::move(s)) { }
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct ArrayFeatureDeserializer : Json::IDeserializer<std::unique_ptr<FeatureParagraph>>
|
||||
{
|
||||
virtual StringView type_name() const override { return "a feature"; }
|
||||
|
||||
virtual Span<const StringView> valid_fields() const override
|
||||
{
|
||||
static const StringView t[] = {
|
||||
FeatureDeserializer::NAME,
|
||||
FeatureDeserializer::DESCRIPTION,
|
||||
FeatureDeserializer::DEPENDENCIES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
|
||||
virtual Optional<std::unique_ptr<FeatureParagraph>> visit_object(Json::Reader& r,
|
||||
const Json::Object& obj) override
|
||||
{
|
||||
std::string name;
|
||||
r.required_object_field(type_name(), obj, FeatureDeserializer::NAME, name, Json::IdentifierDeserializer{});
|
||||
return FeatureDeserializer{std::move(name)}.visit_object(r, obj);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr StringLiteral FeatureDeserializer::NAME;
|
||||
constexpr StringLiteral FeatureDeserializer::DESCRIPTION;
|
||||
constexpr StringLiteral FeatureDeserializer::DEPENDENCIES;
|
||||
|
||||
struct FeaturesFieldDeserializer : Json::IDeserializer<std::vector<std::unique_ptr<FeatureParagraph>>>
|
||||
{
|
||||
virtual StringView type_name() const override { return "a features field"; }
|
||||
|
||||
virtual Span<const StringView> valid_fields() const override { return {}; }
|
||||
|
||||
virtual Optional<std::vector<std::unique_ptr<FeatureParagraph>>> visit_array(Json::Reader& r,
|
||||
const Json::Array& arr) override
|
||||
{
|
||||
return r.visit_value(arr,
|
||||
Json::ArrayDeserializer<ArrayFeatureDeserializer>{"an array of feature objects",
|
||||
Json::AllowEmpty::Yes});
|
||||
}
|
||||
|
||||
virtual Optional<std::vector<std::unique_ptr<FeatureParagraph>>> visit_object(Json::Reader& r,
|
||||
const Json::Object& obj) override
|
||||
{
|
||||
std::vector<std::unique_ptr<FeatureParagraph>> res;
|
||||
std::vector<std::string> extra_fields;
|
||||
|
||||
FeatureDeserializer deserializer;
|
||||
for (const auto& pr : obj)
|
||||
{
|
||||
if (!Json::IdentifierDeserializer::is_ident(pr.first))
|
||||
{
|
||||
extra_fields.push_back(pr.first.to_string());
|
||||
continue;
|
||||
}
|
||||
deserializer.name.assign(pr.first.begin(), pr.first.end());
|
||||
auto field = r.visit_map_field(pr.first, pr.second, deserializer);
|
||||
if (auto p = field.get())
|
||||
{
|
||||
res.push_back(std::move(*p));
|
||||
}
|
||||
}
|
||||
|
||||
if (!extra_fields.empty())
|
||||
{
|
||||
r.add_extra_fields_error(type_name(), std::move(extra_fields));
|
||||
}
|
||||
|
||||
return std::move(res);
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr StringView EXPRESSION_WORDS[] = {
|
||||
"WITH",
|
||||
"AND",
|
||||
@ -717,11 +795,7 @@ namespace vcpkg
|
||||
Json::ArrayDeserializer<Json::IdentifierDeserializer>{"an array of identifiers",
|
||||
Json::AllowEmpty::Yes});
|
||||
|
||||
r.optional_object_field(
|
||||
obj,
|
||||
FEATURES,
|
||||
control_file->feature_paragraphs,
|
||||
Json::ArrayDeserializer<FeatureDeserializer>{"an array of feature definitions", Json::AllowEmpty::Yes});
|
||||
r.optional_object_field(obj, FEATURES, control_file->feature_paragraphs, FeaturesFieldDeserializer{});
|
||||
|
||||
canonicalize(*control_file);
|
||||
return std::move(control_file);
|
||||
@ -1001,16 +1075,15 @@ namespace vcpkg
|
||||
|
||||
if (!scf.feature_paragraphs.empty() || debug)
|
||||
{
|
||||
auto& arr = obj.insert(ManifestDeserializer::FEATURES, Json::Array());
|
||||
auto& map = obj.insert(ManifestDeserializer::FEATURES, Json::Object());
|
||||
for (const auto& feature : scf.feature_paragraphs)
|
||||
{
|
||||
auto& feature_obj = arr.push_back(Json::Object());
|
||||
auto& feature_obj = map.insert(feature->name, Json::Object());
|
||||
for (const auto& el : feature->extra_info)
|
||||
{
|
||||
feature_obj.insert(el.first.to_string(), el.second);
|
||||
}
|
||||
|
||||
feature_obj.insert(FeatureDeserializer::NAME, Json::Value::string(feature->name));
|
||||
serialize_paragraph(feature_obj, FeatureDeserializer::DESCRIPTION, feature->description, true);
|
||||
|
||||
if (!feature->dependencies.empty() || debug)
|
||||
|
Loading…
Reference in New Issue
Block a user