Exemplo n.º 1
0
    def __init__(self, output, runner, settings, conanfile_directory, user=None, channel=None):
        # User defined generators
        self.generators = self.generators if hasattr(self, "generators") else ["txt"]
        if isinstance(self.generators, str):
            self.generators = [self.generators]

        # User defined options
        self.options = create_options(self)
        self.requires = create_requirements(self)
        self.settings = create_settings(self, settings)
        self.exports = create_exports(self)
        self.exports_sources = create_exports_sources(self)
        # needed variables to pack the project
        self.cpp_info = None  # Will be initialized at processing time
        self.deps_cpp_info = DepsCppInfo()

        # environment variables declared in the package_info
        self.env_info = None  # Will be initialized at processing time
        self.deps_env_info = DepsEnvInfo()

        self.copy = None  # initialized at runtime

        # an output stream (writeln, info, warn error)
        self.output = output
        # something that can run commands, as os.sytem
        self._runner = runner

        self._conanfile_directory = conanfile_directory
        self.package_folder = None  # Assigned at runtime
        self._scope = None

        # user specified env variables
        self._env_values = EnvValues()  # Updated at runtime, user specified -e
        self._user = user
        self._channel = channel
Exemplo n.º 2
0
 def __init__(self):
     # Sections
     self.settings = OrderedDict()
     self.package_settings = defaultdict(OrderedDict)
     self.env_values = EnvValues()
     self.options = OptionsValues()
     self.build_requires = OrderedDict()  # conan_ref Pattern: list of conan_ref
Exemplo n.º 3
0
 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():
         for name, value in data:
             env_values.add(name, EnvValues.load_value(value), package)
     return env_values
Exemplo n.º 4
0
    def test_update_concat(self):
        env_info = EnvInfo()
        env_info.path.append("SOME/PATH")
        deps_info = DepsEnvInfo()
        deps_info.update(env_info, "lib")

        deps_info2 = DepsEnvInfo()
        deps_info2.update(env_info, "lib2")

        env = EnvValues()
        env.add("PATH", ["MYPATH"])
        env.update(deps_info)

        self.assertEquals(env.env_dicts(None), ({}, {'PATH': ['MYPATH', 'SOME/PATH']}))

        env.update(deps_info2)

        self.assertEquals(env.env_dicts(None), ({}, {'PATH': ['MYPATH', 'SOME/PATH', 'SOME/PATH']}))
Exemplo n.º 5
0
def _apply_inner_profile(doc, base_profile):
    """

    :param doc: ConfigParser object from the current profile (excluding includes and vars, and with values already replaced)
    :param base_profile: Profile inherited, it's used as a base profile to modify it.
    :return: None
    """

    def get_package_name_value(item):
        """Parse items like package:name=value or name=value"""
        package_name = None
        if ":" in item:
            tmp = item.split(":", 1)
            package_name, item = tmp

        name, value = item.split("=", 1)
        name = name.strip()
        value = unquote(value)
        return package_name, name, value

    for setting in doc.settings.splitlines():
        setting = setting.strip()
        if setting and not setting.startswith("#"):
            if "=" not in setting:
                raise ConanException("Invalid setting line '%s'" % setting)
            package_name, name, value = get_package_name_value(setting)
            if package_name:
                base_profile.package_settings[package_name][name] = value
            else:
                base_profile.settings[name] = value

    if doc.build_requires:
        # FIXME CHECKS OF DUPLICATED?
        for req in doc.build_requires.splitlines():
            tokens = req.split(":", 1)
            if len(tokens) == 1:
                pattern, req_list = "*", req
            else:
                pattern, req_list = tokens
            req_list = [ConanFileReference.loads(r.strip()) for r in req_list.split(",")]
            base_profile.build_requires.setdefault(pattern, []).extend(req_list)

    if doc.scopes:
        base_profile.update_scopes(Scopes.from_list(doc.scopes.splitlines()))

    if doc.options:
        base_profile.options.update(OptionsValues.loads(doc.options))

    base_profile.env_values.update(EnvValues.loads(doc.env))
Exemplo n.º 6
0
    def loads(text):
        parser = ConfigParser(text, ["settings", "full_settings", "options", "full_options",
                                     "requires", "full_requires", "scope", "recipe_hash",
                                     "env"], raise_unexpected_field=False)
        result = ConanInfo()
        result.settings = Values.loads(parser.settings)
        result.full_settings = Values.loads(parser.full_settings)
        result.options = OptionsValues.loads(parser.options)
        result.full_options = OptionsValues.loads(parser.full_options)
        result.full_requires = RequirementsList.loads(parser.full_requires)
        result.requires = RequirementsInfo(result.full_requires)
        result.recipe_hash = parser.recipe_hash or None

        # TODO: Missing handling paring of requires, but not necessary now
        result.env_values = EnvValues.loads(parser.env)
        return result
Exemplo n.º 7
0
def _apply_inner_profile(doc, base_profile):
    """

    :param doc: ConfigParser object from the current profile (excluding includes and vars,
    and with values already replaced)
    :param base_profile: Profile inherited, it's used as a base profile to modify it.
    :return: None
    """

    def get_package_name_value(item):
        """Parse items like package:name=value or name=value"""
        package_name = None
        if ":" in item:
            tmp = item.split(":", 1)
            package_name, item = tmp

        name, value = item.split("=", 1)
        name = name.strip()
        value = unquote(value)
        return package_name, name, value

    for setting in doc.settings.splitlines():
        setting = setting.strip()
        if setting and not setting.startswith("#"):
            if "=" not in setting:
                raise ConanException("Invalid setting line '%s'" % setting)
            package_name, name, value = get_package_name_value(setting)
            if package_name:
                base_profile.package_settings[package_name][name] = value
            else:
                base_profile.settings[name] = value

    if doc.build_requires:
        # FIXME CHECKS OF DUPLICATED?
        for req in doc.build_requires.splitlines():
            _load_single_build_require(base_profile, req)

    if doc.options:
        base_profile.options.update(OptionsValues.loads(doc.options))

    # The env vars from the current profile (read in doc)
    # are updated with the included profiles (base_profile)
    # the current env values has priority
    current_env_values = EnvValues.loads(doc.env)
    current_env_values.update(base_profile.env_values)
    base_profile.env_values = current_env_values
Exemplo n.º 8
0
    def valid_xml_test(self, use_toolset):
        tempdir = temp_folder()
        with chdir(tempdir):
            settings = Settings.loads(default_settings_yml)
            settings.os = "Windows"
            settings.compiler = "Visual Studio"
            settings.compiler.version = "11"
            settings.compiler.runtime = "MD"
            if use_toolset:
                settings.compiler.toolset = "v110"
            conanfile = ConanFile(None, None)
            conanfile.initialize(Settings({}), EnvValues())

            ref = ConanFileReference.loads("MyPkg/0.1@user/testing")
            cpp_info = CppInfo("dummy_root_folder1")
            conanfile.deps_cpp_info.update(cpp_info, ref.name)
            ref = ConanFileReference.loads("My.Fancy-Pkg_2/0.1@user/testing")
            cpp_info = CppInfo("dummy_root_folder2")
            conanfile.deps_cpp_info.update(cpp_info, ref.name)

            settings.arch = "x86"
            settings.build_type = "Debug"
            conanfile.settings = settings

            generator = VisualStudioMultiGenerator(conanfile)
            generator.output_path = ""
            content = generator.content

            self.assertEqual(2, len(content))
            self.assertIn('conanbuildinfo_multi.props', content.keys())
            self.assertIn('conanbuildinfo_debug_win32_v110.props',
                          content.keys())

            content_multi = content['conanbuildinfo_multi.props']
            self.assertIn(
                "<Import Condition=\"'$(Configuration)' == 'Debug' "
                "And '$(Platform)' == 'Win32' "
                "And '$(PlatformToolset)' == 'v110'\" "
                "Project=\"conanbuildinfo_debug_win32_v110.props\"/>",
                content_multi)

            with open('conanbuildinfo_multi.props', 'w') as f:
                f.write(content_multi)

            settings.arch = "x86_64"
            settings.build_type = "Release"
            settings.compiler.version = "15"
            settings.compiler.toolset = "v141"
            conanfile.settings = settings

            generator = VisualStudioMultiGenerator(conanfile)
            generator.output_path = ""
            content = generator.content

            self.assertEqual(2, len(content))
            self.assertIn('conanbuildinfo_multi.props', content.keys())
            self.assertIn('conanbuildinfo_release_x64_v141.props',
                          content.keys())

            content_multi = content['conanbuildinfo_multi.props']
            self.assertIn(
                "<Import Condition=\"'$(Configuration)' == 'Debug' "
                "And '$(Platform)' == 'Win32' "
                "And '$(PlatformToolset)' == 'v110'\" "
                "Project=\"conanbuildinfo_debug_win32_v110.props\"/>",
                content_multi)
            self.assertIn(
                "<Import Condition=\"'$(Configuration)' == 'Release' "
                "And '$(Platform)' == 'x64' "
                "And '$(PlatformToolset)' == 'v141'\" "
                "Project=\"conanbuildinfo_release_x64_v141.props\"/>",
                content_multi)

            os.unlink('conanbuildinfo_multi.props')
Exemplo n.º 9
0
    def test_model(self):
        env = EnvValues()
        env.add("Z", "1")
        self.assertEquals(env.env_dicts(""), ({"Z": "1"}, {}))
        env.add("Z", "2")
        self.assertEquals(env.env_dicts(""), ({"Z": "1"}, {}))
        env.add("B", "223")
        self.assertEquals(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
        env.add("B", "224", "package1")
        self.assertEquals(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
        self.assertEquals(env.env_dicts("package1"), ({"Z": "1", "B": "224"}, {}))
        env.add("A", "1", "package1")
        self.assertEquals(env.env_dicts("package1"), ({"Z": "1", "B": "224", "A": "1"}, {}))
        self.assertEquals(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
        env.add("J", "21", "package21")
        self.assertEquals(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
        self.assertEquals(env.env_dicts("package1"), ({"Z": "1", "B": "224", "A": "1"}, {}))
        env.add("A", ["99"], "package1")
        self.assertEquals(env.env_dicts("package1"), ({"Z": "1", "B": "224", "A": "1"}, {}))
        env.add("M", ["99"], "package1")
        self.assertEquals(env.env_dicts("package1"), ({"Z": "1", "B": "224", "A": "1"}, {"M": ["99"]}))
        env.add("M", "100", "package1")
        self.assertEquals(env.env_dicts("package1"), ({"Z": "1", "B": "224", "A": "1"}, {"M": ["99", "100"]}))

        self.assertEquals(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
Exemplo n.º 10
0
    def update_priority_test(self):

        env = EnvValues()
        env.add("VAR", "VALUE1")

        env2 = EnvValues()
        env2.add("VAR", "VALUE2")

        env.update(env2)

        # Already set by env, discarded new value
        self.assertEquals(env.env_dicts(None),  ({'VAR': 'VALUE1'}, {}))

        # Updates with lists and values
        env = EnvValues()
        env.add("VAR", ["1"])
        env.add("VAR", "2")
        self.assertEquals(env.env_dicts(None), ({}, {'VAR': ['1', '2']}))

        # If the first value is not a list won't append
        env = EnvValues()
        env.add("VAR", "1")
        env.add("VAR", ["2"])
        self.assertEquals(env.env_dicts(None), ({'VAR': '1'}, {}))
Exemplo n.º 11
0
class Profile(object):
    """A profile contains a set of setting (with values), environment variables
    """

    def __init__(self):
        # Sections
        self.settings = OrderedDict()
        self.package_settings = defaultdict(OrderedDict)
        self.env_values = EnvValues()
        self.options = OptionsValues()
        self.build_requires = OrderedDict()  # conan_ref Pattern: list of conan_ref

    @property
    def settings_values(self):
        return Values.from_list(list(self.settings.items()))

    @property
    def package_settings_values(self):
        result = {}
        for pkg, settings in self.package_settings.items():
            result[pkg] = list(settings.items())
        return result

    def dumps(self):
        result = ["[settings]"]
        for name, value in self.settings.items():
            result.append("%s=%s" % (name, value))
        for package, values in self.package_settings.items():
            for name, value in values.items():
                result.append("%s:%s=%s" % (package, name, value))

        result.append("[options]")
        result.append(self.options.dumps())

        result.append("[build_requires]")
        for pattern, req_list in self.build_requires.items():
            result.append("%s: %s" % (pattern, ", ".join(str(r) for r in req_list)))

        result.append("[env]")
        result.append(self.env_values.dumps())

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

    def update(self, other):
        self.update_settings(other.settings)
        self.update_package_settings(other.package_settings)
        # this is the opposite
        other.env_values.update(self.env_values)
        self.env_values = other.env_values
        self.options.update(other.options)
        for pattern, req_list in other.build_requires.items():
            self.build_requires.setdefault(pattern, []).extend(req_list)

    def update_settings(self, new_settings):
        """Mix the specified settings with the current profile.
        Specified settings are prioritized to profile"""

        assert(isinstance(new_settings, OrderedDict))

        # apply the current profile
        res = copy.copy(self.settings)
        if new_settings:
            # Invalidate the current subsettings if the parent setting changes
            # Example: new_settings declare a different "compiler", so invalidate the current "compiler.XXX"
            for name, value in new_settings.items():
                if "." not in name:
                    if name in self.settings and self.settings[name] != value:
                        for cur_name, _ in self.settings.items():
                            if cur_name.startswith("%s." % name):
                                del res[cur_name]
            # Now merge the new values
            res.update(new_settings)
            self.settings = res

    def update_package_settings(self, package_settings):
        """Mix the specified package settings with the specified profile.
        Specified package settings are prioritized to profile"""
        for package_name, settings in package_settings.items():
            self.package_settings[package_name].update(settings)
Exemplo n.º 12
0
    def test_update_priority(self):

        env = EnvValues()
        env.add("VAR", "VALUE1")

        env2 = EnvValues()
        env2.add("VAR", "VALUE2")

        env.update(env2)

        # Already set by env, discarded new value
        self.assertEqual(env.env_dicts(None), ({'VAR': 'VALUE1'}, {}))

        # Updates with lists and values
        env = EnvValues()
        env.add("VAR", ["1"])
        env.add("VAR", "2")
        self.assertEqual(env.env_dicts(None), ({}, {'VAR': ['1', '2']}))

        # If the first value is not a list won't append
        env = EnvValues()
        env.add("VAR", "1")
        env.add("VAR", ["2"])
        self.assertEqual(env.env_dicts(None), ({'VAR': '1'}, {}))
Exemplo n.º 13
0
    def test_toolchain_linux(self, build_type, arch, cppstd, libcxx, shared,
                             fpic):
        settings_mock = _MockSettings(build_type, arch, cppstd, libcxx)
        conanfile = ConanFile(TestBufferConanOutput(), None)
        conanfile.options = {"shared": [True, False], "fPIC": [True, False]}
        conanfile.default_options = {"shared": shared, "fPIC": fpic}
        conanfile.initialize(settings_mock, EnvValues())
        toolchain = MakeToolchain(conanfile)
        content = toolchain.content

        expected_template = Template(
            textwrap.dedent("""
            # Conan generated toolchain file
            ifndef CONAN_TOOLCHAIN_INCLUDED
                CONAN_TOOLCHAIN_INCLUDED = TRUE
                CONAN_TC_BUILD_TYPE = {{build_type}}
                CONAN_TC_OS_HOST = None
                CONAN_TC_ARCH_HOST = {{arch_host}}
                CONAN_TC_TRIPLET_HOST = False
                CONAN_TC_OS_BUILD = Linux
                CONAN_TC_ARCH_BUILD = {{arch_build}}
                CONAN_TC_TRIPLET_BUILD = False
                CONAN_TC_OS_TARGET = None
                CONAN_TC_ARCH_TARGET = None
                CONAN_TC_TRIPLET_TARGET = None
                CONAN_TC_COMPILER = {{compiler}}
                CONAN_TC_COMPILER_VERSION = {{compiler_version}}
                CONAN_TC_COMPILER_RUNTIME = None
                CONAN_TC_LIBCXX = {{libcxx}}
                CONAN_TC_CPPSTD_FLAG = {{cppstd_flag}}
                CONAN_TC_ARCH_FLAG = {{arch_flag}}
                CONAN_TC_BUILD_TYPE_FLAGS = {{build_type_flags}}
                CONAN_TC_DEFINES ={{preserved_space}}

                CONAN_TC_SET_LIBCXX = True
                CONAN_TC_SET_CPPSTD = True
                CONAN_TC_SET_ARCH = True
                CONAN_TC_SET_FPIC = {{set_fpic}}
                CONAN_TC_SET_SHARED = {{set_shared}}

                CONAN_TC_CFLAGS += $(CONAN_TC_BUILD_TYPE_FLAGS)
                CONAN_TC_CXXFLAGS += $(CONAN_TC_BUILD_TYPE_FLAGS)

                ifeq ($(CONAN_TC_BUILD_TYPE),Release)
                    CONAN_TC_DEFINES += NDEBUG
                endif

                ifeq ($(CONAN_TC_SET_LIBCXX),True)
                    CONAN_TC_CLANG_BASED := $(if $(filter $(CONAN_TC_COMPILER),clang apple-clang),true)
                    ifeq ($(CONAN_TC_CLANG_BASED),True)
                        CONAN_TC_LIBSTDCXX_BASED := $(if $(filter $(CONAN_TC_LIBCXX),libstdc++ libstdc++11),true)
                        ifeq ($(CONAN_TC_LIBSTDCXX_BASED),True)
                            CONAN_TC_CXXFLAGS += -stdlib=libstdc++
                        else ifeq ($(CONAN_TC_LIBCXX),libc++)
                            CONAN_TC_CXXFLAGS += -stdlib=libc++
                        endif
                    else ifeq ($(CONAN_TC_COMPILER),sun-cc)
                        ifeq ($(CONAN_TC_LIBCXX),libCstd)
                            CONAN_TC_CXXFLAGS += -library=Cstd++
                        else ifeq ($(CONAN_TC_LIBCXX),libstdcxx)
                            CONAN_TC_CXXFLAGS += -library=stdcxx4
                        else ifeq ($(CONAN_TC_LIBCXX),libstlport)
                            CONAN_TC_CXXFLAGS += -library=stlport4
                        else ifeq ($(CONAN_TC_LIBCXX),libstdc++)
                            CONAN_TC_CXXFLAGS += -library=stdcpp
                        endif
                    endif
                    ifeq ($(CONAN_TC_LIBCXX),libstdc++11)
                        CONAN_TC_DEFINES += GLIBCXX_USE_CXX11_ABI=1
                    else ifeq ($(CONAN_TC_LIBCXX),libstdc++)
                        CONAN_TC_DEFINES += GLIBCXX_USE_CXX11_ABI=0
                    endif
                endif
                ifeq ($(CONAN_TC_SET_CPPSTD),True)
                    CONAN_TC_CXXFLAGS += $(CONAN_TC_CPPSTD_FLAG)
                endif
                ifeq ($(CONAN_TC_SET_ARCH),True)
                    CONAN_TC_CFLAGS += $(CONAN_TC_ARCH_FLAG)
                    CONAN_TC_CXXFLAGS += $(CONAN_TC_ARCH_FLAG)
                    CONAN_TC_SHARED_LINKER_FLAGS += $(CONAN_TC_ARCH_FLAG)
                    CONAN_TC_EXE_LINKER_FLAGS += $(CONAN_TC_ARCH_FLAG)
                endif
                ifeq ($(CONAN_TC_SET_FPIC),True)
                    CONAN_TC_CFLAGS += -fPIC
                    CONAN_TC_CXXFLAGS += -fPIC
                    CONAN_TC_SHARED_LINKER_FLAGS += -fPIC
                    CONAN_TC_EXE_LINKER_FLAGS += -pie
                endif
                ifeq ($(CONAN_TC_SET_SHARED),True)
                    CONAN_TC_LDFLAGS += -shared
                    CONAN_TC_LDFLAGS += $(CONAN_TC_SHARED_LINKER_FLAGS)
                else
                    CONAN_TC_LDFLAGS += $(CONAN_TC_EXE_LINKER_FLAGS)
                endif
            endif

            CONAN_TC_CPPFLAGS += $(addprefix -D,$(CONAN_TC_DEFINES))

            # Call this function in your Makefile to have Conan variables added to the standard variables
            # Example:  $(call CONAN_TC_SETUP)

            CONAN_TC_SETUP =  \\
                $(eval CFLAGS += $(CONAN_TC_CFLAGS)) ; \\
                $(eval CXXFLAGS += $(CONAN_TC_CXXFLAGS)) ; \\
                $(eval CPPFLAGS += $(CONAN_TC_CPPFLAGS)) ; \\
                $(eval LDFLAGS += $(CONAN_TC_LDFLAGS)) ;
        """))

        context = {
            "arch_host": conanfile.settings.get_safe("arch"),
            "arch_build": detected_architecture(),
            "compiler": conanfile.settings.get_safe("compiler"),
            "compiler_version":
            conanfile.settings.get_safe("compiler.version"),
            "arch_flag": architecture_flag(settings_mock),
            "cppstd_flag": cppstd_flag_new(conanfile.settings),
            "build_type_flags": " ".join(build_type_flags(conanfile.settings)),
            "build_type": build_type,
            "libcxx": libcxx,
            "set_shared": shared,
            "set_fpic": fpic,
            "preserved_space": " ",
        }
        #
        expected_content = expected_template.render(context)

        self.maxDiff = None
        self.assertIn(expected_content, content)
Exemplo n.º 14
0
    def variables_setup_test(self):
        conanfile = ConanFile(TestBufferConanOutput(), None)
        conanfile.initialize(Settings({}), EnvValues())

        # Add some cpp_info for dependencies
        ref = ConanFileReference.loads("MyPkg/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder1")
        cpp_info.defines = ["MYDEFINE1"]
        cpp_info.cflags.append("-Flag1=23")
        cpp_info.version = "1.3"
        cpp_info.description = "My cool description"
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("MyPkg2/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder2")
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.version = "2.3"
        cpp_info.exelinkflags = ["-exelinkflag"]
        cpp_info.sharedlinkflags = ["-sharedlinkflag"]
        cpp_info.cxxflags = ["-cxxflag"]
        cpp_info.public_deps = ["MyPkg"]
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        # Add env_info
        env_info = EnvInfo()
        env_info.VAR1 = "env_info-value1"
        env_info.PATH.append("path-extended")
        conanfile.deps_env_info.update(env_info, "env_info_pkg")

        # Add user_info
        user_info = UserInfo()
        user_info.VAR1 = "user_info-value1"
        conanfile.deps_user_info["user_info_pkg"] = user_info

        # Add user_info_build
        conanfile.user_info_build = DepsUserInfo()
        user_info = UserInfo()
        user_info.VAR1 = "user_info_build-value1"
        conanfile.user_info_build["user_info_build_pkg"] = user_info

        generator = JsonGenerator(conanfile)
        json_out = generator.content
        parsed = json.loads(json_out)

        # Check dependencies
        dependencies = parsed["dependencies"]
        self.assertEqual(len(dependencies), 2)
        my_pkg = dependencies[0]
        self.assertEqual(my_pkg["name"], "MyPkg")
        self.assertEqual(my_pkg["description"], "My cool description")
        self.assertEqual(my_pkg["defines"], ["MYDEFINE1"])

        # Check env_info
        env_info = parsed["deps_env_info"]
        self.assertListEqual(sorted(env_info.keys()), sorted(["VAR1", "PATH"]))
        self.assertEqual(env_info["VAR1"], "env_info-value1")
        self.assertListEqual(env_info["PATH"], ["path-extended"])

        # Check user_info
        user_info = parsed["deps_user_info"]
        self.assertListEqual(list(user_info.keys()), ["user_info_pkg"])
        self.assertListEqual(list(user_info["user_info_pkg"].keys()), ["VAR1"])
        self.assertEqual(user_info["user_info_pkg"]["VAR1"],
                         "user_info-value1")

        # Check user_info_build
        user_info_build = parsed["user_info_build"]
        self.assertListEqual(list(user_info_build.keys()),
                             ["user_info_build_pkg"])
        self.assertListEqual(
            list(user_info_build["user_info_build_pkg"].keys()), ["VAR1"])
        self.assertEqual(user_info_build["user_info_build_pkg"]["VAR1"],
                         "user_info_build-value1")
Exemplo n.º 15
0
    def variables_setup_test(self):
        tmp_folder1 = temp_folder()
        tmp_folder2 = temp_folder()
        save(os.path.join(tmp_folder1, "include1", "file.h"), "")
        save(os.path.join(tmp_folder2, "include2", "file.h"), "")
        save(os.path.join(tmp_folder1, "lib1", "file.a"), "")
        save(os.path.join(tmp_folder2, "lib2", "file.a"), "")
        save(os.path.join(tmp_folder1, "bin1", "file.bin"), "")
        save(os.path.join(tmp_folder2, "bin2", "file.bin"), "")

        conanfile = ConanFile(None, None)
        conanfile.initialize(Settings({}), EnvValues())
        ref = ConanFileReference.loads("MyPkg1/0.1@lasote/stables")
        cpp_info = CppInfo(tmp_folder1)
        cpp_info.defines = ["MYDEFINE1"]
        cpp_info.includedirs = ['include1']
        cpp_info.libdirs = ['lib1']
        cpp_info.libs = ['libfoo']
        cpp_info.bindirs = ['bin1']
        cpp_info.version = "0.1"
        cpp_info.cflags = ['-fPIC']
        cpp_info.cppflags = ['-fPIE']
        cpp_info.sharedlinkflags = ['-framework Cocoa']
        cpp_info.exelinkflags = ['-framework QuartzCore']
        conanfile.deps_cpp_info.update(cpp_info, ref.name)
        ref = ConanFileReference.loads("MyPkg2/3.2.3@lasote/stables")
        cpp_info = CppInfo(tmp_folder2)
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.includedirs = ['include2']
        cpp_info.libdirs = ['lib2']
        cpp_info.libs = ['libbar']
        cpp_info.bindirs = ['bin2']
        cpp_info.version = "3.2.3"
        cpp_info.cflags = ['-mtune=native']
        cpp_info.cppflags = ['-march=native']
        cpp_info.sharedlinkflags = ['-framework AudioFoundation']
        cpp_info.exelinkflags = ['-framework VideoToolbox']
        conanfile.deps_cpp_info.update(cpp_info, ref.name)
        generator = PremakeGenerator(conanfile)
        content = generator.content

        self.assertIn('conan_cppdefines = {"MYDEFINE2", "MYDEFINE1"}', content)
        self.assertIn('conan_cppdefines_MyPkg1 = {"MYDEFINE1"}', content)
        self.assertIn('conan_cppdefines_MyPkg2 = {"MYDEFINE2"}', content)

        inc1 = os.path.join(tmp_folder1, 'include1').replace('\\', '/')
        inc2 = os.path.join(tmp_folder2, 'include2').replace('\\', '/')
        self.assertIn('conan_includedirs = {"%s",\n"%s"}' % (inc1, inc2),
                      content)
        self.assertIn('conan_includedirs_MyPkg1 = {"%s"}' % inc1, content)
        self.assertIn('conan_includedirs_MyPkg2 = {"%s"}' % inc2, content)

        lib1 = os.path.join(tmp_folder1, 'lib1').replace('\\', '/')
        lib2 = os.path.join(tmp_folder2, 'lib2').replace('\\', '/')
        self.assertIn('conan_libdirs = {"%s",\n"%s"}' % (lib1, lib2), content)
        self.assertIn('conan_libdirs_MyPkg1 = {"%s"}' % lib1, content)
        self.assertIn('conan_libdirs_MyPkg2 = {"%s"}' % lib2, content)

        bin1 = os.path.join(tmp_folder1, 'bin1').replace('\\', '/')
        bin2 = os.path.join(tmp_folder2, 'bin2').replace('\\', '/')
        self.assertIn('conan_bindirs = {"%s",\n"%s"}' % (bin1, bin2), content)
        self.assertIn('conan_bindirs_MyPkg1 = {"%s"}' % bin1, content)
        self.assertIn('conan_bindirs_MyPkg2 = {"%s"}' % bin2, content)

        self.assertIn('conan_libs = {"libfoo", "libbar"}', content)
        self.assertIn('conan_libs_MyPkg1 = {"libfoo"}', content)
        self.assertIn('conan_libs_MyPkg2 = {"libbar"}', content)

        self.assertIn('conan_cflags = {"-mtune=native", "-fPIC"}', content)
        self.assertIn('conan_cflags_MyPkg1 = {"-fPIC"}', content)
        self.assertIn('conan_cflags_MyPkg2 = {"-mtune=native"}', content)

        self.assertIn('conan_cppflags = {"-march=native", "-fPIE"}', content)
        self.assertIn('conan_cppflags_MyPkg1 = {"-fPIE"}', content)
        self.assertIn('conan_cppflags_MyPkg2 = {"-march=native"}', content)

        self.assertIn(
            'conan_sharedlinkflags = {"-framework AudioFoundation", "-framework Cocoa"}',
            content)
        self.assertIn('conan_sharedlinkflags_MyPkg1 = {"-framework Cocoa"}',
                      content)
        self.assertIn(
            'conan_sharedlinkflags_MyPkg2 = {"-framework AudioFoundation"}',
            content)

        self.assertIn(
            'conan_exelinkflags = {"-framework VideoToolbox", "-framework QuartzCore"}',
            content)
        self.assertIn('conan_exelinkflags_MyPkg1 = {"-framework QuartzCore"}',
                      content)
        self.assertIn(
            'conan_exelinkflags_MyPkg2 = {"-framework VideoToolbox"}', content)
Exemplo n.º 16
0
    def pkg_config_custom_names_test(self):
        conanfile = ConanFile(TestBufferConanOutput(), None)
        conanfile.initialize(Settings({}), EnvValues())

        ref = ConanFileReference.loads("MyPkg/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "/dummy_root_folder1")
        cpp_info.filter_empty = False
        cpp_info.name = "my_pkg"
        cpp_info.names["pkg_config"] = "my_pkg_custom_name"
        cpp_info.defines = ["MYDEFINE1"]
        cpp_info.cflags.append("-Flag1=23")
        cpp_info.version = "1.3"
        cpp_info.description = "My cool description"
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("MyPkg1/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "/dummy_root_folder1")
        cpp_info.filter_empty = False
        cpp_info.name = "MYPKG1"
        cpp_info.names["pkg_config"] = "my_pkg1_custom_name"
        cpp_info.defines = ["MYDEFINE11"]
        cpp_info.cflags.append("-Flag1=21")
        cpp_info.version = "1.7"
        cpp_info.description = "My other cool description"
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("MyPkg2/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "/dummy_root_folder2")
        cpp_info.filter_empty = False
        cpp_info.names["pkg_config"] = "my_pkg2_custom_name"
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.version = "2.3"
        cpp_info.exelinkflags = ["-exelinkflag"]
        cpp_info.sharedlinkflags = ["-sharedlinkflag"]
        cpp_info.cxxflags = ["-cxxflag"]
        cpp_info.public_deps = ["MyPkg", "MyPkg1"]
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("zlib/1.2.11@lasote/stable")
        cpp_info = CppInfo(ref.name, "/dummy_root_folder_zlib")
        cpp_info.filter_empty = False
        cpp_info.name = "ZLIB"
        cpp_info.defines = ["MYZLIBDEFINE2"]
        cpp_info.version = "1.2.11"
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("bzip2/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "/dummy_root_folder2")
        cpp_info.filter_empty = False
        cpp_info.name = "BZip2"
        cpp_info.names["pkg_config"] = "BZip2"
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.version = "2.3"
        cpp_info.exelinkflags = ["-exelinkflag"]
        cpp_info.sharedlinkflags = ["-sharedlinkflag"]
        cpp_info.cxxflags = ["-cxxflag"]
        cpp_info.public_deps = ["MyPkg", "MyPkg1", "zlib"]
        conanfile.deps_cpp_info.add(ref.name, cpp_info)
        generator = PkgConfigGenerator(conanfile)
        files = generator.content

        self.assertEqual(
            files["my_pkg2_custom_name.pc"], """prefix=/dummy_root_folder2
libdir=${prefix}/lib
includedir=${prefix}/include

Name: my_pkg2_custom_name
Description: Conan package: my_pkg2_custom_name
Version: 2.3
Libs: -L${libdir} -sharedlinkflag -exelinkflag
Cflags: -I${includedir} -cxxflag -DMYDEFINE2
Requires: my_pkg_custom_name my_pkg1_custom_name
""")
        self.assertEqual(
            files["my_pkg1_custom_name.pc"], """prefix=/dummy_root_folder1
libdir=${prefix}/lib
includedir=${prefix}/include

Name: my_pkg1_custom_name
Description: My other cool description
Version: 1.7
Libs: -L${libdir}
Cflags: -I${includedir} -Flag1=21 -DMYDEFINE11
""")
        self.assertEqual(
            files["my_pkg_custom_name.pc"], """prefix=/dummy_root_folder1
libdir=${prefix}/lib
includedir=${prefix}/include

Name: my_pkg_custom_name
Description: My cool description
Version: 1.3
Libs: -L${libdir}
Cflags: -I${includedir} -Flag1=23 -DMYDEFINE1
""")
        self.assertEqual(
            files["BZip2.pc"], """prefix=/dummy_root_folder2
libdir=${prefix}/lib
includedir=${prefix}/include

Name: BZip2
Description: Conan package: BZip2
Version: 2.3
Libs: -L${libdir} -sharedlinkflag -exelinkflag
Cflags: -I${includedir} -cxxflag -DMYDEFINE2
Requires: my_pkg_custom_name my_pkg1_custom_name zlib
""")
Exemplo n.º 17
0
class Profile(object):
    """A profile contains a set of setting (with values), environment variables
    """
    def __init__(self):
        # Input sections, as defined by user profile files and command line
        self.settings = OrderedDict()
        self.package_settings = defaultdict(OrderedDict)
        self.env_values = EnvValues()
        self.options = OptionsValues()
        self.build_requires = OrderedDict()  # ref pattern: list of ref
        self.conf = ConfDefinition()

        # Cached processed values
        self.processed_settings = None  # Settings with values, and smart completion
        self._user_options = None
        self._package_settings_values = None
        self.dev_reference = None  # Reference of the package being develop

    @property
    def user_options(self):
        if self._user_options is None:
            self._user_options = self.options.copy()
        return self._user_options

    @property
    def package_settings_values(self):
        if self._package_settings_values is None:
            self._package_settings_values = {}
            for pkg, settings in self.package_settings.items():
                self._package_settings_values[pkg] = list(settings.items())
        return self._package_settings_values

    def process_settings(self, cache, preprocess=True):
        assert self.processed_settings is None, "processed settings must be None"
        self.processed_settings = cache.settings.copy()
        self.processed_settings.values = Values.from_list(
            list(self.settings.items()))
        if preprocess:
            settings_preprocessor.preprocess(self.processed_settings)
            # Redefine the profile settings values with the preprocessed ones
            # FIXME: Simplify the values.as_list()
            self.settings = OrderedDict(
                self.processed_settings.values.as_list())

            # Preprocess also scoped settings
            for pkg, pkg_settings in self.package_settings.items():
                pkg_profile = Profile()
                pkg_profile.settings = self.settings
                pkg_profile.update_settings(pkg_settings)
                try:
                    pkg_profile.process_settings(cache=cache, preprocess=True)
                except Exception as e:
                    pkg_profile = [
                        "{}={}".format(k, v)
                        for k, v in pkg_profile.settings.items()
                    ]
                    raise ConanException(
                        "Error in resulting settings for package"
                        " '{}': {}\n{}".format(pkg, e, '\n'.join(pkg_profile)))
                # TODO: Assign the _validated_ settings and do not compute again

    def dumps(self):
        result = ["[settings]"]
        for name, value in self.settings.items():
            result.append("%s=%s" % (name, value))
        for package, values in self.package_settings.items():
            for name, value in values.items():
                result.append("%s:%s=%s" % (package, name, value))

        result.append("[options]")
        result.append(self.options.dumps())

        result.append("[build_requires]")
        for pattern, req_list in self.build_requires.items():
            result.append("%s: %s" %
                          (pattern, ", ".join(str(r) for r in req_list)))

        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):
        self.update_settings(other.settings)
        self.update_package_settings(other.package_settings)
        # this is the opposite
        other.env_values.update(self.env_values)
        self.env_values = other.env_values
        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_conf_definition(other.conf)

    def update_settings(self, new_settings):
        """Mix the specified settings with the current profile.
        Specified settings are prioritized to profile"""

        assert (isinstance(new_settings, OrderedDict))

        # apply the current profile
        res = copy.copy(self.settings)
        if new_settings:
            # Invalidate the current subsettings if the parent setting changes
            # Example: new_settings declare a different "compiler",
            # so invalidate the current "compiler.XXX"
            for name, value in new_settings.items():
                if "." not in name:
                    if name in self.settings and self.settings[name] != value:
                        for cur_name, _ in self.settings.items():
                            if cur_name.startswith("%s." % name):
                                del res[cur_name]
            # Now merge the new values
            res.update(new_settings)
            self.settings = res

    def update_package_settings(self, package_settings):
        """Mix the specified package settings with the specified profile.
        Specified package settings are prioritized to profile"""
        for package_name, settings in package_settings.items():
            self.package_settings[package_name].update(settings)
Exemplo n.º 18
0
class Profile(object):
    '''A profile contains a set of setting (with values), environment variables
    and scopes'''

    def __init__(self):
        # Sections
        self._settings = OrderedDict()
        self._package_settings = defaultdict(OrderedDict)
        self.env_values = EnvValues()
        self.scopes = Scopes()

    @property
    def package_settings(self):
        return {package_name: list(settings.items()) for package_name, settings in self._package_settings.items()}

    @property
    def settings(self):
        return list(self._settings.items())

    @staticmethod
    def loads(text):

        def get_package_name_value(item):
            '''Parse items like package:name=value or name=value'''
            package_name = None
            if ":" in item:
                tmp = item.split(":", 1)
                package_name, item = tmp

            name, value = item.split("=", 1)
            name = name.strip()
            value = unquote(value)
            return package_name, name, value

        try:
            obj = Profile()
            doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes"])

            for setting in doc.settings.splitlines():
                setting = setting.strip()
                if setting and not setting.startswith("#"):
                    if "=" not in setting:
                        raise ConanException("Invalid setting line '%s'" % setting)
                    package_name, name, value = get_package_name_value(setting)
                    if package_name:
                        obj._package_settings[package_name][name] = value
                    else:
                        obj._settings[name] = value

            if doc.scopes:
                obj.scopes = Scopes.from_list(doc.scopes.splitlines())

            obj.env_values = EnvValues.loads(doc.env)
            obj._order()
            return obj
        except ConanException:
            raise
        except Exception as exc:
            raise ConanException("Error parsing the profile text file: %s" % str(exc))

    def dumps(self):
        self._order()  # gets in order the settings

        def dump_simple_items(items, result):
            for name, value in items:
                result.append("%s=%s" % (name, value))

        def dump_package_items(items, result):
            for package, values in items:
                for name, value in values.items():
                    result.append("%s:%s=%s" % (package, name, value))

        result = ["[settings]"]
        dump_simple_items(self._settings.items(), result)
        dump_package_items(self._package_settings.items(), result)

        result.append("[scopes]")
        if self.scopes[_root].get("dev", None):
            # FIXME: Ugly _root import
            del self.scopes[_root]["dev"]  # Do not include dev
        scopes_txt = self.scopes.dumps()
        result.append(scopes_txt)

        result.append("[env]")
        result.append(self.env_values.dumps())

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

    def update_settings(self, new_settings):
        '''Mix the specified settings with the current profile.
        Specified settings are prioritized to profile'''
        # apply the current profile
        if new_settings:
            self._settings.update(new_settings)
            self._order()

    def update_package_settings(self, package_settings):
        '''Mix the specified package settings with the specified profile.
        Specified package settings are prioritized to profile'''
        for package_name, settings in self._package_settings.items():
            if package_name in package_settings:
                settings.update(dict(package_settings[package_name]))

        # The rest of new packages settings
        for package_name, settings in package_settings.items():
            if package_name not in self._package_settings:
                self._package_settings[package_name].update(dict(settings))

        self._order()

    def _mix_env_with_new(self, env_dict, new_env):

        res_env = OrderedDict()
        for name, value in new_env:
            if name in env_dict:
                del env_dict[name]
            res_env[name] = value  # Insert first in the result

        for name, value in env_dict.items():
            res_env[name] = value  # Insert the rest of env vars at the end

        return res_env

    def update_packages_env(self, new_packages_env):
        '''Priorize new_packages_env to override the current package_env'''
        if not new_packages_env:
            return
        res_env = defaultdict(OrderedDict)

        # Mix the common packages env
        for package, env_vars in self._package_env.items():
            new_env = new_packages_env.get(package, [])
            res_env[package] = self._mix_env_with_new(env_vars, new_env)

        # The rest of new packages env variables
        for package, env_vars in new_packages_env.items():
            if package not in res_env:
                for name, value in env_vars:
                    res_env[package][name] = value  # Insert the rest of env vars at the end

        self._package_env = res_env

    def update_scopes(self, new_scopes):
        '''Mix the specified settings with the current profile.
        Specified settings are prioritized to profile'''
        # apply the current profile
        if new_scopes:
            self.scopes.update(new_scopes)
            self._order()

    def _order(self):

        def order_single_settings(settings):
            ret = OrderedDict()
            # Insert in a good order
            for func in [lambda x: "." not in x,  # First the principal settings
                         lambda x: "." in x]:
                for name, value in settings.items():
                    if func(name):
                        ret[name] = value
            return ret

        # Order global settings
        self._settings = order_single_settings(self._settings)

        # Order package settings
        for package_name, settings in self._package_settings.items():
            self._package_settings[package_name] = order_single_settings(settings)
Exemplo n.º 19
0
 def __init__(self):
     # Sections
     self._settings = OrderedDict()
     self._package_settings = defaultdict(OrderedDict)
     self.env_values = EnvValues()
     self.scopes = Scopes()
Exemplo n.º 20
0
    def setUpClass(cls):
        env = EnvValues()
        env.add("USER_FLAG", "user_value")
        env.add("CL", ["cl1", "cl2"])
        env.add("PATH", [
            "another_path",
        ])
        env.add("PATH2", ["p1", "p2"])
        env.add("PATH3", ["p1", "p2", "p1", "p3", "p4", "p2"])
        conanfile = ConanFile(TestBufferConanOutput(), None)
        conanfile.initialize(Settings({}), env)

        cls.generator = VirtualEnvGenerator(conanfile)
        cls.generator.output_path = "not-used"
        cls.result = cls.generator.content
Exemplo n.º 21
0
class Profile(object):
    """A profile contains a set of setting (with values), environment variables
    and scopes"""

    def __init__(self):
        # Sections
        self.settings = OrderedDict()
        self.package_settings = defaultdict(OrderedDict)
        self.env_values = EnvValues()
        self.scopes = Scopes()
        self.options = OptionsValues()
        self.build_requires = OrderedDict()  # conan_ref Pattern: list of conan_ref

    @property
    def settings_values(self):
        return Values.from_list(list(self.settings.items()))

    @property
    def package_settings_values(self):
        result = {}
        for pkg, settings in self.package_settings.items():
            result[pkg] = list(settings.items())
        return result

    def dumps(self):
        result = ["[build_requires]"]
        for pattern, req_list in self.build_requires.items():
            result.append("%s: %s" % (pattern, ", ".join(str(r) for r in req_list)))
        result.append("[settings]")
        for name, value in self.settings.items():
            result.append("%s=%s" % (name, value))
        for package, values in self.package_settings.items():
            for name, value in values.items():
                result.append("%s:%s=%s" % (package, name, value))

        result.append("[options]")
        result.append(self.options.dumps())

        result.append("[scopes]")
        if self.scopes[_root].get("dev", None):
            # FIXME: Ugly _root import
            del self.scopes[_root]["dev"]  # Do not include dev
        scopes_txt = self.scopes.dumps()
        result.append(scopes_txt)

        result.append("[env]")
        result.append(self.env_values.dumps())

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

    def update(self, other):
        self.update_settings(other.settings)
        self.update_package_settings(other.package_settings)
        self.update_scopes(other.scopes)
        # this is the opposite
        other.env_values.update(self.env_values)
        self.env_values = other.env_values
        self.options.update(other.options)
        for pattern, req_list in other.build_requires.items():
            self.build_requires.setdefault(pattern, []).extend(req_list)

    def update_settings(self, new_settings):
        '''Mix the specified settings with the current profile.
        Specified settings are prioritized to profile'''
        # apply the current profile
        if new_settings:
            self.settings.update(new_settings)

    def update_package_settings(self, package_settings):
        '''Mix the specified package settings with the specified profile.
        Specified package settings are prioritized to profile'''
        for package_name, settings in package_settings.items():
            self.package_settings[package_name].update(settings)

    def update_scopes(self, new_scopes):
        '''Mix the specified settings with the current profile.
        Specified settings are prioritized to profile'''
        # apply the current profile
        if new_scopes:
            self.scopes.update(new_scopes)
Exemplo n.º 22
0
class Profile(object):
    """A profile contains a set of setting (with values), environment variables
    and scopes"""

    def __init__(self):
        # Sections
        self.settings = OrderedDict()
        self.package_settings = defaultdict(OrderedDict)
        self.env_values = EnvValues()
        self.scopes = Scopes()
        self.options = OptionsValues()

    @property
    def settings_values(self):
        return Values.from_list(list(self.settings.items()))

    @property
    def package_settings_values(self):
        result = {}
        for pkg, settings in self.package_settings.items():
            result[pkg] = list(settings.items())
        return result

    @staticmethod
    def read_file(profile_name, cwd, default_folder):
        """ Will look for "profile_name" in disk if profile_name is absolute path,
        in current folder if path is relative or in the default folder otherwise.
        return: a Profile object
        """
        if not profile_name:
            return None

        if os.path.isabs(profile_name):
            profile_path = profile_name
            folder = os.path.dirname(profile_name)
        elif profile_name.startswith("."):  # relative path name
            profile_path = os.path.abspath(os.path.join(cwd, profile_name))
            folder = os.path.dirname(profile_path)
        else:
            folder = default_folder
            if not os.path.exists(folder):
                mkdir(folder)
            profile_path = os.path.join(folder, profile_name)

        try:
            text = load(profile_path)
        except IOError:
            if os.path.exists(folder):
                profiles = [name for name in os.listdir(folder) if not os.path.isdir(name)]
            else:
                profiles = []
            current_profiles = ", ".join(profiles) or "[]"
            raise ConanException("Specified profile '%s' doesn't exist.\nExisting profiles: "
                                 "%s" % (profile_name, current_profiles))

        try:
            text = text.replace("$PROFILE_DIR", os.path.abspath(folder))  # Allows PYTHONPATH=$PROFILE_DIR/pythontools
            return Profile.loads(text)
        except ConanException as exc:
            raise ConanException("Error reading '%s' profile: %s" % (profile_name, exc))

    @staticmethod
    def loads(text):
        """ Parse and return a Profile object from a text config like representation
        """
        def get_package_name_value(item):
            '''Parse items like package:name=value or name=value'''
            package_name = None
            if ":" in item:
                tmp = item.split(":", 1)
                package_name, item = tmp

            name, value = item.split("=", 1)
            name = name.strip()
            value = unquote(value)
            return package_name, name, value

        try:
            obj = Profile()
            doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes", "options"])

            for setting in doc.settings.splitlines():
                setting = setting.strip()
                if setting and not setting.startswith("#"):
                    if "=" not in setting:
                        raise ConanException("Invalid setting line '%s'" % setting)
                    package_name, name, value = get_package_name_value(setting)
                    if package_name:
                        obj.package_settings[package_name][name] = value
                    else:
                        obj.settings[name] = value

            if doc.scopes:
                obj.scopes = Scopes.from_list(doc.scopes.splitlines())

            if doc.options:
                obj.options = OptionsValues.loads(doc.options)

            obj.env_values = EnvValues.loads(doc.env)

            return obj
        except ConanException:
            raise
        except Exception as exc:
            raise ConanException("Error parsing the profile text file: %s" % str(exc))

    def dumps(self):
        result = ["[settings]"]
        for name, value in self.settings.items():
            result.append("%s=%s" % (name, value))
        for package, values in self.package_settings.items():
            for name, value in values.items():
                result.append("%s:%s=%s" % (package, name, value))

        result.append("[options]")
        result.append(self.options.dumps())

        result.append("[scopes]")
        if self.scopes[_root].get("dev", None):
            # FIXME: Ugly _root import
            del self.scopes[_root]["dev"]  # Do not include dev
        scopes_txt = self.scopes.dumps()
        result.append(scopes_txt)

        result.append("[env]")
        result.append(self.env_values.dumps())

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

    def update(self, other):
        self.update_settings(other.settings)
        self.update_package_settings(other.package_settings)
        self.update_scopes(other.scopes)
        # this is the opposite
        other.env_values.update(self.env_values)
        self.env_values = other.env_values
        self.options.update(other.options)

    def update_settings(self, new_settings):
        '''Mix the specified settings with the current profile.
        Specified settings are prioritized to profile'''
        # apply the current profile
        if new_settings:
            self.settings.update(new_settings)

    def update_package_settings(self, package_settings):
        '''Mix the specified package settings with the specified profile.
        Specified package settings are prioritized to profile'''
        for package_name, settings in package_settings.items():
            self.package_settings[package_name].update(settings)

    def update_scopes(self, new_scopes):
        '''Mix the specified settings with the current profile.
        Specified settings are prioritized to profile'''
        # apply the current profile
        if new_scopes:
            self.scopes.update(new_scopes)
Exemplo n.º 23
0
    def variables_setup_test(self):
        conanfile = ConanFile(TestBufferConanOutput(), None)
        conanfile.initialize(Settings({}), EnvValues())
        ref = ConanFileReference.loads("MyPkg/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder1")
        cpp_info.name = "my_pkg"
        cpp_info.defines = ["MYDEFINE1"]
        cpp_info.cflags.append("-Flag1=23")
        cpp_info.version = "1.3"
        cpp_info.description = "My cool description"
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("MyPkg1/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder1")
        cpp_info.name = "MYPKG1"
        cpp_info.defines = ["MYDEFINE11"]
        cpp_info.cflags.append("-Flag1=21")
        cpp_info.version = "1.7"
        cpp_info.description = "My other cool description"
        cpp_info.public_deps = ["MyPkg"]
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("MyPkg2/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder2")
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.version = "2.3"
        cpp_info.exelinkflags = ["-exelinkflag"]
        cpp_info.sharedlinkflags = ["-sharedlinkflag"]
        cpp_info.cxxflags = ["-cxxflag"]
        cpp_info.public_deps = ["MyPkg"]
        conanfile.deps_cpp_info.add(ref.name, cpp_info)
        generator = PkgConfigGenerator(conanfile)
        files = generator.content

        self.assertEqual(
            files["MyPkg2.pc"], """prefix=dummy_root_folder2
libdir=${prefix}/lib
includedir=${prefix}/include

Name: MyPkg2
Description: Conan package: MyPkg2
Version: 2.3
Libs: -L${libdir} -sharedlinkflag -exelinkflag
Cflags: -I${includedir} -cxxflag -DMYDEFINE2
Requires: my_pkg
""")

        self.assertEqual(
            files["mypkg1.pc"], """prefix=dummy_root_folder1
libdir=${prefix}/lib
includedir=${prefix}/include

Name: mypkg1
Description: My other cool description
Version: 1.7
Libs: -L${libdir}
Cflags: -I${includedir} -Flag1=21 -DMYDEFINE11
Requires: my_pkg
""")

        self.assertEqual(
            files["my_pkg.pc"], """prefix=dummy_root_folder1
libdir=${prefix}/lib
includedir=${prefix}/include

Name: my_pkg
Description: My cool description
Version: 1.3
Libs: -L${libdir}
Cflags: -I${includedir} -Flag1=23 -DMYDEFINE1
""")
Exemplo n.º 24
0
    def __init__(self,
                 output,
                 runner,
                 settings,
                 user=None,
                 channel=None,
                 local=None):
        # User defined generators
        self.generators = self.generators if hasattr(
            self, "generators") else ["txt"]
        if isinstance(self.generators, str):
            self.generators = [self.generators]

        # User defined options
        self.options = create_options(self)
        self.requires = create_requirements(self)
        self.settings = create_settings(self, settings, local)
        try:
            if self.settings.os_build and self.settings.os:
                output.writeln("*" * 60, front=Color.BRIGHT_RED)
                output.writeln(
                    "  This package defines both 'os' and 'os_build' ",
                    front=Color.BRIGHT_RED)
                output.writeln(
                    "  Please use 'os' for libraries and 'os_build'",
                    front=Color.BRIGHT_RED)
                output.writeln(
                    "  only for build-requires used for cross-building",
                    front=Color.BRIGHT_RED)
                output.writeln("*" * 60, front=Color.BRIGHT_RED)
        except ConanException:
            pass
        self.exports = create_exports(self)
        self.exports_sources = create_exports_sources(self)
        # needed variables to pack the project
        self.cpp_info = None  # Will be initialized at processing time
        self.deps_cpp_info = DepsCppInfo()

        # environment variables declared in the package_info
        self.env_info = None  # Will be initialized at processing time
        self.deps_env_info = DepsEnvInfo()

        # user declared variables
        self.user_info = None
        # Keys are the package names, and the values a dict with the vars
        self.deps_user_info = DepsUserInfo()

        self.copy = None  # initialized at runtime

        # an output stream (writeln, info, warn error)
        self.output = output
        # something that can run commands, as os.sytem
        self._runner = runner

        self.develop = False

        # user specified env variables
        self._env_values = EnvValues()  # Updated at runtime, user specified -e
        self._user = user
        self._channel = channel

        # Are we in local cache? Suggest a better name
        self.in_local_cache = False

        # Init a description
        self.description = None
Exemplo n.º 25
0
    def test_idempotent(self):
        conanfile = ConanFile(Mock(), None)
        conanfile.initialize(Settings({}), EnvValues())

        # Add some cpp_info
        ref = ConanFileReference.loads("MyPkg/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder1")
        cpp_info.names["txt"] = "mypkg1-txt"
        cpp_info.version = ref.version
        cpp_info.defines = ["MYDEFINE1"]
        cpp_info.cxxflags = ["-cxxflag_parent"]
        cpp_info.includedirs = ["mypkg1/include"]
        cpp_info.filter_empty = False
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("MyPkg2/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder2")
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.cxxflags = ["-cxxflag_dep"]
        cpp_info.filter_empty = False
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        # Add env_info
        env_info = EnvInfo()
        env_info.VAR1 = "value1"
        env_info.PATH.append("path-extended")
        conanfile.deps_env_info.update(env_info, "my_pkg")

        env_info = EnvInfo()
        env_info.VAR1 = "other-value1"
        env_info.PATH.append("other-path-extended")
        conanfile.deps_env_info.update(env_info, "other-pkg")

        # Add user_info for HOST
        user_info = UserInfo()
        user_info.VAR1 = "value1"
        conanfile.deps_user_info["my_pkg"] = user_info

        user_info = UserInfo()
        user_info.VAR1 = "other-value1"
        conanfile.deps_user_info["other-pkg"] = user_info

        # Add user_info for BUILD
        conanfile.user_info_build = DepsUserInfo()
        user_info = UserInfo()
        user_info.VAR1 = "value1"
        conanfile.user_info_build["build_pkg"] = user_info

        user_info = UserInfo()
        user_info.VAR1 = "other-value1"
        conanfile.user_info_build["other-build-pkg"] = user_info

        master_content = TXTGenerator(conanfile).content
        after_cpp_info, after_user_info, after_env_info, after_user_info_build = \
            TXTGenerator.loads(master_content, filter_empty=False)
        # Assign them to a different conanfile
        other_conanfile = ConanFile(Mock(), None)
        other_conanfile.initialize(Settings({}), EnvValues())
        other_conanfile.deps_cpp_info = after_cpp_info
        other_conanfile.deps_env_info = after_env_info
        other_conanfile.deps_user_info = after_user_info
        other_conanfile.user_info_build = after_user_info_build
        after_content = TXTGenerator(other_conanfile).content

        self.assertListEqual(master_content.splitlines(),
                             after_content.splitlines())
Exemplo n.º 26
0
    def variables_setup_test(self):

        conanfile = ConanFile(TestBufferConanOutput(), None)
        conanfile.initialize(Settings({}), EnvValues())

        ref = ConanFileReference.loads("MyPkg/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder1")
        cpp_info.defines = ["MYDEFINE1"]
        cpp_info.cflags.append("-Flag1=23")
        cpp_info.version = "1.3"
        cpp_info.description = "My cool description"
        cpp_info.libs = ["MyLib1"]
        conanfile.deps_cpp_info.add(ref.name, cpp_info)

        ref = ConanFileReference.loads("MyPkg2/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, "dummy_root_folder2")
        cpp_info.libs = ["MyLib2"]
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.version = "2.3"
        cpp_info.exelinkflags = ["-exelinkflag"]
        cpp_info.sharedlinkflags = ["-sharedlinkflag"]
        cpp_info.cxxflags = ["-cxxflag"]
        cpp_info.public_deps = ["MyPkg"]
        cpp_info.libdirs.extend(["Path\\with\\slashes", "regular/path/to/dir"])
        cpp_info.includedirs.extend(
            ["other\\Path\\with\\slashes", "other/regular/path/to/dir"])
        cpp_info.filter_empty = False
        conanfile.deps_cpp_info.add(ref.name, cpp_info)
        generator = BoostBuildGenerator(conanfile)

        self.assertEqual(
            generator.content, """lib MyLib1 :
	: # requirements
	<name>MyLib1
	: # default-build
	: # usage-requirements
	<define>MYDEFINE1
	<cflags>-Flag1=23
	;

lib MyLib2 :
	: # requirements
	<name>MyLib2
	<search>dummy_root_folder2/lib
	<search>dummy_root_folder2/Path/with/slashes
	<search>dummy_root_folder2/regular/path/to/dir
	: # default-build
	: # usage-requirements
	<define>MYDEFINE2
	<include>dummy_root_folder2/include
	<include>dummy_root_folder2/other/Path/with/slashes
	<include>dummy_root_folder2/other/regular/path/to/dir
	<cxxflags>-cxxflag
	<ldflags>-sharedlinkflag
	;

alias conan-deps :
	MyLib1
	MyLib2
;
""")
Exemplo n.º 27
0
class Profile(object):
    """A profile contains a set of setting (with values), environment variables
    """

    def __init__(self):
        # Sections
        self.processed_settings = None
        self.settings = OrderedDict()
        self.package_settings = defaultdict(OrderedDict)
        self.env_values = EnvValues()
        self.options = OptionsValues()
        self.build_requires = OrderedDict()  # ref pattern: list of ref

    def process_settings(self, cache, preprocess=True):
        self.processed_settings = cache.settings.copy()
        self.processed_settings.values = Values.from_list(list(self.settings.items()))
        if preprocess:
            settings_preprocessor.preprocess(self.processed_settings)
            # Redefine the profile settings values with the preprocessed ones
            # FIXME: Simplify the values.as_list()
            self.settings = OrderedDict(self.processed_settings.values.as_list())

    @property
    def package_settings_values(self):
        result = {}
        for pkg, settings in self.package_settings.items():
            result[pkg] = list(settings.items())
        return result

    def dumps(self):
        result = ["[settings]"]
        for name, value in self.settings.items():
            result.append("%s=%s" % (name, value))
        for package, values in self.package_settings.items():
            for name, value in values.items():
                result.append("%s:%s=%s" % (package, name, value))

        result.append("[options]")
        result.append(self.options.dumps())

        result.append("[build_requires]")
        for pattern, req_list in self.build_requires.items():
            result.append("%s: %s" % (pattern, ", ".join(str(r) for r in req_list)))

        result.append("[env]")
        result.append(self.env_values.dumps())

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

    def update(self, other):
        self.update_settings(other.settings)
        self.update_package_settings(other.package_settings)
        # this is the opposite
        other.env_values.update(self.env_values)
        self.env_values = other.env_values
        self.options.update(other.options)
        for pattern, req_list in other.build_requires.items():
            self.build_requires.setdefault(pattern, []).extend(req_list)

    def update_settings(self, new_settings):
        """Mix the specified settings with the current profile.
        Specified settings are prioritized to profile"""

        assert(isinstance(new_settings, OrderedDict))

        # apply the current profile
        res = copy.copy(self.settings)
        if new_settings:
            # Invalidate the current subsettings if the parent setting changes
            # Example: new_settings declare a different "compiler", so invalidate the current "compiler.XXX"
            for name, value in new_settings.items():
                if "." not in name:
                    if name in self.settings and self.settings[name] != value:
                        for cur_name, _ in self.settings.items():
                            if cur_name.startswith("%s." % name):
                                del res[cur_name]
            # Now merge the new values
            res.update(new_settings)
            self.settings = res

    def update_package_settings(self, package_settings):
        """Mix the specified package settings with the specified profile.
        Specified package settings are prioritized to profile"""
        for package_name, settings in package_settings.items():
            self.package_settings[package_name].update(settings)
Exemplo n.º 28
0
    def loads(text):
        """ Parse and return a Profile object from a text config like representation
        """
        def get_package_name_value(item):
            """Parse items like package:name=value or name=value"""
            package_name = None
            if ":" in item:
                tmp = item.split(":", 1)
                package_name, item = tmp

            name, value = item.split("=", 1)
            name = name.strip()
            value = unquote(value)
            return package_name, name, value

        try:
            obj = Profile()
            doc = ConfigParser(text,
                               allowed_fields=[
                                   "build_requires", "settings", "env",
                                   "scopes", "options"
                               ])

            for setting in doc.settings.splitlines():
                setting = setting.strip()
                if setting and not setting.startswith("#"):
                    if "=" not in setting:
                        raise ConanException("Invalid setting line '%s'" %
                                             setting)
                    package_name, name, value = get_package_name_value(setting)
                    if package_name:
                        obj.package_settings[package_name][name] = value
                    else:
                        obj.settings[name] = value

            if doc.build_requires:
                # FIXME CHECKS OF DUPLICATED?
                for req in doc.build_requires.splitlines():
                    tokens = req.split(":", 1)
                    if len(tokens) == 1:
                        pattern, req_list = "*", req
                    else:
                        pattern, req_list = tokens
                    req_list = [
                        ConanFileReference.loads(r.strip())
                        for r in req_list.split(",")
                    ]
                    obj.build_requires.setdefault(pattern, []).extend(req_list)

            if doc.scopes:
                obj.scopes = Scopes.from_list(doc.scopes.splitlines())

            if doc.options:
                obj.options = OptionsValues.loads(doc.options)

            obj.env_values = EnvValues.loads(doc.env)

            return obj
        except ConanException:
            raise
        except Exception as exc:
            raise ConanException("Error parsing the profile text file: %s" %
                                 str(exc))
Exemplo n.º 29
0
    def aux_cmake_test_setup_test(self):
        conanfile = ConanFile(TestBufferConanOutput(), None)
        conanfile.initialize(Settings({}), EnvValues())
        generator = CMakeGenerator(conanfile)
        aux_cmake_test_setup = generator.content

        # extract the conan_basic_setup macro
        macro = self._extract_macro("conan_basic_setup", aux_cmake_test_setup)
        self.assertEqual(
            """macro(conan_basic_setup)
    set(options TARGETS NO_OUTPUT_DIRS SKIP_RPATH KEEP_RPATHS SKIP_STD SKIP_FPIC)
    cmake_parse_arguments(ARGUMENTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )

    if(CONAN_EXPORTED)
        conan_message(STATUS "Conan: called by CMake conan helper")
    endif()

    if(CONAN_IN_LOCAL_CACHE)
        conan_message(STATUS "Conan: called inside local cache")
    endif()

    if(NOT ARGUMENTS_NO_OUTPUT_DIRS)
        conan_message(STATUS "Conan: Adjusting output directories")
        conan_output_dirs_setup()
    endif()

    if(NOT ARGUMENTS_TARGETS)
        conan_message(STATUS "Conan: Using cmake global configuration")
        conan_global_flags()
    else()
        conan_message(STATUS "Conan: Using cmake targets configuration")
        conan_define_targets()
    endif()

    if(ARGUMENTS_SKIP_RPATH)
        # Change by "DEPRECATION" or "SEND_ERROR" when we are ready
        conan_message(WARNING "Conan: SKIP_RPATH is deprecated, it has been renamed to KEEP_RPATHS")
    endif()

    if(NOT ARGUMENTS_SKIP_RPATH AND NOT ARGUMENTS_KEEP_RPATHS)
        # Parameter has renamed, but we keep the compatibility with old SKIP_RPATH
        conan_message(STATUS "Conan: Adjusting default RPATHs Conan policies")
        conan_set_rpath()
    endif()

    if(NOT ARGUMENTS_SKIP_STD)
        conan_message(STATUS "Conan: Adjusting language standard")
        conan_set_std()
    endif()

    if(NOT ARGUMENTS_SKIP_FPIC)
        conan_set_fpic()
    endif()

    conan_check_compiler()
    conan_set_libcxx()
    conan_set_vs_runtime()
    conan_set_find_paths()
    conan_include_build_modules()
    conan_set_find_library_paths()
endmacro()""", macro)

        # extract the conan_set_find_paths macro
        macro = self._extract_macro("conan_set_find_paths",
                                    aux_cmake_test_setup)
        self.assertEqual(
            """macro(conan_set_find_paths)
    # CMAKE_MODULE_PATH does not have Debug/Release config, but there are variables
    # CONAN_CMAKE_MODULE_PATH_DEBUG to be used by the consumer
    # CMake can find findXXX.cmake files in the root of packages
    set(CMAKE_MODULE_PATH ${CONAN_CMAKE_MODULE_PATH} ${CMAKE_MODULE_PATH})

    # Make find_package() to work
    set(CMAKE_PREFIX_PATH ${CONAN_CMAKE_MODULE_PATH} ${CMAKE_PREFIX_PATH})

    # Set the find root path (cross build)
    set(CMAKE_FIND_ROOT_PATH ${CONAN_CMAKE_FIND_ROOT_PATH} ${CMAKE_FIND_ROOT_PATH})
    if(CONAN_CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
        set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ${CONAN_CMAKE_FIND_ROOT_PATH_MODE_PROGRAM})
    endif()
    if(CONAN_CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
        set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ${CONAN_CMAKE_FIND_ROOT_PATH_MODE_LIBRARY})
    endif()
    if(CONAN_CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
        set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ${CONAN_CMAKE_FIND_ROOT_PATH_MODE_INCLUDE})
    endif()
endmacro()""", macro)
Exemplo n.º 30
0
class ConanFile(object):
    """ The base class for all package recipes
    """

    name = None
    version = None  # Any str, can be "1.1" or whatever
    url = None  # The URL where this File is located, as github, to collaborate in package
    # The license of the PACKAGE, just a shortcut, does not replace or
    # change the actual license of the source code
    license = None
    author = None  # Main maintainer/responsible for the package, any format
    build_policy = None
    short_paths = False

    def __init__(self,
                 output,
                 runner,
                 settings,
                 conanfile_directory,
                 user=None,
                 channel=None):
        # User defined generators
        self.generators = self.generators if hasattr(
            self, "generators") else ["txt"]
        if isinstance(self.generators, str):
            self.generators = [self.generators]

        # User defined options
        self.options = create_options(self)
        self.requires = create_requirements(self)
        self.settings = create_settings(self, settings)
        self.exports = create_exports(self)
        self.exports_sources = create_exports_sources(self)
        # needed variables to pack the project
        self.cpp_info = None  # Will be initialized at processing time
        self.deps_cpp_info = DepsCppInfo()

        # environment variables declared in the package_info
        self.env_info = None  # Will be initialized at processing time
        self.deps_env_info = DepsEnvInfo()

        self.copy = None  # initialized at runtime

        # an output stream (writeln, info, warn error)
        self.output = output
        # something that can run commands, as os.sytem
        self._runner = runner

        self._conanfile_directory = conanfile_directory
        self.package_folder = None  # Assigned at runtime
        self._scope = None

        # user specified env variables
        self._env_values = EnvValues()  # Updated at runtime, user specified -e
        self._user = user
        self._channel = channel

    @property
    def env(self):
        simple, multiple = self._env_values.env_dicts(self.name)
        simple.update(multiple)
        return simple

    @property
    def channel(self):
        if not self._channel:
            self._channel = os.getenv("CONAN_CHANNEL")
            if not self._channel:
                raise ConanException(
                    "CONAN_CHANNEL environment variable not defined, "
                    "but self.channel is used in conanfile")
        return self._channel

    @property
    def user(self):
        if not self._user:
            self._user = os.getenv("CONAN_USERNAME")
            if not self._user:
                raise ConanException(
                    "CONAN_USERNAME environment variable not defined, "
                    "but self.user is used in conanfile")
        return self._user

    def collect_libs(self, folder="lib"):
        if not self.package_folder:
            return []
        lib_folder = os.path.join(self.package_folder, folder)
        if not os.path.exists(lib_folder):
            self.output.warn(
                "Package folder doesn't exist, can't collect libraries")
            return []
        files = os.listdir(lib_folder)
        result = []
        for f in files:
            name, ext = os.path.splitext(f)
            if ext in (".so", ".lib", ".a", ".dylib"):
                if ext != ".lib" and name.startswith("lib"):
                    name = name[3:]
                result.append(name)
        return result

    @property
    def scope(self):
        return self._scope

    @scope.setter
    def scope(self, value):
        self._scope = value
        if value.dev:
            self.requires.allow_dev = True
            try:
                if hasattr(self, "dev_requires"):
                    if isinstance(self.dev_requires, tuple):
                        self.requires.add_dev(*self.dev_requires)
                    else:
                        self.requires.add_dev(self.dev_requires, )
            except Exception as e:
                raise ConanException(
                    "Error while initializing dev_requirements. %s" % str(e))

    @property
    def conanfile_directory(self):
        return self._conanfile_directory

    @property
    def build_policy_missing(self):
        return self.build_policy == "missing"

    @property
    def build_policy_always(self):
        return self.build_policy == "always"

    def source(self):
        pass

    def system_requirements(self):
        """ this method can be overwritten to implement logic for system package
        managers, as apt-get

        You can define self.global_system_requirements = True, if you want the installation
        to be for all packages (not depending on settings/options/requirements)
        """

    def config_options(self):
        """ modify options, probably conditioned to some settings. This call is executed
        before config_settings. E.g.
        if self.settings.os == "Windows":
            del self.options.shared  # shared/static not supported in win
        """

    def configure(self):
        """ modify settings, probably conditioned to some options. This call is executed
        after config_options. E.g.
        if self.options.header_only:
            self.settings.clear()
        This is also the place for conditional requirements
        """

    def imports(self):
        pass

    def build(self):
        self.output.warn("This conanfile has no build step")

    def package(self):
        self.output.warn("This conanfile has no package step")

    def package_info(self):
        """ define cpp_build_info, flags, etc
        """

    def run(self, command, output=True, cwd=None):
        """ runs such a command in the folder the Conan
        is defined
        """
        retcode = self._runner(command, output, os.path.abspath(RUN_LOG_NAME),
                               cwd)
        if retcode != 0:
            raise ConanException("Error %d while executing %s" %
                                 (retcode, command))

    def package_id(self):
        """ modify the conans info, typically to narrow values
        eg.: conaninfo.package_references = []
        """

    def test(self):
        raise ConanException(
            "You need to create a method 'test' in your test/conanfile.py")

    def __repr__(self):
        if self.name and self.version and self._channel and self._user:
            return "%s/%s@%s/%s" % (self.name, self.version, self.user,
                                    self.channel)
        elif self.name and self.version:
            return "%s/%s@PROJECT" % (self.name, self.version)
        else:
            return "PROJECT"
Exemplo n.º 31
0
class ConanFile(object):
    """ The base class for all package recipes
    """

    name = None
    version = None  # Any str, can be "1.1" or whatever
    url = None  # The URL where this File is located, as github, to collaborate in package
    # The license of the PACKAGE, just a shortcut, does not replace or
    # change the actual license of the source code
    license = None
    author = None  # Main maintainer/responsible for the package, any format
    build_policy = None
    short_paths = False
    apply_env = True  # Apply environment variables from requires deps_env_info and profiles

    def __init__(self,
                 output,
                 runner,
                 settings,
                 user=None,
                 channel=None,
                 local=None):
        # User defined generators
        self.generators = self.generators if hasattr(
            self, "generators") else ["txt"]
        if isinstance(self.generators, str):
            self.generators = [self.generators]

        # User defined options
        self.options = create_options(self)
        self.requires = create_requirements(self)
        self.settings = create_settings(self, settings, local)
        try:
            if self.settings.os_build and self.settings.os:
                output.writeln("*" * 60, front=Color.BRIGHT_RED)
                output.writeln(
                    "  This package defines both 'os' and 'os_build' ",
                    front=Color.BRIGHT_RED)
                output.writeln(
                    "  Please use 'os' for libraries and 'os_build'",
                    front=Color.BRIGHT_RED)
                output.writeln(
                    "  only for build-requires used for cross-building",
                    front=Color.BRIGHT_RED)
                output.writeln("*" * 60, front=Color.BRIGHT_RED)
        except ConanException:
            pass
        self.exports = create_exports(self)
        self.exports_sources = create_exports_sources(self)
        # needed variables to pack the project
        self.cpp_info = None  # Will be initialized at processing time
        self.deps_cpp_info = DepsCppInfo()

        # environment variables declared in the package_info
        self.env_info = None  # Will be initialized at processing time
        self.deps_env_info = DepsEnvInfo()

        # user declared variables
        self.user_info = None
        # Keys are the package names, and the values a dict with the vars
        self.deps_user_info = DepsUserInfo()

        self.copy = None  # initialized at runtime

        # an output stream (writeln, info, warn error)
        self.output = output
        # something that can run commands, as os.sytem
        self._runner = runner

        self.develop = False

        # user specified env variables
        self._env_values = EnvValues()  # Updated at runtime, user specified -e
        self._user = user
        self._channel = channel

        # Are we in local cache? Suggest a better name
        self.in_local_cache = False

        # Init a description
        self.description = None

    @property
    def env(self):
        """Apply the self.deps_env_info into a copy of self._env_values (will prioritize the
        self._env_values, user specified from profiles or -e first, then inherited)"""
        # Cannot be lazy cached, because it's called in configure node, and we still don't have
        # the deps_env_info objects available
        tmp_env_values = self._env_values.copy()
        tmp_env_values.update(self.deps_env_info)

        ret, multiple = tmp_env_values.env_dicts(self.name)
        ret.update(multiple)
        return ret

    @property
    def channel(self):
        if not self._channel:
            self._channel = os.getenv("CONAN_CHANNEL")
            if not self._channel:
                raise ConanException(
                    "CONAN_CHANNEL environment variable not defined, "
                    "but self.channel is used in conanfile")
        return self._channel

    @property
    def user(self):
        if not self._user:
            self._user = os.getenv("CONAN_USERNAME")
            if not self._user:
                raise ConanException(
                    "CONAN_USERNAME environment variable not defined, "
                    "but self.user is used in conanfile")
        return self._user

    def collect_libs(self, folder="lib"):
        self.output.warn("Use 'self.collect_libs' is deprecated, "
                         "use tools.collect_libs(self) instead")
        return tools.collect_libs(self, folder=folder)

    @property
    def build_policy_missing(self):
        return self.build_policy == "missing"

    @property
    def build_policy_always(self):
        return self.build_policy == "always"

    def source(self):
        pass

    def system_requirements(self):
        """ this method can be overwritten to implement logic for system package
        managers, as apt-get

        You can define self.global_system_requirements = True, if you want the installation
        to be for all packages (not depending on settings/options/requirements)
        """

    def config_options(self):
        """ modify options, probably conditioned to some settings. This call is executed
        before config_settings. E.g.
        if self.settings.os == "Windows":
            del self.options.shared  # shared/static not supported in win
        """

    def configure(self):
        """ modify settings, probably conditioned to some options. This call is executed
        after config_options. E.g.
        if self.options.header_only:
            self.settings.clear()
        This is also the place for conditional requirements
        """

    def build(self):
        self.output.warn("This conanfile has no build step")

    def package(self):
        self.output.warn("This conanfile has no package step")

    def package_info(self):
        """ define cpp_build_info, flags, etc
        """

    def run(self,
            command,
            output=True,
            cwd=None,
            win_bash=False,
            subsystem=None,
            msys_mingw=True):
        if not win_bash:
            retcode = self._runner(command, output,
                                   os.path.abspath(RUN_LOG_NAME), cwd)
        else:
            retcode = tools.run_in_windows_bash(self,
                                                bashcmd=command,
                                                cwd=cwd,
                                                subsystem=subsystem,
                                                msys_mingw=msys_mingw)

        if retcode != 0:
            raise ConanException("Error %d while executing %s" %
                                 (retcode, command))

        return retcode

    def package_id(self):
        """ modify the conans info, typically to narrow values
        eg.: conaninfo.package_references = []
        """

    def test(self):
        raise ConanException(
            "You need to create a method 'test' in your test/conanfile.py")

    def __repr__(self):
        if self.name and self.version and self._channel and self._user:
            return "%s/%s@%s/%s" % (self.name, self.version, self.user,
                                    self.channel)
        elif self.name and self.version:
            return "%s/%s@PROJECT" % (self.name, self.version)
        else:
            return "PROJECT"
Exemplo n.º 32
0
    def b2_test(self):
        settings = Settings.loads(default_settings_yml)
        settings.os = "Linux"
        settings.compiler = "gcc"
        settings.compiler.version = "6.3"
        settings.arch = "x86"
        settings.build_type = "Release"
        settings.cppstd = "gnu17"

        conanfile = ConanFile(None, None)
        conanfile.initialize(Settings({}), EnvValues())
        conanfile.settings = settings

        ref = ConanFileReference.loads("MyPkg/0.1@lasote/stables")
        cpp_info = CppInfo("dummy_root_folder1")
        cpp_info.defines = ["MYDEFINE1"]
        cpp_info.cflags.append("-Flag1=23")
        cpp_info.version = "1.3"
        cpp_info.description = "My cool description"
        cpp_info.libs = ["MyLib1"]

        conanfile.deps_cpp_info.update(cpp_info, ref.name)
        ref = ConanFileReference.loads("MyPkg2/0.1@lasote/stables")
        cpp_info = CppInfo("dummy_root_folder2")
        cpp_info.libs = ["MyLib2"]
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.version = "2.3"
        cpp_info.exelinkflags = ["-exelinkflag"]
        cpp_info.sharedlinkflags = ["-sharedlinkflag"]
        cpp_info.cppflags = ["-cppflag"]
        cpp_info.public_deps = ["MyPkg"]
        cpp_info.lib_paths.extend(
            ["Path\\with\\slashes", "regular/path/to/dir"])
        cpp_info.include_paths.extend(
            ["other\\Path\\with\\slashes", "other/regular/path/to/dir"])
        conanfile.deps_cpp_info.update(cpp_info, ref.name)
        generator = B2Generator(conanfile)

        content = {
            'conanbuildinfo.jam':
            '''#|
    B2 definitions for Conan packages. This is a generated file.
    Edit the corresponding conanfile.txt instead.
|#

import path ;
import project ;
import modules ;
import feature ;

local base-project = [ project.current ] ;
local base-project-mod = [ $(base-project).project-module ] ;
local base-project-location = [ project.attribute $(base-project-mod) location ] ;

rule project-define ( id )
{
    id = $(id:L) ;
    local saved-project = [ modules.peek project : .base-project ] ;
    local id-location = [ path.join $(base-project-location) $(id) ] ;
    local id-mod = [ project.load $(id-location) : synthesize ] ;
    project.initialize $(id-mod) : $(id-location) ;
    project.inherit-attributes $(id-mod) : $(base-project-mod) ;
    local attributes = [ project.attributes $(id-mod) ] ;
    $(attributes).set parent-module : $(base-project-mod) : exact ;
    modules.poke $(base-project-mod) : $(id)-mod : $(id-mod) ;
    modules.poke [ CALLER_MODULE ] : $(id)-mod : $(id-mod) ;
    modules.poke project : .base-project : $(saved-project) ;
    IMPORT $(__name__)
        : constant-if call-in-project
        : $(id-mod)
        : constant-if call-in-project ;
    return $(id-mod) ;
}

rule constant-if ( name : value * )
{
    if $(__define_constants__) && $(value)
    {
        call-in-project : constant $(name) : $(value) ;
        modules.poke $(__name__) : $(name) : [ modules.peek $(base-project-mod) : $(name) ] ;
    }
}

rule call-in-project ( project-mod ? : rule-name args * : * )
{
    project-mod ?= $(base-project-mod) ;
    project.push-current [ project.target $(project-mod) ] ;
    local result = [ modules.call-in $(project-mod) :
        $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) : $(10) :
        $(11) : $(12) : $(13) : $(14) : $(15) : $(16) : $(17) : $(18) :
        $(19) ] ;
    project.pop-current ;
    return $(result) ;
}

rule include-conanbuildinfo ( cbi )
{
    include $(cbi) ;
}

IMPORT $(__name__)
    : project-define constant-if call-in-project include-conanbuildinfo
    : $(base-project-mod)
    : project-define constant-if call-in-project include-conanbuildinfo ;

if ! ( relwithdebinfo in [ feature.values variant ] )
{
    variant relwithdebinfo : : <optimization>speed <debug-symbols>on <inlining>full <runtime-debugging>off ;
}
if ! ( minsizerel in [ feature.values variant ] )
{
    variant minsizerel : : <optimization>space <debug-symbols>off <inlining>full <runtime-debugging>off ;
}

local __conanbuildinfo__ = [ GLOB $(__file__:D) : conanbuildinfo-*.jam : downcase ] ;
{
    local __define_constants__ = yes ;
    for local __cbi__ in $(__conanbuildinfo__)
    {
        call-in-project : include-conanbuildinfo $(__cbi__) ;
    }
}


# mypkg
# mypkg
project-define mypkg ;


# mypkg2
# mypkg2
project-define mypkg2 ;

{
    local __define_targets__ = yes ;
    for local __cbi__ in $(__conanbuildinfo__)
    {
        call-in-project : include-conanbuildinfo $(__cbi__) ;
    }
}
''',
            'conanbuildinfo-316f2f0b155dc874a672d40d98d93f95.jam':
            '''#|
    B2 definitions for Conan packages. This is a generated file.
    Edit the corresponding conanfile.txt instead.
|#

# global
constant-if rootpath(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    ""
    ;

constant-if includedirs(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    "other/Path/with/slashes"
    "other/regular/path/to/dir"
    ;

constant-if libdirs(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    "Path/with/slashes"
    "regular/path/to/dir"
    ;

constant-if defines(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    "MYDEFINE2"
    "MYDEFINE1"
    ;

constant-if cppflags(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    "-cppflag"
    ;

constant-if cflags(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    "-Flag1=23"
    ;

constant-if sharedlinkflags(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    "-sharedlinkflag"
    ;

constant-if exelinkflags(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    "-exelinkflag"
    ;

constant-if requirements(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    <address-model>32
    <architecture>x86
    <cxxstd>17
    <cxxstd:dialect>gnu
    <target-os>linux
    <toolset>gcc-6.3
    <variant>release
    ;

constant-if usage-requirements(conan,32,x86,17,gnu,linux,gcc-6.3,release) :
    <include>$(includedirs(conan,32,x86,17,gnu,linux,gcc-6.3,release))
    <define>$(defines(conan,32,x86,17,gnu,linux,gcc-6.3,release))
    <cflags>$(cflags(conan,32,x86,17,gnu,linux,gcc-6.3,release))
    <cxxflags>$(cppflags(conan,32,x86,17,gnu,linux,gcc-6.3,release))
    <link>shared:<linkflags>$(sharedlinkflags(conan,32,x86,17,gnu,linux,gcc-6.3,release))
    ;

# mypkg
constant-if rootpath(mypkg,32,x86,17,gnu,linux,gcc-6.3,release) :
    "dummy_root_folder1"
    ;

constant-if defines(mypkg,32,x86,17,gnu,linux,gcc-6.3,release) :
    "MYDEFINE1"
    ;

constant-if cflags(mypkg,32,x86,17,gnu,linux,gcc-6.3,release) :
    "-Flag1=23"
    ;

constant-if requirements(mypkg,32,x86,17,gnu,linux,gcc-6.3,release) :
    <address-model>32
    <architecture>x86
    <cxxstd>17
    <cxxstd:dialect>gnu
    <target-os>linux
    <toolset>gcc-6.3
    <variant>release
    ;

constant-if usage-requirements(mypkg,32,x86,17,gnu,linux,gcc-6.3,release) :
    <include>$(includedirs(mypkg,32,x86,17,gnu,linux,gcc-6.3,release))
    <define>$(defines(mypkg,32,x86,17,gnu,linux,gcc-6.3,release))
    <cflags>$(cflags(mypkg,32,x86,17,gnu,linux,gcc-6.3,release))
    <cxxflags>$(cppflags(mypkg,32,x86,17,gnu,linux,gcc-6.3,release))
    <link>shared:<linkflags>$(sharedlinkflags(mypkg,32,x86,17,gnu,linux,gcc-6.3,release))
    ;

# mypkg2
constant-if rootpath(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    "dummy_root_folder2"
    ;

constant-if includedirs(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    "other/Path/with/slashes"
    "other/regular/path/to/dir"
    ;

constant-if libdirs(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    "Path/with/slashes"
    "regular/path/to/dir"
    ;

constant-if defines(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    "MYDEFINE2"
    ;

constant-if cppflags(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    "-cppflag"
    ;

constant-if sharedlinkflags(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    "-sharedlinkflag"
    ;

constant-if exelinkflags(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    "-exelinkflag"
    ;

constant-if requirements(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    <address-model>32
    <architecture>x86
    <cxxstd>17
    <cxxstd:dialect>gnu
    <target-os>linux
    <toolset>gcc-6.3
    <variant>release
    ;

constant-if usage-requirements(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release) :
    <include>$(includedirs(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release))
    <define>$(defines(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release))
    <cflags>$(cflags(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release))
    <cxxflags>$(cppflags(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release))
    <link>shared:<linkflags>$(sharedlinkflags(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release))
    ;

# mypkg
if $(__define_targets__) {
    call-in-project $(mypkg-mod) : lib MyLib1
        :
        : <name>MyLib1 <search>$(libdirs(mypkg,32,x86,17,gnu,linux,gcc-6.3,release)) $(requirements(mypkg,32,x86,17,gnu,linux,gcc-6.3,release))
        :
        : $(usage-requirements(mypkg,32,x86,17,gnu,linux,gcc-6.3,release)) ;
    call-in-project $(mypkg-mod) : explicit MyLib1 ; }

if $(__define_targets__) {
    call-in-project $(mypkg-mod) : alias libs
        : MyLib1
        : $(requirements(mypkg,32,x86,17,gnu,linux,gcc-6.3,release))
        :
        : $(usage-requirements(mypkg,32,x86,17,gnu,linux,gcc-6.3,release)) ;
    call-in-project $(mypkg-mod) : explicit libs ; }

# mypkg2
if $(__define_targets__) {
    call-in-project $(mypkg2-mod) : lib MyLib2
        :
        : <name>MyLib2 <search>$(libdirs(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release)) $(requirements(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release))
        :
        : $(usage-requirements(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release)) ;
    call-in-project $(mypkg2-mod) : explicit MyLib2 ; }

if $(__define_targets__) {
    call-in-project $(mypkg2-mod) : alias libs
        : MyLib2
        : $(requirements(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release))
        :
        : $(usage-requirements(mypkg2,32,x86,17,gnu,linux,gcc-6.3,release)) ;
    call-in-project $(mypkg2-mod) : explicit libs ; }
''',
        }

        for ck, cv in generator.content.items():
            self.assertEquals(cv, content[ck])
Exemplo n.º 33
0
    def test_model(self):
        env = EnvValues()
        env.add("Z", "1")
        self.assertEqual(env.env_dicts(""), ({"Z": "1"}, {}))
        env.add("Z", "2")
        self.assertEqual(env.env_dicts(""), ({"Z": "1"}, {}))
        env.add("B", "223")
        self.assertEqual(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
        env.add("B", "224", "package1")
        self.assertEqual(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
        self.assertEqual(env.env_dicts("package1"), ({
            "Z": "1",
            "B": "224"
        }, {}))
        env.add("A", "1", "package1")
        self.assertEqual(env.env_dicts("package1"), ({
            "Z": "1",
            "B": "224",
            "A": "1"
        }, {}))
        self.assertEqual(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
        env.add("J", "21", "package21")
        self.assertEqual(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
        self.assertEqual(env.env_dicts("package1"), ({
            "Z": "1",
            "B": "224",
            "A": "1"
        }, {}))
        env.add("A", ["99"], "package1")
        self.assertEqual(env.env_dicts("package1"), ({
            "Z": "1",
            "B": "224",
            "A": "1"
        }, {}))
        env.add("M", ["99"], "package1")
        self.assertEqual(env.env_dicts("package1"), ({
            "Z": "1",
            "B": "224",
            "A": "1"
        }, {
            "M": ["99"]
        }))
        env.add("M", "100", "package1")
        self.assertEqual(env.env_dicts("package1"), ({
            "Z": "1",
            "B": "224",
            "A": "1"
        }, {
            "M": ["99", "100"]
        }))

        self.assertEqual(env.env_dicts(""), ({"Z": "1", "B": "223"}, {}))
Exemplo n.º 34
0
class Profile(object):
    """A profile contains a set of setting (with values), environment variables
    and scopes"""
    def __init__(self):
        # Sections
        self.settings = OrderedDict()
        self.package_settings = defaultdict(OrderedDict)
        self.env_values = EnvValues()
        self.scopes = Scopes()
        self.options = OptionsValues()
        self.build_requires = OrderedDict(
        )  # conan_ref Pattern: list of conan_ref

    @property
    def settings_values(self):
        return Values.from_list(list(self.settings.items()))

    @property
    def package_settings_values(self):
        result = {}
        for pkg, settings in self.package_settings.items():
            result[pkg] = list(settings.items())
        return result

    def dumps(self):
        result = ["[build_requires]"]
        for pattern, req_list in self.build_requires.items():
            result.append("%s: %s" %
                          (pattern, ", ".join(str(r) for r in req_list)))
        result.append("[settings]")
        for name, value in self.settings.items():
            result.append("%s=%s" % (name, value))
        for package, values in self.package_settings.items():
            for name, value in values.items():
                result.append("%s:%s=%s" % (package, name, value))

        result.append("[options]")
        result.append(self.options.dumps())

        result.append("[scopes]")
        if self.scopes[_root].get("dev", None):
            # FIXME: Ugly _root import
            del self.scopes[_root]["dev"]  # Do not include dev
        scopes_txt = self.scopes.dumps()
        result.append(scopes_txt)

        result.append("[env]")
        result.append(self.env_values.dumps())

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

    def update(self, other):
        self.update_settings(other.settings)
        self.update_package_settings(other.package_settings)
        self.update_scopes(other.scopes)
        # this is the opposite
        other.env_values.update(self.env_values)
        self.env_values = other.env_values
        self.options.update(other.options)
        for pattern, req_list in other.build_requires.items():
            self.build_requires.setdefault(pattern, []).extend(req_list)

    def update_settings(self, new_settings):
        '''Mix the specified settings with the current profile.
        Specified settings are prioritized to profile'''
        # apply the current profile
        if new_settings:
            self.settings.update(new_settings)

    def update_package_settings(self, package_settings):
        '''Mix the specified package settings with the specified profile.
        Specified package settings are prioritized to profile'''
        for package_name, settings in package_settings.items():
            self.package_settings[package_name].update(settings)

    def update_scopes(self, new_scopes):
        '''Mix the specified settings with the current profile.
        Specified settings are prioritized to profile'''
        # apply the current profile
        if new_scopes:
            self.scopes.update(new_scopes)
Exemplo n.º 35
0
    def variables_setup_test(self):
        tmp_folder1 = temp_folder()
        tmp_folder2 = temp_folder()
        save(os.path.join(tmp_folder1, "include1", "file.h"), "")
        save(os.path.join(tmp_folder2, "include2", "file.h"), "")
        save(os.path.join(tmp_folder1, "lib1", "file.a"), "")
        save(os.path.join(tmp_folder2, "lib2", "file.a"), "")
        save(os.path.join(tmp_folder1, "bin1", "file.bin"), "")
        save(os.path.join(tmp_folder2, "bin2", "file.bin"), "")
        save(os.path.join(tmp_folder1, "SystemFrameworks", "file.bin"), "")

        conanfile = ConanFile(TestBufferConanOutput(), None)
        conanfile.initialize(Settings({}), EnvValues())
        ref = ConanFileReference.loads("MyPkg1/0.1@lasote/stables")
        cpp_info = CppInfo(ref.name, tmp_folder1)
        cpp_info.defines = ["MYDEFINE1"]
        cpp_info.includedirs = ['include1']
        cpp_info.libdirs = ['lib1']
        cpp_info.libs = ['libfoo']
        cpp_info.bindirs = ['bin1']
        cpp_info.version = "0.1"
        cpp_info.cflags = ['-fgimple']
        cpp_info.cxxflags = ['-fdollars-in-identifiers']
        cpp_info.sharedlinkflags = ['-framework Cocoa']
        cpp_info.exelinkflags = ['-framework QuartzCore']
        cpp_info.frameworks = ['AudioUnit']
        cpp_info.frameworkdirs = ['SystemFrameworks']
        cpp_info.system_libs = ["system_lib1"]
        conanfile.deps_cpp_info.add(ref.name, cpp_info)
        ref = ConanFileReference.loads("MyPkg2/3.2.3@lasote/stables")
        cpp_info = CppInfo(ref.name, tmp_folder2)
        cpp_info.defines = ["MYDEFINE2"]
        cpp_info.includedirs = ['include2']
        cpp_info.libdirs = ['lib2']
        cpp_info.libs = ['libbar']
        cpp_info.bindirs = ['bin2']
        cpp_info.version = "3.2.3"
        cpp_info.cflags = ['-fno-asm']
        cpp_info.cxxflags = ['-pthread']
        cpp_info.sharedlinkflags = ['-framework AudioFoundation']
        cpp_info.exelinkflags = ['-framework VideoToolbox']
        cpp_info.system_libs = ["system_lib2"]
        conanfile.deps_cpp_info.add(ref.name, cpp_info)
        generator = MakeGenerator(conanfile)
        content = generator.content

        content_template = """
CONAN_ROOT_MYPKG1 ?=  \\
{conan_root_mypkg1}

CONAN_SYSROOT_MYPKG1 ?=  \\


CONAN_INCLUDE_DIRS_MYPKG1 +=  \\
{conan_include_dirs_mypkg1}

CONAN_LIB_DIRS_MYPKG1 +=  \\
{conan_lib_dirs_mypkg1}

CONAN_BIN_DIRS_MYPKG1 +=  \\
{conan_bin_dirs_mypkg1}

CONAN_BUILD_DIRS_MYPKG1 +=  \\
{conan_build_dirs_mypkg1}

CONAN_RES_DIRS_MYPKG1 +=  \\


CONAN_LIBS_MYPKG1 +=  \\
libfoo

CONAN_SYSTEM_LIBS_MYPKG1 +=  \\
system_lib1

CONAN_DEFINES_MYPKG1 +=  \\
MYDEFINE1

CONAN_CFLAGS_MYPKG1 +=  \\
-fgimple

CONAN_CXXFLAGS_MYPKG1 +=  \\
-fdollars-in-identifiers

CONAN_SHAREDLINKFLAGS_MYPKG1 +=  \\
-framework Cocoa

CONAN_EXELINKFLAGS_MYPKG1 +=  \\
-framework QuartzCore

CONAN_FRAMEWORKS_MYPKG1 +=  \\
AudioUnit

CONAN_FRAMEWORK_PATHS_MYPKG1 +=  \\
{conan_framework_dirs_mypkg1}

CONAN_ROOT_MYPKG2 ?=  \\
{conan_root_mypkg2}

CONAN_SYSROOT_MYPKG2 ?=  \\


CONAN_INCLUDE_DIRS_MYPKG2 +=  \\
{conan_include_dirs_mypkg2}

CONAN_LIB_DIRS_MYPKG2 +=  \\
{conan_lib_dirs_mypkg2}

CONAN_BIN_DIRS_MYPKG2 +=  \\
{conan_bin_dirs_mypkg2}

CONAN_BUILD_DIRS_MYPKG2 +=  \\
{conan_build_dirs_mypkg2}

CONAN_RES_DIRS_MYPKG2 +=  \\


CONAN_LIBS_MYPKG2 +=  \\
libbar

CONAN_SYSTEM_LIBS_MYPKG2 +=  \\
system_lib2

CONAN_DEFINES_MYPKG2 +=  \\
MYDEFINE2

CONAN_CFLAGS_MYPKG2 +=  \\
-fno-asm

CONAN_CXXFLAGS_MYPKG2 +=  \\
-pthread

CONAN_SHAREDLINKFLAGS_MYPKG2 +=  \\
-framework AudioFoundation

CONAN_EXELINKFLAGS_MYPKG2 +=  \\
-framework VideoToolbox

CONAN_FRAMEWORKS_MYPKG2 +=  \\


CONAN_FRAMEWORK_PATHS_MYPKG2 +=  \\


CONAN_ROOTPATH +=  \\
$(CONAN_ROOTPATH_MYPKG1) \\
$(CONAN_ROOTPATH_MYPKG2)

CONAN_SYSROOT +=  \\
$(CONAN_SYSROOT_MYPKG1) \\
$(CONAN_SYSROOT_MYPKG2)

CONAN_INCLUDE_DIRS +=  \\
$(CONAN_INCLUDE_DIRS_MYPKG1) \\
$(CONAN_INCLUDE_DIRS_MYPKG2)

CONAN_LIB_DIRS +=  \\
$(CONAN_LIB_DIRS_MYPKG1) \\
$(CONAN_LIB_DIRS_MYPKG2)

CONAN_BIN_DIRS +=  \\
$(CONAN_BIN_DIRS_MYPKG1) \\
$(CONAN_BIN_DIRS_MYPKG2)

CONAN_BUILD_DIRS +=  \\
$(CONAN_BUILD_DIRS_MYPKG1) \\
$(CONAN_BUILD_DIRS_MYPKG2)

CONAN_RES_DIRS +=  \\
$(CONAN_RES_DIRS_MYPKG1) \\
$(CONAN_RES_DIRS_MYPKG2)

CONAN_LIBS +=  \\
$(CONAN_LIBS_MYPKG1) \\
$(CONAN_LIBS_MYPKG2)

CONAN_DEFINES +=  \\
$(CONAN_DEFINES_MYPKG1) \\
$(CONAN_DEFINES_MYPKG2)

CONAN_CFLAGS +=  \\
$(CONAN_CFLAGS_MYPKG1) \\
$(CONAN_CFLAGS_MYPKG2)

CONAN_CXXFLAGS +=  \\
$(CONAN_CXXFLAGS_MYPKG1) \\
$(CONAN_CXXFLAGS_MYPKG2)

CONAN_SHAREDLINKFLAGS +=  \\
$(CONAN_SHAREDLINKFLAGS_MYPKG1) \\
$(CONAN_SHAREDLINKFLAGS_MYPKG2)

CONAN_EXELINKFLAGS +=  \\
$(CONAN_EXELINKFLAGS_MYPKG1) \\
$(CONAN_EXELINKFLAGS_MYPKG2)

CONAN_FRAMEWORKS +=  \\
$(CONAN_FRAMEWORKS_MYPKG1) \\
$(CONAN_FRAMEWORKS_MYPKG2)

CONAN_FRAMEWORK_PATHS +=  \\
$(CONAN_FRAMEWORK_PATHS_MYPKG1) \\
$(CONAN_FRAMEWORK_PATHS_MYPKG2)
"""
        root1 = tmp_folder1.replace('\\', '/')
        root2 = tmp_folder2.replace('\\', '/')

        inc1 = os.path.join(tmp_folder1, 'include1').replace('\\', '/')
        inc2 = os.path.join(tmp_folder2, 'include2').replace('\\', '/')

        lib1 = os.path.join(tmp_folder1, 'lib1').replace('\\', '/')
        lib2 = os.path.join(tmp_folder2, 'lib2').replace('\\', '/')

        bin1 = os.path.join(tmp_folder1, 'bin1').replace('\\', '/')
        bin2 = os.path.join(tmp_folder2, 'bin2').replace('\\', '/')

        expected_content = content_template.format(
            conan_root_mypkg1=root1,
            conan_include_dirs_mypkg1=inc1,
            conan_lib_dirs_mypkg1=lib1,
            conan_bin_dirs_mypkg1=bin1,
            conan_build_dirs_mypkg1=root1 + "/",
            conan_root_mypkg2=root2,
            conan_include_dirs_mypkg2=inc2,
            conan_lib_dirs_mypkg2=lib2,
            conan_bin_dirs_mypkg2=bin2,
            conan_build_dirs_mypkg2=root2 + "/",
            conan_framework_dirs_mypkg1=root1 + "/SystemFrameworks")
        self.maxDiff = None
        self.assertIn(expected_content, content)
Exemplo n.º 36
0
class ConanFile(object):
    """ The base class for all package recipes
    """

    name = None
    version = None  # Any str, can be "1.1" or whatever
    url = None  # The URL where this File is located, as github, to collaborate in package
    # The license of the PACKAGE, just a shortcut, does not replace or
    # change the actual license of the source code
    license = None
    author = None  # Main maintainer/responsible for the package, any format
    build_policy = None
    short_paths = False

    def __init__(self, output, runner, settings, conanfile_directory, user=None, channel=None):
        # User defined generators
        self.generators = self.generators if hasattr(self, "generators") else ["txt"]
        if isinstance(self.generators, str):
            self.generators = [self.generators]

        # User defined options
        self.options = create_options(self)
        self.requires = create_requirements(self)
        self.settings = create_settings(self, settings)
        self.exports = create_exports(self)
        self.exports_sources = create_exports_sources(self)
        # needed variables to pack the project
        self.cpp_info = None  # Will be initialized at processing time
        self.deps_cpp_info = DepsCppInfo()

        # environment variables declared in the package_info
        self.env_info = None  # Will be initialized at processing time
        self.deps_env_info = DepsEnvInfo()

        self.copy = None  # initialized at runtime

        # an output stream (writeln, info, warn error)
        self.output = output
        # something that can run commands, as os.sytem
        self._runner = runner

        self._conanfile_directory = conanfile_directory
        self.package_folder = None  # Assigned at runtime
        self._scope = None

        # user specified env variables
        self._env_values = EnvValues()  # Updated at runtime, user specified -e
        self._user = user
        self._channel = channel

    @property
    def env(self):
        simple, multiple = self._env_values.env_dicts(self.name)
        simple.update(multiple)
        return simple

    @property
    def channel(self):
        if not self._channel:
            self._channel = os.getenv("CONAN_CHANNEL")
            if not self._channel:
                raise ConanException("CONAN_CHANNEL environment variable not defined, "
                                     "but self.channel is used in conanfile")
        return self._channel

    @property
    def user(self):
        if not self._user:
            self._user = os.getenv("CONAN_USERNAME")
            if not self._user:
                raise ConanException("CONAN_USERNAME environment variable not defined, "
                                     "but self.user is used in conanfile")
        return self._user

    def collect_libs(self, folder="lib"):
        if not self.package_folder:
            return []
        lib_folder = os.path.join(self.package_folder, folder)
        if not os.path.exists(lib_folder):
            self.output.warn("Package folder doesn't exist, can't collect libraries")
            return []
        files = os.listdir(lib_folder)
        result = []
        for f in files:
            name, ext = os.path.splitext(f)
            if ext in (".so", ".lib", ".a", ".dylib"):
                if ext != ".lib" and name.startswith("lib"):
                    name = name[3:]
                result.append(name)
        return result

    @property
    def scope(self):
        return self._scope

    @scope.setter
    def scope(self, value):
        self._scope = value
        if value.dev:
            self.requires.allow_dev = True
            try:
                if hasattr(self, "dev_requires"):
                    if isinstance(self.dev_requires, tuple):
                        self.requires.add_dev(*self.dev_requires)
                    else:
                        self.requires.add_dev(self.dev_requires, )
            except Exception as e:
                raise ConanException("Error while initializing dev_requirements. %s" % str(e))

    @property
    def conanfile_directory(self):
        return self._conanfile_directory

    @property
    def build_policy_missing(self):
        return self.build_policy == "missing"

    @property
    def build_policy_always(self):
        return self.build_policy == "always"

    def source(self):
        pass

    def system_requirements(self):
        """ this method can be overwritten to implement logic for system package
        managers, as apt-get

        You can define self.global_system_requirements = True, if you want the installation
        to be for all packages (not depending on settings/options/requirements)
        """

    def config_options(self):
        """ modify options, probably conditioned to some settings. This call is executed
        before config_settings. E.g.
        if self.settings.os == "Windows":
            del self.options.shared  # shared/static not supported in win
        """

    def configure(self):
        """ modify settings, probably conditioned to some options. This call is executed
        after config_options. E.g.
        if self.options.header_only:
            self.settings.clear()
        This is also the place for conditional requirements
        """

    def imports(self):
        pass

    def build(self):
        self.output.warn("This conanfile has no build step")

    def package(self):
        self.output.warn("This conanfile has no package step")

    def package_info(self):
        """ define cpp_build_info, flags, etc
        """

    def run(self, command, output=True, cwd=None):
        """ runs such a command in the folder the Conan
        is defined
        """
        retcode = self._runner(command, output, os.path.abspath(RUN_LOG_NAME),  cwd)
        if retcode != 0:
            raise ConanException("Error %d while executing %s" % (retcode, command))

    def package_id(self):
        """ modify the conans info, typically to narrow values
        eg.: conaninfo.package_references = []
        """

    def test(self):
        raise ConanException("You need to create a method 'test' in your test/conanfile.py")

    def __repr__(self):
        if self.name and self.version and self._channel and self._user:
            return "%s/%s@%s/%s" % (self.name, self.version, self.user, self.channel)
        elif self.name and self.version:
            return "%s/%s@PROJECT" % (self.name, self.version)
        else:
            return "PROJECT"