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

Concept: Features / Default features / add default features section to troubleshooting guide #255

Merged
merged 9 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
2 changes: 2 additions & 0 deletions vcpkg/TOC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@
href: concepts/triplets.md
- name: Versioning
href: users/versioning.concepts.md
- name: Default features
href: concepts/default-features.md
- name: Reference
items:
- name: vcpkg.json Reference
Expand Down
83 changes: 83 additions & 0 deletions vcpkg/concepts/default-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Understanding default features in vcpkg
description: This article explains the concept of default features, their capabilities, and their expected contents in detail.
author: JavierMatosD
ms.author: javiermat
ms.date: 02/01/2024
ms.topic: concept-article
---

# Concept: Default features

This article delves into the concept of default features, their implications, and strategies for effective management.
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

Default features in vcpkg are a set of features automatically included when a port is installed, unless explicitly disabled. These features ensure that a library maintains a baseline level of functionality, even as the complexity of its dependency graph increases.
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

## Role of default features

Default features are crucial for providing a user-friendly experience with libraries that offer modular functionalities through features. For instance, a library capable of extracting various archive formats might have each format as an optional feature. Without default features, the library might not perform any extraction out of the box, complicating initial use. Default features guarantee that essential functionalities are available immediately, enhancing usability.
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

## Specifying default features

JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved
When adding a library as a dependency in your `vcpkg.json` manifest, default features are included by default. To modify this behavior, you can use the `"default-features": false` attribute to disable them, allowing for a more customized setup based on your specific needs.
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

### Example 1: Including a library with default features

```json
{
"name": "my-application",
"version": "0.15.2",
"dependencies": [
"extract-any"
]
}
```
In this scenario, `extract-any` is installed with its default features, ensuring immediate functionality.
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved


### Example 2: Disabling default features

```json
{
"name": "my-application",
"version": "0.15.2",
"dependencies": [
{
"name": "extract-any",
"default-features": false
}
]
}
```

Here, `extract-any` is installed without its default features, allowing for a tailored setup.

## Default features in action
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

1. Installing a port without specifying default features:
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved
`vcpkg install portA` installs `portA` with its default features (`portA[i]`), due to the absence of specific feature requests.

2. Specifying a feature without disabling defaults:
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved
`vcpkg install portA[j]` leads to the installation of `portA` with both the specified (`j`) and default (`i`) features (`portA[i,j]`).

3. Explicitly disabling default features:
`vcpkg install portA[core]` installs `portA` without any default features, as `[core]` explicitly excludes them.
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

4. Transitive dependencies and default features:
`vcpkg install portA[j] portB` might result in `portA[i,j] portB` being installed if `portB` depends on `portA[j]`, but does not explicitly disable `portA`'s default features.

5. Combining ports with varied feature specifications:
`vcpkg install portA[j] portB` installs `portA[i,j] portB`, including `portA`'s default features unless explicitly excluded.

6. Comprehensive disabling of default features:
`vcpkg install portA[core] portB` ensures that `portA` is installed with only the explicitly requested features, excluding the defaults.

## Managing default features

To effectively manage default features within your projects:

- **Be Explicit**: Specify only the features you need. Use `[core]` to disable default features when necessary.
- **Inspect Dependencies**: Use `vcpkg depend-info <port>` to understand dependency resolutions and adjust your configurations accordingly.
- **Utilize Overrides and Baselines**: Leverage versioning and baseline features for more control over dependency resolutions.
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

Adopting a clear strategy for managing default features will help streamline your project's dependency management, ensuring you include only what's necessary for your application's functionality.
51 changes: 51 additions & 0 deletions vcpkg/users/versioning-troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,57 @@ Resolutions:
run: git fetch --unshallow
```

## <a name="unexpected-default-features"></a> Cause: Unexpected installation of default features in transitive dependencies

When using `vcpkg` to manage your project's dependencies, you might encounter a situation where a transitive dependency installs with its default features, even when you've specified `"depend-defaults": false` in your top-level manifest. This can lead to confusion when features that were intended to be excluded, such as `foo`, are still being installed.
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

### Scenario

You have a dependency on library `Y`, which in turn depends on library `X`. Library `X` has default features, including `foo`, that you want to exclude from your project. Your top-level manifest for library `Y` might look something like this:

```json
{
"name": "my-project",
"dependencies": [
{
"name": "Y",
"features": ["featureB"],
"depend-defaults": false
}
]
}
```

You expect that `X` will be installed without its default features due to the `"depend-defaults": false` setting. However, `X` is still installed with the default feature `foo`.

### Reason

The `depend-defaults` property is only considered at the top-level manifest. This means that default features of transitive dependencies (like `X` in this scenario) are still included unless explicitly disabled at the top level. When library `Y` is resolved, `vcpkg` does not propagate the `"depend-defaults": false` setting to the transitive dependency `X`, resulting in the installation of `X` with its default features.
vicroms marked this conversation as resolved.
Show resolved Hide resolved

### Resolution

To ensure that transitive dependencies like `X` are installed without their default features, you need to promote them to direct dependencies in your top-level manifest and explicitly disable their default features. Modify your `vcpkg.json` to include `X` directly with `"default-features": false`:
Copy link
Contributor

Choose a reason for hiding this comment

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

This instruction doesn't lead to the desired resolution when the user needs third port Z which depends on X but lacks the "default-features": false property on the X dependency just because Z's maintainers weren't aware of the default features (at that time).

  • The user can't override the behavior.
  • The user will face difficulties to realize that this is a port bug in Z.
  • The Z maintainers have no tool support to check which dependencies have default features
  • The Z maintainers have no way to express that they really want to depend on default-features.

All up to brainware.


```json
{
"name": "my-project",
"dependencies": [
{
"name": "Y",
"features": ["featureB"]
},
{
"name": "X",
"default-features": false
}
]
}
```

This approach ensures that `X` is installed without its default features, as now `X` is a direct dependency with an explicit instruction to exclude default features.

For more detailed information on how default features work and how to manage them, see the [default features concept article](../concepts/default-features.md) article.

## Issue isn't listed here

If your issue isn't listed here, visit [our repository](https://github.com/microsoft/vcpkg/issues) to create a new issue.