Skip to content

Commit

Permalink
Explore other more explicit alternatives to automatically manage the …
Browse files Browse the repository at this point in the history
…options (#14320)

* add options_auto_handle to auto handle options

* add with_options_auto_handle

* minor changes

* review

* implement implements

* fix comment

* review

* unused import

---------

Co-authored-by: memsharded <[email protected]>
  • Loading branch information
czoido and memsharded authored Jul 19, 2023
1 parent d09ae5b commit 2dde121
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 68 deletions.
5 changes: 0 additions & 5 deletions conan/tools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
from conans.model.build_info import CppInfo as _CppInfo
from conan.tools.helpers import (
default_config_options,
default_configure,
default_package_id
)


def CppInfo(conanfile):
Expand Down
10 changes: 5 additions & 5 deletions conans/client/conanfile/configure.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from conans.errors import conanfile_exception_formatter
from conans.model.pkg_type import PackageType
from conans.model.requires import BuildRequirements, TestRequirements, ToolRequirements
from conan.tools import default_config_options, default_configure
from conans.client.conanfile.implementations import auto_shared_fpic_config_options, auto_shared_fpic_configure


def run_configure_method(conanfile, down_options, profile_options, ref):
Expand All @@ -10,8 +10,8 @@ def run_configure_method(conanfile, down_options, profile_options, ref):
if hasattr(conanfile, "config_options"):
with conanfile_exception_formatter(conanfile, "config_options"):
conanfile.config_options()
else:
default_config_options(conanfile)
elif "auto_shared_fpic" in conanfile.implements:
auto_shared_fpic_config_options(conanfile)

# Assign only the current package options values, but none of the dependencies
is_consumer = conanfile._conan_is_consumer
Expand All @@ -20,8 +20,8 @@ def run_configure_method(conanfile, down_options, profile_options, ref):
if hasattr(conanfile, "configure"):
with conanfile_exception_formatter(conanfile, "configure"):
conanfile.configure()
else:
default_configure(conanfile)
elif "auto_shared_fpic" in conanfile.implements:
auto_shared_fpic_configure(conanfile)

self_options, up_options = conanfile.options.get_upstream_options(down_options, ref,
is_consumer)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
from conans.model.pkg_type import PackageType


def default_config_options(conanfile):
def auto_shared_fpic_config_options(conanfile):
if conanfile.settings.get_safe("os") == "Windows":
conanfile.options.rm_safe("fPIC")


def default_configure(conanfile):
def auto_shared_fpic_configure(conanfile):
if conanfile.options.get_safe("header_only"):
conanfile.options.rm_safe("fPIC")
conanfile.options.rm_safe("shared")
elif conanfile.options.get_safe("shared"):
conanfile.options.rm_safe("fPIC")


def default_package_id(conanfile):
def auto_header_only_package_id(conanfile):
if conanfile.options.get_safe("header_only") or conanfile.package_type is PackageType.HEADER:
conanfile.info.clear()
7 changes: 4 additions & 3 deletions conans/client/graph/compute_pid.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from conans.errors import conanfile_exception_formatter, ConanInvalidConfiguration, \
conanfile_remove_attr, ConanException
from conans.model.info import ConanInfo, RequirementsInfo, RequirementInfo, PythonRequiresInfo
from conan.tools import default_package_id
from conans.client.conanfile.implementations import auto_header_only_package_id


def compute_package_id(node, new_config):
Expand Down Expand Up @@ -82,6 +82,7 @@ def run_validate_package_id(conanfile):
with conanfile_exception_formatter(conanfile, "package_id"):
with conanfile_remove_attr(conanfile, ['cpp_info', 'settings', 'options'], "package_id"):
conanfile.package_id()
else:
default_package_id(conanfile)
elif "auto_header_only" in conanfile.implements:
auto_header_only_package_id(conanfile)

conanfile.info.validate()
2 changes: 2 additions & 0 deletions conans/model/conan_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class ConanFile:
default_options = None
package_type = None

implements = []

provides = None
deprecated = None

Expand Down
2 changes: 2 additions & 0 deletions conans/test/functional/toolchains/cmake/test_cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class App(ConanFile):
generators = "CMakeDeps"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
implements = ["auto_shared_fpic", "auto_header_only"]
def generate(self):
tc = CMakeToolchain(self)
Expand Down Expand Up @@ -395,6 +396,7 @@ def test_toolchain_linux(self, build_type, cppstd, arch, libcxx, shared):
"CMAKE_EXE_LINKER_FLAGS": arch_str,
"COMPILE_DEFINITIONS": defines,
# fPIC is managed automatically depending on the shared option value
# if implements = ["auto_shared_fpic", "auto_header_only"]
"CMAKE_POSITION_INDEPENDENT_CODE": "ON" if not shared else ""
}

Expand Down
56 changes: 6 additions & 50 deletions conans/test/integration/options/test_configure_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ class ConfigureOptionsTest(unittest.TestCase):
])
def test_methods_not_defined(self, settings_os, shared, fpic, header_only, result):
"""
Test that options are managed automatically when methods config_otpions and configure are not
defined.
Test that options are managed automatically when methods config_options and configure are not
defined and implements = ["auto_shared_fpic", "auto_header_only"].
Check that header only package gets its unique package ID.
"""
client = TestClient()
Expand All @@ -39,6 +39,7 @@ class Pkg(ConanFile):
settings = "os", "compiler", "arch", "build_type"
options = {{"shared": [True, False], "fPIC": [True, False], "header_only": [True, False]}}
default_options = {{"shared": {shared}, "fPIC": {fpic}, "header_only": {header_only}}}
implements = ["auto_shared_fpic", "auto_header_only"]
def build(self):
shared = self.options.get_safe("shared")
Expand Down Expand Up @@ -73,7 +74,7 @@ def build(self):
])
def test_optout(self, settings_os, shared, fpic, header_only, result):
"""
Test that options are not managed automatically when methods are defined.
Test that options are not managed automatically when methods are defined even if implements = ["auto_shared_fpic", "auto_header_only"]
Check that header only package gets its unique package ID.
"""
client = TestClient()
Expand All @@ -84,6 +85,7 @@ class Pkg(ConanFile):
settings = "os", "compiler", "arch", "build_type"
options = {{"shared": [True, False], "fPIC": [True, False], "header_only": [True, False]}}
default_options = {{"shared": {shared}, "fPIC": {fpic}, "header_only": {header_only}}}
implements = ["auto_shared_fpic", "auto_header_only"]
def config_options(self):
pass
Expand All @@ -104,53 +106,6 @@ def build(self):
if header_only:
self.assertIn("Package 'da39a3ee5e6b4b0d3255bfef95601890afd80709' created", client.out)

@parameterized.expand([
["Linux", False, False, False, [False, False, False]],
["Windows", False, False, False, [False, None, False]],
["Windows", True, False, False, [True, None, False]],
["Windows", False, False, True, [None, None, True]],
["Linux", False, False, True, [None, None, True]],
["Linux", True, True, False, [True, None, False]],
["Linux", True, False, False, [True, None, False]],
["Linux", True, True, True, [None, None, True]],
["Linux", True, True, True, [None, None, True]],
["Linux", False, True, False, [False, True, False]],
["Linux", False, True, False, [False, True, False]],
])
def test_methods_defined_explicit(self, settings_os, shared, fpic, header_only, result):
"""
Test that options are managed when the tool is used in methods defined by user.
Check that header only package gets its unique package ID.
"""
client = TestClient()
conanfile = textwrap.dedent(f"""\
from conan import ConanFile
from conan.tools import default_config_options, default_configure
class Pkg(ConanFile):
settings = "os", "compiler", "arch", "build_type"
options = {{"shared": [True, False], "fPIC": [True, False], "header_only": [True, False]}}
default_options = {{"shared": {shared}, "fPIC": {fpic}, "header_only": {header_only}}}
def config_options(self):
default_config_options(self)
def configure(self):
default_configure(self)
def build(self):
shared = self.options.get_safe("shared")
fpic = self.options.get_safe("fPIC")
header_only = self.options.get_safe("header_only")
self.output.info(f"shared: {{shared}}, fPIC: {{fpic}}, header only: {{header_only}}")
""")
client.save({"conanfile.py": conanfile})
client.run(f"create . --name=pkg --version=0.1 -s os={settings_os}")
result = f"shared: {result[0]}, fPIC: {result[1]}, header only: {result[2]}"
self.assertIn(result, client.out)
if header_only:
self.assertIn("Package 'da39a3ee5e6b4b0d3255bfef95601890afd80709' created", client.out)

def test_header_package_type_pid(self):
"""
Test that we get the pid for header only when package type is set to header-library
Expand All @@ -162,6 +117,7 @@ def test_header_package_type_pid(self):
class Pkg(ConanFile):
settings = "os", "compiler", "arch", "build_type"
package_type = "header-library"
implements = ["auto_shared_fpic", "auto_header_only"]
""")
client.save({"conanfile.py": conanfile})
Expand Down
4 changes: 2 additions & 2 deletions conans/test/integration/package_id/test_default_package_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def test_default_package_id_options(typedep, typeconsumer, different_id):
"""
c = TestClient()
dep = GenConanfile("dep", "0.1").with_option("myopt", [True, False]) \
.with_package_type(typedep)
.with_package_type(typedep).with_class_attribute('implements = ["auto_shared_fpic", "auto_header_only"]')
consumer = GenConanfile("consumer", "0.1").with_requires("dep/0.1")\
.with_package_type(typeconsumer)
.with_package_type(typeconsumer).with_class_attribute('implements = ["auto_shared_fpic", "auto_header_only"]')

c.save({"dep/conanfile.py": dep,
"consumer/conanfile.py": consumer})
Expand Down

0 comments on commit 2dde121

Please sign in to comment.