def builds(self, confs):
     """For retro compatibility directly assigning builds"""
     self._named_builds = {}
     self._builds = []
     for values in confs:
         if len(values) == 2:
             self._builds.append(BuildConf(values[0], values[1], {}, {}, self.reference))
         elif len(values) == 4:
             self._builds.append(BuildConf(values[0], values[1], values[2], values[3],
                                           self.reference))
         elif len(values) != 5:
             raise Exception("Invalid build configuration, has to be a tuple of "
                             "(settings, options, env_vars, build_requires, reference)")
         else:
             self._builds.append(BuildConf(*values))
 def named_builds(self, confs):
     self._builds = []
     self._named_builds = {}
     for key, pages in confs.items():
         for values in pages:
             if len(values) == 2:
                 bc = BuildConf(values[0], values[1], {}, {}, self.reference)
                 self._named_builds.setdefault(key, []).append(bc)
             elif len(values) == 4:
                 bc = BuildConf(values[0], values[1], values[2], values[3], self.reference)
                 self._named_builds.setdefault(key, []).append(bc)
             elif len(values) != 5:
                 raise Exception("Invalid build configuration, has to be a tuple of "
                                 "(settings, options, env_vars, build_requires, reference)")
             else:
                 self._named_builds.setdefault(key, []).append(BuildConf(*values))
 def add(self, settings=None, options=None, env_vars=None, build_requires=None, reference=None):
     settings = settings or {}
     options = options or {}
     env_vars = env_vars or {}
     build_requires = build_requires or {}
     if reference:
         reference = ConanFileReference.loads("%s@%s/%s" % (reference,
                                                            self.username, self.channel))
     reference = reference or self.reference
     self._builds.append(BuildConf(settings, options, env_vars, build_requires, reference))
 def test_assign_builds_retrocompatibility(self):
     self.packager = ConanMultiPackager(username="******",
                                        channel="mychannel",
                                        runner=self.runner,
                                        conan_api=self.conan_api,
                                        gcc_versions=["4.3", "5"],
                                        use_docker=True,
                                        reference="lib/1.0",
                                        ci_manager=self.ci_manager)
     self.packager.add_common_builds()
     self.packager.builds = [({"os": "Windows"}, {"option": "value"})]
     self.assertEquals(self.packager.items, [BuildConf(settings={'os': 'Windows'},
                                                       options={'option': 'value'},
                                                       env_vars={}, build_requires={},
                                                       reference="lib/1.0@lasote/mychannel")])
    def add_common_builds(self,
                          shared_option_name=None,
                          pure_c=True,
                          dll_with_static_runtime=False,
                          reference=None,
                          header_only=True,
                          build_all_options_values=None):
        if reference:
            if "@" in reference:
                reference = ConanFileReference.loads(reference)
            else:
                name, version = reference.split("/")
                reference = ConanFileReference(name, version, self.username,
                                               self.channel)
        else:
            reference = self.reference

        if not reference:
            raise Exception(
                "Specify a CONAN_REFERENCE or name and version fields in the recipe"
            )

        if shared_option_name is None:
            env_shared_option_name = os.getenv("CONAN_SHARED_OPTION_NAME",
                                               None)
            shared_option_name = env_shared_option_name if str(
                env_shared_option_name).lower() != "false" else False

        build_all_options_values = build_all_options_values or split_colon_env(
            "CONAN_BUILD_ALL_OPTIONS_VALUES") or []
        if not isinstance(build_all_options_values, list):
            raise Exception(
                "'build_all_options_values' must be a list. e.g. ['foo:opt', 'foo:bar']"
            )

        conanfile = None
        if os.path.exists(os.path.join(self.cwd, self.conanfile)):
            conanfile = load_cf_class(os.path.join(self.cwd, self.conanfile),
                                      self.conan_api)

        header_only_option = None
        if conanfile:
            if hasattr(
                    conanfile, "options"
            ) and conanfile.options and "header_only" in conanfile.options:
                header_only_option = "%s:header_only" % reference.name

        if shared_option_name is None:
            if conanfile:
                if hasattr(
                        conanfile, "options"
                ) and conanfile.options and "shared" in conanfile.options:
                    shared_option_name = "%s:shared" % reference.name

        # filter only valid options
        raw_options_for_building = [
            opt[opt.find(":") + 1:] for opt in build_all_options_values
        ]
        for raw_option in reversed(raw_options_for_building):
            if hasattr(conanfile, "options") and conanfile.options and \
               not isinstance(conanfile.options.get(raw_option), list):
                raw_options_for_building.remove(raw_option)
        if raw_options_for_building and conanfile:
            # get option and its values
            cloned_options = copy.copy(conanfile.options)
            for key, value in conanfile.options.items():
                if key == "shared" and shared_option_name:
                    continue
                elif key not in raw_options_for_building:
                    del cloned_options[key]
            cloned_options2 = {}
            for key, value in cloned_options.items():
                # add package reference to the option name
                if not key.startswith("{}:".format(reference.name)):
                    cloned_options2["{}:{}".format(reference.name,
                                                   key)] = value
            # combine all options x values (cartesian product)
            build_all_options_values = [
                dict(zip(cloned_options2, v))
                for v in product(*cloned_options2.values())
            ]

        builds = self.build_generator.get_builds(pure_c, shared_option_name,
                                                 dll_with_static_runtime,
                                                 reference,
                                                 build_all_options_values)

        if header_only_option and header_only:
            if conanfile.default_options.get("header_only"):
                cloned_builds = copy.deepcopy(builds)
                for settings, options, env_vars, build_requires, reference in cloned_builds:
                    options.update({header_only_option: False})
                builds.extend(cloned_builds)
            else:
                settings, options, env_vars, build_requires, reference = builds[
                    0]
                cloned_options = copy.copy(options)
                cloned_options.update({header_only_option: True})
                builds.append(
                    BuildConf(copy.copy(settings), cloned_options,
                              copy.copy(env_vars), copy.copy(build_requires),
                              reference))

        self._builds.extend(builds)