Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vcpkg manifests] fix some issues #12227

Merged
merged 25 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions docs/maintainers/control-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ The first paragraph in a `CONTROL` file is the Source paragraph. It must have a
### Examples:
```no-highlight
Source: ace
Version: 6.5.5-1
Version: 6.5.5
Description: The ADAPTIVE Communication Environment
```

```no-highlight
Source: vtk
Version: 8.2.0-2
Version: 8.2.0
Port-Version: 2
Description: Software system for 3D computer graphics, image processing, and visualization
Build-Depends: zlib, libpng, tiff, libxml2, jsoncpp, glew, freetype, expat, hdf5, libjpeg-turbo, proj4, lz4, libtheora, atlmfc (windows), eigen3, double-conversion, pugixml, libharu, sqlite3, netcdf-c
```
Expand All @@ -39,15 +40,14 @@ Package collections to check for conflicts:
+ [Packages search](https://pkgs.org/)

#### Version
The port version.
The library version.

This field is an alphanumeric string that may also contain `.`, `_`, or `-`. No attempt at ordering versions is made; all versions are treated as bit strings and are only evaluated for equality.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to remove "No attempt at ordering versions is made" in preparation for adding versioning.


For tagged-release ports, we follow the following convention:

1. If the port follows a scheme like `va.b.c`, we remove the leading `v`. In this case, it becomes `a.b.c`.
2. If the port includes its own name in the version like `curl-7_65_1`, we remove the leading name: `7_65_1`
3. If the port has been modified, we append a `-N` to distinguish the versions: `1.2.1-4`

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.

Expand All @@ -56,11 +56,17 @@ For example, given:
2. The current version string is `2019-02-14-1`
3. Today's date is 2019-06-01.

Then if you update the source version today, you should give it version `2019-06-01`. If you need to make a change which doesn't adjust the source version, you should give it version `2019-02-14-2`.
Then if you update the source version today, you should give it version `2019-06-01`.

#### Port-Version
The version of the port.

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:
```no-highlight
Version: 1.0.5-2
Version: 1.0.5
Port-Version: 2
```
```no-highlight
Version: 2019-03-21
Expand All @@ -77,7 +83,7 @@ Description: C++ header-only JSON library
```
```no-highlight
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
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.
````

Expand Down
3 changes: 2 additions & 1 deletion ports/zlib/CONTROL
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Source: zlib
Version: 1.2.11-6
Version: 1.2.11
Port-Version: 6
Homepage: https://www.zlib.net/
Description: A compression library
71 changes: 52 additions & 19 deletions scripts/buildsystems/vcpkg.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ option(VCPKG_VERBOSE "Enables messages from the VCPKG toolchain for debugging pu
mark_as_advanced(VCPKG_VERBOSE)

function(_vcpkg_get_directory_name_of_file_above OUT DIRECTORY FILENAME)
if(DEFINED ${OUT})
strega-nil marked this conversation as resolved.
Show resolved Hide resolved
return()
endif()

set(_vcpkg_get_dir_candidate ${DIRECTORY})
while(IS_DIRECTORY ${_vcpkg_get_dir_candidate} AND NOT DEFINED _vcpkg_get_dir_out)
if(EXISTS ${_vcpkg_get_dir_candidate}/${FILENAME})
Expand All @@ -27,24 +23,37 @@ function(_vcpkg_get_directory_name_of_file_above OUT DIRECTORY FILENAME)
set(${OUT} ${_vcpkg_get_dir_out} CACHE INTERNAL "_vcpkg_get_directory_name_of_file_above: ${OUT}")
endfunction()

_vcpkg_get_directory_name_of_file_above(_VCPKG_MANIFEST_DIR ${CMAKE_CURRENT_SOURCE_DIR} "vcpkg.json")
if(_VCPKG_MANIFEST_DIR)
set(_VCPKG_MANIFEST_MODE_DEFAULT ON)
if(NOT DEFINED VCPKG_MANIFEST_MODE)
_vcpkg_get_directory_name_of_file_above(_VCPKG_MANIFEST_DIR ${CMAKE_CURRENT_SOURCE_DIR} "vcpkg.json")

if(_VCPKG_MANIFEST_DIR)
set(VCPKG_MANIFEST_MODE ON)
else()
set(VCPKG_MANIFEST_MODE OFF)
endif()
elseif(VCPKG_MANIFEST_MODE)
_vcpkg_get_directory_name_of_file_above(_VCPKG_MANIFEST_DIR ${CMAKE_CURRENT_SOURCE_DIR} "vcpkg.json")

if(NOT _VCPKG_MANIFEST_DIR)
message(FATAL_ERROR
"vcpkg manifest mode was enabled, but we couldn't find a manifest file (vcpkg.json) "
"in any directories above ${CMAKE_CURRENT_SOURCE_DIR}. Please add a manifest, or "
"disable manifests by turning off VCPKG_MANIFEST_MODE.")
endif()
else()
set(_VCPKG_MANIFEST_MODE_DEFAULT OFF)
set(VCPKG_MANIFEST_MODE OFF)
strega-nil marked this conversation as resolved.
Show resolved Hide resolved
endif()

option(VCPKG_MANIFEST_MODE "Set vcpkg to manifest mode" ${_VCPKG_MANIFEST_MODE_DEFAULT})

if(NOT _VCPKG_MANIFEST_DIR AND VCPKG_MANIFEST_MODE)
message(FATAL_ERROR
"vcpkg manifest mode was enabled, but we couldn't find a manifest file (vcpkg.json) "
"in any directories above ${CMAKE_CURRENT_SOURCE_DIR}. Please add a manifest, or "
"disable manifests by turning off VCPKG_MANIFEST_MODE.")
if(VCPKG_MANIFEST_MODE)
option(VCPKG_MANIFEST_INSTALL
[[
Install the dependencies listed in your manifest:
If this is off, you will have to manually install your dependencies.
See https://github.com/microsoft/vcpkg/tree/master/docs/specifications/manifests.md for more info.
]]
ON)
endif()

option(VCPKG_MANIFEST_INSTALL "Install packages from the manifest" ON)

# Determine whether the toolchain is loaded during a try-compile configuration
get_property(_CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)

Expand Down Expand Up @@ -271,11 +280,31 @@ endforeach()
# CMAKE_EXECUTABLE_SUFFIX is not yet defined
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
set(_VCPKG_EXECUTABLE_SUFFIX ".exe")
set(_VCPKG_SCRIPT_SUFFIX ".bat")
else()
set(_VCPKG_EXECUTABLE_SUFFIX "")
set(_VCPKG_SCRIPT_SUFFIX ".sh")
endif()
strega-nil marked this conversation as resolved.
Show resolved Hide resolved

if(VCPKG_MANIFEST_MODE AND VCPKG_MANIFEST_INSTALL AND NOT _CMAKE_IN_TRY_COMPILE)
set(_VCPKG_EXECUTABLE "${_VCPKG_ROOT_DIR}/vcpkg${_VCPKG_EXECUTABLE_SUFFIX}")
strega-nil marked this conversation as resolved.
Show resolved Hide resolved

if(NOT EXISTS "${_VCPKG_EXECUTABLE}")
message(STATUS "Bootstrapping vcpkg before install")

execute_process(
COMMAND "${_VCPKG_ROOT_DIR}/bootstrap-vcpkg${_VCPKG_SCRIPT_SUFFIX}"
RESULT_VARIABLE _VCPKG_BOOTSTRAP_RESULT)

if (_VCPKG_BOOTSTRAP_RESULT EQUAL 0)
message(STATUS "Bootstrapping vcpkg before install - done")
else()
message(FATAL_ERROR "Bootstrapping vcpkg before install - failed")
endif()
endif()

message(STATUS "Running vcpkg install")

execute_process(
COMMAND "${_VCPKG_ROOT_DIR}/vcpkg${_VCPKG_EXECUTABLE_SUFFIX}" install
strega-nil marked this conversation as resolved.
Show resolved Hide resolved
--triplet ${VCPKG_TARGET_TRIPLET}
Expand All @@ -284,9 +313,13 @@ if(VCPKG_MANIFEST_MODE AND VCPKG_MANIFEST_INSTALL AND NOT _CMAKE_IN_TRY_COMPILE)
--x-install-root=${_VCPKG_INSTALLED_DIR}
--binarycaching
RESULT_VARIABLE _VCPKG_INSTALL_RESULT)
if (NOT _VCPKG_INSTALL_RESULT EQUAL 0)
message(FATAL_ERROR "vcpkg install failed")

if (_VCPKG_INSTALL_RESULT EQUAL 0)
strega-nil marked this conversation as resolved.
Show resolved Hide resolved
message(STATUS "Running vcpkg install - done")
else()
message(FATAL_ERROR "Running vcpkg install - failed")
endif()

set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
"${_VCPKG_MANIFEST_DIR}/vcpkg.json"
"${_VCPKG_INSTALLED_DIR}/vcpkg/status")
Expand Down
3 changes: 3 additions & 0 deletions toolsrc/include/vcpkg/base/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ namespace vcpkg::Files
virtual void current_path(const fs::path& path, std::error_code&) = 0;
void current_path(const fs::path& path, LineInfo li);

// waits forever for the file lock
virtual fs::SystemHandle take_exclusive_file_lock(const fs::path& path, std::error_code&) = 0;
// waits, at most, 1.5 seconds, for the file lock
virtual fs::SystemHandle try_take_exclusive_file_lock(const fs::path& path, std::error_code&) = 0;
virtual void unlock_file_lock(fs::SystemHandle handle, std::error_code&) = 0;

Expand Down
3 changes: 3 additions & 0 deletions toolsrc/include/vcpkg/vcpkgcmdarguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ namespace vcpkg
constexpr static StringLiteral PRINT_METRICS_SWITCH = "printmetrics";
Optional<bool> print_metrics = nullopt;

constexpr static StringLiteral WAIT_FOR_LOCK_SWITCH = "x-wait-for-lock";
Optional<bool> wait_for_lock = nullopt;

// feature flags
constexpr static StringLiteral FEATURE_FLAGS_ENV = "VCPKG_FEATURE_FLAGS";
constexpr static StringLiteral FEATURE_FLAGS_ARG = "feature-flags";
Expand Down
13 changes: 7 additions & 6 deletions toolsrc/include/vcpkg/versiont.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ namespace vcpkg
struct VersionT
{
VersionT() noexcept;
VersionT(std::string&& value);
VersionT(const std::string& value);
VersionT(std::string&& value, int port_version);
VersionT(const std::string& value, int port_version);

const std::string& to_string() const;
std::string to_string() const;

friend bool operator==(const VersionT& left, const VersionT& right);
friend bool operator!=(const VersionT& left, const VersionT& right);

private:
std::string value;
int port_version;
};

bool operator==(const VersionT& left, const VersionT& right);
bool operator!=(const VersionT& left, const VersionT& right);

struct VersionDiff
{
VersionT left;
Expand Down
84 changes: 64 additions & 20 deletions toolsrc/src/vcpkg/base/files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -873,15 +873,18 @@ namespace vcpkg::Files
fs::stdfs::current_path(path, ec);
}

virtual fs::SystemHandle try_take_exclusive_file_lock(const fs::path& path, std::error_code& ec) override
struct TakeExclusiveFileLockHelper
{
fs::SystemHandle res;
fs::SystemHandle& res;
fs::path::string_type native;
strega-nil marked this conversation as resolved.
Show resolved Hide resolved
TakeExclusiveFileLockHelper(fs::SystemHandle& res, const fs::path::string_type& native)
: res(res), native(native)
{ }

const auto system_file_name = path.native();
#if defined(WIN32)
constexpr static auto busy_error = ERROR_BUSY;
const auto system_try_take_file_lock = [&] {
auto handle = CreateFileW(system_file_name.c_str(),
bool operator()(std::error_code& ec) {
auto handle = CreateFileW(native.c_str(),
GENERIC_READ,
0 /* no sharing */,
nullptr /* no security attributes */,
Expand All @@ -900,17 +903,23 @@ namespace vcpkg::Files

res.system_handle = reinterpret_cast<intptr_t>(handle);
return true;
};
}
#else // ^^^ WIN32 / !WIN32 vvv
constexpr static auto busy_error = EBUSY;
int fd = open(system_file_name.c_str(), 0);
if (fd < 0)
{
ec.assign(errno, std::system_category());
return res;
}
const auto system_try_take_file_lock = [&] {
if (flock(fd, LOCK_EX | LOCK_NB) != 0)
int fd = -1;

bool operator()(std::error_code& ec) {
if (fd == -1)
{
fd = ::open(native.c_str(), 0);
if (fd < 0)
{
ec.assign(errno, std::system_category());
strega-nil marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
}

if (::flock(fd, LOCK_EX | LOCK_NB) != 0)
{
if (errno != EWOULDBLOCK)
{
Expand All @@ -920,11 +929,48 @@ namespace vcpkg::Files
}

res.system_handle = fd;
fd = -1;
return true;
};

~TakeExclusiveFileLockHelper() {
if (fd != -1)
{
::close(fd);
}
}
#endif
};

if (system_try_take_file_lock() || ec)
virtual fs::SystemHandle take_exclusive_file_lock(const fs::path& path, std::error_code& ec) override
{
fs::SystemHandle res;
TakeExclusiveFileLockHelper helper(res, path.native());

if (helper(ec) || ec)
strega-nil marked this conversation as resolved.
Show resolved Hide resolved
{
return res;
}

System::printf("Waiting to take filesystem lock on %s...\n", path.u8string());
const auto wait = std::chrono::milliseconds(1000);
// infinite loop
strega-nil marked this conversation as resolved.
Show resolved Hide resolved
for (;;)
{
std::this_thread::sleep_for(wait);
if (helper(ec) || ec)
{
return res;
}
}
}

virtual fs::SystemHandle try_take_exclusive_file_lock(const fs::path& path, std::error_code& ec) override
{
fs::SystemHandle res;
TakeExclusiveFileLockHelper helper(res, path.native());

if (helper(ec) || ec)
{
return res;
}
Expand All @@ -935,19 +981,17 @@ namespace vcpkg::Files
while (wait < std::chrono::milliseconds(1000))
{
std::this_thread::sleep_for(wait);
if (system_try_take_file_lock() || ec)
if (helper(ec) || ec)
{
return res;
}
wait *= 2;
}

#if !defined(WIN32)
close(fd);
#endif
ec.assign(busy_error, std::system_category());
ec.assign(helper.busy_error, std::system_category());
return res;
}

virtual void unlock_file_lock(fs::SystemHandle handle, std::error_code& ec) override
{
#if defined(WIN32)
Expand Down
5 changes: 3 additions & 2 deletions toolsrc/src/vcpkg/commands.list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ namespace vcpkg::Commands::List

static void do_print(const StatusParagraph& pgh, const bool full_desc)
{
auto full_version = pgh.package.port_version == 0 ? pgh.package.version : Strings::format("%s#%d", pgh.package.version, pgh.package.port_version);
if (full_desc)
{
System::printf("%-50s %-16s %s\n",
pgh.package.displayname(),
pgh.package.version,
full_version,
Strings::join("\n ", pgh.package.description));
}
else
Expand All @@ -28,7 +29,7 @@ namespace vcpkg::Commands::List
}
System::printf("%-50s %-16s %s\n",
vcpkg::shorten_text(pgh.package.displayname(), 50),
vcpkg::shorten_text(pgh.package.version, 16),
vcpkg::shorten_text(full_version, 16),
vcpkg::shorten_text(description, 51));
}
}
Expand Down
5 changes: 4 additions & 1 deletion toolsrc/src/vcpkg/commands.portsdiff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ namespace vcpkg::Commands::PortsDiff
Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string);
std::map<std::string, VersionT> names_and_versions;
for (auto&& port : all_ports)
names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version);
{
const auto& core_pgh = *port->core_paragraph;
names_and_versions.emplace(port->core_paragraph->name, VersionT(core_pgh.version, core_pgh.port_version));
}
fs.remove_all(temp_checkout_path, VCPKG_LINE_INFO);
return names_and_versions;
}
Expand Down
Loading