Vcpkg: Installing an additional feature of a port also includes default features of that port

Created on 30 Jul 2019  路  6Comments  路  Source: microsoft/vcpkg

Describe the bug
If you have a small set of features installed for a port, then try to install 1 more feature, you also get all the default features of that port.

Environment

  • OS: Windows, though it shouldn't matter.
  • Compiler: VS 2019 Update 2.

To Reproduce
As part of an experiment to enable control of the HTTP compression feature in cpprestsdk, I set my CONTROL file to:

Source: cpprestsdk
Version: 2.10.14
Build-Depends: openssl (!uwp&!windows), boost-system (!uwp&!windows), boost-date-time (!uwp&!windows), boost-regex (!uwp&!windows), boost-thread (!uwp&!windows), boost-filesystem (!uwp&!windows), boost-random (!uwp&!windows), boost-chrono (!uwp&!windows), boost-asio (!uwp&!windows)
Homepage: https://github.com/Microsoft/cpprestsdk
Description: C++11 JSON, REST, and OAuth library
  The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.
Default-Features: default-features

Feature: default-features
Build-Depends: cpprestsdk[brotli] (windows), cpprestsdk[compression], cpprestsdk[websockets]
Description: Features installed by default

Feature: compression
Build-Depends: zlib
Description: HTTP Compression support

Feature: websockets
Build-Depends: websocketpp (!uwp), openssl (!uwp), boost-system (!uwp), boost-date-time (!uwp), boost-regex (!uwp)
Description: Websockets support

Feature: brotli
Build-Depends: cpprestsdk[compression], brotli
Description: Brotli compression support

and my portfile to:

include(vcpkg_common_functions)

vcpkg_from_github(
    OUT_SOURCE_PATH SOURCE_PATH
    REPO Microsoft/cpprestsdk
    REF v2.10.14
    SHA512 7208b8c31e42a9bda2bf1d5c65527e54e3f946ec57743aaf7058c12a311de78de354d5ff859f35b3a8936c8964ac5695a692e234f3365edc426cf9580f76cd4f
    HEAD_REF master
)

set(OPTIONS)
if(NOT VCPKG_CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
    SET(WEBSOCKETPP_PATH "${CURRENT_INSTALLED_DIR}/share/websocketpp")
    list(APPEND OPTIONS
        -DWEBSOCKETPP_CONFIG=${WEBSOCKETPP_PATH}
        -DWEBSOCKETPP_CONFIG_VERSION=${WEBSOCKETPP_PATH})
endif()

set(CPPREST_EXCLUDE_BROTLI ON)
if ("brotli" IN_LIST FEATURES)
    set(CPPREST_EXCLUDE_BROTLI OFF)
endif()

set(CPPREST_EXCLUDE_COMPRESSION ON)
if ("compression" IN_LIST FEATURES)
    set(CPPREST_EXCLUDE_COMPRESSION OFF)
endif()

set(CPPREST_EXCLUDE_WEBSOCKETS ON)
if("websockets" IN_LIST FEATURES)
    set(CPPREST_EXCLUDE_WEBSOCKETS OFF)
endif()

vcpkg_configure_cmake(
    SOURCE_PATH ${SOURCE_PATH}/Release
    PREFER_NINJA
    OPTIONS
        ${OPTIONS}
        -DBUILD_TESTS=OFF
        -DBUILD_SAMPLES=OFF
        -DCPPREST_EXCLUDE_BROTLI=${CPPREST_EXCLUDE_BROTLI}
        -DCPPREST_EXCLUDE_COMPRESSION=${CPPREST_EXCLUDE_COMPRESSION}
        -DCPPREST_EXCLUDE_WEBSOCKETS=${CPPREST_EXCLUDE_WEBSOCKETS}
        -DCPPREST_EXPORT_DIR=share/cpprestsdk
        -DWERROR=OFF
    OPTIONS_DEBUG
        -DCPPREST_INSTALL_HEADERS=OFF
)

vcpkg_install_cmake()

vcpkg_fixup_cmake_targets(CONFIG_PATH lib/share/cpprestsdk)
file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/lib/share ${CURRENT_PACKAGES_DIR}/lib/share)

file(INSTALL
    ${SOURCE_PATH}/license.txt
    DESTINATION ${CURRENT_PACKAGES_DIR}/share/cpprestsdk RENAME copyright)

vcpkg_copy_pdbs()

I don't know if these files work yet; I encountered this issue attempting to test it.

Steps to reproduce the behavior:

  1. (change cpprestsdk ports to the above)
  2. ./vcpkg install cpprestsdk[core]
  3. (vcpkg will happily install the core features)
  4. ./vcpkg install cpprestsdk[compression], note that vcpkg also added a whole bunch of unselected features:
C:\Dev\vcpkg>.\vcpkg.exe install cpprestsdk[compression]
The following packages will be rebuilt:
    cpprestsdk[brotli,compression,core,default-features,websockets]:x86-windows
The following packages will be built and installed:
  * boost-algorithm[core]:x86-windows
  * boost-array[core]:x86-windows
  * boost-asio[core]:x86-windows
  * boost-assert[core]:x86-windows
  * boost-atomic[core]:x86-windows
  * boost-bind[core]:x86-windows
  * boost-build[core]:x86-windows
  * boost-chrono[core]:x86-windows
  * boost-compatibility[core]:x86-windows
  * boost-concept-check[core]:x86-windows
  * boost-config[core]:x86-windows
  * boost-container[core]:x86-windows
  * boost-container-hash[core]:x86-windows
  * boost-context[core]:x86-windows
  * boost-conversion[core]:x86-windows
  * boost-core[core]:x86-windows
  * boost-coroutine[core]:x86-windows
  * boost-date-time[core]:x86-windows
  * boost-detail[core]:x86-windows
  * boost-exception[core]:x86-windows
  * boost-function[core]:x86-windows
  * boost-function-types[core]:x86-windows
  * boost-functional[core]:x86-windows
  * boost-fusion[core]:x86-windows
  * boost-integer[core]:x86-windows
  * boost-intrusive[core]:x86-windows
  * boost-io[core]:x86-windows
  * boost-iterator[core]:x86-windows
  * boost-lambda[core]:x86-windows
  * boost-lexical-cast[core]:x86-windows
  * boost-math[core]:x86-windows
  * boost-modular-build-helper[core]:x86-windows
  * boost-move[core]:x86-windows
  * boost-mpl[core]:x86-windows
  * boost-multiprecision[core]:x86-windows
  * boost-numeric-conversion[core]:x86-windows
  * boost-optional[core]:x86-windows
  * boost-pool[core]:x86-windows
  * boost-predef[core]:x86-windows
  * boost-preprocessor[core]:x86-windows
  * boost-range[core]:x86-windows
  * boost-ratio[core]:x86-windows
  * boost-rational[core]:x86-windows
  * boost-regex[core]:x86-windows
  * boost-smart-ptr[core]:x86-windows
  * boost-static-assert[core]:x86-windows
  * boost-system[core]:x86-windows
  * boost-thread[core]:x86-windows
  * boost-throw-exception[core]:x86-windows
  * boost-tokenizer[core]:x86-windows
  * boost-tuple[core]:x86-windows
  * boost-type-index[core]:x86-windows
  * boost-type-traits[core]:x86-windows
  * boost-typeof[core]:x86-windows
  * boost-unordered[core]:x86-windows
  * boost-utility[core]:x86-windows
  * boost-vcpkg-helpers[core]:x86-windows
  * boost-winapi[core]:x86-windows
  * brotli[core]:x86-windows
  * openssl[core]:x86-windows
  * openssl-windows[core]:x86-windows
  * websocketpp[core]:x86-windows
  * zlib[core]:x86-windows
Additional packages (*) will be modified to complete this operation.
If you are sure you want to rebuild the above packages, run the command with the --recurse option

Expected behavior
After vcpkg install package[feature] either:

  1. The configuration of the package is changed to contain only [feature], or
  2. The existing installed features of the package are added to [feature], the existing package is purged, and then package[feature, whatever was there before] is installed.

Failure logs
(N/A)

Additional context
(N/A)

vcpkg-bug

Most helpful comment

If the design is

port[feature1,feature2] is intended to mean the same thing all the time, regardless of what you have installed

that is not the current behavior. If the port is already installed, you get completely different behavior. For example (with the changes at https://github.com/microsoft/vcpkg/pull/7472 ):

C:\Dev\vcpkg>vcpkg list
brotli:x86-windows                                 1.0.7            a generic-purpose lossless compression algorithm...
zlib:x86-windows                                   1.2.11-5         A compression library

C:\Dev\vcpkg>.\vcpkg.exe install cpprestsdk[core,compression]
The following packages will be built and installed:
    cpprestsdk[compression,core]:x86-windows
Starting package 1/1: cpprestsdk:x86-windows
Building package cpprestsdk[compression,core]:x86-windows...
-- Using cached C:/Dev/vcpkg_downloads/Microsoft-cpprestsdk-v2.10.14.tar.gz
-- Using source at C:/Dev/vcpkg/buildtrees/cpprestsdk/src/v2.10.14-101423beaf
-- Configuring x86-windows
-- Building x86-windows-dbg
-- Building x86-windows-rel
-- Installing: C:/Dev/vcpkg/packages/cpprestsdk_x86-windows/share/cpprestsdk/copyright
-- Performing post-build validation
-- Performing post-build validation done
Building package cpprestsdk[compression,core]:x86-windows... done
Installing package cpprestsdk[compression,core]:x86-windows...
Installing package cpprestsdk[compression,core]:x86-windows... done
Elapsed time for package cpprestsdk:x86-windows: 21.18 s

Total elapsed time: 21.18 s

The package cpprestsdk:x86-windows provides CMake targets:

    find_package(cpprestsdk CONFIG REQUIRED)
    target_link_libraries(main PRIVATE cpprestsdk::cpprest cpprestsdk::cpprestsdk_zlib_internal)

OK fine.

C:\Dev\vcpkg>.\vcpkg.exe install cpprestsdk[core,compression,brotli]
The following packages will be rebuilt:
    cpprestsdk[brotli,compression,core,default-features,websockets]:x86-windows
The following packages will be built and installed:
  * boost-algorithm[core]:x86-windows
  * boost-array[core]:x86-windows
  * boost-asio[core]:x86-windows
  * boost-assert[core]:x86-windows
  * boost-atomic[core]:x86-windows
  * boost-bind[core]:x86-windows
  * boost-build[core]:x86-windows
  * boost-chrono[core]:x86-windows
  * boost-compatibility[core]:x86-windows
  * boost-concept-check[core]:x86-windows
  * boost-config[core]:x86-windows
  * boost-container[core]:x86-windows
  * boost-container-hash[core]:x86-windows
  * boost-context[core]:x86-windows
  * boost-conversion[core]:x86-windows
  * boost-core[core]:x86-windows
  * boost-coroutine[core]:x86-windows
  * boost-date-time[core]:x86-windows
  * boost-detail[core]:x86-windows
  * boost-exception[core]:x86-windows
  * boost-function[core]:x86-windows
  * boost-function-types[core]:x86-windows
  * boost-functional[core]:x86-windows
  * boost-fusion[core]:x86-windows
  * boost-integer[core]:x86-windows
  * boost-intrusive[core]:x86-windows
  * boost-io[core]:x86-windows
  * boost-iterator[core]:x86-windows
  * boost-lambda[core]:x86-windows
  * boost-lexical-cast[core]:x86-windows
  * boost-math[core]:x86-windows
  * boost-modular-build-helper[core]:x86-windows
  * boost-move[core]:x86-windows
  * boost-mpl[core]:x86-windows
  * boost-multiprecision[core]:x86-windows
  * boost-numeric-conversion[core]:x86-windows
  * boost-optional[core]:x86-windows
  * boost-pool[core]:x86-windows
  * boost-predef[core]:x86-windows
  * boost-preprocessor[core]:x86-windows
  * boost-range[core]:x86-windows
  * boost-ratio[core]:x86-windows
  * boost-rational[core]:x86-windows
  * boost-regex[core]:x86-windows
  * boost-smart-ptr[core]:x86-windows
  * boost-static-assert[core]:x86-windows
  * boost-system[core]:x86-windows
  * boost-thread[core]:x86-windows
  * boost-throw-exception[core]:x86-windows
  * boost-tokenizer[core]:x86-windows
  * boost-tuple[core]:x86-windows
  * boost-type-index[core]:x86-windows
  * boost-type-traits[core]:x86-windows
  * boost-typeof[core]:x86-windows
  * boost-unordered[core]:x86-windows
  * boost-utility[core]:x86-windows
  * boost-vcpkg-helpers[core]:x86-windows
  * boost-winapi[core]:x86-windows
  * openssl[core]:x86-windows
  * openssl-windows[core]:x86-windows
  * websocketpp[core]:x86-windows
Additional packages (*) will be modified to complete this operation.
If you are sure you want to rebuild the above packages, run the command with the --recurse option

Wait, what? Why did default-features and websockets show up?

C:\Dev\vcpkg>.\vcpkg remove cpprestsdk
The following packages will be removed:
    cpprestsdk:x86-windows
Removing package cpprestsdk:x86-windows...
Removing package cpprestsdk:x86-windows... done
Purging package cpprestsdk:x86-windows...
Purging package cpprestsdk:x86-windows... done

C:\Dev\vcpkg>.\vcpkg.exe install cpprestsdk[core,compression,brotli]
The following packages will be built and installed:
    cpprestsdk[brotli,compression,core]:x86-windows
Starting package 1/1: cpprestsdk:x86-windows
Building package cpprestsdk[brotli,compression,core]:x86-windows...
-- Using cached C:/Dev/vcpkg_downloads/Microsoft-cpprestsdk-v2.10.14.tar.gz
-- Using source at C:/Dev/vcpkg/buildtrees/cpprestsdk/src/v2.10.14-101423beaf
-- Configuring x86-windows
-- Building x86-windows-dbg
-- Building x86-windows-rel
-- Installing: C:/Dev/vcpkg/packages/cpprestsdk_x86-windows/share/cpprestsdk/copyright
-- Performing post-build validation
-- Performing post-build validation done
Building package cpprestsdk[brotli,compression,core]:x86-windows... done
Installing package cpprestsdk[brotli,compression,core]:x86-windows...
Installing package cpprestsdk[brotli,compression,core]:x86-windows... done
Elapsed time for package cpprestsdk:x86-windows: 20.83 s

Total elapsed time: 20.83 s

The package cpprestsdk:x86-windows provides CMake targets:

    find_package(cpprestsdk CONFIG REQUIRED)
    target_link_libraries(main PRIVATE cpprestsdk::cpprest cpprestsdk::cpprestsdk_zlib_internal cpprestsdk::cpprestsdk_brotli_internal)

If you remove the package first, and then ask for it, you get only the features you asked for.

All 6 comments

Hmmm this actually seems to be because core is missing, so vcpkg is adding the default features.

Actually it does look borked, I tried adding core explicitly and it still tries to install everything...

Let me explain what factors cause the current behavior:

  1. port[feature1,feature2] is intended to mean the same thing all the time, regardless of what you have installed
  2. port implies all default features
  3. port[feature1] implies all default features + feature1
  4. port[core,feature1] is how to "spell" a reference to only feature1 of port

Therefore, the current design's interpretation of install cpprestsdk[compression] is "install everything implied by cpprestsdk[compression], which means cpprestsdk[default-features,compression]."

The behaviors described in your "expected behavior" have the following "issues":

  1. This option results in "install" removing features. This seems highly unexpected -- but we _are_ looking at an alternative command which does exactly this (set-installed, see [1]).
  2. This option makes cpprestsdk[compression] mean different things depending on what is currently installed. If cpprestsdk[core] is currently installed, then you don't get websockets support. If cpprestsdk isn't currently installed, then you do get websockets support.

Finally, the by-current-design method to get the behavior you want is to run vcpkg install cpprestsdk[core,compression]. Under all circumstances, this will result in an installed cpprestsdk package which contains _at least_ the compression feature and preserves the implied semantics of all previous install commands.

[1] https://github.com/microsoft/vcpkg/pull/6873

Hmmm that suggests this behavior was broken: https://github.com/microsoft/vcpkg/blob/master/ports/cpprestsdk/CONTROL#L10 since it does cpprestsdk[brotli] (windows), cpprestsdk[websockets] but would have to do cpprestsdk[core,brotli] (windows), cpprestsdk[core,websockets] ?

Those are entries in the "default-features" feature, which implies that all default features are being included. So in this _specific_ instance it's benign, but you're right about the general case :)

If the design is

port[feature1,feature2] is intended to mean the same thing all the time, regardless of what you have installed

that is not the current behavior. If the port is already installed, you get completely different behavior. For example (with the changes at https://github.com/microsoft/vcpkg/pull/7472 ):

C:\Dev\vcpkg>vcpkg list
brotli:x86-windows                                 1.0.7            a generic-purpose lossless compression algorithm...
zlib:x86-windows                                   1.2.11-5         A compression library

C:\Dev\vcpkg>.\vcpkg.exe install cpprestsdk[core,compression]
The following packages will be built and installed:
    cpprestsdk[compression,core]:x86-windows
Starting package 1/1: cpprestsdk:x86-windows
Building package cpprestsdk[compression,core]:x86-windows...
-- Using cached C:/Dev/vcpkg_downloads/Microsoft-cpprestsdk-v2.10.14.tar.gz
-- Using source at C:/Dev/vcpkg/buildtrees/cpprestsdk/src/v2.10.14-101423beaf
-- Configuring x86-windows
-- Building x86-windows-dbg
-- Building x86-windows-rel
-- Installing: C:/Dev/vcpkg/packages/cpprestsdk_x86-windows/share/cpprestsdk/copyright
-- Performing post-build validation
-- Performing post-build validation done
Building package cpprestsdk[compression,core]:x86-windows... done
Installing package cpprestsdk[compression,core]:x86-windows...
Installing package cpprestsdk[compression,core]:x86-windows... done
Elapsed time for package cpprestsdk:x86-windows: 21.18 s

Total elapsed time: 21.18 s

The package cpprestsdk:x86-windows provides CMake targets:

    find_package(cpprestsdk CONFIG REQUIRED)
    target_link_libraries(main PRIVATE cpprestsdk::cpprest cpprestsdk::cpprestsdk_zlib_internal)

OK fine.

C:\Dev\vcpkg>.\vcpkg.exe install cpprestsdk[core,compression,brotli]
The following packages will be rebuilt:
    cpprestsdk[brotli,compression,core,default-features,websockets]:x86-windows
The following packages will be built and installed:
  * boost-algorithm[core]:x86-windows
  * boost-array[core]:x86-windows
  * boost-asio[core]:x86-windows
  * boost-assert[core]:x86-windows
  * boost-atomic[core]:x86-windows
  * boost-bind[core]:x86-windows
  * boost-build[core]:x86-windows
  * boost-chrono[core]:x86-windows
  * boost-compatibility[core]:x86-windows
  * boost-concept-check[core]:x86-windows
  * boost-config[core]:x86-windows
  * boost-container[core]:x86-windows
  * boost-container-hash[core]:x86-windows
  * boost-context[core]:x86-windows
  * boost-conversion[core]:x86-windows
  * boost-core[core]:x86-windows
  * boost-coroutine[core]:x86-windows
  * boost-date-time[core]:x86-windows
  * boost-detail[core]:x86-windows
  * boost-exception[core]:x86-windows
  * boost-function[core]:x86-windows
  * boost-function-types[core]:x86-windows
  * boost-functional[core]:x86-windows
  * boost-fusion[core]:x86-windows
  * boost-integer[core]:x86-windows
  * boost-intrusive[core]:x86-windows
  * boost-io[core]:x86-windows
  * boost-iterator[core]:x86-windows
  * boost-lambda[core]:x86-windows
  * boost-lexical-cast[core]:x86-windows
  * boost-math[core]:x86-windows
  * boost-modular-build-helper[core]:x86-windows
  * boost-move[core]:x86-windows
  * boost-mpl[core]:x86-windows
  * boost-multiprecision[core]:x86-windows
  * boost-numeric-conversion[core]:x86-windows
  * boost-optional[core]:x86-windows
  * boost-pool[core]:x86-windows
  * boost-predef[core]:x86-windows
  * boost-preprocessor[core]:x86-windows
  * boost-range[core]:x86-windows
  * boost-ratio[core]:x86-windows
  * boost-rational[core]:x86-windows
  * boost-regex[core]:x86-windows
  * boost-smart-ptr[core]:x86-windows
  * boost-static-assert[core]:x86-windows
  * boost-system[core]:x86-windows
  * boost-thread[core]:x86-windows
  * boost-throw-exception[core]:x86-windows
  * boost-tokenizer[core]:x86-windows
  * boost-tuple[core]:x86-windows
  * boost-type-index[core]:x86-windows
  * boost-type-traits[core]:x86-windows
  * boost-typeof[core]:x86-windows
  * boost-unordered[core]:x86-windows
  * boost-utility[core]:x86-windows
  * boost-vcpkg-helpers[core]:x86-windows
  * boost-winapi[core]:x86-windows
  * openssl[core]:x86-windows
  * openssl-windows[core]:x86-windows
  * websocketpp[core]:x86-windows
Additional packages (*) will be modified to complete this operation.
If you are sure you want to rebuild the above packages, run the command with the --recurse option

Wait, what? Why did default-features and websockets show up?

C:\Dev\vcpkg>.\vcpkg remove cpprestsdk
The following packages will be removed:
    cpprestsdk:x86-windows
Removing package cpprestsdk:x86-windows...
Removing package cpprestsdk:x86-windows... done
Purging package cpprestsdk:x86-windows...
Purging package cpprestsdk:x86-windows... done

C:\Dev\vcpkg>.\vcpkg.exe install cpprestsdk[core,compression,brotli]
The following packages will be built and installed:
    cpprestsdk[brotli,compression,core]:x86-windows
Starting package 1/1: cpprestsdk:x86-windows
Building package cpprestsdk[brotli,compression,core]:x86-windows...
-- Using cached C:/Dev/vcpkg_downloads/Microsoft-cpprestsdk-v2.10.14.tar.gz
-- Using source at C:/Dev/vcpkg/buildtrees/cpprestsdk/src/v2.10.14-101423beaf
-- Configuring x86-windows
-- Building x86-windows-dbg
-- Building x86-windows-rel
-- Installing: C:/Dev/vcpkg/packages/cpprestsdk_x86-windows/share/cpprestsdk/copyright
-- Performing post-build validation
-- Performing post-build validation done
Building package cpprestsdk[brotli,compression,core]:x86-windows... done
Installing package cpprestsdk[brotli,compression,core]:x86-windows...
Installing package cpprestsdk[brotli,compression,core]:x86-windows... done
Elapsed time for package cpprestsdk:x86-windows: 20.83 s

Total elapsed time: 20.83 s

The package cpprestsdk:x86-windows provides CMake targets:

    find_package(cpprestsdk CONFIG REQUIRED)
    target_link_libraries(main PRIVATE cpprestsdk::cpprest cpprestsdk::cpprestsdk_zlib_internal cpprestsdk::cpprestsdk_brotli_internal)

If you remove the package first, and then ask for it, you get only the features you asked for.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pakdel picture pakdel  路  3Comments

grandprixgp picture grandprixgp  路  3Comments

pkeir picture pkeir  路  3Comments

tzbo picture tzbo  路  3Comments

invy picture invy  路  3Comments