def test_install(self): hello_cpp = gen_function_cpp(name="hello") hello_h = gen_function_h(name="hello") test_package_cpp = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) self.t.save({ "conanfile.py": self._conanfile_py, "meson.build": self._meson_build, "hello.cpp": hello_cpp, "hello.h": hello_h, os.path.join("test_package", "conanfile.py"): self._test_package_conanfile_py, os.path.join("test_package", "CMakeLists.txt"): self._test_package_cmake_lists, os.path.join("test_package", "test_package.cpp"): test_package_cpp }) self.t.run("create . hello/0.1@ %s" % self._settings_str) self._check_binary()
def test_build(self): hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp( name="hello", preprocessor=["TEST_DEFINITION1", "TEST_DEFINITION2"]) app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) self.t.save({ "conanfile.py": self._conanfile_py, "meson.build": self._meson_build, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": app }) self.t.run("install . %s" % self._settings_str) content = self.t.load("conan_meson_native.ini") self.assertIn("[built-in options]", content) self.assertIn("buildtype = 'release'", content) self.t.run("build .") self.t.run_command(os.path.join("build", "demo")) self.assertIn("hello: Release!", self.t.out) self.assertIn("TEST_DEFINITION1: TestPpdValue1", self.t.out) self.assertIn("TEST_DEFINITION2: TestPpdValue2", self.t.out) self._check_binary()
def _build(self, settings): self.t = TestClient() settings_str = " ".join('-s %s="%s"' % (k, v) for k, v in settings.items() if v) hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", preprocessor=["STRING_DEFINITION"]) app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) self.t.save({"conanfile.py": self._conanfile_py, "meson.build": self._meson_build, "meson_options.txt": self._meson_options_txt, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": app}) self.t.run("install . %s" % settings_str) content = self.t.load("conan_meson_native.ini") self.assertIn("[project options]", content) self.assertIn("STRING_DEFINITION = 'Text'", content) self.assertIn("TRUE_DEFINITION = true", content) self.assertIn("FALSE_DEFINITION = false", content) self.assertIn("INT_DEFINITION = 42", content) self.assertIn("ARRAY_DEFINITION = ['Text1', 'Text2']", content) self.assertIn("[built-in options]", content) self.assertIn("buildtype = 'release'", content) self.t.run("build .") self.t.run_command(os.path.join("build", "demo")) self.assertIn("hello: Release!", self.t.out) self.assertIn("STRING_DEFINITION: Text", self.t.out)
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_catalyst(self, arch): profile = textwrap.dedent(""" include(default) [settings] os = Macos os.version = 12.0 os.sdk = macosx os.subsystem = catalyst os.subsystem.ios_version = 13.1 arch = {arch} """).format(arch=arch) self.t = TestClient() hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello") main_cpp = textwrap.dedent(""" #include "hello.h" #include <TargetConditionals.h> #include <iostream> int main() { #if TARGET_OS_MACCATALYST std::cout << "running catalyst " << __IPHONE_OS_VERSION_MIN_REQUIRED << std::endl; #else #error "not building for Apple Catalyst" #endif } """) self.t.save({ "Makefile": self.makefile, "hello.h": hello_h, "hello.cpp": hello_cpp, "app.cpp": main_cpp, "conanfile.py": self.conanfile_py, "profile": profile }) self.t.run("install . --profile:host=profile") self.t.run("build .") libhello = os.path.join(self.t.current_folder, "libhello.a") app = os.path.join(self.t.current_folder, "app") self.assertTrue(os.path.isfile(libhello)) self.assertTrue(os.path.isfile(app)) expected_arch = to_apple_arch(arch) self.t.run_command('lipo -info "%s"' % libhello) self.assertIn("architecture: %s" % expected_arch, self.t.out) self.t.run_command('lipo -info "%s"' % app) self.assertIn("architecture: %s" % expected_arch, self.t.out) if arch == "x86_64": self.t.run_command('"%s"' % app) self.assertIn("running catalyst 130100", self.t.out)
def test_apple_meson_toolchain_cross_compiling(arch, os_, os_version, sdk): profile = textwrap.dedent(""" include(default) [settings] os = {os} os.version = {os_version} os.sdk = {os_sdk} arch = {arch} compiler = apple-clang compiler.version = 12.0 compiler.libcxx = libc++ [conf] tools.apple:sdk_path={sdk_path} """) xcrun = XCRun(None, sdk) sdk_path = xcrun.sdk_path hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", preprocessor=["STRING_DEFINITION"]) app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) profile = profile.format(os=os_, os_version=os_version, os_sdk=sdk, arch=arch, sdk_path=sdk_path) t = TestClient() t.save({ "conanfile.py": _conanfile_py, "meson.build": _meson_build, "meson_options.txt": _meson_options_txt, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": app, "profile_host": profile }) t.run("install . --profile:build=default --profile:host=profile_host") t.run("build .") libhello = os.path.join(t.current_folder, "build", "libhello.a") assert os.path.isfile(libhello) is True demo = os.path.join(t.current_folder, "build", "demo") assert os.path.isfile(demo) is True lipo = xcrun.find('lipo') t.run_command('"%s" -info "%s"' % (lipo, libhello)) assert "architecture: %s" % to_apple_arch(arch) in t.out t.run_command('"%s" -info "%s"' % (lipo, demo)) assert "architecture: %s" % to_apple_arch(arch) in t.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_cpp_info_link_objects(): client = TestClient() obj_ext = "obj" if platform.system() == "Windows" else "o" cpp_info = {"objects": [os.path.join("lib", "myobject.{}".format(obj_ext))]} object_cpp = gen_function_cpp(name="myobject") object_h = gen_function_h(name="myobject") cmakelists = textwrap.dedent(""" cmake_minimum_required(VERSION 3.15) project(MyObject) file(GLOB HEADERS *.h) add_library(myobject OBJECT myobject.cpp) if( WIN32 ) set(OBJ_PATH "myobject.dir/Release/myobject${CMAKE_C_OUTPUT_EXTENSION}") else() set(OBJ_PATH "CMakeFiles/myobject.dir/myobject.cpp${CMAKE_C_OUTPUT_EXTENSION}") endif() install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OBJ_PATH} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib RENAME myobject${CMAKE_C_OUTPUT_EXTENSION}) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include) """) test_package_cpp = gen_function_cpp(name="main", includes=["myobject"], calls=["myobject"]) test_package_cmakelists = textwrap.dedent(""" cmake_minimum_required(VERSION 3.15) project(example) find_package(myobject REQUIRED) add_executable(example example.cpp) target_link_libraries(example myobject::myobject) """) client.save({"CMakeLists.txt": cmakelists, "conanfile.py": GenConanfile("myobject", "1.0").with_package_info(cpp_info=cpp_info, env_info={}) .with_exports_sources("*") .with_cmake_build() .with_package("cmake = CMake(self)", "cmake.install()"), "myobject.cpp": object_cpp, "myobject.h": object_h, "test_package/conanfile.py": GenConanfile().with_cmake_build() .with_import("import os") .with_test('path = "{}".format(self.settings.build_type) ' 'if self.settings.os == "Windows" else "."') .with_test('self.run("{}{}example".format(path, os.sep))'), "test_package/example.cpp": test_package_cpp, "test_package/CMakeLists.txt": test_package_cmakelists}) client.run("create . -s build_type=Release") assert "myobject: Release!" in client.out
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 test_android_meson_toolchain_cross_compiling(self, arch, expected_arch, expected_class, expected_machine): self.arch = arch hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", preprocessor=["STRING_DEFINITION"]) app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) self.t = TestClient() self.t.save({ "conanfile.py": _conanfile_py, "meson.build": _meson_build, "meson_options.txt": _meson_options_txt, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": app, "profile_host": self.profile() }) self.t.run( "install . --profile:build=default --profile:host=profile_host") self.t.run("build .") libhello = os.path.join(self.t.current_folder, "build", "libhello.a") self.assertTrue(os.path.isfile(libhello)) demo = os.path.join(self.t.current_folder, "build", "demo") self.assertTrue(os.path.isfile(demo)) readelf = self._tool('readelf') objdump = self._tool('objdump') self.t.run_command('"%s" -f "%s"' % (objdump, libhello)) self.assertIn("architecture: %s" % expected_arch, self.t.out) self.t.run_command('"%s" -h "%s"' % (readelf, demo)) self.assertIn("Class: %s" % expected_class, self.t.out) self.assertIn("OS/ABI: UNIX - System V", self.t.out) self.assertIn( "Machine: %s" % expected_machine, self.t.out)
def test_android_meson_toolchain_cross_compiling(arch, expected_arch): profile_host = textwrap.dedent(""" include(default) [settings] os = Android os.api_level = 21 arch = {arch} [conf] tools.android:ndk_path={ndk_path} """) hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", preprocessor=["STRING_DEFINITION"]) app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) profile_host = profile_host.format( arch=arch, ndk_path=os.getenv("TEST_CONAN_ANDROID_NDK")) client = TestClient() client.save({ "conanfile.py": _conanfile_py, "meson.build": _meson_build, "meson_options.txt": _meson_options_txt, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": app, "profile_host": profile_host }) client.run("install . --profile:build=default --profile:host=profile_host") client.run("build .") content = client.load(os.path.join("conan_meson_cross.ini")) assert "needs_exe_wrapper = true" in content assert "Target machine cpu family: {}".format( expected_arch if expected_arch != "i386" else "x86") in client.out assert "Target machine cpu: {}".format(arch) in client.out libhello_name = "libhello.a" if platform.system( ) != "Windows" else "libhello.lib" libhello = os.path.join(client.current_folder, "build", libhello_name) demo = os.path.join(client.current_folder, "build", "demo") assert os.path.isfile(libhello) assert os.path.isfile(demo) # Check binaries architecture if platform.system() == "Darwin": client.run_command('objdump -f "%s"' % libhello) assert "architecture: %s" % expected_arch in 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(): 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_meson_toolchain(self, arch, os_, os_version, sdk): self.xcrun = XCRun(None, sdk) self.arch = arch self.os = os_ self.os_version = os_version hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", preprocessor=["STRING_DEFINITION"]) app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) self.t = TestClient() self.t.save({ "conanfile.py": self._conanfile_py, "meson.build": self._meson_build, "meson_options.txt": self._meson_options_txt, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": app, "profile_host": self.profile() }) self.t.run( "install . --profile:build=default --profile:host=profile_host") self.t.run("build .") libhello = os.path.join(self.t.current_folder, "build", "libhello.a") self.assertTrue(os.path.isfile(libhello)) demo = os.path.join(self.t.current_folder, "build", "demo") self.assertTrue(os.path.isfile(demo)) lipo = self.xcrun.find('lipo') self.t.run_command('"%s" -info "%s"' % (lipo, libhello)) self.assertIn("architecture: %s" % to_apple_arch(self.arch), self.t.out) self.t.run_command('"%s" -info "%s"' % (lipo, demo)) self.assertIn("architecture: %s" % to_apple_arch(self.arch), self.t.out)
def test_makefile_arch(self, arch, os_, os_version): self.arch = arch self.os = os_ self.os_version = os_version profile = textwrap.dedent(""" include(default) [settings] os = {os} os.version = {os_version} arch = {arch} """).format(os=self.os, arch=self.arch, os_version=self.os_version) self.t = TestClient() hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello") main_cpp = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) self.t.save({ "Makefile": self.makefile, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": main_cpp, "conanfile.py": self.conanfile_py, "profile": profile }) self.t.run("install . --profile:host=profile") self.t.run("build .") libhello = os.path.join(self.t.current_folder, "libhello.a") app = os.path.join(self.t.current_folder, "app") self.assertTrue(os.path.isfile(libhello)) self.assertTrue(os.path.isfile(app)) expected_arch = to_apple_arch(self.arch) self.t.run_command('lipo -info "%s"' % libhello) self.assertIn("architecture: %s" % expected_arch, self.t.out) self.t.run_command('lipo -info "%s"' % app) self.assertIn("architecture: %s" % expected_arch, self.t.out)
def test_build(self): hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", preprocessor=["STRING_DEFINITION"]) app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) self.t.save({ "conanfile.py": self._conanfile_py, "meson.build": self._meson_build, "meson_options.txt": self._meson_options_txt, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": app }) self.t.run("install . %s" % self._settings_str) content = self.t.load( os.path.join("build", "gen_folder", "conan_meson_native.ini")) self.assertIn("[project options]", content) self.assertIn("STRING_DEFINITION = 'Text'", content) self.assertIn("TRUE_DEFINITION = true", content) self.assertIn("FALSE_DEFINITION = false", content) self.assertIn("INT_DEFINITION = 42", content) self.assertIn("ARRAY_DEFINITION = ['Text1', 'Text2']", content) self.assertIn("[built-in options]", content) self.assertIn("buildtype = 'release'", content) self.t.run("build .") self.t.run_command(os.path.join("build", "demo")) self.assertIn("hello: Release!", self.t.out) self.assertIn("STRING_DEFINITION: Text", self.t.out) self.assertIn("[properties]", content) self.assertNotIn("needs_exe_wrapper", content) self._check_binary()
def test_makefile_arch(config): arch, os_, os_version = config profile = textwrap.dedent(""" include(default) [settings] os = {os} os.version = {os_version} arch = {arch} """).format(os=os_, arch=arch, os_version=os_version) t = TestClient() hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello") main_cpp = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) t.save({ "Makefile": makefile, "hello.h": hello_h, "hello.cpp": hello_cpp, "app.cpp": main_cpp, "conanfile.py": conanfile_py, "profile": profile }) t.run("install . --profile:host=profile --profile:build=default") t.run("build .") libhello = os.path.join(t.current_folder, "libhello.a") app = os.path.join(t.current_folder, "app") assert os.path.isfile(libhello) assert os.path.isfile(app) expected_arch = to_apple_arch(arch) t.run_command('lipo -info "%s"' % libhello) assert "architecture: %s" % expected_arch in t.out t.run_command('lipo -info "%s"' % app) assert "architecture: %s" % expected_arch in t.out
def test_no_soname_flag(): """ This test case is testing this graph structure: * 'LibNoSoname' -> 'OtherLib' -> 'Executable' Where: * LibNoSoname: is a package built as shared and without the SONAME flag. * OtherLib: is a package which requires LibNoSoname. * Executable: is the final consumer building an application and depending on OtherLib. """ client = TestClient() conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout class {name}Conan(ConanFile): name = "{name}" version = "1.0" # Binary configuration settings = "os", "compiler", "build_type", "arch" options = {{"shared": [True, False], "fPIC": [True, False]}} default_options = {{"shared": True, "fPIC": True}} # Sources are located in the same place as this recipe, copy them to the recipe exports_sources = "CMakeLists.txt", "src/*" {generators} {requires} def config_options(self): if self.settings.os == "Windows": del self.options.fPIC def layout(self): cmake_layout(self) def generate(self): tc = CMakeToolchain(self) tc.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): cmake = CMake(self) cmake.install() def package_info(self): self.cpp_info.libs = ["{name}"] """) cmakelists_nosoname = textwrap.dedent(""" cmake_minimum_required(VERSION 3.15) project(nosoname CXX) add_library(nosoname SHARED src/nosoname.cpp) # Adding NO_SONAME flag to main library set_target_properties(nosoname PROPERTIES PUBLIC_HEADER "src/nosoname.h" NO_SONAME 1) install(TARGETS nosoname DESTINATION "." PUBLIC_HEADER DESTINATION include RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) """) cpp = gen_function_cpp(name="nosoname") h = gen_function_h(name="nosoname") client.save({ "CMakeLists.txt": cmakelists_nosoname, "src/nosoname.cpp": cpp, "src/nosoname.h": h, "conanfile.py": conanfile.format(name="nosoname", requires="", generators="") }) # Now, let's create both libraries client.run("create .") cmakelists_libB = textwrap.dedent(""" cmake_minimum_required(VERSION 3.15) project(libB CXX) find_package(nosoname CONFIG REQUIRED) add_library(libB SHARED src/libB.cpp) target_link_libraries(libB nosoname::nosoname) set_target_properties(libB PROPERTIES PUBLIC_HEADER "src/libB.h") install(TARGETS libB DESTINATION "." PUBLIC_HEADER DESTINATION include RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) """) cpp = gen_function_cpp(name="libB", includes=["nosoname"], calls=["nosoname"]) h = gen_function_h(name="libB") client.save( { "CMakeLists.txt": cmakelists_libB, "src/libB.cpp": cpp, "src/libB.h": h, "conanfile.py": conanfile.format(name="libB", requires='requires = "nosoname/1.0"', generators='generators = "CMakeDeps"') }, clean_first=True) # Now, let's create both libraries client.run("create .") # Now, let's create the application consuming libB cmakelists = textwrap.dedent(""" cmake_minimum_required(VERSION 3.15) project(PackageTest CXX) find_package(libB CONFIG REQUIRED) add_executable(example src/example.cpp) target_link_libraries(example libB::libB) """) conanfile = textwrap.dedent(""" [requires] libB/1.0 [generators] CMakeDeps CMakeToolchain """) cpp = gen_function_cpp(name="main", includes=["libB"], calls=["libB"]) client.save( { "CMakeLists.txt": cmakelists.format(current_folder=client.current_folder), "src/example.cpp": cpp, "conanfile.txt": conanfile }, clean_first=True) client.run('install . ') client.run_command( 'cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="./conan_toolchain.cmake" .' ' -DCMAKE_BUILD_TYPE=Release && cmake --build . && ./example')
class Base(unittest.TestCase): conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake, CMakeToolchain class App(ConanFile): settings = "os", "arch", "compiler", "build_type" requires = "hello/0.1" generators = "cmake_find_package_multi" options = {"shared": [True, False], "fPIC": [True, False]} default_options = {"shared": False, "fPIC": True} def generate(self): tc = CMakeToolchain(self) tc.variables["MYVAR"] = "MYVAR_VALUE" tc.variables["MYVAR2"] = "MYVAR_VALUE2" tc.variables.debug["MYVAR_CONFIG"] = "MYVAR_DEBUG" tc.variables.release["MYVAR_CONFIG"] = "MYVAR_RELEASE" tc.variables.debug["MYVAR2_CONFIG"] = "MYVAR2_DEBUG" tc.variables.release["MYVAR2_CONFIG"] = "MYVAR2_RELEASE" tc.preprocessor_definitions["MYDEFINE"] = "MYDEF_VALUE" tc.preprocessor_definitions.debug["MYDEFINE_CONFIG"] = "MYDEF_DEBUG" tc.preprocessor_definitions.release["MYDEFINE_CONFIG"] = "MYDEF_RELEASE" tc.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build() """) lib_h = gen_function_h(name="app") lib_cpp = gen_function_cpp( name="app", msg="App", includes=["hello"], calls=["hello"], preprocessor=["MYVAR", "MYVAR_CONFIG", "MYDEFINE", "MYDEFINE_CONFIG"]) main = gen_function_cpp(name="main", includes=["app"], calls=["app"]) cmakelist = textwrap.dedent(""" cmake_minimum_required(VERSION 2.8) project(App C CXX) if(CONAN_TOOLCHAIN_INCLUDED AND CMAKE_VERSION VERSION_LESS "3.15") include("${CMAKE_BINARY_DIR}/conan_project_include.cmake") endif() if(NOT CMAKE_TOOLCHAIN_FILE) message(FATAL ">> Not using toolchain") endif() message(">> CMAKE_GENERATOR_PLATFORM: ${CMAKE_GENERATOR_PLATFORM}") message(">> CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") message(">> CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") message(">> CMAKE_CXX_FLAGS_DEBUG: ${CMAKE_CXX_FLAGS_DEBUG}") message(">> CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}") message(">> CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") message(">> CMAKE_C_FLAGS_DEBUG: ${CMAKE_C_FLAGS_DEBUG}") message(">> CMAKE_C_FLAGS_RELEASE: ${CMAKE_C_FLAGS_RELEASE}") message(">> CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}") message(">> CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}") message(">> CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}") message(">> CMAKE_CXX_EXTENSIONS: ${CMAKE_CXX_EXTENSIONS}") message(">> CMAKE_POSITION_INDEPENDENT_CODE: ${CMAKE_POSITION_INDEPENDENT_CODE}") message(">> CMAKE_SKIP_RPATH: ${CMAKE_SKIP_RPATH}") message(">> CMAKE_INSTALL_NAME_DIR: ${CMAKE_INSTALL_NAME_DIR}") message(">> CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}") message(">> CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}") message(">> BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") get_directory_property(_COMPILE_DEFS DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS) message(">> COMPILE_DEFINITIONS: ${_COMPILE_DEFS}") find_package(hello REQUIRED) add_library(app_lib app_lib.cpp) target_link_libraries(app_lib PRIVATE hello::hello) target_compile_definitions(app_lib PRIVATE MYVAR="${MYVAR}") target_compile_definitions(app_lib PRIVATE MYVAR_CONFIG=${MYVAR_CONFIG}) add_executable(app app.cpp) target_link_libraries(app PRIVATE app_lib) """) def setUp(self): self.client = TestClient(path_with_spaces=True) conanfile = textwrap.dedent(""" from conans import ConanFile from conans.tools import save import os class Pkg(ConanFile): settings = "build_type" def package(self): save(os.path.join(self.package_folder, "include/hello.h"), '''#include <iostream> void hello(){std::cout<< "Hello: %s" <<std::endl;}''' % self.settings.build_type) """) self.client.save({"conanfile.py": conanfile}) self.client.run("create . hello/0.1@ -s build_type=Debug") self.client.run("create . hello/0.1@ -s build_type=Release") # Prepare the actual consumer package self.client.save({ "conanfile.py": self.conanfile, "CMakeLists.txt": self.cmakelist, "app.cpp": self.main, "app_lib.cpp": self.lib_cpp, "app.h": self.lib_h }) def _run_build(self, settings=None, options=None): # Build the profile according to the settings provided settings = settings or {} settings = " ".join('-s %s="%s"' % (k, v) for k, v in settings.items() if v) options = " ".join("-o %s=%s" % (k, v) for k, v in options.items()) if options else "" # Run the configure corresponding to this test case build_directory = os.path.join(self.client.current_folder, "build").replace("\\", "/") with self.client.chdir(build_directory): self.client.run("install .. %s %s" % (settings, options)) install_out = self.client.out self.client.run("build ..") return install_out def _modify_code(self): lib_cpp = gen_function_cpp(name="app", msg="AppImproved", includes=["hello"], calls=["hello"], preprocessor=[ "MYVAR", "MYVAR_CONFIG", "MYDEFINE", "MYDEFINE_CONFIG" ]) self.client.save({"app_lib.cpp": lib_cpp}) content = self.client.load("CMakeLists.txt") content = content.replace(">>", "++>>") self.client.save({"CMakeLists.txt": content}) def _incremental_build(self, build_type=None): build_directory = os.path.join(self.client.current_folder, "build").replace("\\", "/") with self.client.chdir(build_directory): config = "--config %s" % build_type if build_type else "" self.client.run_command("cmake --build . %s" % config) def _run_app(self, build_type, bin_folder=False, msg="App", dyld_path=None): if dyld_path: build_directory = os.path.join(self.client.current_folder, "build").replace("\\", "/") command_str = 'DYLD_LIBRARY_PATH="%s" build/app' % build_directory else: command_str = "build/%s/app.exe" % build_type if bin_folder else "build/app" if platform.system() == "Windows": command_str = command_str.replace("/", "\\") self.client.run_command(command_str) self.assertIn("Hello: %s" % build_type, self.client.out) self.assertIn("%s: %s!" % (msg, build_type), self.client.out) self.assertIn("MYVAR: MYVAR_VALUE", self.client.out) self.assertIn("MYVAR_CONFIG: MYVAR_%s" % build_type.upper(), self.client.out) self.assertIn("MYDEFINE: MYDEF_VALUE", self.client.out) self.assertIn("MYDEFINE_CONFIG: MYDEF_%s" % build_type.upper(), self.client.out)
def check_build_vs_project_with_a(vs_version): client = TestClient() client.save({"conanfile.py": GenConanfile()}) client.run("create . updep.pkg.team/0.1@") conanfile = textwrap.dedent(""" from conans import ConanFile, CMake class HelloConan(ConanFile): settings = "os", "build_type", "compiler", "arch" exports = '*' requires = "updep.pkg.team/0.1@" def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): self.copy("*.h", dst="include") self.copy("*.a", dst="lib", keep_path=False) def package_info(self): self.cpp_info.libs = ["hello.a"] """) hello_cpp = gen_function_cpp(name="hello") hello_h = gen_function_h(name="hello") cmake = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.15) project(MyLib CXX) set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") add_library(hello hello.cpp) """) client.save({ "conanfile.py": conanfile, "CMakeLists.txt": cmake, "hello.cpp": hello_cpp, "hello.h": hello_h }) client.run( 'create . mydep.pkg.team/0.1@ -s compiler="Visual Studio"' ' -s compiler.version={vs_version}'.format(vs_version=vs_version)) consumer = textwrap.dedent(""" from conans import ConanFile from conan.tools.microsoft import MSBuild class HelloConan(ConanFile): settings = "os", "build_type", "compiler", "arch" requires = "mydep.pkg.team/0.1@" generators = "MSBuildDeps", "MSBuildToolchain" def build(self): msbuild = MSBuild(self) msbuild.build("MyProject.sln") """) files = get_vs_project_files() main_cpp = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) files["MyProject/main.cpp"] = main_cpp files["conanfile.py"] = consumer props = os.path.join(client.current_folder, "conandeps.props") old = r'<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />' new = old + '<Import Project="{props}" />'.format(props=props) files["MyProject/MyProject.vcxproj"] = files[ "MyProject/MyProject.vcxproj"].replace(old, new) client.save(files, clean_first=True) client.run( 'install . -s compiler="Visual Studio"' ' -s compiler.version={vs_version}'.format(vs_version=vs_version)) client.run("build .") client.run_command(r"x64\Release\MyProject.exe") assert "hello: Release!" in client.out
def test_same_name_global_target_collision(self, generator): # https://github.com/conan-io/conan/issues/7889 conanfile_tpl = textwrap.dedent(""" from conans import ConanFile, CMake class Conan(ConanFile): name = "{name}" version = "1.0" settings = "os", "compiler", "build_type", "arch" generators = "cmake" exports_sources = "src/*" def build(self): cmake = CMake(self) cmake.configure(source_folder="src") 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) def package_info(self): self.cpp_info.names["{generator}"] = "nonstd" self.cpp_info.filenames["{generator}"] = "{name}" self.cpp_info.set_property("cmake_target_name", "nonstd", "{generator}") self.cpp_info.set_property("cmake_file_name", "{name}", "{generator}") self.cpp_info.components["1"].names["{generator}"] = "{name}" self.cpp_info.components["1"].set_property("cmake_target_name", "{name}", "{generator}") self.cpp_info.components["1"].libs = ["{name}"] """) client = TestClient() for name in ["expected", "variant"]: client.run("new {name}/1.0 -s".format(name=name)) client.save({ "conanfile.py": conanfile_tpl.format(name=name, generator=generator) }) client.run("create . {name}/1.0@".format(name=name)) middle_cmakelists = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) project(middle CXX) cmake_minimum_required(VERSION 3.1) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() find_package(expected) find_package(variant) add_library(middle middle.cpp) target_link_libraries(middle nonstd::nonstd) """) middle_h = gen_function_h(name="middle") middle_cpp = gen_function_cpp( name="middle", includes=["middle", "expected", "variant"], calls=["expected", "variant"]) middle_conanfile = textwrap.dedent(""" from conans import ConanFile, CMake class Conan(ConanFile): name = "middle" version = "1.0" settings = "os", "compiler", "build_type", "arch" generators = "cmake", "{}" exports_sources = "src/*" requires = "expected/1.0", "variant/1.0" def build(self): cmake = CMake(self) cmake.configure(source_folder="src") 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) def package_info(self): self.cpp_info.libs = ["middle"] """.format(generator)) client.save( { "conanfile.py": middle_conanfile, "src/CMakeLists.txt": middle_cmakelists, "src/middle.h": middle_h, "src/middle.cpp": middle_cpp }, clean_first=True) client.run("create . middle/1.0@") conanfile = textwrap.dedent(""" import os from conans import ConanFile, CMake class Conan(ConanFile): name = "consumer" version = "1.0" generators = "{}", "cmake" settings = "os", "compiler", "build_type", "arch" exports_sources = "src/*" requires = "middle/1.0" def build(self): cmake = CMake(self) cmake.configure(source_folder="src") cmake.build() self.run(os.path.join("bin", "main")) """.format(generator)) cmakelists = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) project(consumer CXX) cmake_minimum_required(VERSION 3.1) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() find_package(middle) get_target_property(tmp middle::middle INTERFACE_LINK_LIBRARIES) message("Middle link libraries: ${tmp}") add_executable(main main.cpp) target_link_libraries(main middle::middle) """) main_cpp = gen_function_cpp(name="main", includes=["middle"], calls=["middle"]) client.save( { "conanfile.py": conanfile, "src/CMakeLists.txt": cmakelists, "src/main.cpp": main_cpp }, clean_first=True) client.run("create . consumer/1.0@") assert 'main: Release!' in client.out assert 'middle: Release!' in client.out assert 'expected/1.0: Hello World Release!' in client.out assert 'variant/1.0: Hello World Release!' in client.out
def test_same_names(generator): client = TestClient() conanfile_greetings = textwrap.dedent(""" from conans import ConanFile, CMake class HelloConan(ConanFile): name = "hello" version = "0.0.1" settings = "os", "compiler", "build_type", "arch" generators = "cmake" exports_sources = "src/*" def build(self): cmake = CMake(self) cmake.configure(source_folder="src") 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) def package_info(self): self.cpp_info.components["global"].name = "hello" self.cpp_info.components["global"].libs = ["hello"] """) hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", includes=["hello"]) cmakelists_greetings = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.0) project(greetings CXX) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() add_library(hello hello.cpp) """) test_package_greetings_conanfile = textwrap.dedent(""" import os from conans import ConanFile, CMake class HelloTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "cmake", "{}" def build(self): cmake = CMake(self) cmake.configure() cmake.build() def test(self): os.chdir("bin") self.run(".%sexample" % os.sep) """.format(generator)) test_package_greetings_cpp = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) test_package_greetings_cmakelists = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() find_package(hello) add_executable(example example.cpp) target_link_libraries(example hello::hello) """) client.save({ "conanfile.py": conanfile_greetings, "src/CMakeLists.txt": cmakelists_greetings, "src/hello.h": hello_h, "src/hello.cpp": hello_cpp, "test_package/conanfile.py": test_package_greetings_conanfile, "test_package/example.cpp": test_package_greetings_cpp, "test_package/CMakeLists.txt": test_package_greetings_cmakelists }) client.run("create .") assert "hello: Release!" in client.out
def create_chat(client, generator, components, package_info, cmake_find, test_cmake_find): conanfile = textwrap.dedent(""" from conans import ConanFile, CMake class Chat(ConanFile): name = "chat" version = "0.0.1" settings = "os", "compiler", "build_type", "arch" generators = "{}", "cmake" exports_sources = "src/*" requires = "greetings/0.0.1" default_options = {{"greetings:components": "{}"}} def build(self): cmake = CMake(self) cmake.configure(source_folder="src") 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) def package_info(self): {} """).format(generator, components, "\n ".join(package_info.splitlines())) sayhello_h = gen_function_h(name="sayhello") sayhello_cpp = gen_function_cpp(name="sayhello", includes=["hello"], calls=["hello"]) sayhellobye_h = gen_function_h(name="sayhellobye") sayhellobye_cpp = gen_function_cpp(name="sayhellobye", includes=["sayhello", "bye"], calls=["sayhello", "bye"]) cmakelists = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.0) project(world CXX) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_output_dirs_setup() %s """ % cmake_find) test_conanfile = textwrap.dedent(""" import os from conans import ConanFile, CMake class WorldTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "cmake", "{}" requires = "chat/0.0.1" def build(self): cmake = CMake(self) cmake.configure() cmake.build() def test(self): os.chdir("bin") self.run(".%sexample" % os.sep) self.run(".%sexample2" % os.sep) """.format(generator)) test_example_cpp = gen_function_cpp(name="main", includes=["sayhellobye"], calls=["sayhellobye"]) test_cmakelists = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_output_dirs_setup() # necessary for the local set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR} ${CMAKE_MODULE_PATH}) set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR} ${CMAKE_PREFIX_PATH}) %s """ % test_cmake_find) client.save( { "conanfile.py": conanfile, "src/CMakeLists.txt": cmakelists, "src/sayhello.h": sayhello_h, "src/sayhello.cpp": sayhello_cpp, "src/sayhellobye.h": sayhellobye_h, "src/sayhellobye.cpp": sayhellobye_cpp, "test_package/conanfile.py": test_conanfile, "test_package/CMakeLists.txt": test_cmakelists, "test_package/example.cpp": test_example_cpp }, clean_first=True) client.run("create . -s build_type=Release") assert "sayhellobye: Release!" in client.out assert "sayhello: Release!" in client.out assert "hello: Release!" in client.out assert "bye: Release!" in client.out client.run("create . -s build_type=Debug") assert "sayhellobye: Debug!" in client.out assert "sayhello: Debug!" in client.out assert "hello: Debug!" in client.out assert "bye: Debug!" in client.out
def setup_client_with_greetings(): """ creates a multi-component package with 2 components "hello" and "bye """ hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", includes=["hello"]) bye_h = gen_function_h(name="bye") bye_cpp = gen_function_cpp(name="bye", includes=["bye"]) conanfile_greetings = textwrap.dedent(""" from conans import ConanFile, CMake class GreetingsConan(ConanFile): name = "greetings" version = "0.0.1" settings = "os", "compiler", "build_type", "arch" generators = "cmake" exports_sources = "src/*" options = {"components": ["standard", "custom", "none"]} default_options = {"components": "standard"} def build(self): cmake = CMake(self) cmake.configure(source_folder="src") 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) def package_info(self): if self.options.components == "standard": self.cpp_info.components["hello"].libs = ["hello"] self.cpp_info.components["bye"].libs = ["bye"] elif self.options.components == "custom": self.cpp_info.filenames["cmake_find_package_multi"] = "MYG" self.cpp_info.filenames["cmake_find_package"] = "MYG" self.cpp_info.set_property("cmake_file_name", "MYG") self.cpp_info.names["cmake_find_package_multi"] = "MyGreetings" self.cpp_info.names["cmake_find_package"] = "MyGreetings" self.cpp_info.set_property("cmake_target_name", "MyGreetings") self.cpp_info.components["hello"].names["cmake_find_package_multi"] = "MyHello" self.cpp_info.components["bye"].names["cmake_find_package_multi"] = "MyBye" self.cpp_info.components["hello"].names["cmake_find_package"] = "MyHello" self.cpp_info.components["bye"].names["cmake_find_package"] = "MyBye" self.cpp_info.components["hello"].set_property("cmake_target_name", "MyHello") self.cpp_info.components["bye"].set_property("cmake_target_name", "MyBye") self.cpp_info.components["hello"].libs = ["hello"] self.cpp_info.components["bye"].libs = ["bye"] else: self.cpp_info.libs = ["hello", "bye"] def package_id(self): del self.info.options.components """) cmakelists_greetings = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.0) project(greetings CXX) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_output_dirs_setup() add_library(hello hello.cpp) add_library(bye bye.cpp) """) test_package_greetings_conanfile = textwrap.dedent(""" import os from conans import ConanFile, CMake class GreetingsTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "cmake", "cmake_find_package_multi" requires = "greetings/0.0.1" def build(self): cmake = CMake(self) cmake.configure() cmake.build() def test(self): os.chdir("bin") self.run(".%sexample" % os.sep) """) test_package_greetings_cpp = gen_function_cpp(name="main", includes=["hello", "bye"], calls=["hello", "bye"]) test_package_greetings_cmakelists = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_output_dirs_setup() find_package(greetings) add_executable(example example.cpp) target_link_libraries(example greetings::greetings) """) client = TestClient() client.save({ "conanfile.py": conanfile_greetings, "src/CMakeLists.txt": cmakelists_greetings, "src/hello.h": hello_h, "src/hello.cpp": hello_cpp, "src/bye.h": bye_h, "src/bye.cpp": bye_cpp, "test_package/conanfile.py": test_package_greetings_conanfile, "test_package/example.cpp": test_package_greetings_cpp, "test_package/CMakeLists.txt": test_package_greetings_cmakelists }) client.run("create . -s build_type=Release") assert "hello: Release!" in client.out assert "bye: Release!" in client.out client.run("create . -s build_type=Debug") assert "hello: Debug!" in client.out assert "bye: Debug!" in client.out return client
def test_toolchain_posix(self): client = TestClient(path_with_spaces=False) settings = { "arch": "x86_64", "build_type": "Release", "compiler": "gcc", "compiler.version": "9", "compiler.libcxx": "libstdc++11", } settings_str = " ".join('-s %s="%s"' % (k, v) for k, v in settings.items() if v) conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.gnu import MakeToolchain class App(ConanFile): settings = "os", "arch", "compiler", "build_type" def generate(self): tc = MakeToolchain(self) tc.variables["TEST_VAR"] = "TestVarValue" tc.preprocessor_definitions["TEST_DEFINITION"] = "TestPpdValue" tc.generate() def build(self): self.run("make -C ..") """) hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello", preprocessor=["TEST_DEFINITION"]) makefile = textwrap.dedent(""" include conan_toolchain.mak #------------------------------------------------- # Make variables for a sample App #------------------------------------------------- OUT_DIR ?= out SRC_DIR ?= src INCLUDE_DIR ?= include PROJECT_NAME = hello STATIC_LIB_FILENAME = lib$(PROJECT_NAME).a SRCS += $(wildcard $(SRC_DIR)/*.cpp) OBJS += $(patsubst $(SRC_DIR)/%.cpp,$(OUT_DIR)/%.o,$(SRCS)) CPPFLAGS += $(addprefix -I,$(INCLUDE_DIR)) #------------------------------------------------- # Append CONAN_ variables to standards #------------------------------------------------- CPPFLAGS += $(CONAN_TC_CPPFLAGS) #------------------------------------------------- # Print variables to be tested #------------------------------------------------- $(info >> CPPFLAGS: $(CPPFLAGS)) $(info >> TEST_VAR: $(TEST_VAR)) #------------------------------------------------- # Make Rules #------------------------------------------------- .PHONY : static static : $(OBJS) $(AR) $(ARFLAGS) $(OUT_DIR)/$(STATIC_LIB_FILENAME) $(OBJS) $(OUT_DIR)/%.o : $(SRC_DIR)/%.cpp $(OUT_DIR) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@ $(OUT_DIR): -mkdir $@ """) files_to_save = { "conanfile.py": conanfile, "Makefile": makefile, "src/hello.cpp": hello_cpp, "include/hello.h": hello_h } client.save(files_to_save, clean_first=True) client.run("install . hello/0.1@ %s" % settings_str) client.run_command("make static") client.run_command("nm -C out/libhello.a | grep 'hello()'") self.assertIn("hello()", client.out)
class Base(unittest.TestCase): conanfile = textwrap.dedent(""" from conan.tools.google import Bazel from conans import ConanFile class App(ConanFile): name="test_bazel_app" version="0.0" settings = "os", "compiler", "build_type", "arch" generators = "BazelDeps", "BazelToolchain" exports_sources = "WORKSPACE", "app/*" def build(self): bazel = Bazel(self) bazel.configure() bazel.build(label="//app:main") def package(self): self.copy('*', src='bazel-bin') """) buildfile = textwrap.dedent(""" load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") cc_library( name = "hello", srcs = ["hello.cpp"], hdrs = ["hello.h",], ) cc_binary( name = "main", srcs = ["main.cpp"], deps = [":hello"], ) """) lib_h = gen_function_h(name="hello") lib_cpp = gen_function_cpp(name="hello", msg="Hello", includes=["hello"]) main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) workspace_file = textwrap.dedent(""" load("@//bazel-build/conandeps:dependencies.bzl", "load_conan_dependencies") load_conan_dependencies() """) def setUp(self): self.client = TestClient(path_with_spaces=False ) # bazel doesn't work with paths with spaces conanfile = textwrap.dedent(""" from conans import ConanFile from conans.tools import save import os class Pkg(ConanFile): settings = "build_type" def package(self): save(os.path.join(self.package_folder, "include/hello.h"), '''#include <iostream> void hello(){std::cout<< "Hello: %s" <<std::endl;}''' % self.settings.build_type) """) self.client.save({"conanfile.py": conanfile}) self.client.run("create . hello/0.1@ -s build_type=Debug") self.client.run("create . hello/0.1@ -s build_type=Release") # Prepare the actual consumer package self.client.save({ "conanfile.py": self.conanfile, "WORKSPACE": self.workspace_file, "app/BUILD": self.buildfile, "app/main.cpp": self.main, "app/hello.cpp": self.lib_cpp, "app/hello.h": self.lib_h }) def _run_build(self): build_directory = os.path.join(self.client.current_folder, "bazel-build").replace("\\", "/") with self.client.chdir(build_directory): self.client.run("install .. ") install_out = self.client.out self.client.run("build ..") return install_out def _modify_code(self): lib_cpp = gen_function_cpp(name="hello", msg="HelloImproved", includes=["hello"]) self.client.save({"app/hello.cpp": lib_cpp}) def _incremental_build(self): with self.client.chdir(self.client.current_folder): self.client.run_command( "bazel build --explain=output.txt //app:main") def _run_app(self, bin_folder=False): command_str = "bazel-bin/app/main.exe" if bin_folder else "bazel-bin/app/main" if platform.system() == "Windows": command_str = command_str.replace("/", "\\") self.client.run_command(command_str)
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 .")
def test_makefile_arch(self, arch, os_, os_version): self.arch = arch self.os = os_ self.os_version = os_version makefile = textwrap.dedent(""" .PHONY: all all: libhello.a app app: main.o libhello.a $(CXX) $(CFLAGS) -o app main.o -lhello -L. libhello.a: hello.o $(AR) rcs libhello.a hello.o main.o: main.cpp $(CXX) $(CFLAGS) -c -o main.o main.cpp hello.o: hello.cpp $(CXX) $(CFLAGS) -c -o hello.o hello.cpp """) profile = textwrap.dedent(""" include(default) [settings] os = {os} os.version = {os_version} arch = {arch} """).format(os=self.os, arch=self.arch, os_version=self.os_version) conanfile_py = textwrap.dedent(""" from conans import ConanFile, tools, AutoToolsBuildEnvironment class App(ConanFile): settings = "os", "arch", "compiler", "build_type" options = {"shared": [True, False], "fPIC": [True, False]} default_options = {"shared": False, "fPIC": True} def config_options(self): if self.settings.os == "Windows": del self.options.fPIC def build(self): env_build = AutoToolsBuildEnvironment(self) env_build.make() """) self.t = TestClient() hello_h = gen_function_h(name="hello") hello_cpp = gen_function_cpp(name="hello") main_cpp = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) self.t.save({ "Makefile": makefile, "hello.h": hello_h, "hello.cpp": hello_cpp, "main.cpp": main_cpp, "conanfile.py": conanfile_py, "profile": profile }) self.t.run("install . --profile:host=profile") self.t.run("build .") libhello = os.path.join(self.t.current_folder, "libhello.a") app = os.path.join(self.t.current_folder, "app") self.assertTrue(os.path.isfile(libhello)) self.assertTrue(os.path.isfile(app)) expected_arch = to_apple_arch(self.arch) self.t.run_command('lipo -info "%s"' % libhello) self.assertIn("architecture: %s" % expected_arch, self.t.out) self.t.run_command('lipo -info "%s"' % app) self.assertIn("architecture: %s" % expected_arch, self.t.out)
def create_chat(client, components, package_info, cmake_find, test_cmake_find): conanfile = textwrap.dedent(""" from conans import ConanFile from conan.tools.cmake import CMake class Chat(ConanFile): name = "chat" version = "0.0.1" settings = "os", "compiler", "build_type", "arch" generators = "CMakeDeps", "CMakeToolchain" exports_sources = "src/*" requires = "greetings/0.0.1" default_options = {{"greetings:components": "{}"}} def build(self): cmake = CMake(self) cmake.configure(build_script_folder="src") 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) def package_info(self): {} """).format(components, "\n ".join(package_info.splitlines())) sayhello_h = gen_function_h(name="sayhello") sayhello_cpp = gen_function_cpp(name="sayhello", includes=["hello"], calls=["hello"]) sayhellobye_h = gen_function_h(name="sayhellobye") sayhellobye_cpp = gen_function_cpp(name="sayhellobye", includes=["sayhello", "bye"], calls=["sayhello", "bye"]) cmakelists = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.0) project(world CXX) %s """ % cmake_find) test_conanfile = textwrap.dedent(""" import os from conans import ConanFile from conan.tools.cmake import CMake class WorldTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "CMakeDeps", "CMakeToolchain" requires = "chat/0.0.1" def build(self): cmake = CMake(self) cmake.configure() cmake.build() def test(self): path = "{}".format(self.settings.build_type) if self.settings.os == "Windows" else "." self.run("{}{}example".format(path, os.sep)) self.run("{}{}example2".format(path, os.sep)) """) test_example_cpp = gen_function_cpp(name="main", includes=["sayhellobye"], calls=["sayhellobye"]) test_cmakelists = textwrap.dedent(""" set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CXX_ABI_COMPILED 1) cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) %s """ % test_cmake_find) client.save( { "conanfile.py": conanfile, "src/CMakeLists.txt": cmakelists, "src/sayhello.h": sayhello_h, "src/sayhello.cpp": sayhello_cpp, "src/sayhellobye.h": sayhellobye_h, "src/sayhellobye.cpp": sayhellobye_cpp, "test_package/conanfile.py": test_conanfile, "test_package/CMakeLists.txt": test_cmakelists, "test_package/example.cpp": test_example_cpp }, clean_first=True) client.run("create . -s build_type=Release") assert "sayhellobye: Release!" in client.out assert "sayhello: Release!" in client.out assert "hello: Release!" in client.out assert "bye: Release!" in client.out client.run("create . -s build_type=Debug") assert "sayhellobye: Debug!" in client.out assert "sayhello: Debug!" in client.out assert "hello: Debug!" in client.out assert "bye: Debug!" in client.out
def test_same_name_global_target_collision(self): # https://github.com/conan-io/conan/issues/7889 conanfile_tpl = textwrap.dedent(""" import os from conans import ConanFile, CMake class Conan(ConanFile): name = "{name}" version = "1.0" settings = "os", "compiler", "build_type", "arch" generators = "cmake" exports_sources = "src/*" def build(self): cmake = CMake(self) cmake.configure(source_folder="src") 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) def package_info(self): self.cpp_info.names["cmake_find_package_multi"] = "nonstd" self.cpp_info.filenames["cmake_find_package_multi"] = "{name}" self.cpp_info.components["1"].names["cmake_find_package_multi"] = "{name}" self.cpp_info.components["1"].libs = ["{name}"] """) client = TestClient() for name in ["expected", "variant"]: client.run("new {name}/1.0 -s".format(name=name)) client.save({"conanfile.py": conanfile_tpl.format(name=name)}) client.run("create . {name}/1.0@".format(name=name)) middle_cmakelists = textwrap.dedent(""" project(middle) cmake_minimum_required(VERSION 3.1) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() find_package(expected) find_package(variant) add_library(middle middle.cpp) target_link_libraries(middle nonstd::nonstd) """) middle_h = gen_function_h(name="middle") middle_cpp = textwrap.dedent(""" #include "middle.h" #include "expected.h" #include "variant.h" int middle() { expected(); variant(); return 0; } """) middle_conanfile = textwrap.dedent(""" import os from conans import ConanFile, CMake class Conan(ConanFile): name = "middle" version = "1.0" settings = "os", "compiler", "build_type", "arch" generators = "cmake", "cmake_find_package_multi" exports_sources = "src/*" requires = "expected/1.0", "variant/1.0" def build(self): cmake = CMake(self) cmake.configure(source_folder="src") 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) def package_info(self): self.cpp_info.libs = ["middle"] """) client.save({"conanfile.py": middle_conanfile, "src/CMakeLists.txt": middle_cmakelists, "src/middle.h": middle_h, "src/middle.cpp": middle_cpp}, clean_first=True) client.run("create . middle/1.0@") conanfile = textwrap.dedent(""" import os from conans import ConanFile, CMake class Conan(ConanFile): name = "consumer" version = "1.0" generators = "cmake_find_package_multi", "cmake" settings = "os", "compiler", "build_type", "arch" exports_sources = "src/*" requires = "middle/1.0" def build(self): cmake = CMake(self) cmake.configure(source_folder="src") cmake.build() self.run(os.path.join("bin", "main")) """) cmakelists = textwrap.dedent(""" project(consumer) cmake_minimum_required(VERSION 3.1) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() find_package(middle) get_target_property(tmp middle::middle INTERFACE_LINK_LIBRARIES) message("Middle link libraries: ${tmp}") add_executable(main main.cpp) target_link_libraries(main middle::middle) """) main_cpp = textwrap.dedent(""" #include "middle.h" int main() { middle(); } """) client.save({"conanfile.py": conanfile, "src/CMakeLists.txt": cmakelists, "src/main.cpp": main_cpp}, clean_first=True) client.run("create . consumer/1.0@") self.assertIn('Library middle found', client.out) self.assertIn('Library expected found', client.out) self.assertIn('Library variant found', client.out) self.assertIn("Middle link libraries: " "$<$<CONFIG:Debug>:;>;$<$<CONFIG:MinSizeRel>:;>;$<$<CONFIG:RelWithDebInfo>:;>;" "$<$<CONFIG:Release>:CONAN_LIB::middle_middle_RELEASE;nonstd::nonstd;$", client.out) self.assertIn('expected/1.0: Hello World Release!', client.out) self.assertIn('variant/1.0: Hello World Release!', client.out)