Пример #1
0
def create_package(conanfile, source_folder, build_folder, package_folder, install_folder,
                   output, local=False, copy_info=False):
    """ copies built artifacts, libs, headers, data, etc. from build_folder to
    package folder
    """
    mkdir(package_folder)

    # Make the copy of all the patterns
    output.info("Generating the package")
    output.info("Package folder %s" % package_folder)

    try:
        package_output = ScopedOutput("%s package()" % output.scope, output)
        output.highlight("Calling package()")
        conanfile.package_folder = package_folder
        conanfile.source_folder = source_folder
        conanfile.install_folder = install_folder
        conanfile.build_folder = build_folder

        def recipe_has(attribute):
            return attribute in conanfile.__class__.__dict__

        if source_folder != build_folder:
            conanfile.copy = FileCopier(source_folder, package_folder, build_folder)
            with conanfile_exception_formatter(str(conanfile), "package"):
                with tools.chdir(source_folder):
                    conanfile.package()
            copy_done = conanfile.copy.report(package_output)
            if not copy_done and recipe_has("package"):
                output.warn("No files copied from source folder!")

        conanfile.copy = FileCopier(build_folder, package_folder)
        with tools.chdir(build_folder):
            with conanfile_exception_formatter(str(conanfile), "package"):
                conanfile.package()
        copy_done = conanfile.copy.report(package_output)
        if not copy_done and recipe_has("build") and recipe_has("package"):
            output.warn("No files copied from build folder!")
    except Exception as e:
        if not local:
            os.chdir(build_folder)
            try:
                rmdir(package_folder)
            except Exception as e_rm:
                output.error("Unable to remove package folder %s\n%s" % (package_folder, str(e_rm)))
                output.warn("**** Please delete it manually ****")

        if isinstance(e, ConanExceptionInUserConanfileMethod):
            raise
        raise ConanException(e)

    _create_aux_files(install_folder, package_folder, conanfile, copy_info)
    output.success("Package '%s' created" % os.path.basename(package_folder))
Пример #2
0
def test_windows_case_insensitive_ps1(env):
    display = textwrap.dedent("""\
        echo "MyVar=$env:MyVar!!"
        echo "MyVar1=$env:MyVar1!!"
        echo "MyVar2=$env:MyVar2!!"
        """)

    prevenv = {
        "MYVAR2": "OldValue2",
    }
    prevenv.update(dict(os.environ.copy()))

    with chdir(temp_folder()):
        env.save_ps1("test.ps1")
        save("display.ps1", display)
        cmd = "powershell.exe .\\test.ps1 ; .\\display.ps1 ; .\\deactivate_test.ps1 ; .\\display.ps1"
        check_command_output(cmd, prevenv)
Пример #3
0
def test_windows_case_insensitive_bat(env):
    display = textwrap.dedent("""\
        @echo off
        echo MyVar=%MyVar%!!
        echo MyVar1=%MyVar1%!!
        echo MyVar2=%MyVar2%!!
        """)

    prevenv = {
        "MYVAR2": "OldValue2",
    }

    with chdir(temp_folder()):
        env.save_bat("test.bat")
        save("display.bat", display)
        cmd = "test.bat && display.bat && deactivate_test.bat && display.bat"
        check_command_output(cmd, prevenv)
Пример #4
0
    def basic_test2(self):
        with chdir(self.cache.store):
            ref1 = ConanFileReference.loads("opencv/2.4.10@lasote/testing")
            root_folder = str(ref1).replace("@", "/")
            artifacts = ["a", "b", "c"]
            reg1 = "%s/%s" % (root_folder, EXPORT_FOLDER)
            os.makedirs(reg1)
            for artif_id in artifacts:
                build1 = "%s/%s/%s" % (root_folder, BUILD_FOLDER, artif_id)
                artif1 = "%s/%s/%s" % (root_folder, PACKAGES_FOLDER, artif_id)
                os.makedirs(build1)
                info = ConanInfo().loads("[settings]\n[options]")
                save(os.path.join(artif1, CONANINFO), info.dumps())

            packages = search_packages(self.cache, ref1, "")
            all_artif = [_artif for _artif in sorted(packages)]
            self.assertEqual(all_artif, artifacts)
Пример #5
0
    def test_virtualrunenv(self):
        client = TestClient(servers=self.servers,
                            users={"default": [("lasote", "mypass")]})
        client.run("install Pkg/0.1@lasote/testing -g virtualrunenv")

        with tools.chdir(client.current_folder):
            if platform.system() == "Windows":
                command = "activate_run.bat && say_hello"
            else:
                # It is not necessary to use the DYLD_LIBRARY_PATH in OSX because the activate_run.sh
                # will work perfectly. It is inside bash, so the loader will use DYLD_LIBRARY_PATH
                # values. It also works in command line with export DYLD_LIBRARY_PATH=[path] and then
                # running, or in the same line "$ DYLD_LIBRARY_PATH=[path] say_hello"
                command = "bash -c 'source activate_run.sh && say_hello'"

            output = check_output_runner(command)
            self.assertIn("Hello Tool!", output)
Пример #6
0
def _process_git_repo(repo_url,
                      cache,
                      output,
                      tmp_folder,
                      verify_ssl,
                      args=None):
    output.info("Trying to clone repo: %s" % repo_url)

    with tools.chdir(tmp_folder):
        try:
            args = args or ""
            git = Git(verify_ssl=verify_ssl, output=output)
            git.clone(repo_url, args=args)
            output.info("Repo cloned!")
        except Exception as e:
            raise ConanException("Can't clone repo: %s" % str(e))
    _process_folder(tmp_folder, cache, output)
Пример #7
0
def _run_source(conanfile, conanfile_path, src_folder, hook_manager, reference,
                cache, export_folder, export_source_folder,
                local_sources_path):
    """Execute the source core functionality, both for local cache and user space, in order:
        - Calling pre_source hook
        - Getting sources from SCM
        - Getting sources from exported folders in the local cache
        - Clean potential TGZ and other files in the local cache
        - Executing the recipe source() method
        - Calling post_source hook
    """
    conanfile.source_folder = src_folder
    conanfile.build_folder = None
    conanfile.package_folder = None
    with tools.chdir(src_folder):
        try:
            with get_env_context_manager(conanfile):
                hook_manager.execute("pre_source",
                                     conanfile=conanfile,
                                     conanfile_path=conanfile_path,
                                     reference=reference)
                output = conanfile.output
                output.info('Configuring sources in %s' % src_folder)
                _run_scm(conanfile,
                         src_folder,
                         local_sources_path,
                         output,
                         cache=cache)

                if cache:
                    _get_sources_from_exports(conanfile, src_folder,
                                              export_folder,
                                              export_source_folder, cache)
                    _clean_source_folder(src_folder)
                with conanfile_exception_formatter(conanfile.display_name,
                                                   "source"):
                    conanfile.source()

                hook_manager.execute("post_source",
                                     conanfile=conanfile,
                                     conanfile_path=conanfile_path,
                                     reference=reference)
        except ConanExceptionInUserConanfileMethod:
            raise
        except Exception as e:
            raise ConanException(e)
Пример #8
0
    def install_custom_args_test(self):
        """ should install from a git repo
        """

        folder = self._create_profile_folder()
        with tools.chdir(folder):
            self.client.runner('git init .')
            self.client.runner('git add .')
            self.client.runner('git config user.name myname')
            self.client.runner('git config user.email [email protected]')
            self.client.runner('git commit -m "mymsg"')

        self.client.run(
            'config install "%s/.git" --args="-c init.templateDir=value"' %
            folder)
        check_path = os.path.join(folder, ".git")
        self._check("git, %s, True, -c init.templateDir=value" % check_path)
Пример #9
0
    def case_insensitive_test(self):
        with chdir(self.paths.store):
            root_folder2 = "sdl/1.5/lasote/stable"
            conan_ref2 = ConanFileReference.loads("sdl/1.5@lasote/stable")
            os.makedirs("%s/%s" % (root_folder2, EXPORT_FOLDER))

            root_folder3 = "assimp/0.14/phil/testing"
            conan_ref3 = ConanFileReference.loads("assimp/0.14@phil/testing")
            os.makedirs("%s/%s" % (root_folder3, EXPORT_FOLDER))

            root_folder4 = "sdl/2.10/lasote/stable"
            conan_ref4 = ConanFileReference.loads("sdl/2.10@lasote/stable")
            os.makedirs("%s/%s" % (root_folder4, EXPORT_FOLDER))

            root_folder5 = "SDL_fake/1.10/lasote/testing"
            conan_ref5 = ConanFileReference.loads(
                "SDL_fake/1.10@lasote/testing")
            os.makedirs("%s/%s" % (root_folder5, EXPORT_FOLDER))
            # Case insensitive searches

            reg_conans = sorted(
                [str(_reg) for _reg in search_recipes(self.paths, "*")])
            self.assertEqual(reg_conans, [
                str(conan_ref5),
                str(conan_ref3),
                str(conan_ref2),
                str(conan_ref4)
            ])

            reg_conans = sorted([
                str(_reg)
                for _reg in search_recipes(self.paths, pattern="sdl*")
            ])
            self.assertEqual(
                reg_conans,
                [str(conan_ref5),
                 str(conan_ref2),
                 str(conan_ref4)])

            # Case sensitive search
            self.assertEqual(
                str(
                    search_recipes(self.paths,
                                   pattern="SDL*",
                                   ignorecase=False)[0]), str(conan_ref5))
Пример #10
0
    def scm_sources_test(self):
        """ Test conan_sources.tgz is deleted in server when removing 'exports_sources' and using
        'scm'"""
        conanfile = """from conans import ConanFile
class TestConan(ConanFile):
    name = "test"
    version = "1.0"
"""
        exports_sources = """
    exports_sources = "include/*"
"""
        servers = {"upload_repo": TestServer([("*/*@*/*", "*")], [("*/*@*/*", "*")],
                                             users={"lasote": "mypass"})}
        client = TestClient(servers=servers, users={"upload_repo": [("lasote", "mypass")]})
        client.save({"conanfile.py": conanfile + exports_sources, "include/file": "content"})
        client.run("create . danimtb/testing")
        client.run("upload test/1.0@danimtb/testing -r upload_repo")
        self.assertIn("Uploading conan_sources.tgz", client.out)
        ref = ConanFileReference("test", "1.0", "danimtb", "testing")
        export_sources_path = os.path.join(servers["upload_repo"].server_store.export(ref),
                                           "conan_sources.tgz")
        self.assertTrue(os.path.exists(export_sources_path))

        scm = """
    scm = {"type": "git",
           "url": "auto",
           "revision": "auto"}
"""
        client.save({"conanfile.py": conanfile + scm})
        with chdir(client.current_folder):
            client.runner("git init")
            client.runner('git config user.email "*****@*****.**"')
            client.runner('git config user.name "Your Name"')
            client.runner("git remote add origin https://github.com/fake/fake.git")
            client.runner("git add .")
            client.runner("git commit -m \"initial commit\"")
        client.run("create . danimtb/testing")
        self.assertIn("Repo origin deduced by 'auto': https://github.com/fake/fake.git", client.out)
        client.run("upload test/1.0@danimtb/testing -r upload_repo")
        self.assertNotIn("Uploading conan_sources.tgz", client.out)
        export_sources_path = os.path.join(servers["upload_repo"].server_store.export(ref),
                                           "conan_sources.tgz")
        self.assertFalse(os.path.exists(export_sources_path))
Пример #11
0
def _run_source(conanfile, conanfile_path, hook_manager, reference, cache,
                get_sources_from_exports):
    """Execute the source core functionality, both for local cache and user space, in order:
        - Calling pre_source hook
        - Getting sources from SCM
        - Getting sources from exported folders in the local cache
        - Clean potential TGZ and other files in the local cache
        - Executing the recipe source() method
        - Calling post_source hook
    """

    src_folder = conanfile.source_folder if hasattr(conanfile, "layout") \
        else conanfile.folders.base_source
    mkdir(src_folder)

    with tools.chdir(src_folder):
        try:
            with get_env_context_manager(conanfile):
                hook_manager.execute("pre_source", conanfile=conanfile,
                                     conanfile_path=conanfile_path,
                                     reference=reference)
                output = conanfile.output
                output.info('Configuring sources in %s' % src_folder)
                get_sources_from_exports()

                if cache:
                    # Clear the conanfile.py to avoid errors cloning git repositories.
                    _clean_source_folder(src_folder)
                with conanfile_exception_formatter(conanfile.display_name, "source"):

                    with conan_v2_property(conanfile, 'settings',
                                           "'self.settings' access in source() method is deprecated"):
                        with conan_v2_property(conanfile, 'options',
                                               "'self.options' access in source() method is deprecated"):
                            conanfile.source()

                hook_manager.execute("post_source", conanfile=conanfile,
                                     conanfile_path=conanfile_path,
                                     reference=reference)
        except ConanExceptionInUserConanfileMethod:
            raise
        except Exception as e:
            raise ConanException(e)
Пример #12
0
def call_package_info(conanfile, package_folder):
    conanfile.cpp_info = CppInfo(package_folder)
    conanfile.cpp_info.version = conanfile.version
    conanfile.cpp_info.description = conanfile.description
    conanfile.env_info = EnvInfo()
    conanfile.user_info = UserInfo()

    # Get deps_cpp_info from upstream nodes
    public_deps = [name for name, req in conanfile.requires.items() if not req.private]
    conanfile.cpp_info.public_deps = public_deps
    # Once the node is build, execute package info, so it has access to the
    # package folder and artifacts
    with tools.chdir(package_folder):
        with conanfile_exception_formatter(str(conanfile), "package_info"):
            conanfile.package_folder = package_folder
            conanfile.source_folder = None
            conanfile.build_folder = None
            conanfile.install_folder = None
            conanfile.package_info()
Пример #13
0
    def _call_package_info(self, conanfile, package_folder, ref):
        conanfile.cpp_info = CppInfo(package_folder)
        conanfile.cpp_info.name = conanfile.name
        conanfile.cpp_info.version = conanfile.version
        conanfile.cpp_info.description = conanfile.description
        conanfile.env_info = EnvInfo()
        conanfile.user_info = UserInfo()

        # Get deps_cpp_info from upstream nodes
        public_deps = [
            name for name, req in conanfile.requires.items()
            if not req.private and not req.override
        ]
        conanfile.cpp_info.public_deps = public_deps
        # Once the node is build, execute package info, so it has access to the
        # package folder and artifacts
        conan_v2 = get_env(CONAN_V2_MODE_ENVVAR, False)
        with pythonpath(conanfile) if not conan_v2 else no_op(
        ):  # Minimal pythonpath, not the whole context, make it 50% slower
            with tools.chdir(package_folder):
                with conanfile_exception_formatter(str(conanfile),
                                                   "package_info"):
                    conanfile.package_folder = package_folder
                    conanfile.source_folder = None
                    conanfile.build_folder = None
                    conanfile.install_folder = None
                    self._hook_manager.execute("pre_package_info",
                                               conanfile=conanfile,
                                               reference=ref)
                    conanfile.package_info()
                    if conanfile._conan_dep_cpp_info is None:
                        try:
                            conanfile.cpp_info._raise_incorrect_components_definition(
                                conanfile.name, conanfile.requires)
                        except ConanException as e:
                            raise ConanException("%s package_info(): %s" %
                                                 (str(conanfile), e))
                        conanfile._conan_dep_cpp_info = DepCppInfo(
                            conanfile.cpp_info)
                    self._hook_manager.execute("post_package_info",
                                               conanfile=conanfile,
                                               reference=ref)
Пример #14
0
def _run_method(conanfile, method, origin_folder, destination_folder, output):
    export_method = getattr(conanfile, method, None)
    if export_method:
        if not callable(export_method):
            raise ConanException("conanfile '%s' must be a method" % method)
        output.highlight("Calling %s()" % method)
        copier = FileCopier([origin_folder], destination_folder)
        conanfile.copy = copier
        default_options = conanfile.default_options
        try:
            # TODO: Poor man attribute control access. Convert to nice decorator
            conanfile.default_options = None
            with chdir(origin_folder):
                with conanfile_exception_formatter(str(conanfile), method):
                    export_method()
        finally:
            conanfile.default_options = default_options
        export_method_output = ScopedOutput(
            "%s %s() method" % (output.scope, method), output)
        copier.report(export_method_output)
Пример #15
0
    def _call_package_info(conanfile, package_folder):
        conanfile.cpp_info = CppInfo(package_folder)
        conanfile.cpp_info.version = conanfile.version
        conanfile.cpp_info.description = conanfile.description
        conanfile.env_info = EnvInfo()
        conanfile.user_info = UserInfo()

        # Get deps_cpp_info from upstream nodes
        public_deps = [name for name, req in conanfile.requires.items() if not req.private]
        conanfile.cpp_info.public_deps = public_deps
        # Once the node is build, execute package info, so it has access to the
        # package folder and artifacts
        with pythonpath(conanfile):  # Minimal pythonpath, not the whole context, make it 50% slower
            with tools.chdir(package_folder):
                with conanfile_exception_formatter(str(conanfile), "package_info"):
                    conanfile.package_folder = package_folder
                    conanfile.source_folder = None
                    conanfile.build_folder = None
                    conanfile.install_folder = None
                    conanfile.package_info()
Пример #16
0
    def _call_package_info(self, conanfile, package_folder, ref):
        conanfile.cpp_info = CppInfo(conanfile.name, package_folder)
        conanfile.cpp_info.version = conanfile.version
        conanfile.cpp_info.description = conanfile.description
        conanfile.env_info = EnvInfo()
        conanfile.user_info = UserInfo()

        # Get deps_cpp_info from upstream nodes
        public_deps = [
            name for name, req in conanfile.requires.items()
            if not req.private and not req.override
        ]
        conanfile.cpp_info.public_deps = public_deps
        # Once the node is build, execute package info, so it has access to the
        # package folder and artifacts
        # Minimal pythonpath, not the whole context, make it 50% slower
        # FIXME Conan 2.0, Remove old ways of reusing python code
        with pythonpath(conanfile):
            with tools.chdir(package_folder):
                with conanfile_exception_formatter(str(conanfile),
                                                   "package_info"):
                    conanfile.layout.set_base_package_folder(package_folder)
                    conanfile.layout.set_base_source_folder(None)
                    conanfile.layout.set_base_build_folder(None)
                    conanfile.layout.set_base_install_folder(None)
                    self._hook_manager.execute("pre_package_info",
                                               conanfile=conanfile,
                                               reference=ref)
                    conanfile.package_info()
                    if conanfile._conan_dep_cpp_info is None:
                        try:
                            conanfile.cpp_info._raise_incorrect_components_definition(
                                conanfile.name, conanfile.requires)
                        except ConanException as e:
                            raise ConanException("%s package_info(): %s" %
                                                 (str(conanfile), e))
                        conanfile._conan_dep_cpp_info = DepCppInfo(
                            conanfile.cpp_info)
                    self._hook_manager.execute("post_package_info",
                                               conanfile=conanfile,
                                               reference=ref)
Пример #17
0
def _run_source(conanfile, conanfile_path, src_folder, hook_manager, reference, cache,
                get_sources_from_exports):
    """Execute the source core functionality, both for local cache and user space, in order:
        - Calling pre_source hook
        - Getting sources from SCM
        - Getting sources from exported folders in the local cache
        - Clean potential TGZ and other files in the local cache
        - Executing the recipe source() method
        - Calling post_source hook
    """
    conanfile.source_folder = src_folder
    conanfile.build_folder = None
    conanfile.package_folder = None
    with tools.chdir(src_folder):
        try:
            with get_env_context_manager(conanfile):
                hook_manager.execute("pre_source", conanfile=conanfile,
                                     conanfile_path=conanfile_path,
                                     reference=reference)
                output = conanfile.output
                output.info('Configuring sources in %s' % src_folder)
                get_sources_from_exports()

                if cache:
                    _clean_source_folder(src_folder)  # TODO: Why is it needed in cache?
                with conanfile_exception_formatter(conanfile.display_name, "source"):

                    with conan_v2_property(conanfile, 'settings',
                                           "'self.settings' access in source() method is deprecated"):
                        with conan_v2_property(conanfile, 'options',
                                               "'self.options' access in source() method is deprecated"):
                            conanfile.source()

                hook_manager.execute("post_source", conanfile=conanfile,
                                     conanfile_path=conanfile_path,
                                     reference=reference)
        except ConanExceptionInUserConanfileMethod:
            raise
        except Exception as e:
            raise ConanException(e)
Пример #18
0
def test_env_files_sh(env, prevenv):
    display = textwrap.dedent("""\
        echo MyVar=$MyVar!!
        echo MyVar1=$MyVar1!!
        echo MyVar2=$MyVar2!!
        echo MyVar3=$MyVar3!!
        echo MyVar4=$MyVar4!!
        echo MyVar5=$MyVar5!!
        echo MyVar6=$MyVar6!!
        echo MyPath1=$MyPath1!!
        echo MyPath2=$MyPath2!!
        echo MyPath3=$MyPath3!!
        echo MyPath4=$MyPath4!!
        """)

    with chdir(temp_folder()):
        env = env.vars(ConanFileMock())
        env.save_sh("test.sh")
        save("display.sh", display)
        os.chmod("display.sh", 0o777)
        cmd = '. ./test.sh && ./display.sh && . ./deactivate_test.sh && ./display.sh'
        check_env_files_output(cmd, prevenv)
Пример #19
0
def test_env_files_bat(env, prevenv):
    display = textwrap.dedent("""\
        @echo off
        echo MyVar=%MyVar%!!
        echo MyVar1=%MyVar1%!!
        echo MyVar2=%MyVar2%!!
        echo MyVar3=%MyVar3%!!
        echo MyVar4=%MyVar4%!!
        echo MyVar5=%MyVar5%!!
        echo MyVar6=%MyVar6%!!
        echo MyPath1=%MyPath1%!!
        echo MyPath2=%MyPath2%!!
        echo MyPath3=%MyPath3%!!
        echo MyPath4=%MyPath4%!!
        """)

    with chdir(temp_folder()):
        env = env.vars(ConanFileMock())
        env.save_bat("test.bat")
        save("display.bat", display)
        cmd = "test.bat && display.bat && deactivate_test.bat && display.bat"
        check_env_files_output(cmd, prevenv)
Пример #20
0
def run_deploy(conanfile, install_folder):
    deploy_output = ScopedOutput("%s deploy()" % conanfile.display_name, conanfile.output)
    file_importer = _FileImporter(conanfile, install_folder)
    package_copied = set()

    # This is necessary to capture FileCopier full destination paths
    # Maybe could be improved in FileCopier
    def file_copier(*args, **kwargs):
        file_copy = FileCopier(conanfile.package_folder, install_folder)
        copied = file_copy(*args, **kwargs)
        _make_files_writable(copied)
        package_copied.update(copied)

    conanfile.copy_deps = file_importer
    conanfile.copy = file_copier
    conanfile.install_folder = install_folder
    with get_env_context_manager(conanfile):
        with tools.chdir(install_folder):
            conanfile.deploy()

    copied_files = file_importer.copied_files
    copied_files.update(package_copied)
    _report_save_manifest(copied_files, deploy_output, install_folder, "deploy_manifest.txt")
Пример #21
0
def test_env_files_ps1(env, prevenv):
    prevenv.update(dict(os.environ.copy()))

    display = textwrap.dedent("""\
        echo "MyVar=$env:MyVar!!"
        echo "MyVar1=$env:MyVar1!!"
        echo "MyVar2=$env:MyVar2!!"
        echo "MyVar3=$env:MyVar3!!"
        echo "MyVar4=$env:MyVar4!!"
        echo "MyVar5=$env:MyVar5!!"
        echo "MyVar6=$env:MyVar6!!"
        echo "MyPath1=$env:MyPath1!!"
        echo "MyPath2=$env:MyPath2!!"
        echo "MyPath3=$env:MyPath3!!"
        echo "MyPath4=$env:MyPath4!!"
    """)

    with chdir(temp_folder()):
        env = env.vars(ConanFileMock())
        env.save_ps1("test.ps1")
        save("display.ps1", display)
        cmd = "powershell.exe .\\test.ps1 ; .\\display.ps1 ; .\\deactivate_test.ps1 ; .\\display.ps1"
        check_env_files_output(cmd, prevenv)
Пример #22
0
    def _call_package_info(self, conanfile, package_folder, ref):
        conanfile.cpp_info = CppInfo(package_folder)
        conanfile.cpp_info.version = conanfile.version
        conanfile.cpp_info.description = conanfile.description
        conanfile.env_info = EnvInfo()
        conanfile.user_info = UserInfo()

        # Get deps_cpp_info from upstream nodes
        public_deps = [name for name, req in conanfile.requires.items() if not req.private]
        conanfile.cpp_info.public_deps = public_deps
        # Once the node is build, execute package info, so it has access to the
        # package folder and artifacts
        with pythonpath(conanfile):  # Minimal pythonpath, not the whole context, make it 50% slower
            with tools.chdir(package_folder):
                with conanfile_exception_formatter(str(conanfile), "package_info"):
                    conanfile.package_folder = package_folder
                    conanfile.source_folder = None
                    conanfile.build_folder = None
                    conanfile.install_folder = None
                    self._hook_manager.execute("pre_package_info", conanfile=conanfile,
                                               reference=ref)
                    conanfile.package_info()
                    self._hook_manager.execute("post_package_info", conanfile=conanfile,
                                               reference=ref)
Пример #23
0
    def curdir_test(self):
        tmp_folder = temp_folder()
        conanfile = """from conans import ConanFile
class Pkg(ConanFile):
    name = "lib"
    version = "1.0"
"""
        tools.save(os.path.join(tmp_folder, "conanfile.py"), conanfile)
        with tools.chdir(tmp_folder):
            # Needed to not write in the real computer cache
            with tools.environment_append({"CONAN_USER_HOME": tmp_folder}):
                api, _, _ = ConanAPIV1.factory()
                api.create(".",
                           name="lib",
                           version="1.0",
                           user="******",
                           channel="channel")
                self.assertEqual(tmp_folder, os.getcwd())
                api.create(".",
                           name="lib",
                           version="1.0",
                           user="******",
                           channel="channel2")
                self.assertEqual(tmp_folder, os.getcwd())
Пример #24
0
def create_local_svn_checkout(files,
                              repo_url,
                              rel_project_path=None,
                              commit_msg='default commit message',
                              delete_checkout=True,
                              folder=None):
    tmp_dir = folder or temp_folder()
    try:
        rel_project_path = rel_project_path or str(uuid.uuid4())
        # Do not use SVN class as it is what we will be testing
        subprocess.check_output('svn co "{url}" "{path}"'.format(url=repo_url,
                                                                 path=tmp_dir),
                                shell=True)
        tmp_project_dir = os.path.join(tmp_dir, rel_project_path)
        mkdir(tmp_project_dir)
        save_files(tmp_project_dir, files)
        with chdir(tmp_project_dir):
            subprocess.check_output("svn add .", shell=True)
            subprocess.check_output('svn commit -m "{}"'.format(commit_msg),
                                    shell=True)
            if SVN.get_version() >= SVN.API_CHANGE_VERSION:
                rev = check_output_runner(
                    "svn info --show-item revision").strip()
            else:
                import xml.etree.ElementTree as ET
                output = check_output_runner("svn info --xml").strip()
                root = ET.fromstring(output)
                rev = root.findall("./entry")[0].get("revision")
        project_url = repo_url + "/" + quote(
            rel_project_path.replace("\\", "/"))
        return project_url, rev
    finally:
        if delete_checkout:
            shutil.rmtree(tmp_dir,
                          ignore_errors=False,
                          onerror=try_remove_readonly)
Пример #25
0
    def _run_app(self, client, arch, build_type, shared=None):
        if build_type == "Release" and shared:
            configuration = "ReleaseShared"
        else:
            configuration = build_type

        if arch == "x86":
            command_str = "%s\\MyApp.exe" % configuration
        else:
            command_str = "x64\\%s\\MyApp.exe" % configuration
        # To run the app without VS IDE, we need to copy the .exe to the DLLs folder
        new_cmd = "conan\\%s\\%s\\MyApp.exe" % (arch, configuration)
        with chdir(client.current_folder):
            mkdir(os.path.dirname(new_cmd))
            shutil.copy(command_str, new_cmd)
        client.run_command(new_cmd)
        if arch == "x86":
            self.assertIn("main _M_IX86 defined", client.out)
        else:
            self.assertIn("main _M_X64 defined", client.out)
        self.assertIn("Hello World %s" % build_type, client.out)
        self.assertIn("main: %s!" % build_type, client.out)
        self.assertIn("DEFINITIONS_BOTH: True", client.out)
        self.assertIn("DEFINITIONS_CONFIG: %s" % build_type, client.out)
Пример #26
0
def create_package(conanfile,
                   pkg_id,
                   source_folder,
                   build_folder,
                   package_folder,
                   install_folder,
                   output,
                   hook_manager,
                   conanfile_path,
                   reference,
                   local=False,
                   copy_info=False):
    """ copies built artifacts, libs, headers, data, etc. from build_folder to
    package folder
    """
    mkdir(package_folder)

    # Make the copy of all the patterns
    output.info("Generating the package")
    output.info("Package folder %s" % package_folder)

    try:
        conanfile.package_folder = package_folder
        conanfile.source_folder = source_folder
        conanfile.install_folder = install_folder
        conanfile.build_folder = build_folder

        hook_manager.execute("pre_package",
                             conanfile=conanfile,
                             conanfile_path=conanfile_path,
                             reference=reference,
                             package_id=pkg_id)

        package_output = ScopedOutput("%s package()" % output.scope, output)
        output.highlight("Calling package()")

        def recipe_has(attribute):
            return attribute in conanfile.__class__.__dict__

        if source_folder != build_folder:
            conanfile.copy = FileCopier(source_folder, package_folder,
                                        build_folder)
            with conanfile_exception_formatter(str(conanfile), "package"):
                with tools.chdir(source_folder):
                    conanfile.package()
            copy_done = conanfile.copy.report(package_output)
            if not copy_done and recipe_has("package"):
                output.warn("No files copied from source folder!")

        conanfile.copy = FileCopier(build_folder, package_folder)
        with tools.chdir(build_folder):
            with conanfile_exception_formatter(str(conanfile), "package"):
                conanfile.package()
        copy_done = conanfile.copy.report(package_output)
        if not copy_done and recipe_has("build") and recipe_has("package"):
            output.warn("No files copied from build folder!")
    except Exception as e:
        if not local:
            os.chdir(build_folder)
            try:
                rmdir(package_folder)
            except Exception as e_rm:
                output.error("Unable to remove package folder %s\n%s" %
                             (package_folder, str(e_rm)))
                output.warn("**** Please delete it manually ****")

        if isinstance(e, ConanExceptionInUserConanfileMethod):
            raise
        raise ConanException(e)

    _create_aux_files(install_folder, package_folder, conanfile, copy_info)
    pkg_id = pkg_id or os.path.basename(package_folder)
    output.success("Package '%s' created" % pkg_id)
    hook_manager.execute("post_package",
                         conanfile=conanfile,
                         conanfile_path=conanfile_path,
                         reference=reference,
                         package_id=pkg_id)
Пример #27
0
    def test_shared_in_current_directory(self):
        """
        - There is a package building a shared library
        - There is a consumer project importing the shared library (and the executable)
        - The consumer tries to execute the imported shared library and executable in the same
          directory, and it fails in Linux, but works on OSX and WIndows.
        - Then I move the shared library to a different directory, and it fails,
          I'm making sure that there is no harcoded rpaths messing.
        - Finally I use the virtualrunenvironment that declares de LD_LIBRARY_PATH,
          PATH and DYLD_LIBRARY_PATH to run the executable, and.. magic!
          it's running agains the shared in the local cache.
        """

        conanfile = """
from conans import ConanFile, CMake, tools


class LibConan(ConanFile):
    name = "lib"
    version = "1.0"
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False]}
    default_options = "shared=True"
    generators = "cmake"
    exports_sources = "*"

    def build(self):
        cmake = CMake(self)
        self.run('cmake %s' % cmake.command_line)
        self.run("cmake --build . %s" % cmake.build_config)

    def package(self):
        self.copy("*.h", dst="include", src="hello")
        self.copy("*.lib", dst="lib", keep_path=False)
        self.copy("*.dll", dst="bin", keep_path=False)
        self.copy("*.so", dst="lib", keep_path=False)
        self.copy("*.dylib", dst="lib", keep_path=False)
        self.copy("*main*", dst="bin", keep_path=False)

"""
        cmakelists = """
set(CMAKE_CXX_COMPILER_WORKS 1)
set(CMAKE_CXX_ABI_COMPILED 1)
project(mytest)

SET(CMAKE_SKIP_RPATH 1)
ADD_LIBRARY(hello SHARED hello.c)
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main hello)
"""

        hello_h = """#pragma once
#ifdef WIN32
  #define HELLO_EXPORT __declspec(dllexport)
#else
  #define HELLO_EXPORT
#endif

HELLO_EXPORT void hello();
"""

        client = TestClient()
        files = {CONANFILE: conanfile,
                 "CMakeLists.txt": cmakelists,
                 "hello.c": '#include "hello.h"\nvoid hello(){\nreturn;}',
                 "hello.h": hello_h,
                 "main.c": '#include "hello.h"\nint main(){\nhello();\nreturn 0;\n}'}

        client.save(files)
        client.run("export . conan/stable")
        client.run("install lib/1.0@conan/stable -o lib:shared=True --build missing")
        client.save({"conanfile.txt": '''
[requires]
lib/1.0@conan/stable
[generators]
virtualrunenv
[imports]
bin, * -> ./bin
lib, * -> ./bin
'''}, clean_first=True)

        client.run("install .")
        # Break possible rpaths built in the exe with absolute paths
        os.rename(os.path.join(client.current_folder, "bin"),
                  os.path.join(client.current_folder, "bin2"))

        with tools.chdir(os.path.join(client.current_folder, "bin2")):
            if platform.system() == "Windows":
                self.assertEqual(os.system("main.exe"), 0)
            elif platform.system() == "Darwin":
                self.assertEqual(os.system("./main"), 0)
            else:
                self.assertNotEqual(os.system("./main"), 0)
                self.assertEqual(os.system("LD_LIBRARY_PATH=$(pwd) ./main"), 0)
                self.assertEqual(os.system("LD_LIBRARY_PATH=. ./main"), 0)

            # If we move the shared library it won't work, at least we use the virtualrunenv
            os.mkdir(os.path.join(client.current_folder, "bin2", "subdir"))
            name = {"Darwin": "libhello.dylib",
                    "Windows": "hello.dll"}.get(platform.system(), "libhello.so")

            os.rename(os.path.join(client.current_folder, "bin2", name),
                      os.path.join(client.current_folder, "bin2", "subdir", name))

            if platform.system() == "Windows":
                self.assertNotEqual(os.system("main.exe"), 0)
            elif platform.system() == "Darwin":
                self.assertNotEqual(os.system("./main"), 0)
            else:
                self.assertNotEqual(os.system("LD_LIBRARY_PATH=$(pwd) ./main"), 0)

            # Will use the shared from the local cache
            if platform.system() != "Windows":
                command = "bash -c 'source ../activate_run.sh && ./main'"
            else:
                command = "cd .. && activate_run.bat && cd bin2 && main.exe"

            self.assertEqual(os.system(command), 0)
Пример #28
0
    def _call_package_info(self, conanfile, package_folder, ref, is_editable):
        conanfile.cpp_info = CppInfo(conanfile.name, package_folder)
        conanfile.cpp_info.version = conanfile.version
        conanfile.cpp_info.description = conanfile.description

        conanfile.env_info = EnvInfo()
        conanfile.user_info = UserInfo()

        # Get deps_cpp_info from upstream nodes
        public_deps = [
            name for name, req in conanfile.requires.items()
            if not req.private and not req.override
        ]
        conanfile.cpp_info.public_deps = public_deps
        # Once the node is build, execute package info, so it has access to the
        # package folder and artifacts
        # Minimal pythonpath, not the whole context, make it 50% slower
        # FIXME Conan 2.0, Remove old ways of reusing python code
        with pythonpath(conanfile):
            with tools.chdir(package_folder):
                with conanfile_exception_formatter(str(conanfile),
                                                   "package_info"):
                    self._hook_manager.execute("pre_package_info",
                                               conanfile=conanfile,
                                               reference=ref)
                    if hasattr(conanfile, "layout"):
                        # Old cpp info without defaults (the defaults are in the new one)
                        conanfile.cpp_info = CppInfo(
                            conanfile.name,
                            package_folder,
                            default_values=CppInfoDefaultValues())
                        if not is_editable:
                            conanfile.cpp.package.set_relative_base_folder(
                                conanfile.package_folder)
                            # Copy the infos.package into the old cppinfo
                            fill_old_cppinfo(conanfile.cpp.package,
                                             conanfile.cpp_info)
                        else:
                            conanfile.cpp_info.filter_empty = False

                    conanfile.package_info()

                    if hasattr(conanfile, "layout") and is_editable:
                        # Adjust the folders of the layout to consolidate the rootfolder of the
                        # cppinfos inside
                        # convert directory entries to be relative to the declared folders.build
                        conanfile.cpp.build.set_relative_base_folder(
                            conanfile.build_folder)

                        # convert directory entries to be relative to the declared folders.source
                        conanfile.cpp.source.set_relative_base_folder(
                            conanfile.source_folder)

                        full_editable_cppinfo = NewCppInfo()
                        full_editable_cppinfo.merge(conanfile.cpp.source)
                        full_editable_cppinfo.merge(conanfile.cpp.build)
                        # Paste the editable cpp_info but prioritizing it, only if a
                        # variable is not declared at build/source, the package will keep the value
                        fill_old_cppinfo(full_editable_cppinfo,
                                         conanfile.cpp_info)

                    if conanfile._conan_dep_cpp_info is None:
                        try:
                            if not is_editable and not hasattr(
                                    conanfile, "layout"):
                                # FIXME: The default for the cppinfo from build are not the same
                                #        so this check fails when editable
                                # FIXME: Remove when new cppinfo model. If using the layout method
                                #        the cppinfo object is filled from self.cpp.package new
                                #        model and we cannot check if the defaults have been modified
                                #        because it doesn't exist in the new model where the defaults
                                #        for the components are always empty
                                conanfile.cpp_info._raise_incorrect_components_definition(
                                    conanfile.name, conanfile.requires)
                        except ConanException as e:
                            raise ConanException("%s package_info(): %s" %
                                                 (str(conanfile), e))
                        conanfile._conan_dep_cpp_info = DepCppInfo(
                            conanfile.cpp_info)
                    self._hook_manager.execute("post_package_info",
                                               conanfile=conanfile,
                                               reference=ref)
Пример #29
0
def call_package_info(conanfile, package_folder):
    # Once the node is build, execute package info, so it has access to the
    # package folder and artifacts
    with tools.chdir(package_folder):
        with conanfile_exception_formatter(str(conanfile), "package_info"):
            conanfile.package_info()
Пример #30
0
    def test_shared_run_environment(self):
        servers = {"default": TestServer()}
        client = TestClient(servers=servers,
                            users={"default": [("lasote", "mypass")]})
        cmake = """set(CMAKE_CXX_COMPILER_WORKS 1)
set(CMAKE_CXX_ABI_COMPILED 1)
project(MyHello CXX)
cmake_minimum_required(VERSION 2.8.12)
add_library(hello SHARED hello.cpp)
add_executable(say_hello main.cpp)
target_link_libraries(say_hello hello)"""
        hello_h = """#ifdef WIN32
  #define HELLO_EXPORT __declspec(dllexport)
#else
  #define HELLO_EXPORT
#endif

HELLO_EXPORT void hello();
"""
        hello_cpp = r"""#include "hello.h"
#include <iostream>
void hello(){
    std::cout<<"Hello Tool!\n";
}
"""
        main = """#include "hello.h"
        int main(){
            hello();
        }
        """
        conanfile = """from conans import ConanFile, CMake
class Pkg(ConanFile):
    exports_sources = "*"
    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

    def package(self):
        self.copy("*say_hello.exe", dst="bin", keep_path=False)
        self.copy("*say_hello", dst="bin", keep_path=False)
        self.copy(pattern="*.dll", dst="bin", keep_path=False)
        self.copy(pattern="*.dylib", dst="lib", keep_path=False)
        self.copy(pattern="*.so", dst="lib", keep_path=False)
"""
        client.save({
            "conanfile.py": conanfile,
            "CMakeLists.txt": cmake,
            "main.cpp": main,
            "hello.cpp": hello_cpp,
            "hello.h": hello_h
        })
        client.run("create . Pkg/0.1@lasote/testing")
        client.run("upload Pkg* --all --confirm")
        client.run('remove "*" -f')
        client.run("search")
        self.assertIn("There are no packages", client.out)

        # MAKE SURE WE USE ANOTHER CLIENT, with another USER HOME PATH
        client2 = TestClient(servers=servers,
                             users={"default": [("lasote", "mypass")]})
        self.assertNotEqual(client2.base_folder, client.base_folder)
        reuse = '''from conans import ConanFile
class HelloConan(ConanFile):
    requires = "Pkg/0.1@lasote/testing"

    def build(self):
        self.run("say_hello", run_environment=True)
'''

        client2.save({"conanfile.py": reuse}, clean_first=True)
        client2.run("install .")
        client2.run("build .")
        self.assertIn("Hello Tool!", client2.out)

        if platform.system() != "Darwin":
            # This test is excluded from OSX, because of the SIP protection. CMake helper will
            # launch a subprocess with shell=True, which CLEANS the DYLD_LIBRARY_PATH. Injecting its
            # value via run_environment=True doesn't work, because it prepends its value to:
            # command = "cd [folder] && cmake [cmd]" => "DYLD_LIBRARY_PATH=[path] cd [folder] && cmake [cmd]"
            # and then only applies to the change directory "cd"
            # If CMake binary is in user folder, it is not under SIP, and it can work. For cmake installed in
            # system folders, then no possible form of "DYLD_LIBRARY_PATH=[folders] cmake" can work
            reuse = '''from conans import ConanFile, CMake, tools
class HelloConan(ConanFile):
    exports = "CMakeLists.txt"
    requires = "Pkg/0.1@lasote/testing"

    def build(self):
        with tools.run_environment(self):
            cmake = CMake(self)
            cmake.configure()
            cmake.build()
    '''
            cmake = """set(CMAKE_CXX_COMPILER_WORKS 1)
set(CMAKE_CXX_ABI_COMPILED 1)
project(MyHello CXX)
cmake_minimum_required(VERSION 2.8.12)
execute_process(COMMAND say_hello)
"""
            client2.save({
                "conanfile.py": reuse,
                "CMakeLists.txt": cmake
            },
                         clean_first=True)
            client2.run("install . -g virtualrunenv")
            client2.run("build .")
            self.assertIn("Hello Tool!", client2.out)
        else:
            client2.run("install . -g virtualrunenv")

        with tools.chdir(client2.current_folder):
            if platform.system() == "Windows":
                command = "activate_run.bat && say_hello"
            else:
                # It is not necessary to use the DYLD_LIBRARY_PATH in OSX because the activate_run.sh
                # will work perfectly. It is inside the bash, so the loader will use DYLD_LIBRARY_PATH
                # values. It also works in command line with export DYLD_LIBRARY_PATH=[path] and then
                # running, or in the same line "$ DYLD_LIBRARY_PATH=[path] say_hello"
                command = "bash -c 'source activate_run.sh && say_hello'"

            output = subprocess.check_output(command, shell=True)
            self.assertIn("Hello Tool!", str(output))
Пример #31
0
def cmd_build(app,
              conanfile_path,
              base_path,
              source_folder,
              build_folder,
              package_folder,
              install_folder,
              test=False,
              should_configure=True,
              should_build=True,
              should_install=True,
              should_test=True):
    """ Call to build() method saved on the conanfile.py
    param conanfile_path: path to a conanfile.py
    """
    logger.debug("BUILD: folder '%s'" % build_folder)
    logger.debug("BUILD: Conanfile at '%s'" % conanfile_path)

    try:
        conan_file = app.graph_manager.load_consumer_conanfile(
            conanfile_path, install_folder, deps_info_required=True, test=test)
    except NotFoundException:
        # TODO: Auto generate conanfile from requirements file
        raise ConanException("'%s' file is needed for build.\n"
                             "Create a '%s' and move manually the "
                             "requirements and generators from '%s' file" %
                             (CONANFILE, CONANFILE, CONANFILE_TXT))

    if test:
        try:
            conan_file.requires.add_ref(test)
        except ConanException:
            pass

    conan_file.should_configure = should_configure
    conan_file.should_build = should_build
    conan_file.should_install = should_install
    conan_file.should_test = should_test

    try:
        # FIXME: Conan 2.0 all these build_folder, source_folder will disappear
        #  Only base_path and conanfile_path will remain
        if hasattr(conan_file, "layout"):
            conanfile_folder = os.path.dirname(conanfile_path)
            conan_file.folders.set_base_build(conanfile_folder)
            conan_file.folders.set_base_source(conanfile_folder)
            conan_file.folders.set_base_package(conanfile_folder)
            conan_file.folders.set_base_generators(conanfile_folder)
            conan_file.folders.set_base_install(conanfile_folder)
        else:
            conan_file.folders.set_base_build(build_folder)
            conan_file.folders.set_base_source(source_folder)
            conan_file.folders.set_base_package(package_folder)
            conan_file.folders.set_base_generators(base_path)
            conan_file.folders.set_base_install(install_folder)

        mkdir(conan_file.build_folder)
        with chdir(conan_file.build_folder):
            run_build_method(conan_file,
                             app.hook_manager,
                             conanfile_path=conanfile_path)

        if test:
            with get_env_context_manager(conan_file):
                conan_file.output.highlight("Running test()")
                with conanfile_exception_formatter(str(conan_file), "test"):
                    with chdir(conan_file.build_folder):
                        conan_file.test()

    except ConanException:
        raise  # Raise but not let to reach the Exception except (not print traceback)
    except Exception:
        import traceback
        trace = traceback.format_exc().split('\n')
        raise ConanException("Unable to build it successfully\n%s" %
                             '\n'.join(trace[3:]))
Пример #32
0
    def complete_creation_reuse_test(self):
        client = TestClient(path_with_spaces=False)
        client.run("new myhello/1.0.0 --sources")
        conanfile_path = os.path.join(client.current_folder, "conanfile.py")
        replace_in_file(conanfile_path,
                        "{\"shared\": [True, False]}",
                        "{\"shared\": [True, False], \"fPIC\": [True, False]}",
                        output=client.out)
        replace_in_file(conanfile_path,
                        "\"shared=False\"",
                        "\"shared=False\", \"fPIC=True\"",
                        output=client.out)
        client.run("create . danimtb/testing")
        hellowrapper_include = """
#pragma once

void hellowrapper();
"""
        hellowrapper_impl = """
#include "hello.h"

#include "hellowrapper.h"

void hellowrapper(){
    hello();
}
"""
        makefile = """
include conanbuildinfo.mak

#----------------------------------------
#     Make variables for a sample App
#----------------------------------------

INCLUDE_DIRS = \
./include

CXX_SRCS = \
src/hellowrapper.cpp

CXX_OBJ_FILES = \
hellowrapper.o

STATIC_LIB_FILENAME = \
libhellowrapper.a

SHARED_LIB_FILENAME = \
libhellowrapper.so

CXXFLAGS += \
-fPIC

#----------------------------------------
#     Prepare flags from variables
#----------------------------------------

CFLAGS              += $(CONAN_CFLAGS)
CXXFLAGS            += $(CONAN_CXXFLAGS)
CPPFLAGS            += $(addprefix -I, $(INCLUDE_DIRS) $(CONAN_INCLUDE_DIRS))
CPPFLAGS            += $(addprefix -D, $(CONAN_DEFINES))
LDFLAGS             += $(addprefix -L, $(CONAN_LIB_DIRS))
LDLIBS              += $(addprefix -l, $(CONAN_LIBS))
SHAREDLINKFLAGS     += $(CONAN_SHAREDLINKFLAGS)

#----------------------------------------
#     Make Commands
#----------------------------------------

COMPILE_CXX_COMMAND         ?= \
	g++ -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@

CREATE_SHARED_LIB_COMMAND   ?= \
	g++ -shared $(CXX_OBJ_FILES) \
	$(CXXFLAGS) $(LDFLAGS) $(LDLIBS) $(SHAREDLINKFLAGS) \
	-o $(SHARED_LIB_FILENAME)

CREATE_STATIC_LIB_COMMAND   ?= \
	ar rcs $(STATIC_LIB_FILENAME) $(CXX_OBJ_FILES)


#----------------------------------------
#     Make Rules
#----------------------------------------

.PHONY                  :   static shared
static                  :   $(STATIC_LIB_FILENAME)
shared                  :   $(SHARED_LIB_FILENAME)

$(SHARED_LIB_FILENAME)  :   $(CXX_OBJ_FILES)
	$(CREATE_SHARED_LIB_COMMAND)

$(STATIC_LIB_FILENAME)  :   $(CXX_OBJ_FILES)
	$(CREATE_STATIC_LIB_COMMAND)

$(CXX_OBJ_FILES)        :   $(CXX_SRCS)
	$(COMPILE_CXX_COMMAND)
"""
        conanfile = """
from conans import ConanFile

class HelloWrapper(ConanFile):
    name = "hellowrapper"
    version = "1.0"
    settings = "os", "compiler", "build_type", "arch"
    requires = "myhello/1.0.0@danimtb/testing"
    generators = "make"
    exports_sources = "include/hellowrapper.h", "src/hellowrapper.cpp", "Makefile"
    options = {"shared": [True, False]}
    default_options = {"shared": False}

    def build(self):
        make_command = "make shared" if self.options.shared else "make static"
        self.run(make_command)

    def package(self):
        self.copy("*.h", dst="include", src="include")
        self.copy("*.so", dst="lib", keep_path=False)
        self.copy("*.a", dst="lib", keep_path=False)

    def package_info(self):
        self.cpp_info.libs = ["hellowrapper"]
"""
        client.save(
            {
                "include/hellowrapper.h": hellowrapper_include,
                "src/hellowrapper.cpp": hellowrapper_impl,
                "Makefile": makefile,
                "conanfile.py": conanfile
            },
            clean_first=True)
        client.run("create . danimtb/testing")
        # Test also shared
        client.run("create . danimtb/testing -o hellowrapper:shared=True")

        main = """
#include "hellowrapper.h"
int main()
{
     hellowrapper();
     return 0;
}
"""
        makefile = """
include conanbuildinfo.mak

#----------------------------------------
#     Make variables for a sample App
#----------------------------------------

CXX_SRCS = \
src/main.cpp

CXX_OBJ_FILES = \
main.o

EXE_FILENAME = \
main

CXXFLAGS += \
-fPIC

EXELINKFLAGS += \
-fPIE

#----------------------------------------
#     Prepare flags from variables
#----------------------------------------

CFLAGS              += $(CONAN_CFLAGS)
CXXFLAGS            += $(CONAN_CXXFLAGS)
CPPFLAGS            += $(addprefix -I, $(CONAN_INCLUDE_DIRS))
CPPFLAGS            += $(addprefix -D, $(CONAN_DEFINES))
LDFLAGS             += $(addprefix -L, $(CONAN_LIB_DIRS))
LDLIBS              += $(addprefix -l, $(CONAN_LIBS))
EXELINKFLAGS        += $(CONAN_EXELINKFLAGS)

#----------------------------------------
#     Make Commands
#----------------------------------------

COMPILE_CXX_COMMAND         ?= \
	g++ -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@

CREATE_EXE_COMMAND          ?= \
	g++ $(CXX_OBJ_FILES) \
	$(CXXFLAGS) $(LDFLAGS) $(LDLIBS) $(EXELINKFLAGS) \
	-o $(EXE_FILENAME)


#----------------------------------------
#     Make Rules
#----------------------------------------

.PHONY                  :   exe
exe                     :   $(EXE_FILENAME)

$(EXE_FILENAME)         :   $(CXX_OBJ_FILES)
	$(CREATE_EXE_COMMAND)

$(CXX_OBJ_FILES)        :   $(CXX_SRCS)
	$(COMPILE_CXX_COMMAND)
"""
        conanfile_txt = """
[requires]
hellowrapper/1.0@danimtb/testing

[generators]
make
"""
        client.save(
            {
                "src/main.cpp": main,
                "Makefile": makefile,
                "conanfile.txt": conanfile_txt
            },
            clean_first=True)
        with chdir(client.current_folder):
            client.run("install .")
            client.runner("make exe")
            client.runner("./main")
            self.assertIn("Hello World Release!", client.out)

            # Test it also builds with shared lib
            client.run("install . -o hellowrapper:shared=True")
            client.runner("rm main main.o")
            client.runner("make exe")
            client.runner("ldd main")
            self.assertIn("libhellowrapper.so", client.out)