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

New "conf" configuration mechanism #8266

Merged
merged 29 commits into from
Jan 14, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f1b3e68
working on config
memsharded Dec 23, 2020
fee01dc
working
memsharded Dec 27, 2020
3c6c059
working
memsharded Dec 27, 2020
a641daa
marking tests as visual
memsharded Dec 27, 2020
f69fef1
add command line
memsharded Dec 27, 2020
71418ed
Merge branch 'develop' into poc/config
memsharded Dec 28, 2020
5908f92
removed command line support
memsharded Dec 28, 2020
df76450
Merge branch 'develop' into poc/config
memsharded Dec 28, 2020
bbd8644
updates for composition and inclusion working
memsharded Dec 29, 2020
a32ec10
trying delimiters
memsharded Dec 29, 2020
8fc1ac4
removed unrelated refactor
memsharded Dec 29, 2020
9e1dee8
proposing config not in profile
memsharded Dec 29, 2020
4242f1d
Merge branch 'develop' into poc/config
memsharded Dec 29, 2020
6483c49
working
memsharded Dec 30, 2020
614d4d3
working
memsharded Dec 30, 2020
b575e18
working
memsharded Dec 30, 2020
8e8596c
user vs global config
memsharded Dec 30, 2020
6dbc141
working
memsharded Dec 30, 2020
43dcbab
merged develop
memsharded Dec 30, 2020
3774403
fix Py2 error
memsharded Dec 30, 2020
054da0e
more general paackage pattern match
memsharded Dec 31, 2020
888ec72
adding MSBuildToolchain compile_options conf example
memsharded Jan 3, 2021
a70ed07
added some package_id capabilities
memsharded Jan 3, 2021
62a5311
added assignment of conf for virtual and txt
memsharded Jan 3, 2021
e2167f0
more tests
memsharded Jan 10, 2021
0e2664a
merged develop
memsharded Jan 10, 2021
ae63225
merged develop
memsharded Jan 11, 2021
d2c39f8
review
memsharded Jan 11, 2021
8d497a8
changed file name conan.cfg
memsharded Jan 11, 2021
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
10 changes: 9 additions & 1 deletion conan/tools/microsoft/msbuild.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from conan.tools.microsoft.visual import vcvars_arch, vcvars_command
from conans.client.tools import intel_compilervars_command
from conans.errors import ConanException


class MSBuild(object):
Expand Down Expand Up @@ -29,9 +30,16 @@ def command(self, sln):
cvars = vcvars_command(self.version, architecture=self.vcvars_arch,
platform_type=None, winsdk_version=None,
vcvars_ver=None)
cmd = ('%s && msbuild "%s" /p:Configuration=%s /p:Platform=%s '
cmd = ('%s && msbuild "%s" /p:Configuration=%s /p:Platform=%s'
% (cvars, sln, self.build_type, self.platform))

conf = self._conanfile.conf["tools.microsoft.MSBuild"]
verbosity = conf.verbosity
if verbosity:
if verbosity not in ("Quiet", "Minimal", "Normal", "Detailed", "Diagnostic"):
raise ConanException("Uknown MSBuild verbosity: {}".format(verbosity))
cmd += ' /verbosity:%s' % verbosity

return cmd

def build(self, sln):
Expand Down
6 changes: 5 additions & 1 deletion conans/client/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,8 @@ def create(self, *args):
lockfile=args.lockfile,
lockfile_out=args.lockfile_out,
ignore_dirty=args.ignore_dirty,
profile_build=profile_build)
profile_build=profile_build,
conf=args.conf)
except ConanException as exc:
info = exc.info
raise
Expand Down Expand Up @@ -2169,6 +2170,9 @@ def _add_common_install_arguments(parser, build_help, update_help=None, lockfile

parser.add_argument("-u", "--update", action='store_true', default=False,
help=update_help)

parser.add_argument("-c", "--conf", action=Extender, help="Specify conf")
memsharded marked this conversation as resolved.
Show resolved Hide resolved

if lockfile:
parser.add_argument("-l", "--lockfile", action=OnceArgument,
help="Path to a lockfile")
Expand Down
12 changes: 7 additions & 5 deletions conans/client/conan_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ def create(self, conanfile_path, name=None, version=None, user=None, channel=Non
keep_source=False, keep_build=False, verify=None,
manifests=None, manifests_interactive=None,
remote_name=None, update=False, cwd=None, test_build_folder=None,
lockfile=None, lockfile_out=None, ignore_dirty=False, profile_build=None):
lockfile=None, lockfile_out=None, ignore_dirty=False, profile_build=None, conf=None):
"""
API method to create a conan package

Expand All @@ -359,7 +359,8 @@ def create(self, conanfile_path, name=None, version=None, user=None, channel=Non
remotes = self.app.load_remotes(remote_name=remote_name, update=update)
lockfile = _make_abs_path(lockfile, cwd) if lockfile else None
graph_info = get_graph_info(profile_host, profile_build, cwd, None,
self.app.cache, self.app.out, lockfile=lockfile)
self.app.cache, self.app.out, lockfile=lockfile,
conf=conf)

# Make sure keep_source is set for keep_build
keep_source = keep_source or keep_build
Expand Down Expand Up @@ -1406,7 +1407,7 @@ def lock_create(self, path, lockfile_out,


def get_graph_info(profile_host, profile_build, cwd, install_folder, cache, output,
name=None, version=None, user=None, channel=None, lockfile=None):
name=None, version=None, user=None, channel=None, lockfile=None, conf=None):
if lockfile:
try:
graph_info_folder = lockfile if os.path.isdir(lockfile) else os.path.dirname(lockfile)
Expand Down Expand Up @@ -1455,12 +1456,13 @@ def get_graph_info(profile_host, profile_build, cwd, install_folder, cache, outp
% install_folder)

phost = profile_from_args(profile_host.profiles, profile_host.settings, profile_host.options,
profile_host.env, cwd, cache)
profile_host.env, cwd, cache, conf=conf)
phost.process_settings(cache)
if profile_build:
# Only work on the profile_build if something is provided
pbuild = profile_from_args(profile_build.profiles, profile_build.settings,
profile_build.options, profile_build.env, cwd, cache)
profile_build.options, profile_build.env, cwd, cache,
conf=conf)
pbuild.process_settings(cache)
else:
pbuild = None
Expand Down
2 changes: 2 additions & 0 deletions conans/client/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ def _initialize_conanfile(conanfile, profile):
tmp_settings.update_values(pkg_settings)

conanfile.initialize(tmp_settings, profile.env_values)
# FIXME: Name of the package, full name?
conanfile.conf = profile.conf.get_conanfile_conf(conanfile.name)
memsharded marked this conversation as resolved.
Show resolved Hide resolved

def load_consumer(self, conanfile_path, profile_host, name=None, version=None, user=None,
channel=None, lock_python_requires=None):
Expand Down
28 changes: 17 additions & 11 deletions conans/client/profile_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ def _load_profile(text, profile_path, default_folder):

# Current profile before update with parents (but parent variables already applied)
doc = ConfigParser(profile_parser.profile_text,
allowed_fields=["build_requires", "settings", "env", "scopes", "options"])
allowed_fields=["build_requires", "settings", "env", "scopes", "options",
"conf"])
if 'scopes' in doc._sections:
conan_v2_behavior("Field 'scopes' in profile is deprecated")

Expand Down Expand Up @@ -221,8 +222,11 @@ def get_package_name_value(item):
current_env_values.update(base_profile.env_values)
base_profile.env_values = current_env_values

if doc.conf:
base_profile.conf.loads(doc.conf)

def profile_from_args(profiles, settings, options, env, cwd, cache):

def profile_from_args(profiles, settings, options, env, cwd, cache, conf=None):
""" Return a Profile object, as the result of merging a potentially existing Profile
file and the args command-line arguments
"""
Expand All @@ -236,7 +240,7 @@ def profile_from_args(profiles, settings, options, env, cwd, cache):
tmp, _ = read_profile(p, cwd, cache.profiles_path)
result.update(tmp)

args_profile = _profile_parse_args(settings, options, env)
args_profile = _profile_parse_args(settings, options, env, conf)

if result:
result.update(args_profile)
Expand All @@ -245,7 +249,7 @@ def profile_from_args(profiles, settings, options, env, cwd, cache):
return result


def _profile_parse_args(settings, options, envs):
def _profile_parse_args(settings, options, envs, conf):
""" return a Profile object result of parsing raw data
"""
def _get_tuples_list_from_extender_arg(items):
Expand Down Expand Up @@ -276,14 +280,14 @@ def _get_simple_and_package_tuples(items):
simple_items.append((name, value))
return simple_items, package_items

def _get_env_values(env, package_env):
env_values = EnvValues()
for name, value in env:
env_values.add(name, EnvValues.load_value(value))
for package, data in package_env.items():
def _get_env_values(envs, package_env_values):
env_values_result = EnvValues()
for name, value in envs:
env_values_result.add(name, EnvValues.load_value(value))
for package, data in package_env_values.items():
for name, value in data:
env_values.add(name, EnvValues.load_value(value), package)
return env_values
env_values_result.add(name, EnvValues.load_value(value), package)
return env_values_result

result = Profile()
options = _get_tuples_list_from_extender_arg(options)
Expand All @@ -295,4 +299,6 @@ def _get_env_values(env, package_env):
result.settings = OrderedDict(settings)
for pkg, values in package_settings.items():
result.package_settings[pkg] = OrderedDict(values)
if conf:
result.conf.loads("\n".join(conf))
return result
100 changes: 100 additions & 0 deletions conans/model/profile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import fnmatch
from collections import OrderedDict, defaultdict

from conans.client import settings_preprocessor
Expand All @@ -8,6 +9,99 @@
from conans.model.values import Values


class _ConfModule(object):
def __init__(self):
self._confs = {} # Component => dict {config-name: value}

def __getattr__(self, item):
return self._confs.get(item)

def set_value(self, k, v):
self._confs[k] = v

def __repr__(self):
return "_ConfModule: " + repr(self._confs)

def items(self):
return self._confs.items()


class Conf(object):
def __init__(self):
self._conf_modules = {} # Module => _ConfModule

def __getitem__(self, item):
return self._conf_modules.get(item, _ConfModule())

def __repr__(self):
return "Conf: " + repr(self._conf_modules)

def items(self):
return self._conf_modules.items()

def update(self, other):
"""
:type other: Conf
"""
# FIXME: This doesn't update the inner per-module conf
self._conf_modules.update(other._conf_modules)

def set_value(self, module_name, k, v):
self._conf_modules.setdefault(module_name, _ConfModule()).set_value(k, v)


class ProfileConf(object):
def __init__(self):
self._pattern_confs = OrderedDict() # pattern (including None) => Conf

def __bool__(self):
return bool(self._pattern_confs)

__nonzero__ = __bool__

def get_conanfile_conf(self, name):
result = Conf()
for pattern, conf in self._pattern_confs.items():
# TODO: standardize this package-pattern matching
if pattern is None or fnmatch.fnmatch(name, pattern):
result.update(conf)
return result

def update(self, other):
"""
:type other: ProfileConf
"""
self._pattern_confs.update(other._pattern_confs)

def dumps(self):
result = []
for pattern, conf in self._pattern_confs.items():
for name, values in conf.items():
for k, v in values.items():
if pattern:
result.append("{}:{}:{}={}".format(pattern, name, k, v))
else:
result.append("{}:{}={}".format(name, k, v))
return "\n".join(result)

def loads(self, text):
self._pattern_confs = {}
for line in text.splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
left, value = line.split("=", 1)
tokens = left.split(":", 2)
if len(tokens) == 3:
pattern, conf_module, name = tokens
else:
assert len(tokens) == 2
conf_module, name = tokens
pattern = None
conf = self._pattern_confs.setdefault(pattern, Conf())
conf.set_value(conf_module, name, value)


class Profile(object):
"""A profile contains a set of setting (with values), environment variables
"""
Expand All @@ -19,6 +113,7 @@ def __init__(self):
self.env_values = EnvValues()
self.options = OptionsValues()
self.build_requires = OrderedDict() # ref pattern: list of ref
self.conf = ProfileConf()

# Cached processed values
self.processed_settings = None # Settings with values, and smart completion
Expand Down Expand Up @@ -81,6 +176,10 @@ def dumps(self):
result.append("[env]")
result.append(self.env_values.dumps())

if self.conf:
result.append("[conf]")
result.append(self.conf.dumps())

return "\n".join(result).replace("\n\n", "\n")

def update(self, other):
Expand All @@ -92,6 +191,7 @@ def update(self, other):
self.options.update(other.options)
for pattern, req_list in other.build_requires.items():
self.build_requires.setdefault(pattern, []).extend(req_list)
self.conf.update(other.conf)

def update_settings(self, new_settings):
"""Mix the specified settings with the current profile.
Expand Down