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

[question] How to get environment variable from the tested reference to the test_package test()? #3876

Open
1 task done
Adnn opened this issue Oct 15, 2024 · 4 comments
Open
1 task done
Assignees
Milestone

Comments

@Adnn
Copy link

Adnn commented Oct 15, 2024

What is your question?

Hi!

We are porting a recipe which is publishing an env var (in its package_info()), and this variable is tested by the test_package test() method.

We read several pages from the documentation:

But none seems to indicate any limitation regarding the run environment not being propagated to the test() method, nor any specific requirement to retrieve environment variables.

(side note: the doc for conanfile.run() mentions an env parameter, but does not describe it).

Due to this lack of guidance, we tried several approaches in the upstream to try and forward the env var:

def package_info(self):
    self.runenv_info.define_path("WIX", self.package_folder)

    bindir = os.path.join(self.package_folder, "bin")
    self.cpp_info.bindirs = [bindir] # By the doc, this should be automatically appended to path for both Run and Build envs
    self.env_info.PATH.append(bindir) # as found in CMake recipe

And made several attempts to retrieve WIX or PATH environment variables:

def test(self):
    w = os.environ.get("PATH", "")
    self.output.info(f"Path: {w}")

    w = os.environ.get("WIX", "")
    self.output.info(f"Wix: {w}")

    self.run("echo %WIX%")

    self.run("echo %WIX%", env="conanrun")

Sadly, the WIX variable remains undefined, and the PATH variable is not appended with the value of bindir.

Accessing the package environment from its test package would seems like a common requirement, yet as you could probably infer it generated a lot of frustration and confusion.

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide
@memsharded memsharded self-assigned this Oct 15, 2024
@memsharded
Copy link
Member

Hi @Adnn

Thanks for your report.

I am not sure what could be failing. This is intended to work relatively simply, sorry for the lack of documentation, the idea is that besides the env="conanrun" nothing more would be necessary.

I have just tried with this unittest in Windows and it works:

def test_runenv_info_test_package_access():
    c = TestClient()
    lib = textwrap.dedent("""
        from conan import ConanFile
        class Lib(ConanFile):
            name = "lib"
            version = "0.1"
            def package_info(self):
                self.runenv_info.define("MY_TEST_LIBVAR", "MY_TEST_LIBVALUE")
        """)
    test_package = textwrap.dedent("""
        from conan import ConanFile

        class TestTool(ConanFile):
            settings = "os"
            def requirements(self):
                self.requires(self.tested_reference_str)

            def test(self):
                self.run("set", env="conanrun")
        """)
    c.save({"conanfile.py": lib,
            "test_package/conanfile.py": test_package})
    c.run("create .")
    assert "MY_TEST_LIBVAR=MY_TEST_LIBVALUE" in c.out

Note that the os.environ.get("PATH", "") and similar approaches won't work, as the environment is not globally activated. It is activated by self.run() that calls the environment scripts with env="conanrun", or otherwise it can be explicitly activated with the apply() (see https://docs.conan.io/2/reference/tools/env/envvars.html#applying-the-environment-variables)

Also finally, please note that the echo %MY_TEST_LIBVAR% will not work in Windows, because this is a shell preprocess replacement mechanism, it is not an actual env-var retrieval evaluation. That means this:

$ set SOME_VAR=value && echo %SOME_VAR%
%SOME_VAR%
$ echo %SOME_VAR%
value

Because it is not evaluated, it is just replaced verbatim in the command line from env-vars, but before the actual evaluation of the command line. This is why the second time it works, because the env-var was previously defined.

This is why the test above with set works.
In practice it means that instead of running shell commands, it is better to put them inside a myfile.bat and launch that file instead.

@memsharded
Copy link
Member

Hi @Adnn

Did you manage to see my test above? Any further feedback that could help? Thanks!

@Adnn
Copy link
Author

Adnn commented Oct 22, 2024

Hi @memsharded,

As usual, thank you very much for taking the time to give an answer which is both practical and give some interesting details.

I am not sure what could be failing. This is intended to work relatively simply.

What was failing was what you pointed out at the end: an inline command provided to conanfile.run() cannot access the environment variables on Windows. And since we only tried variations of that on the consumer side: no cigar.


Having recently been in the position of the frustrated neophyte, I will use the occasion to report what I think could have made me sort it out without bothering you on the issue tracker:

Windows limitation

In practice it means that instead of running shell commands, it is better to put them inside a myfile.bat and launch that file instead.

Imho, this was the biggest problem: what feels like the canonical way to consume an env-var - and the simplest/shortest test of this feature - is to echo %THE_VAR%. Coupled to the fact that this was working with Conan 1.X, I think this important limitation could appear in some warning box on conanfile.run() doc, as well as maybe in the migration guide or conanfile.test() (as I expect it to be the common place were newcomers might first try to consume the env-vars).

self.run() env parameter

In the page you pointed out was https://docs.conan.io/2/reference/tools/env/envvars.html#running-with-environment-files, which is a good explanation of the env parameter and how it is translated into a shell command. Yet it could probably be more discoverable if it was directly on self.run() documentation, or if a link to this paragraph existed there.

Thanks again for you help!

@memsharded
Copy link
Member

What was failing was what you pointed out at the end: an inline command provided to conanfile.run() cannot access the environment variables on Windows. And since we only tried variations of that on the consumer side: no cigar.

Yes, I agree. Windows is particularly confusing in this regard, not so many people are aware of how it works.

Imho, this was the biggest problem: what feels like the canonical way to consume an env-var - and the simplest/shortest test of this feature - is to echo %THE_VAR%. Coupled to the fact that this was working with Conan 1.X, I think this important limitation could appear in some warning box on conanfile.run() doc, as well as maybe in the migration guide or conanfile.test() (as I expect it to be the common place were newcomers might first try to consume the env-vars).

One of the major "blocker" or problems that Conan generated in Conan 1 that users could not fix is that Conan 1 was automatically and by default activating the environment before calling the recipe methods. So os.environ had all the information before running build() and other methods. So if something in the environment was not correct, there was no space for the consumer recipe to fix it, breaking one of the intended design principles of Conan, that the "end consumer" should always have precedence and a way to customize what they need.

This is why the new "environment" management (introduced in Conan 1) uses always environment scripts that can be activated ,deactivated, changed, added etc directly from the consumer code, and use different environments for different self.run() calls (important when there is build-time and run-time).

But I agree that this can create this confusion with the Windows env-var evaluation process.
I am moving this ticket to the docs to try to add there some clarifications and examples.

@memsharded memsharded transferred this issue from conan-io/conan Oct 23, 2024
@memsharded memsharded added this to the 2 milestone Oct 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants