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/patches following layout #9361

Merged
merged 5 commits into from Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
9 changes: 3 additions & 6 deletions conan/tools/cmake/cmake.py
@@ -1,18 +1,15 @@
import os
import os
import platform

from conan.tools.cmake.utils import is_multi_configuration
from conan.tools.files import load_toolchain_args
from conan.tools.files import load_toolchain_args, chdir, mkdir
from conan.tools.gnu.make import make_jobs_cmd_line_arg
from conan.tools.meson.meson import ninja_jobs_cmd_line_arg
from conan.tools.microsoft.msbuild import msbuild_verbosity_cmd_line_arg, \
msbuild_max_cpu_count_cmd_line_arg
from conans.client import tools
from conans.client.tools.files import chdir
from conans.client.tools.oss import cpu_count, args_to_string
from conans.errors import ConanException
from conans.util.files import mkdir


def _validate_recipe(conanfile):
Expand Down Expand Up @@ -85,7 +82,7 @@ def configure(self, source_folder=None):
build_folder = self._conanfile.build_folder
generator_folder = self._conanfile.generators_folder

mkdir(build_folder)
mkdir(self._conanfile, build_folder)

arg_list = [self._cmake_program]
if self._generator:
Expand Down Expand Up @@ -142,7 +139,7 @@ def build(self, build_type=None, target=None):
def install(self, build_type=None):
if not self._conanfile.should_install:
return
mkdir(self._conanfile.package_folder)
mkdir(self._conanfile, self._conanfile.package_folder)
self._build(build_type=build_type, target="install")

def test(self, build_type=None, target=None, output_on_failure=False):
Expand Down
2 changes: 1 addition & 1 deletion conan/tools/files/__init__.py
@@ -1,4 +1,4 @@
from conan.tools.files.files import load, save, mkdir, ftp_download, download, get, rename, \
load_toolchain_args, save_toolchain_args
load_toolchain_args, save_toolchain_args, chdir
from conan.tools.files.patches import patch, apply_conandata_patches
from conan.tools.files.cpp_package import CppPackage
11 changes: 11 additions & 0 deletions conan/tools/files/files.py
Expand Up @@ -3,6 +3,7 @@
import os
import platform
import subprocess
from contextlib import contextmanager

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE, CONAN_TOOLCHAIN_ARGS_SECTION
from conans.client.downloaders.download import run_downloader
Expand Down Expand Up @@ -222,3 +223,13 @@ def save_toolchain_args(content, generators_folder=None):
toolchain_config[CONAN_TOOLCHAIN_ARGS_SECTION] = content_
with open(args_file, "w") as f:
toolchain_config.write(f)


@contextmanager
def chdir(newdir):
lasote marked this conversation as resolved.
Show resolved Hide resolved
old_path = os.getcwd()
os.chdir(newdir)
try:
yield
finally:
os.chdir(old_path)
21 changes: 13 additions & 8 deletions conan/tools/files/patches.py
Expand Up @@ -2,6 +2,7 @@

import patch_ng

from conan.tools.files import chdir
from conans.errors import ConanException

try:
Expand Down Expand Up @@ -37,8 +38,10 @@ def patch(conanfile, base_path=None, patch_file=None, patch_string=None,
:param kwargs: Extra parameters that can be added and will contribute to output information
"""

base_path = base_path or conanfile.source_folder
lasote marked this conversation as resolved.
Show resolved Hide resolved
patch_type = kwargs.get('patch_type')
patch_description = kwargs.get('patch_description')

if patch_type or patch_description:
patch_type_str = ' ({})'.format(patch_type) if patch_type else ''
patch_description_str = ': {}'.format(patch_description) if patch_description else ''
Expand Down Expand Up @@ -97,11 +100,13 @@ def apply_conandata_patches(conanfile):
"""

patches = conanfile.conan_data.get('patches')
if isinstance(patches, dict):
assert conanfile.version, "Can only be applied if conanfile.version is already defined"
entries = patches.get(conanfile.version, [])
for it in entries:
patch(conanfile, **it)
elif isinstance(patches, Iterable):
for it in patches:
patch(conanfile, **it)

with chdir(conanfile.folders.base_source):
if isinstance(patches, dict):
assert conanfile.version, "Can only be applied if conanfile.version is already defined"
entries = patches.get(conanfile.version, [])
for it in entries:
patch(conanfile, **it)
elif isinstance(patches, Iterable):
for it in patches:
patch(conanfile, **it)
24 changes: 17 additions & 7 deletions conans/test/functional/tools/test_files.py
Expand Up @@ -106,11 +106,13 @@ def build(self):
client.save({"conanfile.py": conanfile})
client.run('create .')

assert mock_patch_ng.apply_args == (None, 0, False)
assert os.path.exists(mock_patch_ng.apply_args[0])
assert mock_patch_ng.apply_args[1:] == (0, False)
assert 'mypkg/1.0: Apply patch (security)' in str(client.out)


def test_apply_conandata_patches(mock_patch_ng):
@pytest.mark.parametrize("use_base_path", [False, True])
def test_apply_conandata_patches(mock_patch_ng, use_base_path):
conanfile = textwrap.dedent("""
from conans import ConanFile
from conan.tools.files import apply_conandata_patches
Expand All @@ -119,29 +121,37 @@ class Pkg(ConanFile):
name = "mypkg"
version = "1.11.0"

def layout(self):
self.folders.source = "source_subfolder"

def build(self):
apply_conandata_patches(self)
""")
conandata_yml = textwrap.dedent("""
patches:
"1.11.0":
- patch_file: "patches/0001-buildflatbuffers-cmake.patch"
base_path: "source_subfolder"
{base}
- patch_file: "patches/0002-implicit-copy-constructor.patch"
base_path: "source_subfolder"
{base}
patch_type: backport
patch_source: https://github.com/google/flatbuffers/pull/5650
patch_description: Needed to build with modern clang compilers.
"1.12.0":
- patch_file: "patches/0001-buildflatbuffers-cmake.patch"
base_path: "source_subfolder"
""")
{base}
""".format(base='base_path: "source_subfolder"' if use_base_path else ""))

client = TestClient()
client.save({'conanfile.py': conanfile,
'conandata.yml': conandata_yml})
client.run('create .')

assert mock_patch_ng.apply_args == ('source_subfolder', 0, False)
if use_base_path:
assert mock_patch_ng.apply_args == ('source_subfolder', 0, False)
else:
assert mock_patch_ng.apply_args[0].endswith('source_subfolder')
assert mock_patch_ng.apply_args[1:] == (0, False)

assert 'mypkg/1.11.0: Apply patch (backport): Needed to build with modern' \
' clang compilers.' in str(client.out)
6 changes: 4 additions & 2 deletions conans/test/unittests/tools/files/test_patches.py
Expand Up @@ -35,21 +35,23 @@ def mock_fromstring(string):

def test_single_patch_file(mock_patch_ng):
conanfile = ConanFileMock()
conanfile.folders.set_base_source("my_source")
conanfile.display_name = 'mocked/ref'
patch(conanfile, patch_file='patch-file')
assert mock_patch_ng.filename == 'patch-file'
assert mock_patch_ng.string is None
assert mock_patch_ng.apply_args == (None, 0, False)
assert mock_patch_ng.apply_args == ("my_source", 0, False)
assert len(str(conanfile.output)) == 0


def test_single_patch_string(mock_patch_ng):
conanfile = ConanFileMock()
conanfile.folders.set_base_source("my_folder")
conanfile.display_name = 'mocked/ref'
patch(conanfile, patch_string='patch_string')
assert mock_patch_ng.string == b'patch_string'
assert mock_patch_ng.filename is None
assert mock_patch_ng.apply_args == (None, 0, False)
assert mock_patch_ng.apply_args == ("my_folder", 0, False)
assert len(str(conanfile.output)) == 0


Expand Down