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

proposal for source() buildenv discussion #15153

Merged
merged 15 commits into from
Dec 14, 2023
Merged
1 change: 1 addition & 0 deletions conan/tools/env/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from conan.tools.env.environment import Environment
from conan.tools.env.virtualbuildenv import VirtualBuildEnv
from conan.tools.env.virtualrunenv import VirtualRunEnv
from conan.tools.env.virtualbuildenv import buildenv
36 changes: 25 additions & 11 deletions conan/tools/env/virtualbuildenv.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
from contextlib import contextmanager

from conan.internal import check_duplicated_generator
from conan.tools.env import Environment
from conan.tools.env.virtualrunenv import runenv_from_cpp_info


@contextmanager
def buildenv(conanfile):
with VirtualBuildEnv(conanfile).vars().apply():
yield


class VirtualBuildEnv:
""" Calculates the environment variables of the build time context and produces a conanbuildenv
.bat or .sh script
Expand All @@ -12,21 +20,27 @@ def __init__(self, conanfile):
self._conanfile = conanfile
self._conanfile.virtualbuildenv = False
self.basename = "conanbuildenv"
# TODO: Make this use the settings_build
self.configuration = conanfile.settings.get_safe("build_type")
if self.configuration:
self.configuration = self.configuration.lower()
self.arch = conanfile.settings.get_safe("arch")
if self.arch:
self.arch = self.arch.lower()
self.configuration = None
self.arch = None

@property
def _filename(self):
if not self.configuration:
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved
# TODO: Make this use the settings_build
configuration = self._conanfile.settings.get_safe("build_type")
configuration = configuration.lower() if configuration else None
else:
configuration = self.configuration
if not self.arch:
arch = self._conanfile.settings.get_safe("arch")
arch = arch.lower() if arch else None
else:
arch = self.arch
f = self.basename
if self.configuration:
f += "-" + self.configuration.replace(".", "_")
if self.arch:
f += "-" + self.arch.replace(".", "_")
if configuration:
f += "-" + configuration.replace(".", "_")
if arch:
f += "-" + arch.replace(".", "_")
return f

def environment(self):
Expand Down
1 change: 0 additions & 1 deletion conans/client/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ def config_source(export_source_folder, conanfile, hook_manager):
# First of all get the exported scm sources (if auto) or clone (if fixed)
# Now move the export-sources to the right location
merge_directories(export_source_folder, conanfile.folders.base_source)

run_source_method(conanfile, hook_manager)


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import textwrap

from conans.test.utils.tools import TestClient


def test_build_requires_source():
c = TestClient()
tool = textwrap.dedent(r"""
import os
from conan import ConanFile
from conan.tools.files import chdir, save

class Tool(ConanFile):
name = "tool"
version = "0.1"
def package(self):
with chdir(self, self.package_folder):
echo = f"@echo off\necho MY-TOOL! {self.name}/{self.version}!!"
save(self, "bin/mytool.bat", echo)
save(self, "bin/mytool.sh", echo)
os.chmod("bin/mytool.sh", 0o777)
""")
pkg = textwrap.dedent("""
from conan import ConanFile
from conan.tools.env import buildenv
import platform

class Pkg(ConanFile):
name = "pkg"
version = "0.1"
tool_requires = "tool/0.1"

def source(self):
cmd = "mytool.bat" if platform.system() == "Windows" else "mytool.sh"
with buildenv(self):
self.run(cmd)
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved
""")
c.save({"tool/conanfile.py": tool,
"pkg/conanfile.py": pkg})
c.run("create tool")
c.run("create pkg")
assert "MY-TOOL! tool/0.1" in c.out

c.run("install pkg") # to generate conanbuild script first, so it is available
c.run("source pkg")
assert "MY-TOOL! tool/0.1" in c.out


"""
ALTERNATIVE 1: in recipe, explicit
def source(self):
cmd = "mytool.bat" if platform.system() == "Windows" else "mytool.sh"
with VirtualBuildEnv(conanfile).vars().apply():
self.run(cmd)

- Need to bypass ``settings`` restriction in ``source()``
- we can make a nice helper ``with buildenv``
"""

"""
ALTERNATIVE 2: in recipe, attribute
inject_source_buildenv = True

def source(self):
cmd = "mytool.bat" if platform.system() == "Windows" else "mytool.sh"
self.run(cmd)

- No need to bypass ``settings`` restriction in ``source()``
"""

"""
ALTERNATIVE 3: always, this should be the expected default behavior

def source(self):
cmd = "mytool.bat" if platform.system() == "Windows" else "mytool.sh"
self.run(cmd)

- No need to bypass ``settings`` restriction in ``source()``
- We might want to do an opt-out, just in case?
"""

"""
ALTERNATIVE 4: global, controlled by conf

def source(self):
cmd = "mytool.bat" if platform.system() == "Windows" else "mytool.sh"
self.run(cmd)

- No need to bypass ``settings`` restriction in ``source()``
- [conf] core.source:inject_buildenv=True/False
"""