def test_buildirs_working(): """ If a recipe declares cppinfo.buildirs those dirs will be exposed to be consumer to allow a cmake "include" function call after a find_package""" c = TestClient() conanfile = str( GenConanfile().with_name("my_lib").with_version("1.0").with_import( "import os").with_import("from conans import tools")) conanfile += """ def package(self): tools.save(os.path.join(self.package_folder, "my_build_dir", "my_cmake_script.cmake"), 'set(MYVAR "Like a Rolling Stone")') def package_info(self): self.cpp_info.builddirs=["my_build_dir"] """ c.save({"conanfile.py": conanfile}) c.run("create .") consumer_conanfile = GenConanfile().with_name("consumer").with_version("1.0")\ .with_cmake_build().with_require("my_lib/1.0") \ .with_settings("os", "arch", "build_type", "compiler") \ .with_exports_sources("*.txt") cmake = gen_cmakelists(find_package=["my_lib"]) cmake += """ message("CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}") include("my_cmake_script") message("MYVAR=>${MYVAR}") """ c.save({"conanfile.py": consumer_conanfile, "CMakeLists.txt": cmake}) c.run("create .") assert "MYVAR=>Like a Rolling Stone" in c.out
def test_cmake_toolchain_multiple_user_toolchain(): """ A consumer consuming two packages that declare: self.conf_info["tools.cmake.cmaketoolchain:user_toolchain"] The consumer wants to use apply both toolchains in the CMakeToolchain. There are two ways to customize the CMakeToolchain (parametrized): 1. Altering the context of the block (with_context = True) 2. Using the t.blocks["user_toolchain"].user_toolchains = [] (with_context = False) """ client = TestClient() conanfile = textwrap.dedent(""" import os from conans import ConanFile class Pkg(ConanFile): exports_sources = "*" def package(self): self.copy("*") def package_info(self): f = os.path.join(self.package_folder, "mytoolchain.cmake") self.conf_info["tools.cmake.cmaketoolchain:user_toolchain"] = f """) client.save({"conanfile.py": conanfile, "mytoolchain.cmake": 'message(STATUS "mytoolchain1.cmake !!!running!!!")'}) client.run("create . toolchain1/0.1@") client.save({"conanfile.py": conanfile, "mytoolchain.cmake": 'message(STATUS "mytoolchain2.cmake !!!running!!!")'}) client.run("create . toolchain2/0.1@") conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake, CMakeToolchain class Pkg(ConanFile): settings = "os", "compiler", "arch", "build_type" exports_sources = "CMakeLists.txt" tool_requires = "toolchain1/0.1", "toolchain2/0.1" def generate(self): # Get the toolchains from "tools.cmake.cmaketoolchain:user_toolchain" conf at the # tool_requires user_toolchains = [] for dep in self.dependencies.direct_build.values(): ut = dep.conf_info["tools.cmake.cmaketoolchain:user_toolchain"] if ut: user_toolchains.append(ut.replace('\\\\', '/')) # Modify the context of the user_toolchain block t = CMakeToolchain(self) t.blocks["user_toolchain"].values["paths"] = user_toolchains t.generate() def build(self): cmake = CMake(self) cmake.configure() """) client.save({"conanfile.py": conanfile, "CMakeLists.txt": gen_cmakelists()}, clean_first=True) client.run("create . pkg/0.1@") assert "mytoolchain1.cmake !!!running!!!" in client.out assert "mytoolchain2.cmake !!!running!!!" in client.out
def test_exports_source_without_subfolder(): """If we have some sources in the root (like the CMakeLists.txt) we don't declare folders.source""" conan_file = GenConanfile() \ .with_name("app").with_version("1.0") \ .with_settings("os", "arch", "build_type", "compiler") \ .with_exports_sources("CMakeLists.txt", "my_src/*")\ .with_cmake_build() conan_file = str(conan_file) conan_file += """ def layout(self): self.folders.build = str(self.settings.build_type) """ cmake = gen_cmakelists(appname="my_app", appsources=["my_src/main.cpp"]) app = gen_function_cpp(name="main") client = TestClient() client.save({ "conanfile.py": conan_file, "my_src/main.cpp": app, "CMakeLists.txt": cmake }) client.run("install . -if=install") client.run("build . -if=install") assert os.path.exists( os.path.join(client.current_folder, "Release", app_name)) client.run("create . ") assert "Created package revision" in client.out
def test_exports_source_with_src_subfolder(no_copy_source): """If we have the sources in a subfolder, specifying it in the self.folders.source will work both locally (conan build) or in the cache (exporting the sources)""" conan_file = GenConanfile() \ .with_name("app").with_version("1.0") \ .with_settings("os", "arch", "build_type", "compiler") \ .with_exports_sources("my_src/*")\ .with_cmake_build()\ .with_class_attribute("no_copy_source={}".format(no_copy_source)) conan_file = str(conan_file) conan_file += """ def layout(self): self.folders.source = "my_src" self.folders.build = str(self.settings.build_type) """ cmake = gen_cmakelists(appname="my_app", appsources=["main.cpp"]) app = gen_function_cpp(name="main") client = TestClient() client.save({ "conanfile.py": conan_file, "my_src/main.cpp": app, "my_src/CMakeLists.txt": cmake }) client.run("install . -if=install") client.run("build . -if=install") assert os.path.exists( os.path.join(client.current_folder, "Release", app_name)) client.run("create . ") assert "Created package revision" in client.out
def pkg_cmake_test(require_name): conanfile = textwrap.dedent("""\ import os from conans import ConanFile from conan.tools.cmake import CMake, cmake_layout class Pkg(ConanFile): settings = "os", "compiler", "arch", "build_type" generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv" def layout(self): cmake_layout(self) def build(self): cmake = CMake(self) cmake.configure() cmake.build() def test(self): cmd = os.path.join(self.cpp.build.bindirs[0], "test") self.run(cmd, env="conanrun") """) deps = [require_name] src = gen_function_cpp(name="main", includes=deps, calls=deps) cmake = gen_cmakelists(appname="test", appsources=["src/test.cpp"], find_package=deps) return { "test_package/src/test.cpp": src, "test_package/CMakeLists.txt": cmake, "test_package/conanfile.py": conanfile }
def pkg_cmake(name, version, requires=None): refs = [ConanFileReference.loads(r) for r in requires or []] pkg_name = name name = name.replace(".", "_") conanfile = textwrap.dedent("""\ import os from conans import ConanFile from conan.tools.cmake import CMake from conan.tools.layout import cmake_layout class Pkg(ConanFile): name = "{pkg_name}" version = "{version}" exports_sources = "src/*" {deps} settings = "os", "compiler", "arch", "build_type" options = {{"shared": [True, False]}} default_options = {{"shared": False}} generators = "CMakeToolchain", "CMakeDeps" def layout(self): cmake_layout(self) def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): self.copy("*.h", dst="include") self.copy("*.lib", dst="lib", keep_path=False) self.copy("*.dll", dst="bin", keep_path=False) self.copy("*.dylib*", dst="lib", keep_path=False) self.copy("*.so", dst="lib", keep_path=False) self.copy("*.a", dst="lib", keep_path=False) def package_info(self): self.cpp_info.libs = ["{name}"] """) deps = "requires = " + ", ".join('"{}"'.format(r) for r in requires) if requires else "" conanfile = conanfile.format(pkg_name=pkg_name, name=name, version=version, deps=deps) hdr = gen_function_h(name=name) deps = [r.name.replace(".", "_") for r in refs] src = gen_function_cpp(name=name, includes=deps, calls=deps) deps = [r.name for r in refs] cmake = gen_cmakelists(libname=name, libsources=["{}.cpp".format(name)], find_package=deps) return { "src/{}.h".format(name): hdr, "src/{}.cpp".format(name): src, "src/CMakeLists.txt": cmake, "conanfile.py": conanfile }
def test_cmake_toolchain_user_toolchain_from_dep(): client = TestClient() conanfile = textwrap.dedent(""" import os from conans import ConanFile class Pkg(ConanFile): exports_sources = "*" def package(self): self.copy("*") def package_info(self): f = os.path.join(self.package_folder, "mytoolchain.cmake") self.conf_info.append("tools.cmake.cmaketoolchain:user_toolchain", f) """) client.save({"conanfile.py": conanfile, "mytoolchain.cmake": 'message(STATUS "mytoolchain.cmake !!!running!!!")'}) client.run("create . toolchain/0.1@") conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake class Pkg(ConanFile): settings = "os", "compiler", "arch", "build_type" exports_sources = "CMakeLists.txt" build_requires = "toolchain/0.1" generators = "CMakeToolchain" def build(self): cmake = CMake(self) cmake.configure() """) client.save({"conanfile.py": conanfile, "CMakeLists.txt": gen_cmakelists()}, clean_first=True) client.run("create . pkg/0.1@") assert "mytoolchain.cmake !!!running!!!" in client.out
def test_m1(op_system): os_version = "os.version=12.0" if op_system == "iOS" else "" os_sdk = "" if op_system == "Macos" else "os.sdk=iphoneos" profile = textwrap.dedent(""" include(default) [settings] os={} {} {} arch=armv8 """.format(op_system, os_sdk, os_version)) client = TestClient(path_with_spaces=False) client.save({"m1": profile}, clean_first=True) client.run("new hello/0.1 --template=cmake_lib") client.run("create . --profile:build=default --profile:host=m1 -tf None") main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) custom_content = 'message("CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") \n' \ 'message("CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") \n' cmakelists = gen_cmakelists(find_package=["hello"], appname="main", appsources=["main.cpp"], custom_content=custom_content) conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake, cmake_layout class TestConan(ConanFile): requires = "hello/0.1" settings = "os", "compiler", "arch", "build_type" exports_sources = "CMakeLists.txt", "main.cpp" generators = "CMakeDeps", "CMakeToolchain" def layout(self): cmake_layout(self) def build(self): cmake = CMake(self) cmake.configure() cmake.build() """) client.save({"conanfile.py": conanfile, "CMakeLists.txt": cmakelists, "main.cpp": main, "m1": profile}, clean_first=True) client.run("install . --profile:build=default --profile:host=m1") client.run("build .") system_name = 'Darwin' if op_system == 'Macos' else 'iOS' assert "CMAKE_SYSTEM_NAME: {}".format(system_name) in client.out assert "CMAKE_SYSTEM_PROCESSOR: arm64" in client.out main_path = "./build/Release/main.app/main" if op_system == "iOS" \ else "./build/Release/main" client.run_command(main_path, assert_error=True) assert "Bad CPU type in executable" in client.out client.run_command("lipo -info {}".format(main_path)) assert "Non-fat file" in client.out assert "is architecture: arm64" in client.out
def client(): t = TestClient() cpp = gen_function_cpp(name="mydep") h = gen_function_h(name="mydep") cmake = gen_cmakelists(libname="mydep", libsources=["mydep.cpp"]) conanfile = textwrap.dedent(""" import os from conans import ConanFile from conan.tools.cmake import CMake class Conan(ConanFile): name = "mydep" version = "1.0" settings = "os", "arch", "compiler", "build_type" exports_sources = "*.cpp", "*.h", "CMakeLists.txt" generators = "CMakeToolchain" def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): self.copy("*.h", dst="include") self.copy("*.lib", dst="lib", keep_path=False) self.copy("*.dll", dst="bin", keep_path=False) self.copy("*.dylib*", dst="lib", keep_path=False) self.copy("*.so", dst="lib", keep_path=False) self.copy("*.a", dst="lib", keep_path=False) def package_info(self): self.cpp_info.set_property("cmake_find_mode", "both") self.cpp_info.set_property("cmake_file_name", "MyDep") self.cpp_info.set_property("cmake_target_name", "MyDepTarget") self.cpp_info.set_property("cmake_module_file_name", "mi_dependencia") self.cpp_info.set_property("cmake_module_target_name", "mi_dependencia_target") self.cpp_info.set_property("cmake_module_target_namespace", "mi_dependencia_namespace") self.cpp_info.components["crispin"].libs = ["mydep"] self.cpp_info.components["crispin"].set_property("cmake_target_name", "MyCrispinTarget") self.cpp_info.components["crispin"].set_property("cmake_module_target_name", "mi_crispin_target") """) t.save({"conanfile.py": conanfile, "mydep.cpp": cpp, "mydep.h": h, "CMakeLists.txt": cmake}) t.run("create .") return t
def test_transitive_multi(client): # TODO: Make a full linking example, with correct header transitivity # Save conanfile and example conanfile = textwrap.dedent(""" [requires] libb/0.1 [generators] CMakeDeps CMakeToolchain """) example_cpp = gen_function_cpp(name="main", includes=["libb", "liba"], preprocessor=["MYVARliba", "MYVARlibb"]) client.save({"conanfile.txt": conanfile, "CMakeLists.txt": gen_cmakelists(appname="example", appsources=["example.cpp"], find_package=["libb"]), "example.cpp": example_cpp}, clean_first=True) with client.chdir("build"): for bt in ("Debug", "Release"): client.run("install .. user/channel -s build_type={}".format(bt)) # Test that we are using find_dependency with the NO_MODULE option # to skip finding first possible FindBye somewhere assert "find_dependency(${_DEPENDENCY} REQUIRED NO_MODULE)" \ in client.load("libb-config.cmake") if platform.system() == "Windows": client.run_command('cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake') client.run_command('cmake --build . --config Debug') client.run_command('cmake --build . --config Release') client.run_command('Debug\\example.exe') assert "main: Debug!" in client.out assert "MYVARliba: Debug" in client.out assert "MYVARlibb: Debug" in client.out client.run_command('Release\\example.exe') assert "main: Release!" in client.out assert "MYVARliba: Release" in client.out assert "MYVARlibb: Release" in client.out else: # The TOOLCHAIN IS MESSING WITH THE BUILD TYPE and then ignores the -D so I remove it replace_in_file(os.path.join(client.current_folder, "conan_toolchain.cmake"), "CMAKE_BUILD_TYPE", "DONT_MESS_WITH_BUILD_TYPE") for bt in ("Debug", "Release"): client.run_command('cmake .. -DCMAKE_BUILD_TYPE={} ' '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake'.format(bt)) client.run_command('cmake --build . --clean-first') client.run_command('./example') assert "main: {}!".format(bt) in client.out assert "MYVARliba: {}".format(bt) in client.out assert "MYVARlibb: {}".format(bt) in client.out
def test_zip_download_with_subfolder_new_tools(no_copy_source): """If we have a zip with the sources in a subfolder, specifying it in the self.folders.source will unzip in the base and will work both locally (conan build) or in the cache (exporting the sources)""" tmp = TestClient() # Used only to save some files, sorry for the lazyness cmake = gen_cmakelists(appname="my_app", appsources=["main.cpp"]) app = gen_function_cpp(name="main") tmp.save({ "subfolder/main.cpp": app, "subfolder/CMakeLists.txt": cmake, "ignored_subfolder/ignored.txt": "" }) zippath = os.path.join(tmp.current_folder, "my_sources.zip") zipdir(tmp.current_folder, zippath) conan_file = GenConanfile() \ .with_import("import os") \ .with_import("from conan.tools.files import get") \ .with_import("from conan.tools.cmake import CMake") \ .with_name("app").with_version("1.0") \ .with_settings("os", "arch", "build_type", "compiler") \ .with_generator("CMakeToolchain") \ .with_class_attribute("no_copy_source={}".format(no_copy_source)) conan_file = str(conan_file) conan_file += """ def source(self): get(self, "http://fake_url/my_sources.zip") def layout(self): self.folders.source = "subfolder" def build(self): assert os.path.exists(os.path.join(self.source_folder, "CMakeLists.txt")) assert "subfolder" in self.source_folder assert os.path.exists(os.path.join(self.source_folder, "..", "ignored_subfolder", "ignored.txt")) cmake = CMake(self) cmake.configure() cmake.build() """ client = TestClient() client.save({"conanfile.py": conan_file}) with mock.patch("conan.tools.files.files.download") as mock_download: def download_zip(*args, **kwargs): copy(zippath, os.getcwd()) mock_download.side_effect = download_zip client.run("create . ")
def test_m1(op_system): os_version = "os.version=12.0" if op_system == "iOS" else "" profile = textwrap.dedent(""" include(default) [settings] os={} {} arch=armv8 """.format(op_system, os_version)) client = TestClient(path_with_spaces=False) client.save({"m1": profile}, clean_first=True) client.run("new hello/0.1 --template=v2_cmake") client.run("create . --profile:build=default --profile:host=m1 -tf None") main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) cmakelists = gen_cmakelists(find_package=["hello"], appname="main", appsources=["main.cpp"]) conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake class TestConan(ConanFile): requires = "hello/0.1" settings = "os", "compiler", "arch", "build_type" exports_sources = "CMakeLists.txt", "main.cpp" generators = "CMakeDeps", "CMakeToolchain" def build(self): cmake = CMake(self) cmake.configure() cmake.build() """) client.save( { "conanfile.py": conanfile, "CMakeLists.txt": cmakelists, "main.cpp": main, "m1": profile }, clean_first=True) client.run("install . --profile:build=default --profile:host=m1") client.run("build .") main_path = "./main.app/main" if op_system == "iOS" else "./main" client.run_command(main_path, assert_error=True) assert "Bad CPU type in executable" in client.out client.run_command("lipo -info {}".format(main_path)) assert "Non-fat file" in client.out assert "is architecture: arm64" in client.out
def pkg_cmake_app(name, version, requires=None): refs = [ConanFileReference.loads(r) for r in requires or []] pkg_name = name name = name.replace(".", "_") conanfile = textwrap.dedent("""\ import os from conans import ConanFile from conan.tools.cmake import CMake from conan.tools.layout import cmake_layout class Pkg(ConanFile): name = "{pkg_name}" version = "{version}" exports_sources = "src/*" {deps} settings = "os", "compiler", "arch", "build_type" generators = "CMakeToolchain", "CMakeDeps" def layout(self): cmake_layout(self) def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): self.copy("*/app.exe", dst="bin", keep_path=False) self.copy("*app", dst="bin", keep_path=False) """) deps = "requires = " + ", ".join('"{}"'.format(r) for r in requires) if requires else "" conanfile = conanfile.format(pkg_name=pkg_name, name=name, version=version, deps=deps) deps = [r.name.replace(".", "_") for r in refs] src = gen_function_cpp(name="main", includes=deps, calls=deps) deps = [r.name for r in refs] cmake = gen_cmakelists(appname=name, appsources=["{}.cpp".format(name)], find_package=deps) return { "src/{}.cpp".format(name): src, "src/CMakeLists.txt": cmake, "conanfile.py": conanfile }
def setUp(self): self.servers = {"default": TestServer()} client = TestClient(servers=self.servers, users={"default": [("lasote", "mypass")]}) cmake = gen_cmakelists(libname="hello", libsources=["hello.cpp"], libtype="SHARED", appname="say_hello", appsources=["main.cpp"]) hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", msg="Hello Tool!", includes=["hello"]) main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) conanfile = textwrap.dedent(""" from conans import ConanFile, CMake class Pkg(ConanFile): settings = "os", "compiler", "build_type", "arch" 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)
def client_weird_lib_name(): c = TestClient() conanfile = textwrap.dedent(""" import os, platform from conans import ConanFile from conan.tools.cmake import CMake from conan.tools.layout import cmake_layout class Pkg(ConanFile): exports_sources = "CMakeLists.txt", "src/*" settings = "os", "compiler", "arch", "build_type" generators = "CMakeToolchain", "CMakeDeps" def layout(self): cmake_layout(self) def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): self.copy("*.h", dst="include", src="src") self.copy("*.lib", dst="lib", keep_path=False) self.copy("*.a", dst="lib", keep_path=False) ext = "a" if platform.system() != "Windows" else "lib" prefix = "lib" if platform.system() != "Windows" else "" os.chdir(os.path.join(self.package_folder, "lib")) os.rename("{}hello_0.1.{}".format(prefix, ext), "{}[email protected].{}".format(prefix, ext)) def package_info(self): self.cpp_info.libs = ["[email protected]"] """) hdr = gen_function_h(name="hello") src = gen_function_cpp(name="hello") cmake = gen_cmakelists(libname="hello_0.1", libsources=["src/hello.cpp"]) c.save({ "src/hello.h": hdr, "src/hello.cpp": src, "CMakeLists.txt": cmake, "conanfile.py": conanfile }) c.run("create . hello/0.1@") return c
def client(): c = TestClient() save(c.cache.new_config_path, "tools.env.virtualenv:auto_use=True") clang_profile = textwrap.dedent(""" [settings] os=Windows arch=x86_64 build_type=Release compiler=clang compiler.version=12 [buildenv] CC=clang CXX=clang++ RC=clang """) conanfile = textwrap.dedent(""" import os from conans import ConanFile from conan.tools.cmake import CMake from conan.tools.layout import cmake_layout class Pkg(ConanFile): settings = "os", "compiler", "build_type", "arch" exports_sources = "*" generators = "CMakeToolchain" def layout(self): cmake_layout(self) def build(self): cmake = CMake(self) cmake.configure() cmake.build() cmd = os.path.join(self.cpp.build.bindirs[0], "my_app") self.run(cmd, env=["conanrunenv"]) """) c.save({ "conanfile.py": conanfile, "clang": clang_profile, "src/CMakeLists.txt": gen_cmakelists(appname="my_app", appsources=["main.cpp"]), "src/main.cpp": gen_function_cpp(name="main") }) return c
def client(): conanfile = textwrap.dedent(""" import os from conans import ConanFile from conan.tools.cmake import CMake, CMakeToolchain class Library(ConanFile): name = "hello" version = "1.0" settings = 'os', 'arch', 'compiler', 'build_type' exports_sources = 'hello.h', '*.cpp', 'CMakeLists.txt' options = {'shared': [True, False]} default_options = {'shared': False} def generate(self): tc = CMakeToolchain(self, generator="Ninja") tc.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build() self.run(os.sep.join([".", "myapp"])) def package(self): cmake = CMake(self) cmake.install() """) test_client = TestClient(path_with_spaces=False) test_client.save({ 'conanfile.py': conanfile, "CMakeLists.txt": gen_cmakelists(libsources=["hello.cpp"], appsources=["main.cpp"], install=True), "hello.h": gen_function_h(name="hello"), "hello.cpp": gen_function_cpp(name="hello", includes=["hello"]), "main.cpp": gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) }) return test_client
def test_zlib_not_included(client): main = gen_function_cpp(name="main", include="doxygen.h") cmake = gen_cmakelists(find_package=["doxygen"], appsources=["main.cpp"], appname="main") conanfile_consumer = textwrap.dedent(''' from conans import ConanFile from conan.tools.cmake import CMakeDeps class Consumer(ConanFile): settings = "build_type", "os", "arch", "compiler" build_requires = ["doxygen/1.0"] generators = "CMakeToolchain" def generate(self): d = CMakeDeps(self) d.build_context_activated = ["doxygen"] d.generate() ''') client.save( { "main.cpp": main, "CMakeLists.txt": cmake, "conanfile.py": conanfile_consumer }, clean_first=True) client.run("install . -pr:h=default -pr:b=default") # The compilation works, so it finds the doxygen without transitive failures client.run_command( "cmake . -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release" ) # Assert there is no zlib target assert "Target declared 'zlib::zlib'" not in client.out # Of course we find the doxygen-config.cmake assert os.path.exists( os.path.join(client.current_folder, "doxygen-config.cmake")) # The -config files for zlib are not there assert not os.path.exists( os.path.join(client.current_folder, "zlib-config.cmake"))
def test_msvc_vs_versiontoolset(version, vs_version): settings = { "compiler": "msvc", "compiler.version": version, "compiler.runtime": "static", "compiler.cppstd": "14", "arch": "x86_64", "build_type": "Release", } client = TestClient() save(client.cache.new_config_path, "tools.microsoft.msbuild:vs_version={}".format(vs_version)) conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake class App(ConanFile): settings = "os", "arch", "compiler", "build_type" generators = "CMakeToolchain" options = {"shared": [True, False], "fPIC": [True, False]} default_options = {"shared": False, "fPIC": True} exports_sources = "*" def build(self): cmake = CMake(self) cmake.configure() cmake.build() self.run("Release\\myapp.exe") """) cmakelists = gen_cmakelists(appname="myapp", appsources=["app.cpp"]) main = gen_function_cpp(name="main") client.save({ "conanfile.py": conanfile, "CMakeLists.txt": cmakelists, "app.cpp": main, }) settings = " ".join('-s %s="%s"' % (k, v) for k, v in settings.items() if v) client.run("create . app/1.0@ {}".format(settings)) assert '-G "Visual Studio 15 2017"' in client.out check_exe_run(client.out, "main", "msvc", version, "Release", "x86_64", "14")
def test_scm_with_source_layout(): """If we have the sources in git repository""" conan_file = GenConanfile() \ .with_name("app").with_version("1.0") \ .with_settings("os", "arch", "build_type", "compiler") \ .with_scm({"type": "git", "revision": "auto", "url": "auto"})\ .with_cmake_build() conan_file = str(conan_file) conan_file += """ def layout(self): self.folders.source = "my_src" self.folders.build = "build_{}".format(self.settings.build_type) """ cmake = gen_cmakelists(appname="my_app", appsources=["main.cpp"]) app = gen_function_cpp(name="main") remote_path, _ = create_local_git_repo({"foo": "var"}, branch="my_release") client = TestClient() client.save({ "conanfile.py": conan_file, "my_src/main.cpp": app, "my_src/CMakeLists.txt": cmake, ".gitignore": "build_*\n" }) client.init_git_repo() client.run_command('git remote add origin "%s"' % remote_path.replace("\\", "/")) client.run_command('git push origin master') client.run("install . -if=install") client.run("build . -if=install") assert os.path.exists( os.path.join(client.current_folder, "build_Release", app_name)) client.run("create . ") assert "Created package revision" in client.out
def test_transitive_multi(client): # TODO: Make a full linking example, with correct header transitivity # Save conanfile and example conanfile = textwrap.dedent(""" [requires] libb/0.1 [generators] CMakeDeps """) example_cpp = gen_function_cpp(name="main", includes=["libb", "liba"], preprocessor=["MYVARliba", "MYVARlibb"]) client.save( { "conanfile.txt": conanfile, "CMakeLists.txt": gen_cmakelists(appname="example", appsources=["example.cpp"], find_package=["libb"]), "example.cpp": example_cpp }, clean_first=True) with client.chdir("build"): for bt in ("Debug", "Release"): client.run("install .. user/channel -s build_type={}".format(bt)) # Test that we are using find_dependency with the NO_MODULE option # to skip finding first possible FindBye somewhere assert "find_dependency(liba REQUIRED NO_MODULE)" in client.load( "libb-config.cmake") if platform.system() == "Windows": client.run_command('cmake .. -G "Visual Studio 15 Win64" ' '-DCMAKE_PREFIX_PATH="{}"'.format( client.current_folder)) client.run_command('cmake --build . --config Debug') client.run_command('cmake --build . --config Release') client.run_command('Debug\\example.exe') assert "main: Debug!" in client.out assert "MYVARliba: Debug" in client.out assert "MYVARlibb: Debug" in client.out client.run_command('Release\\example.exe') assert "main: Release!" in client.out assert "MYVARliba: Release" in client.out assert "MYVARlibb: Release" in client.out else: for bt in ("Debug", "Release"): client.run_command('cmake .. -DCMAKE_BUILD_TYPE={} ' '-DCMAKE_PREFIX_PATH="{}"'.format( bt, client.current_folder)) client.run_command('cmake --build . --clean-first') client.run_command('./example') assert "main: {}!".format(bt) in client.out assert "MYVARliba: {}".format(bt) in client.out assert "MYVARlibb: {}".format(bt) in client.out
def client(): c = TestClient() save(c.cache.new_config_path, "tools.env.virtualenv:auto_use=True") clang_profile = textwrap.dedent(""" [settings] arch=armv7 build_type=RelWithDebInfo compiler=clang compiler.libcxx=libstdc++11 compiler.version=12 os=VxWorks os.version=7 [buildenv] CC=clang CXX=clang++ """) conanfile = textwrap.dedent(""" import os from conans import ConanFile from conan.tools.cmake import CMake, cmake_layout class Pkg(ConanFile): settings = "os", "compiler", "build_type", "arch" exports_sources = "*" generators = "CMakeToolchain" def layout(self): cmake_layout(self) def build(self): cmake = CMake(self) cmake.configure() cmake.build() cmd = os.path.join(self.cpp.build.bindirs[0], "my_app") self.run('readelf -s ' + cmd, env=["conanrunenv"]) """) toolchain_file = textwrap.dedent(""" set(vsb "/vsb") # location of VxWorks Source Build (vsb) set(CMAKE_LINKER "ldarm") set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" CACHE STRING "Workaround for clang, use GNU linker not clang/lld" FORCE) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${vsb}/usr/h ${vsb}/usr/h/public ${vsb}/h/config ${vsb}/share/h/public ) add_compile_definitions( ARMEL CPU=_VX_ARMARCH7 _REENTRANT INET _VSB_CONFIG_FILE="${vsb}/h/config/vsbConfig.h" ) add_compile_options( -fno-builtin -pipe ) add_compile_definitions( _C99 _HAS_C9X _VX_CPU=_VX_ARMARCH7 __RTP__ TOOL=llvm TOOL_FAMILY=llvm CPU_FAMILY=ARM __ELF__ __vxworks __VXWORKS__ _USE_INIT_ARRAY ) add_compile_options( -fasm -fomit-frame-pointer -ffunction-sections -fdata-sections --target=arm-eabi -mabi=aapcs -mcpu=cortex-a9 -mfloat-abi=hard -mfpu=vfpv3 -mlittle-endian -mno-implicit-float -nostdinc++ -nostdlibinc -march=armv7 -gdwarf-3 -mllvm -two-entry-phi-node-folding-threshold=2 ) add_link_options( --target2=rel ) link_directories( ${vsb}/usr/lib/common ) set(CMAKE_CXX_STANDARD 14) set(CMAKE_C_STANDARD_LIBRARIES "--start-group --as-needed -lllvm -lc -lc_internal --end-group") set(CMAKE_CXX_STANDARD_LIBRARIES "-lnet --start-group --as-needed -lc -lc_internal -lllvm -lcplusplus -lllvmcplus -ldl --end-group") set(CMAKE_EXE_LINKER_FLAGS "--defsym __wrs_rtp_base=0x80000000 -u __wr_need_frame_add -u __tls__ -T${vsb}/usr/ldscripts/rtp.ld -static -EL ${vsb}/usr/lib/common/crt0.o" CACHE STRING "" FORCE) """) c.save({ "conanfile.py": conanfile, "clang": clang_profile, "toolchain-vxworks.cmake": toolchain_file, "CMakeLists.txt": gen_cmakelists(appname="my_app", appsources=["src/main.cpp"]), "src/main.cpp": gen_function_cpp(name="main") }) return c
def test_file_api(): """ simple library providing 3 targets: - decoder - encoder - transcoder (requires decoder and encoder) generates the following targets: - triunfo::decoder - triunfo::encoder - triunfo::transcoder (depends on triunfo::decoder and triunfo::encoder) consumer uses find_package(triunfo COMPONENTS <component>) """ client = TestClient() conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake, CMakeFileAPI from conan.tools.files import CppPackage class Triunfo(ConanFile): name = "triunfo" version = "1.0" settings = "os", "compiler", "arch", "build_type" exports_sources = "*CMakeLists.txt", "*.cpp", "*.h" generators = "CMakeToolchain" def build(self): file_api = CMakeFileAPI(self) file_api.query(CMakeFileAPI.CODEMODELV2) cmake = CMake(self) cmake.configure() reply = file_api.reply(CMakeFileAPI.CODEMODELV2) package = reply.to_conan_package() package.save() cmake.build() def package(self): cmake = CMake(self) cmake.install() self.copy(CppPackage.DEFAULT_FILENAME) def package_info(self): cpp_package = CppPackage.load(CppPackage.DEFAULT_FILENAME) cpp_package.package_info(self) """) decoder_cpp = gen_function_cpp(name="decoder", includes=["decoder"]) encoder_cpp = gen_function_cpp(name="encoder", includes=["encoder"]) transcoder_cpp = gen_function_cpp( name="transcoder", calls=["decoder", "encoder"], includes=["transcoder", "../decoder/decoder", "../encoder/encoder"]) decoder_h = gen_function_h(name="decoder") encoder_h = gen_function_h(name="encoder") transcoder_h = gen_function_h(name="transcoder") decoder_cmake = gen_cmakelists(libname="decoder", libsources=["decoder.cpp"], install=True, public_header="decoder.h") encoder_cmake = gen_cmakelists(libname="encoder", libsources=["encoder.cpp"], install=True, public_header="encoder.h") transcoder_cmake = gen_cmakelists(libname="transcoder", libsources=["transcoder.cpp"], install=True, public_header="transcoder.h", deps=["decoder", "encoder"]) common_cmake = textwrap.dedent(""" cmake_minimum_required(VERSION 2.8) project(triunfo) add_subdirectory(decoder) add_subdirectory(encoder) add_subdirectory(transcoder) """) client.save({ "conanfile.py": conanfile, os.path.join("decoder", "decoder.cpp"): decoder_cpp, os.path.join("encoder", "encoder.cpp"): encoder_cpp, os.path.join("transcoder", "transcoder.cpp"): transcoder_cpp, os.path.join("decoder", "decoder.h"): decoder_h, os.path.join("encoder", "encoder.h"): encoder_h, os.path.join("transcoder", "transcoder.h"): transcoder_h, os.path.join("decoder", "CMakeLists.txt"): decoder_cmake, os.path.join("encoder", "CMakeLists.txt"): encoder_cmake, os.path.join("transcoder", "CMakeLists.txt"): transcoder_cmake, "CMakeLists.txt": common_cmake, }) client.run("create .") conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake, CMakeFileAPI from conan.tools.files import CppPackage class Elogio(ConanFile): name = "elogio" version = "1.0" requires = "triunfo/1.0" settings = "os", "compiler", "arch", "build_type" exports_sources = "*CMakeLists.txt", "*.cpp", "*.h" generators = "CMakeDeps", "CMakeToolchain" def build(self): file_api = CMakeFileAPI(self) file_api.query(CMakeFileAPI.CODEMODELV2) cmake = CMake(self) cmake.configure() reply = file_api.reply(CMakeFileAPI.CODEMODELV2) package = reply.to_conan_package() package.save() cmake.build() """) use_decoder_cpp = gen_function_cpp(name="main", includes=["decoder"], calls=["decoder"]) use_encoder_cpp = gen_function_cpp(name="main", includes=["encoder"], calls=["encoder"]) use_transcoder_cpp = gen_function_cpp(name="main", includes=["transcoder"], calls=["transcoder"]) use_decoder_cmake = gen_cmakelists(appname="use_decoder", appsources=["use_decoder.cpp"], find_package={"triunfo": "decoder"}) use_encoder_cmake = gen_cmakelists(appname="use_encoder", appsources=["use_encoder.cpp"], find_package={"triunfo": "encoder"}) use_transcoder_cmake = gen_cmakelists( appname="use_transcoder", appsources=["use_transcoder.cpp"], find_package={"triunfo": "transcoder"}) common_cmake = textwrap.dedent(""" cmake_minimum_required(VERSION 2.8) project(elogio) add_subdirectory(use_decoder) add_subdirectory(use_encoder) add_subdirectory(use_transcoder) """) client.save( { "conanfile.py": conanfile, os.path.join("use_decoder", "use_decoder.cpp"): use_decoder_cpp, os.path.join("use_encoder", "use_encoder.cpp"): use_encoder_cpp, os.path.join("use_transcoder", "use_transcoder.cpp"): use_transcoder_cpp, os.path.join("use_decoder", "CMakeLists.txt"): use_decoder_cmake, os.path.join("use_encoder", "CMakeLists.txt"): use_encoder_cmake, os.path.join("use_transcoder", "CMakeLists.txt"): use_transcoder_cmake, "CMakeLists.txt": common_cmake, }, clean_first=True) client.run("install .") client.run("build .")