diff --git a/reference/conanfile/tools/env.rst b/reference/conanfile/tools/env.rst index 47d31fa3b52..db66accf559 100644 --- a/reference/conanfile/tools/env.rst +++ b/reference/conanfile/tools/env.rst @@ -1,10 +1,15 @@ conan.tools.env =============== +.. warning:: + + These tools are **experimental** and subject to breaking changes. + .. toctree:: :maxdepth: 2 env/environment + env/envvars env/virtualbuildenv env/virtualrunenv diff --git a/reference/conanfile/tools/env/environment.rst b/reference/conanfile/tools/env/environment.rst index 5cbd92f26ed..73482ae639d 100644 --- a/reference/conanfile/tools/env/environment.rst +++ b/reference/conanfile/tools/env/environment.rst @@ -8,19 +8,12 @@ Environment This is a **very experimental** feature and it will have breaking changes in future releases. -``Environment`` is a class that helps defining modifications to the environment variables. +``Environment`` is a generic class that helps defining modifications to the environment variables. This class is used by other tools like the :ref:`conan.tools.gnu` autotools helpers and the :ref:`VirtualBuildEnv` and :ref:`VirtualRunEnv` -generator. - -Constructor -+++++++++++ - -.. code:: python - - def __init__(self, conanfile): - -- ``conanfile``: the current recipe object. Always use ``self``. +generator. It is important to highlight that this is a generic class, to be able to use it, a specialization +for the current context (shell script, bat file, path separators, etc), a ``EnvVars`` object needs to be obtained +from it. Variable declaration @@ -30,18 +23,18 @@ Variable declaration from conan.tools.env import Environment - env = Environment(self) - env.define("MYVAR1", "MyValue1") # Overwrite previously existing MYVAR1 with new value - env.append("MYVAR2", "MyValue2") # Append to existing MYVAR2 the new value - env.prepend("MYVAR3", "MyValue3") # Prepend to existing MYVAR3 the new value - env.remove("MYVAR3", "MyValue3") # Remove the MyValue3 from MYVAR3 - env.unset("MYVAR4") # Remove MYVAR4 definition from environment - - - # And the equivalent with paths - env.define_path("MYPATH1", "path/one") # Overwrite previously existing MYPATH1 with new value - env.append_path("MYPATH2", "path/two") # Append to existing MYPATH2 the new value - env.prepend_path("MYPATH3", "path/three") # Prepend to existing MYPATH3 the new value + def generate(self): + env = Environment() + env.define("MYVAR1", "MyValue1") # Overwrite previously existing MYVAR1 with new value + env.append("MYVAR2", "MyValue2") # Append to existing MYVAR2 the new value + env.prepend("MYVAR3", "MyValue3") # Prepend to existing MYVAR3 the new value + env.remove("MYVAR3", "MyValue3") # Remove the MyValue3 from MYVAR3 + env.unset("MYVAR4") # Remove MYVAR4 definition from environment + + # And the equivalent with paths + env.define_path("MYPATH1", "path/one") # Overwrite previously existing MYPATH1 with new value + env.append_path("MYPATH2", "path/two") # Append to existing MYPATH2 the new value + env.prepend_path("MYPATH3", "path/three") # Prepend to existing MYPATH3 the new value The "normal" variables (the ones declared with ``define``, ``append`` and ``prepend``) will be appended with a space, by default, but the ``separator`` argument can be provided to define a custom one. @@ -59,118 +52,51 @@ Environments can be composed: from conan.tools.env import Environment - env1 = Environment(self) + env1 = Environment() env1.define(...) - env2 = Environment(self) + env2 = Environment() env2.append(...) - env1.compose(env2) # env1 has priority, and its modifications will prevail - - -Creating launcher files -+++++++++++++++++++++++ + env1.compose_env(env2) # env1 has priority, and its modifications will prevail -Environments can generate launcher files: - -.. code:: python - - def generate(self): - env1 = Environment(self) - env1.define("foo", "var") - env1.save_script("my_launcher") - - -Although it potentially could be used in other methods, this functionality is intended to work in the ``generate()`` -method. - -It will generate automatically a ``my_launcher.bat`` for Windows systems or ``my_launcher.sh`` otherwise. - -Also, by default, Conan will automatically append that launcher file path to a list that will be used to -create a ``conanbuild.bat|sh`` file aggregating all the launchers in order. The ``conanbuild.sh/bat`` launcher -will be created after the execution of the ``generate()`` method. - -The ``conanbuild.bat/sh`` launcher will be executed by default before calling every ``self.run()`` command. This -would be typically done in the ``build()`` method. - -You can change the default launcher with the ``env`` argument: - -.. code:: python - ... - def build(self): - # This will automatically wrap the "foo" command with the correct launcher: - # my_launcher.sh && foo - self.run("foo", env=["my_launcher"]) - -The ``group`` argument (``"build"`` by default) can be used to define different groups of environment files, to -aggregate them separately. For example, using a ``group="run"``, like the ``VirtualRunEnv`` generator does, will -aggregate and create a ``conanrun.bat|sh`` script: - -.. code:: python - - def generate(self): - env1 = Environment(self) - env1.define("foo", "var") - # Will append "my_launcher" to "conanrun.bat|sh" - env1.save_script("my_launcher", group="run") - - -You can also use ``group=None`` argument to avoid appending the script to the aggregated ``conanbuild.bat|sh``: - -.. code:: python - - env1 = Environment(self) - env1.define("foo", "var") - # Will not append "my_launcher" to "conanbuild.bat|sh" - env1.save_script("my_launcher", group=None) - - - -Applying the environment -++++++++++++++++++++++++ +Obtaining environment variables +++++++++++++++++++++++++++++++++ -As an alternative to a launcher, environments can be applied in the python environment, but the usage -of the launchers is recommended if possible: +You can obtain an ``EnvVars`` object with the ``vars()`` method like this: .. code:: python from conan.tools.env import Environment - env1 = Environment(self) - env1.define("foo", "var") - with env1.apply(): - # Here os.getenv("foo") == "var" - ... - -Iterating the Environment object -++++++++++++++++++++++++++++++++ - -You can iterate an Environment object like this: - -.. code:: python + def generate(self): + env = Environment() + env.define("MYVAR1", "MyValue1") + envvars = env.vars(self, scope="build") + # use the envvars object - env1 = Environment() - env1.append("foo", "var") - env1.append("foo", "var2") - for name, value in env.items(): - assert name == "foo": - assert value == "var var2" +The default ``scope`` is equal ``"build"``, which means that if this ``envvars`` generate a script to +activate the variables, such script will be automatically added to the ``conanbuild.sh|bat`` one, for +users and recipes convenience. Conan generators use ``build`` and ``run`` scope, but it might be possible +to manage other scopes too. -Other Environment usage -++++++++++++++++++++++++ +Environment definition +++++++++++++++++++++++ -There are some other places where this ``Environment`` is used internally by Conan: +There are some other places where ``Environment`` can be defined and used: -- In recipes ``package_info()`` method, in new ``self.buildenv_info`` and ``self.runenv_info``. -- In generators like ``AutootoolsDeps``, ``AutotoolsToolchain``, that need to define environment. -- In profiles new ``[buildenv]`` and ``[runenv]`` sections. +- In recipes ``package_info()`` method, in new ``self.buildenv_info`` and ``self.runenv_info``, this + environment will be propagated via ``VirtualBuildEnv`` and ``VirtualRunEnv`` respectively to packages + depending on this recipe. +- In generators like ``AutootoolsDeps``, ``AutotoolsToolchain``, that need to define environment for the + current recipe. +- In profiles new ``[buildenv]`` section. The definition in ``package_info()`` is as follow, taking into account that both ``self.buildenv_info`` and ``self.runenv_info`` are objects of ``Environment()`` class. - .. code:: python from conans import ConanFile @@ -189,4 +115,3 @@ are objects of ``Environment()`` class. # at runtime self.runenv_info.define("MYPKG_DATA_DIR", os.path.join(self.package_folder, "datadir")) - diff --git a/reference/conanfile/tools/env/envvars.rst b/reference/conanfile/tools/env/envvars.rst new file mode 100644 index 00000000000..2b9e7bb0e0e --- /dev/null +++ b/reference/conanfile/tools/env/envvars.rst @@ -0,0 +1,109 @@ +EnvVars +======= + +.. warning:: + + This is a **very experimental** feature and it will have breaking changes in future releases. + + +``EnvVars`` is a class that represents an instance of environment variables for a given system. +It is obtained from the generic ``Environment`` class. + +This class is used by other tools like the :ref:`conan.tools.gnu` autotools helpers and +the :ref:`VirtualBuildEnv` and :ref:`VirtualRunEnv` +generator. + + +Creating launcher files ++++++++++++++++++++++++ + +``EnvVars`` object can generate launcher (shell or bat scripts) files: + +.. code:: python + + def generate(self): + env1 = Environment(self) + env1.define("foo", "var") + envvars = env1.vars(self) + env1.save_script("my_launcher") + + +Although it potentially could be used in other methods, this functionality is intended to work in the ``generate()`` +method. + +It will generate automatically a ``my_launcher.bat`` for Windows systems or ``my_launcher.sh`` otherwise. + +Also, by default, Conan will automatically append that launcher file path to a list that will be used to +create a ``conanbuild.bat|sh`` file aggregating all the launchers in order. The ``conanbuild.sh/bat`` launcher +will be created after the execution of the ``generate()`` method. + +The ``conanbuild.bat/sh`` launcher will be executed by default before calling every ``self.run()`` command. This +would be typically done in the ``build()`` method. + +You can change the default launcher with the ``env`` argument: + +.. code:: python + + ... + def build(self): + # This will automatically wrap the "foo" command with the correct launcher: + # my_launcher.sh && foo + self.run("foo", env=["my_launcher"]) + +The ``scope`` argument (``"build"`` by default) can be used to define different scope of environment files, to +aggregate them separately. For example, using a ``scope="run"``, like the ``VirtualRunEnv`` generator does, will +aggregate and create a ``conanrun.bat|sh`` script: + +.. code:: python + + def generate(self): + env1 = Environment(self) + env1.define("foo", "var") + envvars = env1.vars(self, scope="run") + # Will append "my_launcher" to "conanrun.bat|sh" + envvars.save_script("my_launcher") + + +You can also use ``scope=None`` argument to avoid appending the script to the aggregated ``conanbuild.bat|sh``: + +.. code:: python + + env1 = Environment(self) + env1.define("foo", "var") + # Will not append "my_launcher" to "conanbuild.bat|sh" + envvars = env1.vars(self, scope=None) + envvars.save_script("my_launcher") + + + +Applying the environment variables +++++++++++++++++++++++++++++++++++ + +As an alternative to a launcher, environments can be applied in the python environment, but the usage +of the launchers is recommended if possible: + +.. code:: python + + from conan.tools.env import Environment + + env1 = Environment(self) + env1.define("foo", "var") + envvars = env1.vars(self) + with envvars.apply(): + # Here os.getenv("foo") == "var" + ... + +Iterating the variables ++++++++++++++++++++++++ + +You can iterate an ``EnvVars`` object like this: + +.. code:: python + + env1 = Environment() + env1.append("foo", "var") + env1.append("foo", "var2") + envvars = env1.vars(self) + for name, value in envvars.items(): + assert name == "foo": + assert value == "var var2" diff --git a/reference/conanfile/tools/env/virtualbuildenv.rst b/reference/conanfile/tools/env/virtualbuildenv.rst index 84b9101cc7b..16133bb78da 100644 --- a/reference/conanfile/tools/env/virtualbuildenv.rst +++ b/reference/conanfile/tools/env/virtualbuildenv.rst @@ -52,14 +52,16 @@ will create the following files: like PATH, LD_LIBRARY_PATH, etc, and any other variable defined in the dependencies ``buildenv_info`` corresponding to the ``build`` context, and to the current installed configuration. If a repeated call is done with other settings, a different file will be created. + After the execution or sourcing of this file, a new deactivation script will be generated, capturing the current + environment, so the environment can be restored when desired. The file will be named also following the + current active configuration, like ``deactivate_conanbuildenv-release-x86_64.bat``. - conanbuild.(bat|sh): Accumulates the calls to one or more other scripts, in case there are multiple tools in the generate process that create files, to give one single convenient file for all. This only calls the latest specific configuration one, that is, if ``conan install`` is called first for Release build type, and then for Debug, ``conanbuild.(bat|sh)`` script will call the Debug one. +- deactivate_conanbuild.(bat|sh): Accumulates the deactivation calls defined in the above ``conanbuild.(bat|sh)``. + This file should only be called after the accumulated activate has been called first. -After the execution of one of those files, a new deactivation script will be generated, capturing the current -environment, so the environment can be restored when desired. The file will be named also following the -current active configuration, like ``deactivate_conanbuildenv-release-x86_64.bat``. Constructor +++++++++++ @@ -76,10 +78,10 @@ generate() .. code:: python - def generate(self, group="build"): + def generate(self, scope="build"): Parameters: - * **group** (Defaulted to ``"build"``): Add the launcher automatically to the ``conanbuild`` launcher. Read more + * **scope** (Defaulted to ``"build"``): Add the launcher automatically to the ``conanbuild`` launcher. Read more in the :ref:`Environment documentation `. diff --git a/reference/conanfile/tools/env/virtualrunenv.rst b/reference/conanfile/tools/env/virtualrunenv.rst index 1978fbedaac..37adbde1989 100644 --- a/reference/conanfile/tools/env/virtualrunenv.rst +++ b/reference/conanfile/tools/env/virtualrunenv.rst @@ -75,10 +75,10 @@ generate() .. code:: python - def generate(self, group="run"): + def generate(self, scope="run"): Parameters: - * **group** (Defaulted to ``run``): Add the launcher automatically to the ``conanrun`` launcher. Read more + * **scope** (Defaulted to ``run``): Add the launcher automatically to the ``conanrun`` launcher. Read more in the :ref:`Environment documentation `. diff --git a/reference/conanfile/tools/microsoft.rst b/reference/conanfile/tools/microsoft.rst index f3ad4d48600..e8c15fb38f1 100644 --- a/reference/conanfile/tools/microsoft.rst +++ b/reference/conanfile/tools/microsoft.rst @@ -304,9 +304,9 @@ generate() .. code:: python - def generate(self, group="build"): + def generate(self, scope="build"): Parameters: - * **group** (Defaulted to ``"build"``): Add the launcher automatically to the ``conanbuild`` launcher. Read more + * **scope** (Defaulted to ``"build"``): Add the launcher automatically to the ``conanbuild`` launcher. Read more in the :ref:`Environment documentation `.