[bug] graph build-order build_args do not reproduce transitive dependency options
Describe the bug
Environment details:
- Ubuntu
latest - Python
3.12 - Conan
2.32.0 - Conan
2.33.0-devfromdevelop2ate42971dc2952c83b7f5ab17cdf6bc49ac12b7c97
conan graph build-order returns a package node that cannot be recreated from its generated build_args and the same build and host profiles.
The minimal graph is:
app -> middle -> leafapp sets these options through default_options:
{"middle/*:shared": True, "leaf/*:shared": True}The full graph resolves middle against leaf:shared=True. The generated build_args for middle only preserve middle/*:shared=True:
--requires=middle/1.0 --build=middle/1.0 -o="middle/*:shared=True"Evaluating those arguments with the same -pr:h=default -pr:b=default profiles changes leaf to its default shared=False. This also changes the package ID of middle:
leaf shared: True -> False
middle package_id: d70f758157f8902dfd15aa2b587fc96bb482f1e0 -> 0c1b59e1b79b09d06a2d6c704bf4c486b2c74832The graph build-order documentation describes build_args as the "arguments needed for a conan install <args> to fire the build of this package". The default_options documentation also documents setting options for requirements with a reference pattern.
Why this is a bug
The build-order element identifies one concrete middle package ID and its concrete leaf dependency. Its build_args are attached to that exact element. Replaying those arguments with the same profiles must therefore resolve the same node.
Instead, one Conan result describes two incompatible configurations:
- The element identifies
middle:d70f...built againstleaf:shared=True. - Its
build_argsresolvemiddle:0c1b...built againstleaf:shared=False.
The missing value is not profile or command-line state. It originates in the root recipe and was already accepted when Conan computed the full graph. There is no additional profile argument that a caller can replay to recover it.
The default_options documentation recommends profiles for complex dependency configuration and describes precedence limitations. Neither changes this result. There is no precedence conflict in this linear graph. Conan has already resolved leaf:shared=True and emitted a concrete package ID for middle.
The generated command should recreate the package node it belongs to. It should either preserve leaf/*:shared=True or provide another self-consistent way to resolve the same dependency configuration and package ID.
Related issues
- #14637 is the closest report. It was answered in terms of reapplying profile and command-line inputs. This reproducer explicitly reapplies identical build and host profiles. The missing input comes from the root recipe, so that workaround cannot restore it.
- #16593 reported invalid option serialization in
build_argsand was fixed by #16594. This case is different because the generated arguments are syntactically valid but semantically incomplete. - #18096 reported missing
build_argsfor editable nodes and was fixed by #18097. This case produces non-null arguments, but they resolve a different package node.
How to reproduce it
The complete reproducer is available at:
https://github.com/Devsh-Graphics-Programming/conan-repros/tree/main/build-order-transitive-options
It contains three recipes with no source files and no build logic. The Python script:
- Creates a temporary Conan home.
- Exports the three recipes.
- Computes the full build order for
app/1.0. - Extracts the generated
build_argsformiddle/1.0. - Evaluates those arguments with the same build and host profiles.
- Compares the option values and package IDs.
Run it with:
python build-order-transitive-options/reproduce.pyBoth tested versions reproduce the mismatch:
The output ends with:
build_args: --requires=middle/1.0 --build=middle/1.0 -o="middle/*:shared=True"
leaf shared: True -> False
middle package_id: d70f758157f8902dfd15aa2b587fc96bb482f1e0 -> 0c1b59e1b79b09d06a2d6c704bf4c486b2c74832
BUG REPRODUCEDSource: conan-io/conan