conan-io / conan-package-tools

Conan Package Tools. Helps with massive package creation and CI integration (Travis CI, Appveyor...)
MIT License
166 stars 71 forks source link

settings not handled correctly? #258

Open sunj1 opened 6 years ago

sunj1 commented 6 years ago

I am using multiple compilers which have different sets of allowed settings. In my default profile, there are some settings which are specific to one compiler. In my configure() method (it is in base class using python_requires), I check the compiler and alter the compiler-sub-settings accordingly.

It works fine using conan install, but does not seem to work using build.py.

Below error is thrown:

Traceback (most recent call last):
  File "build.py", line 126, in <module>
    builder.run()
  File "/usr/lib/python2.7/site-packages/cpt/packager.py", line 394, in run
    self.run_builds(base_profile_name=base_profile_name)
  File "/usr/lib/python2.7/site-packages/cpt/packager.py", line 471, in run_builds
    r.run()
  File "/usr/lib/python2.7/site-packages/cpt/runner.py", line 74, in run
    test_folder=self._test_folder)
  File "/usr/lib/python2.7/site-packages/conans/client/conan_api.py", line 82, in wrapper
    return f(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/conans/client/conan_api.py", line 326, in create
    test_build_folder, test_folder, conanfile_path)
  File "/usr/lib/python2.7/site-packages/conans/client/cmd/create.py", line 40, in create
    test_build_folder=test_build_folder)
  File "/usr/lib/python2.7/site-packages/conans/client/cmd/test.py", line 39, in install_build_and_test
    keep_build=keep_build)
  File "/usr/lib/python2.7/site-packages/conans/client/manager.py", line 119, in install
    None)
  File "/usr/lib/python2.7/site-packages/conans/client/graph/graph_manager.py", line 108, in load_graph
    cache_settings.values = profile.settings_values
  File "/usr/lib/python2.7/site-packages/conans/model/settings.py", line 281, in __setattr__
    return super(Settings, self).__setattr__(field, value)
  File "/usr/lib/python2.7/site-packages/conans/model/settings.py", line 319, in values
    self.values_list = vals.as_list()
  File "/usr/lib/python2.7/site-packages/conans/model/settings.py", line 281, in __setattr__
    return super(Settings, self).__setattr__(field, value)
  File "/usr/lib/python2.7/site-packages/conans/model/settings.py", line 314, in values_list
    setattr(attr, list_settings[-1], str(value))
  File "/usr/lib/python2.7/site-packages/conans/model/settings.py", line 140, in __setattr__
    return setattr(sub_config_dict, item, value)
  File "/usr/lib/python2.7/site-packages/conans/model/settings.py", line 283, in __setattr__
    self._check_field(field)
  File "/usr/lib/python2.7/site-packages/conans/model/settings.py", line 267, in _check_field
    raise undefined_field(self._name, field, self.fields, self._parent_value)
conans.errors.ConanException: 'settings.compiler.XYZ' doesn't exist for 'my-GCC'
'settings.compiler' possible configurations are ['A', 'B']
sunj1 commented 6 years ago

Actually the issue seems with the handling of different types of settings: My actual settings being passed:

SETTINGS:  {'compiler.version': '7.1', 'compiler.sanitize': None, 'compiler': 'gcc'}
SETTINGS:  {'compiler.version': '7.0', 'compiler': 'my-GCC', 'compiler.mode': 'A'}

settings shown by CPT:

+--------------------+---------------------+-----------------+------------+
|   compiler.version | compiler.sanitize   | compiler.mode   | compiler   |
|--------------------+---------------------+-----------------+------------|
|                7.1 | None                |                 | gcc        |
|                7.0 | undefined           | A               | my-GCC     |
+--------------------+---------------------+-----------------+------------+
lasote commented 6 years ago

settings shown by CPT:

How it shows in the table shouldn't be relevant, it is only a visual table.

I would need an example to reproduce the issue.

sunj1 commented 6 years ago

Here is my settings,yml:

os: [Windows, Linux]
arch: [x86, x86_64]
compiler:
    gcc:
        version: ["4.8", "7.1"]
        libcxx: [libstdc++, libstdc++11]
        sanitize: ["address", "undefined", None]
    myGcc:
        version: ["7.0"]
        mode: [A, B]

This is my default profile:

[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=7.1
compiler.libcxx=libstdc++
compiler.sanitize=None
build_type=Release
[options]
[build_requires]
[env]

in my conanfile.py:

    def configure(self):
        if self.settings.compiler == "myGcc":
            self.settings.compiler["myGcc"].remove("libcxx")
            self.settings.compiler["myGcc"].remove("sanitize")

Please let me know if should provide more information.

lasote commented 6 years ago

How looks your build.py?

sunj1 commented 6 years ago

build.py

from conan.packager import ConanMultiPackager

username = "demo"
channel = "stable"

myoption = {}

builder = ConanMultiPackager(username=username,channel=channel, stable_channel=channel)

mysetting = {'compiler.version': '7.1', 'compiler.sanitize': None, 'compiler': 'gcc'} 
builder.add(options=myoption, settings=mysetting)

mysetting = {'compiler.version': '7.0', 'compiler.mode': 'A', 'compiler': 'myGcc'} 
builder.add(options=myoption, settings=mysetting)

builder.run()
lasote commented 6 years ago

I reproduced but I think it is not a bug, it happens even with a "conan create". The configure() method is not valid here, removing a setting means "discard this setting to apply to my configuration" but not skips the check that a subsetting is being applied to a compiler (mygcc) that do not contain that subsetting in the yml. The root issue is that the default profile contains non-common settings for all the configurations, I would recommend you to alter the default profile and add only the libcxx and sanitize to the gcc one. You can change also the default profile, read here: https://github.com/conan-io/conan-package-tools#specifying-a-different-base-profile

sunj1 commented 6 years ago

In my case, base_profiles will need to be changed at run-time. CPT allows to change base profile in run() method, which will remain the same for the entire run, correct?

lasote commented 6 years ago

correct, and you can execute several run() in the same build.py, of course.

sunj1 commented 6 years ago

The below manual workflow works fine for my case:

conan export . demo/test
conan install . -u
for each AddedConfig:
    rm -rf build && mkdir build && cd build
    conan install .. <AddedConfig>
    conan build ..
    conan export-pkg .. demo/test -f
lasote commented 6 years ago

CPT is not skipping anything. It is running a conan create command per configuration. In the example above you are calling the local methods, I don't know exactly why it works but it is not very common to use conan like that.

sunj1 commented 6 years ago

From the conan docs at https://docs.conan.io/en/latest/creating_packages/getting_started.html#creating-and-testing-packages: Using Conan commands, the conan create command would be equivalent to:

$ conan export . demo/testing
$ conan install Hello/0.1@demo/testing --build=Hello
# package is created now, use test to test it
$ conan test test_package Hello/0.1@demo/testing

I'm using the same workflow, just that I'm executing conan build explicitly, and then doing export-pkg instead of conan test

Moreover, from the docs related to configure() at https://docs.conan.io/en/latest/reference/conanfile/methods.html?highlight=configure#configure-config-options It also demonstrates changing/removing settings.

lasote commented 6 years ago

Yes I know about the local commands and the docs very well, I meant that using local methods exactly to avoid write just "conan create" is not very common. Probably it is working because known limitations processing the settings from the conan.info file created on the conan install command. About the configure() docs and removing settings, as I already commented, the check is before the configure of your recipe is being called and it is checking that the settings inputted are correct following the current settings.yml

sunj1 commented 6 years ago

Ok, so the way to go forward for me would be to call run() method of CPT individually for each compiler. I think the issue can be closed if this is the final resolution. Thanks for the details.