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

[bug]buildenv entries with ampersand not added correctly to package build environment #17611

Open
tb-hh-si opened this issue Jan 22, 2025 · 4 comments
Assignees

Comments

@tb-hh-si
Copy link

Describe the bug

Environment: Conan 2.11, Linux (WSL)
Description:
When I define a buildenv entry in a profile for all dependencies (env_test=dependency) and then override it with the ampersand syntax for my package (&:env_test=package) then conan will generate a different build-environment shell script for dependencies and my package. As expected.

But when I add an additional entry just for my local package (&:unrelated_env=test) the incorrect value is generated into the build-environment of my package for env_test.

How to reproduce it

profile_test.txt

See this example:
Expectation is that env_test is "package" for my package and "dependency" for all dependencies. But it's not.

It works as expected if:

  • I delete the &:unrelated_env line
  • I use the mypackage/*:unrelated_env=test syntax instead.
  • I add a global dummy definition before overriding it for my package:
    unrelated_env=
    &:unrelated_env=test
@tb-hh-si tb-hh-si changed the title [bug]buildenv entires with ampersand bot added correctly to package build environment [bug]buildenv entries with ampersand bot added correctly to package build environment Jan 22, 2025
@tb-hh-si tb-hh-si changed the title [bug]buildenv entries with ampersand bot added correctly to package build environment [bug]buildenv entries with ampersand not added correctly to package build environment Jan 22, 2025
@AbrilRBS AbrilRBS self-assigned this Jan 22, 2025
@AbrilRBS
Copy link
Member

Hi @tb-hh-si thanks a lot for your report

While this is a bit confusing, and we're looking if changing the behaviour to be less suprissing would be feasible, for now this is expected behaviour, Conan right now gives precedence to the latest declared environment.

If you define env_test without a scope before the consumer scoped ones, this will work around the issue for now, and you should see the expected priority, let me know if this helps

@tb-hh-si
Copy link
Author

Hi @AbrilRBS thanks for the reply.

Could you elaborate on the precedence rules? So for instance if I have multiple definitions do I have to group them together like this?`

[buildenv]
my_var1=test1
my_var2=test2
my_var3=
# leave my_var3 empty because it shall only be injected into consumer space

&:my_var1=override1
&:my_var2=override2
&:my_var3=override3

@tb-hh-si
Copy link
Author

tb-hh-si commented Jan 23, 2025

Also: does this behavior only apply for the buildenv sections? Or also for settings/options/conf?

And is the syntax treated differently when using &:my_var instead of mypackage/*:my_var? Because I got a different result in my tests.

This doesn't work as I expected:

[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=8
compiler.cppstd=17
compiler.libcxx=libstdc++11
build_type=Release

[buildenv]
# unrelated setting; only for this package
&:unrelated_env=test

# setting for dependencies
env_test=dependency

# override setting for this package
&:env_test=package

But this works in my tests:

[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=8
compiler.cppstd=17
compiler.libcxx=libstdc++11
build_type=Release

[buildenv]
# unrelated setting; only for this package. Unset for all other packages
unrelated_env=
&:unrelated_env=test

# setting for dependencies
env_test=dependency

# override setting for this package
&:env_test=package

And explicitly using package names also works for me:

[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=8
compiler.cppstd=17
compiler.libcxx=libstdc++11
build_type=Release

[buildenv]
# unrelated setting; only for this package
mypackage/*:unrelated_env=test

# setting for dependencies
env_test=dependency

# override setting for this package
mypackage/*:env_test=package

@memsharded
Copy link
Member

To give some context:

  • Yes, in general the per-package items (like per-package settings or per-package conf) groups things by patterns
  • Then, they are applied and processed in order of appearenace, but as they are grouped, it means the order of first appearance of the pattern.
  • In settings, it is not as relevant, as they are not cumulative, but conf can perform append-like actions that accumulate, and as such different patterns including the no-pattern or global one can accumulate, and the other matters.

This means that in practice, yes, confs using the same pattern should be together in profiles, and not interleaved with other confs.

  • In your first code (not working), you have first &:unrelated_env=test. This means that the & pattern will be applied first. So the global env_test=dependency comes later and that has the final result value
  • In the second code (working), you define first unrelated_env=, so the global (empty) scope applies first, and the & pattern later. So &:env_test=package wins, as it is applied later.

In the last case, it doesn't work as you say, the following test passes:

def test_profile_buildenv_patterns():
    profile = textwrap.dedent("""\
        [buildenv]
        # unrelated setting; only for this package
        mypackage/*:unrelated_env=test

        # setting for dependencies
        env_test=dependency

        # override setting for this package
        mypackage/*:env_test=package
        """)
    current_profile_path = os.path.join(temp_folder(), "default")
    save(current_profile_path, profile)

    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error
    profile = profile_loader.load_profile(current_profile_path)
    buildenv = profile.buildenv
    env = buildenv.get_profile_env(RecipeReference("mypackage", "1.0"), is_consumer=True)
    text = env.dumps()
    assert "unrelated_env=test" in text
    assert "env_test=dependency" in text

Proving that as mypackage/* is applied first, the value that will win is env_test=dependency (unless the package is not named mypackage, as in that case, env_test=dependency is the only possibility anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants