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

Feature/tools virtualenv #2060

Merged
merged 4 commits into from Mar 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Expand Up @@ -9,7 +9,6 @@ __pycache__/

# Distribution / packaging
.Python
env/
_build/
develop-eggs/
dist/
Expand Down
1 change: 1 addition & 0 deletions reference/conanfile/tools.rst
Expand Up @@ -40,4 +40,5 @@ Contents:
tools/meson
tools/microsoft
tools/qbs
tools/env
tools/files
9 changes: 9 additions & 0 deletions reference/conanfile/tools/env.rst
@@ -0,0 +1,9 @@
conan.tools.env
===============


.. toctree::
:maxdepth: 2

env/environment
env/virtualenv
78 changes: 78 additions & 0 deletions reference/conanfile/tools/env/environment.rst
@@ -0,0 +1,78 @@
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.

It allows different operations like:

.. code:: python

from conan.tools.env import Environment

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.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

Normal variables will be appended by default with space, but ``separator`` argument can be provided to define
a custom one.
Path variables will be appended with the default system path separator, either ``:`` or ``;``, but it also
allows defining which one.

Environments can compose:

.. code:: python

from conan.tools.env import Environment

env1 = Environment()
env1.define(...)
env2 = Environment()
env2.append(...)

env1.compose(env2) # env1 has priority, and its modifications will prevail


There are some places where this ``Environment`` is used:

- In recipes ``package_info()`` method, in new ``self.buildenv_info`` and ``self.runenv_info``.
- In other generators like ``AutootoolsDeps`` and ``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.


.. code:: python

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"))


44 changes: 44 additions & 0 deletions reference/conanfile/tools/env/virtualenv.rst
@@ -0,0 +1,44 @@
VirtualEnv
==========

.. warning::

This is a **very experimental** feature and it will have breaking changes in future releases.


The ``VirtualEnv`` generator can be used by name in conanfiles:

.. code-block:: python
:caption: conanfile.py

class Pkg(ConanFile):
generators = "VirtualEnv"

.. code-block:: text
:caption: conanfile.txt

[generators]
VirtualEnv

And it can also be fully instantiated in the conanfile ``generate()`` method:

.. code-block:: python
:caption: conanfile.py

from conans import ConanFile
from conan.tools.env import VirtualEnv

class Pkg(ConanFile):
settings = "os", "compiler", "arch", "build_type"
requires = "zlib/1.2.11", "bzip2/1.0.8"

def generate(self):
ms = VirtualEnv(self)
ms.generate()

When the ``VirtualEnv`` generator is used, calling ``conan install`` will generate files containing environment variables information:


- *conanbuildenv* .bat or .sh scripts, that are automatically loaded if existing by the ``self.run()`` recipes methods. *conanbuildenv* is the build time environment information. It is collected from the direct ``build_requires`` in "build" context recipes from the ``self.buildenv_info`` definition plus the ``self.runenv_info`` of the transitive dependencies of those ``build_requires``.
- *conanrunenv* .bat or .sh scripts, that can be explicitly opted-in in ``self.run()`` recipes methods with ``self.run(..., env=["conanrunenv"])``. *conanrunenv* is the runtime environment information, anything that is necessary in the environment to actually run the compiled executables and applications.
- In both cases, whenever the runtime environment information is necessary, it wil also be automatically deduced from the ``self.cpp_info`` definition of the package, to define ``PATH``, ``LD_LIBRARY_PATH``, ``DYLD_LIBRARY_PATH`` and ``DYLD_FRAMEWORK_PATH`` environment variables.