Environment
Warning
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.
This class is used by other tools like the conan.tools.gnu autotools helpers and
the VirtualBuildEnv and VirtualRunEnv
generator.
Constructor
def __init__(self, conanfile):
conanfile
: the current recipe object. Always useself
.
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
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.
The “path” variables (the ones declared with define_path
, append_path
and prepend_path
) will be appended
with the default system path separator, either :
or ;
, but it also allows defining which one.
Composition
Environments can be composed:
from conan.tools.env import Environment
env1 = Environment(self)
env1.define(...)
env2 = Environment(self)
env2.append(...)
env1.compose(env2) # env1 has priority, and its modifications will prevail
Creating launcher files
Environments can generate launcher files:
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:
...
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:
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
:
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
As an alternative to a launcher, environments can be applied in the python environment, but the usage of the launchers is recommended if possible:
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:
env1 = Environment()
env1.append("foo", "var")
env1.append("foo", "var2")
for name, value in env.items():
assert name == "foo":
assert value == "var var2"
Other Environment usage
There are some other places where this Environment
is used internally by Conan:
In recipes
package_info()
method, in newself.buildenv_info
andself.runenv_info
.In generators like
AutootoolsDeps
,AutotoolsToolchain
, that need to define environment.In profiles new
[buildenv]
and[runenv]
sections.
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.
from conans import ConanFile
class App(ConanFile):
name = "mypkg"
version = "1.0"
settings = "os", "arch", "compiler", "build_type"
def package_info(self):
# This is information needed by consumers to build using this package
self.buildenv_info.append("MYVAR", "MyValue")
self.buildenv_info.prepend_path("MYPATH", "some/path/folder")
# This is information needed by consumers to run apps that depends on this package
# at runtime
self.runenv_info.define("MYPKG_DATA_DIR", os.path.join(self.package_folder,
"datadir"))