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
28 changes: 17 additions & 11 deletions conan/tools/env/virtualbuildenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,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
10 changes: 8 additions & 2 deletions conans/client/source.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os

from conan.api.output import ConanOutput
from conan.tools.env import VirtualBuildEnv
from conans.errors import ConanException, conanfile_exception_formatter, NotFoundException, \
conanfile_remove_attr
from conans.util.files import (is_dirty, mkdir, rmdir, set_dirty_context_manager,
Expand Down Expand Up @@ -67,8 +68,13 @@ 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)
if getattr(conanfile, "source_buildenv", None):
prev_status = conanfile.virtualbuildenv
with VirtualBuildEnv(conanfile).vars().apply():
run_source_method(conanfile, hook_manager)
conanfile.virtualbuildenv = prev_status
else:
run_source_method(conanfile, hook_manager)


def 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
import platform

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

source_buildenv = True

def source(self):
cmd = "mytool.bat" if platform.system() == "Windows" else "mytool.sh"
self.run(cmd)
""")
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
"""