def test_replace_in_file(self): replace_in_file(self.win_file, "nis", "nus") replace_in_file(self.bytes_file, "nis", "nus") content = tools.load(self.win_file) self.assertNotIn("nis", content) self.assertIn("nus", content) content = tools.load(self.bytes_file) self.assertNotIn("nis", content) self.assertIn("nus", content)
def get_version(): try: content = tools.load("jamroot.jam") match = re.search(r"constant\s*VERSION\s*:\s*(\S+)\s*;", content) return match.group(1) except: pass
def _get_file_conf(self, section, varname=None): """ Gets the section or variable from config file. If the queried element is not found an exception is raised. """ try: if not os.path.exists(self.config_filename): jwt_random_secret = ''.join(random.choice(string.ascii_letters) for _ in range(24)) updown_random_secret = ''.join(random.choice(string.ascii_letters) for _ in range(24)) server_conf = default_server_conf.format(jwt_secret=jwt_random_secret, updown_secret=updown_random_secret) save(self.config_filename, server_conf) if not self._loaded: self._loaded = True # To avoid encoding problems we use our tools.load if six.PY3: self.read_string(tools.load(self.config_filename)) else: self.read(self.config_filename) if varname: section = dict(self.items(section)) return section[varname] else: return self.items(section) except NoSectionError: raise ConanException("No section '%s' found" % section) except Exception as exc: logger.debug(exc) raise ConanException("Invalid configuration, " "missing %s: %s" % (section, varname))
def _configure_cmake(self): if self._cmake: return self._cmake self._cmake = CMake(self, generator="Ninja") self._cmake.definitions["INSTALL_MKSPECSDIR"] = os.path.join(self.package_folder, "res", "archdatadir", "mkspecs") self._cmake.definitions["INSTALL_ARCHDATADIR"] = os.path.join(self.package_folder, "res", "archdatadir") self._cmake.definitions["INSTALL_DATADIR"] = os.path.join(self.package_folder, "res", "datadir") self._cmake.definitions["INSTALL_SYSCONFDIR"] = os.path.join(self.package_folder, "res", "sysconfdir") self._cmake.definitions["QT_BUILD_TESTS"] = "OFF" self._cmake.definitions["QT_BUILD_EXAMPLES"] = "OFF" if self.settings.compiler == "Visual Studio": if self.settings.compiler.runtime == "MT" or self.settings.compiler.runtime == "MTd": self._cmake.definitions["FEATURE_static_runtime"] = "ON" if self.options.multiconfiguration: self._cmake.generator = "Ninja Multi-Config" self._cmake.definitions["CMAKE_CONFIGURATION_TYPES"] = "Release;Debug" self._cmake.definitions["FEATURE_optimize_size"] = ("ON" if self.settings.build_type == "MinSizeRel" else "OFF") for module in self._submodules: if module != 'qtbase': self._cmake.definitions["BUILD_%s" % module] = ("ON" if self.options.get_safe(module) else "OFF") self._cmake.definitions["FEATURE_system_zlib"] = "ON" self._cmake.definitions["INPUT_opengl"] = self.options.get_safe("opengl", "no") # openSSL if not self.options.openssl: self._cmake.definitions["INPUT_openssl"] = "no" else: if self.options["openssl"].shared: self._cmake.definitions["INPUT_openssl"] = "runtime" else: self._cmake.definitions["INPUT_openssl"] = "linked" for opt, conf_arg in [("with_glib", "glib"), ("with_icu", "icu"), ("with_fontconfig", "fontconfig"), ("with_mysql", "sql_mysql"), ("with_pq", "sql_psql"), ("with_odbc", "sql_odbc"), ("gui", "gui"), ("widgets", "widgets"), ("with_zstd", "zstd"), ("with_vulkan", "vulkan"), ("with_brotli", "brotli")]: self._cmake.definitions["FEATURE_%s" % conf_arg] = ("ON" if self.options.get_safe(opt, False) else "OFF") for opt, conf_arg in [ ("with_doubleconversion", "doubleconversion"), ("with_freetype", "freetype"), ("with_harfbuzz", "harfbuzz"), ("with_libjpeg", "jpeg"), ("with_libpng", "png"), ("with_sqlite3", "sqlite"), ("with_pcre2", "pcre2"),]: if self.options.get_safe(opt, False): if self.options.multiconfiguration: self._cmake.definitions["FEATURE_%s" % conf_arg] = "ON" else: self._cmake.definitions["FEATURE_system_%s" % conf_arg] = "ON" else: self._cmake.definitions["FEATURE_%s" % conf_arg] = "OFF" self._cmake.definitions["FEATURE_system_%s" % conf_arg] = "OFF" if self.settings.os == "Macos": self._cmake.definitions["FEATURE_framework"] = "OFF" elif self.settings.os == "Android": self._cmake.definitions["CMAKE_ANDROID_NATIVE_API_LEVEL"] = self.settings.os.api_level self._cmake.definitions["ANDROID_ABI"] = {"armv7": "armeabi-v7a", "armv8": "arm64-v8a", "x86": "x86", "x86_64": "x86_64"}.get(str(self.settings.arch)) if self.options.sysroot: self._cmake.definitions["CMAKE_SYSROOT"] = self.options.sysroot if self.options.device: self._cmake.definitions["QT_QMAKE_TARGET_MKSPEC"] = os.path.join("devices", self.options.device) else: xplatform_val = self._xplatform() if xplatform_val: self._cmake.definitions["QT_QMAKE_TARGET_MKSPEC"] = xplatform_val else: self.output.warn("host not supported: %s %s %s %s" % (self.settings.os, self.settings.compiler, self.settings.compiler.version, self.settings.arch)) if self.options.cross_compile: self._cmake.definitions["QT_QMAKE_DEVICE_OPTIONS"] = "CROSS_COMPILE=%s" % self.options.cross_compile self._cmake.definitions["FEATURE_pkg_config"] = "ON" if self.settings.compiler == "gcc" and self.settings.build_type == "Debug" and not self.options.shared: self._cmake.definitions["BUILD_WITH_PCH"]= "OFF" # disabling PCH to save disk space try: self._cmake.configure(source_folder="qt6") except: cmake_err_log = os.path.join(self.build_folder, "CMakeFiles", "CMakeError.log") cmake_out_log = os.path.join(self.build_folder, "CMakeFiles", "CMakeOutput.log") if (os.path.isfile(cmake_err_log)): self.output.info(tools.load(cmake_err_log)) if (os.path.isfile(cmake_out_log)): self.output.info(tools.load(cmake_out_log)) raise return self._cmake
class LibvncserverConan(ConanFile): name = "libvncserver" version = tools.load("version.txt") license = "GPL 2.0" author = "David Callu - callu.david at gmail.com" url = "https://github.com/ledocc/conan-libvncserver" description = "A library for easy implementation of a VNC server" topics = ("vnc" "vnc-client" "vnc-server" "library" "remote-desktop") settings = "os", "compiler", "build_type", "arch" options = dict({ "shared": [True, False], "with_24bpp": [True, False], "with_ffmpeg": [True, False], # "with_gcrypt": [True, False], # "with_gnutls": [True, False], "with_ipv6": [True, False], "with_jpeg": [True, False], # "with_lzo": [True, False], "with_openssl": [True, False], "with_png": [True, False], # "with_sasl": [True, False], # "with_sdl": [True, False], # "with_systemd": [True, False], "with_threads": [True, False], "with_tightvnc_filetransfer": [True, False], "with_websockets": [True, False], "with_zlib": [True, False] }) default_options = dict({ "shared": False, "with_24bpp": True, "with_ffmpeg": False, # "with_gcrypt": False, # "with_gnutls": False, "with_ipv6": True, "with_jpeg": True, # "with_lzo": False, "with_openssl": True, "with_png": True, # "with_sasl": False, # "with_sdl": False, # "with_systemd": False, "with_threads": True, "with_tightvnc_filetransfer": False, "with_websockets": True, "with_zlib": True }) generators = "cmake" homepage = "https://github.com/LibVNC/libvncserver" build_requires = (("cmake_installer/3.15.3@conan/stable"), ("ninja_installer/1.9.0@bincrafters/stable")) exports_sources = ['patches/*'] exports = ['version.txt'] folder_name = "libvncserver-LibVNCServer-{}".format(version) def configure(self): del self.settings.compiler.libcxx def source(self): archive_name = "LibVNCServer-" + self.version + ".tar.gz" tools.get( self.homepage + "/archive/" + archive_name, sha256= "33cbbb4e15bb390f723c311b323cef4a43bcf781984f92d92adda3243a116136") tools.patch(patch_file="patches/cmake_export.patch", base_path=os.path.join(self.source_folder, self.folder_name)) def requirements(self): if self.options.with_ffmpeg: self.requires("ffmpeg/4.2@bincrafters/stable") # if self.options.with_gcrypt: # self.requires("") # if self.options.with_gnutls: # self.requires("") if self.options.with_jpeg: self.requires("libjpeg/9c@bincrafters/stable") # if self.options.with_lzo: # self.requires("") if self.options.with_openssl: self.requires("OpenSSL/1.1.1c@conan/stable") if self.options.with_png: self.requires("libpng/1.6.37@bincrafters/stable") # if self.options.with_sasl: # self.requires("") # if self.options.with_sdl: # self.requires("") # if self.options.with_systemd: # self.requires("") if self.options.with_zlib: self.requires("zlib/1.2.11@conan/stable") def build(self): cmake = self._configure_cmake() cmake.build() if self._should_build_test() and self._should_run_test(): self.run("ctest --output_on_failure --timeout=3000", cwd=cmake.build_folder) def package(self): cmake = self._configure_cmake() cmake.install() self.copy("COPYING", dst="licenses/LibVNCServer", ignore_case=True) def _configure_cmake(self): cmake = CMake(self, set_cmake_flags=True) cmake.generator = "Ninja" cmake.verbose = True if not self._should_build_test(): cmake.definitions["BUILD_TESTING"] = "OFF" cmake.definitions[ "WITH_24BPP"] = "ON" if self.options.with_24bpp else "OFF" cmake.definitions[ "WITH_FFMPEG"] = "ON" if self.options.with_ffmpeg else "OFF" cmake.definitions[ "WITH_GCRYPT"] = "OFF" #"ON" if self.options.with_gcrypt else "OFF" cmake.definitions[ "WITH_GNUTLS"] = "OFF" #"ON" if self.options.with_gnutls else "OFF" cmake.definitions[ "WITH_IPV6"] = "ON" if self.options.with_ipv6 else "OFF" cmake.definitions[ "WITH_JPEG"] = "ON" if self.options.with_jpeg else "OFF" cmake.definitions[ "WITH_LZO"] = "OFF" #"ON" if self.options.with_lzo else "OFF" cmake.definitions[ "WITH_OPENSSL"] = "ON" if self.options.with_openssl else "OFF" cmake.definitions[ "WITH_PNG"] = "ON" if self.options.with_png else "OFF" cmake.definitions[ "WITH_SASL"] = "OFF" #"ON" if self.options.with_sasl else "OFF" cmake.definitions[ "WITH_SDL"] = "OFF" #"ON" if self.options.with_sdl else "OFF" cmake.definitions[ "WITH_SYSTEMD"] = "OFF" #"ON" if self.options.with_systemd else "OFF" cmake.definitions[ "WITH_THREADS"] = "ON" if self.options.with_threads else "OFF" cmake.definitions[ "WITH_TIGHTVNC_FILETRANSFER"] = "ON" if self.options.with_tightvnc_filetransfer else "OFF" cmake.definitions[ "WITH_WEBSOCKETS"] = "ON" if self.options.with_websockets else "OFF" cmake.definitions[ "WITH_ZLIB"] = "ON" if self.options.with_zlib else "OFF" cmake.configure(source_dir="../" + self.folder_name, build_dir="build") return cmake def _should_build_test(self): if (self.settings.get_safe("compiler") == "Visual Studio") and (self.settings.get_safe("build_type") == "Debug"): self.output.warn( "Skipping test : Visual Studio build in Debug mode fail to compile." ) return False return True def _should_run_test(self): if tools.cross_building(self.settings): self.output.warn("Skipping test : cross built package.") return False return True
def _extract_license(self): with tools.chdir( os.path.join(self.source_folder, self._source_subfolder)): tmp = tools.load("zlib.h") license_contents = tmp[2:tmp.find("*/", 1)] tools.save("LICENSE", license_contents)
def _project_version(self): version_file = os.path.join(self.recipe_folder, "..", "VERSION") return tools.load(version_file).strip()
def _extract_license(self): file_content = tools.load( os.path.join(self.source_folder, self._source_subfolder, "test.cpp")) return file_content[:file_content.find("*/")]
def set_version(self): self.version = tools.load(path.join(self.recipe_folder, "version.txt")).strip()
def pre_export(output, conanfile, conanfile_path, reference, **kwargs): conanfile_content = tools.load(conanfile_path) export_folder_path = os.path.dirname(conanfile_path) settings = _get_settings(conanfile) header_only = _is_recipe_header_only(conanfile) installer = settings is not None and "os_build" in settings and "arch_build" in settings @run_test("KB-H001", output) def test(out): if settings and "cppstd" in settings: out.error( "The 'cppstd' setting is deprecated. Use the 'compiler.cppstd' " "subsetting instead") @run_test("KB-H002", output) def test(out): if reference.name != reference.name.lower(): out.error("The library name has to be lowercase") if reference.version != reference.version.lower(): out.error("The library version has to be lowercase") @run_test("KB-H003", output) def test(out): def _message_attr(attributes, out_method): for field in attributes: field_value = getattr(conanfile, field, None) if not field_value: out_method("Conanfile doesn't have '%s' attribute. " % field) if not re.search(r"(\s{4}|\t)name\s*=", conanfile_content): out.error("Conanfile doesn't have 'name' attribute.") _message_attr(["url", "license", "description", "homepage", "topics"], out.error) @run_test("KB-H005", output) def test(out): no_copy_source = getattr(conanfile, "no_copy_source", None) if not settings and header_only and not no_copy_source: out.warn( "This recipe is a header only library as it does not declare " "'settings'. Please include 'no_copy_source' to avoid unnecessary copy steps" ) @run_test("KB-H006", output) def test(out): options = getattr(conanfile, "options", None) if settings and options and not header_only and "fPIC" not in options and not installer: out.warn( "This recipe does not include an 'fPIC' option. Make sure you are using the " "right casing") @run_test("KB-H008", output) def test(out): # This regex takes advantage that a conan reference is always a string vrange_match = re.compile( r'.*[\'"][a-zA-Z0-9_+.-]+/\[.+\]@[a-zA-Z0-9_+./-]+[\'"].*') for num, line in enumerate(conanfile_content.splitlines(), 1): if vrange_match.match(line): out.error("Possible use of version ranges, line %s:\n %s" % (num, line)) @run_test("KB-H009", output) def test(out): max_folder_size = int(os.getenv("CONAN_MAX_RECIPE_FOLDER_SIZE_KB", 256)) dir_path = os.path.dirname(conanfile_path) total_size = 0 for path, dirs, files in os.walk(dir_path): dirs[:] = [d for d in dirs if d not in [".conan"] ] # Discard the generated .conan directory if os.path.relpath(path, dir_path).replace( "\\", "/").startswith("test_package/build"): # Discard any file in temp builds continue for files_it in files: file_path = os.path.join(path, files_it) total_size += os.path.getsize(file_path) total_size_kb = total_size / 1024 out.success("Total recipe size: %s KB" % total_size_kb) if total_size_kb > max_folder_size: out.error( "The size of your recipe folder ({} KB) is larger than the maximum allowed" " size ({}KB).".format(total_size_kb, max_folder_size)) @run_test("KB-H023", output) def test(out): for attr_it in ["exports", "exports_sources"]: exports = getattr(conanfile, attr_it, None) out.info("exports: {}".format(exports)) if exports is None: continue exports = [exports] if isinstance(exports, str) else exports for exports_it in exports: for license_it in ["copying", "license", "copyright"]: if license_it in exports_it.lower(): out.error("This recipe is exporting a license file. " "Remove %s from `%s`" % (exports_it, attr_it)) @run_test("KB-H024", output) def test(out): dir_path = os.path.dirname(conanfile_path) test_package_path = os.path.join(dir_path, "test_package") if not os.path.exists(test_package_path): out.error("There is no 'test_package' for this recipe") elif not os.path.exists(os.path.join(test_package_path, "conanfile.py")): out.error("There is no 'conanfile.py' in 'test_package' folder") @run_test("KB-H025", output) def test(out): def _search_for_metaline(from_line, to_line, lines): for index in range(from_line, to_line): line_number = index + 1 if "# -*- coding:" in lines[index] or \ "# coding=" in lines[index]: out.error( "PEP 263 (encoding) is not allowed in the conanfile. " "Remove the line {}".format(line_number)) if "#!" in lines[index]: out.error("Shebang (#!) detected in your recipe. " "Remove the line {}".format(line_number)) if "# vim:" in lines[index]: out.error( "vim editor configuration detected in your recipe. " "Remove the line {}".format(line_number)) conanfile_lines = conanfile_content.splitlines() first_lines_range = 5 if len(conanfile_lines) > 5 else len( conanfile_lines) _search_for_metaline(0, first_lines_range, conanfile_lines) last_lines_range = len(conanfile_lines) - 3 if len( conanfile_lines) > 8 else len(conanfile_lines) _search_for_metaline(last_lines_range, len(conanfile_lines), conanfile_lines) @run_test("KB-H027", output) def test(out): url = getattr(conanfile, "url", None) if url and not url.startswith( "https://github.com/conan-io/conan-center-index"): out.error("The attribute 'url' should point to: " "https://github.com/conan-io/conan-center-index") @run_test("KB-H028", output) def test(out): def _find_cmake_minimum(folder): for (root, _, filenames) in os.walk(folder): for filename in filenames: if filename.lower().startswith("cmake") and \ (filename.endswith(".txt") or filename.endswith(".cmake")) and \ os.path.join("test_package", "build") not in root: cmake_path = os.path.join(root, filename) cmake_content = tools.load(cmake_path).lower() for line in cmake_content.splitlines(): if line.startswith("#") or re.search( r"^\s+#", line) or len(line.strip()) == 0: continue elif "cmake_minimum_required(version" in line or \ "cmake_minimum_required (version" in line: break else: file_path = os.path.join( os.path.relpath(root), filename) out.error( "The CMake file '%s' must contain a minimum version " "declared at the beginning (e.g. cmake_minimum_required(VERSION 3.1.2))" % file_path) dir_path = os.path.dirname(conanfile_path) _find_cmake_minimum(dir_path) @run_test("KB-H029", output) def test(out): test_package_path = os.path.join(export_folder_path, "test_package") if not os.path.exists(os.path.join(test_package_path, "conanfile.py")): return test_package_conanfile = tools.load( os.path.join(test_package_path, "conanfile.py")) if "RunEnvironment" in test_package_conanfile and \ not re.search(r"self\.run\(.*, run_environment=True\)", test_package_conanfile): out.error( "The 'RunEnvironment()' build helper is no longer needed. " "It has been integrated into the self.run(..., run_environment=True)" ) @run_test("KB-H032", output) def test(out): if conanfile.name in ["libusb", "backward-cpp" ] or conanfile.version == "system": out.info("'{}' is part of the allowlist.".format(conanfile.name)) return if "def system_requirements" in conanfile_content and \ "SystemPackageTool" in conanfile_content: import re match = re.search(r'(\S+)\s?=\s?(tools.)?SystemPackageTool', conanfile_content) if ("SystemPackageTool().install" in conanfile_content) or \ (match and "{}.install".format(match.group(1)) in conanfile_content): out.error( "The method 'SystemPackageTool.install' is not allowed in the recipe." ) @run_test("KB-H030", output) def test(out): conandata_path = os.path.join(export_folder_path, "conandata.yml") version = conanfile.version allowed_first_level = ["sources", "patches"] allowed_sources = ["url", "sha256", "sha1", "md5"] allowed_patches = [ "patch_file", "base_path", "url", "sha256", "sha1", "md5" ] def _not_allowed_entries(info, allowed_entries): not_allowed = [] fields = info if isinstance(info, list) else [info] for field in fields: if isinstance(field, dict): return _not_allowed_entries(list(field.keys()), allowed_entries) else: if field not in allowed_entries: not_allowed.append(field) return not_allowed conandata_yml = load_yml(conandata_path) if not conandata_yml: return entries = _not_allowed_entries(list(conandata_yml.keys()), allowed_first_level) if entries: out.error( "First level entries %s not allowed. Use only first level entries %s in " "conandata.yml" % (entries, allowed_first_level)) for entry in conandata_yml: if entry in ['sources', 'patches']: if not isinstance(conandata_yml[entry], dict): out.error( "Expecting a dictionary with versions as keys under '{}' element" .format(entry)) else: versions = conandata_yml[entry].keys() if any([not isinstance(it, str) for it in versions]): out.error( "Versions in conandata.yml should be strings. Add quotes around the numbers" ) def validate_one(e, name, allowed): not_allowed = _not_allowed_entries(e, allowed) if not_allowed: out.error( "Additional entries %s not allowed in '%s':'%s' of " "conandata.yml" % (not_allowed, name, version)) return False return True def validate_recursive(e, data, name, allowed): if isinstance( e, str) and e not in allowed_sources and not isinstance( data[e], str): for child in data[e]: if not validate_recursive(child, data[e], name, allowed): return False return True else: return validate_one(e, name, allowed) if version not in conandata_yml[entry]: continue for element in conandata_yml[entry][version]: if entry == "patches": if not validate_recursive( element, conandata_yml[entry][version], "patches", allowed_patches): return if entry == "sources": if not validate_recursive( element, conandata_yml[entry][version], "sources", allowed_sources): return @run_test("KB-H034", output) def test(out): test_package_path = os.path.join(export_folder_path, "test_package") if not os.path.exists(os.path.join(test_package_path, "conanfile.py")): return test_package_conanfile = tools.load( os.path.join(test_package_path, "conanfile.py")) if "def imports" in test_package_conanfile: out.error( "The method `imports` is not allowed in test_package/conanfile.py" ) @run_test("KB-H037", output) def test(out): author = getattr(conanfile, "author", None) if author: if isinstance(author, str): author = '"%s"' % author out.error( "Conanfile should not contain author. Remove 'author = {}'". format(author)) @run_test("KB-H040", output) def test(out): if "self.cpp_info.name =" in conanfile_content: out.error("CCI uses the name of the package for cmake generator." " Use 'cpp_info.names' instead.") for generator in ["cmake", "cmake_multi"]: if "self.cpp_info.names['{}']".format(generator) in conanfile_content or \ 'self.cpp_info.names["{}"]'.format(generator) in conanfile_content: out.error( "CCI uses the name of the package for {0} generator. " "Conanfile should not contain 'self.cpp_info.names['{0}']'. " " Use 'cmake_find_package' and 'cmake_find_package_multi' instead." .format(generator)) @run_test("KB-H041", output) def test(out): checked_fileexts = ".c", ".cc", ".cpp", ".cxx", ".h", ".hxx", ".hpp", \ ".py", ".txt", ".yml", ".cmake", ".xml", ".patch", ".md" files_noext = "Makefile", "GNUMakefile" def _check_final_newline(path): try: last_char = tools.load(path)[-1] except (OSError, IndexError): return # File is empty ==> ignore if last_char not in ("\n", "\r"): out.error( "File '{}' does not end with an endline".format(path)) for root, _, filenames in os.walk(export_folder_path): if os.path.relpath(root, export_folder_path).replace( "\\", "/").startswith("test_package/build"): # Discard any file in temp builds continue for filename in filenames: _, fileext = os.path.splitext(filename) if filename in files_noext or fileext.lower( ) in checked_fileexts: _check_final_newline(os.path.join(root, filename)) config_yml = os.path.join(export_folder_path, os.path.pardir, "config.yml") if os.path.isfile(config_yml): _check_final_newline(config_yml) @run_test("KB-H044", output) def test(out): for forbidden in ["self.requires.add", "self.build_requires.add"]: if forbidden in conanfile_content: out.error( "The method '{}()' is not allowed. Use '{}()' instead.". format(forbidden, forbidden.replace(".add", ""))) @run_test("KB-H045", output) def test(out): if "self.options.remove" in conanfile_content: out.error( "Found 'self.options.remove'. Replace it by 'del self.options.<opt>'." ) @run_test("KB-H047", output) def test(out): def _check_non_ascii(filename, content): import unicodedata for num, line in enumerate(content.splitlines(), 1): bad_chars = { num: char for num, char in enumerate(line, 1) if ord(char) >= 128 } if bad_chars: out.error( "The file '{}' contains a non-ascii character at line ({})." " Only ASCII characters are allowed, please remove it." .format(filename, num)) indexes = bad_chars.keys() draw = [ '^' if i in indexes else ' ' for i in range(1, len(line)) ] draw = ''.join(draw) bad_chars = bad_chars.values() bad_chars = [ "\\x%s (%s)" % (format(ord(c), 'x'), unicodedata.name(c)) for c in bad_chars ] message = "bad characters: " + ' '.join(bad_chars) output.info(message) output.info(line) output.info(draw) _check_non_ascii("conanfile.py", conanfile_content) test_package_dir = os.path.join(os.path.dirname(conanfile_path), "test_package") test_package_path = os.path.join(test_package_dir, "conanfile.py") if os.path.exists(test_package_path): test_package_content = tools.load(test_package_path) _check_non_ascii("test_package/conanfile.py", test_package_content) @run_test("KB-H046", output) def test(out): def check_for_verbose_flag(cmakelists_path): cmake_content = tools.load(cmakelists_path) if "cmake_verbose_makefile" in cmake_content.lower(): out.error( "The CMake definition 'set(CMAKE_VERBOSE_MAKEFILE ON)' is not allowed. " "Remove it from {}.".format( os.path.relpath(cmakelists_path))) dir_path = os.path.dirname(conanfile_path) test_package_path = os.path.join(dir_path, "test_package") for cmake_path in [ os.path.join(dir_path, "CMakeLists.txt"), os.path.join(test_package_path, "CMakeLists.txt") ]: if os.path.exists(cmake_path): check_for_verbose_flag(cmake_path) @run_test("KB-H048", output) def test(out): dir_path = os.path.dirname(conanfile_path) cmake_test_pkg = os.path.join(dir_path, "test_package", "CMakeLists.txt") if os.path.isfile(cmake_test_pkg): cmake_content = tools.load(cmake_test_pkg) if re.search(r"cmake_minimum_required\(version [\"']?2", cmake_content.lower()): out.error( "The test_package/CMakeLists.txt requires CMake 3.1 at least." " Update to 'cmake_minimum_required(VERSION 3.1)'.") cmake_path = os.path.join(dir_path, "CMakeLists.txt") if os.path.isfile(cmake_path): cmake_content = tools.load(cmake_path) if re.search(r"cmake_minimum_required\(version [\"']?2", cmake_content.lower()) and \ "cxx_standard" in cmake_content.lower(): out.error( "The CMake definition CXX_STANDARD requires CMake 3.1 at least." " Update to 'cmake_minimum_required(VERSION 3.1)'.") @run_test("KB-H049", output) def test(out): dir_path = os.path.dirname(conanfile_path) cmake_path = os.path.join(dir_path, "CMakeLists.txt") if os.path.isfile(cmake_path): cmake_content = tools.load(cmake_path) match = re.search( r"cmake_minimum_required\s?\(VERSION (\d?\.?\d?\.?\d+)\)", cmake_content, re.I) if match and tools.Version(match.group(1)) < "3.4": for cmake_def in [ "CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS", "WINDOWS_EXPORT_ALL_SYMBOLS" ]: if cmake_def in cmake_content: out.error( "The CMake definition {} requires CMake 3.4 at least. Update " "CMakeLists.txt to 'cmake_minimum_required(VERSION 3.4)'." .format(cmake_def)) break @run_test("KB-H051", output) def test(out): default_options = getattr(conanfile, "default_options") if default_options and not isinstance(default_options, dict): out.error("Use a dictionary to declare 'default_options'") @run_test("KB-H052", output) def test(out): config_path = os.path.abspath( os.path.join(export_folder_path, os.path.pardir, "config.yml")) config_yml = load_yml(config_path) conandata_path = os.path.join(export_folder_path, "conandata.yml") conandata_yml = load_yml(conandata_path) if not config_yml or not conandata_yml: return if 'versions' not in config_yml: return if 'sources' not in conandata_yml: return versions_conandata = conandata_yml['sources'].keys() versions_config = config_yml['versions'].keys() conandata_path = os.path.relpath(conandata_path, export_folder_path) config_path = os.path.relpath(config_path, export_folder_path) for version in versions_conandata: if version not in versions_config: out.error( 'The version "{}" exists in "{}" but not in "{}", so it will not be built.' ' Please update "{}" to include newly added ' 'version "{}".'.format(version, conandata_path, config_path, config_path, version)) @run_test("KB-H053", output) def test(out): def _is_private_import(line): if line in ["from conans.model import Generator"]: return False allowed_list = ["tools", "errors"] for pattern in ["from conans.", "import conans."]: if line.startswith(pattern): for allowed in allowed_list: if line.startswith(pattern + allowed): return False return True return False def _check_private_imports(filename, content): for num, line in enumerate(content.splitlines(), 1): if _is_private_import(line): out.error( "The file {} imports private conan API on line {}, " "this is strongly discouraged.".format(filename, num)) out.error(line) _check_private_imports("conanfile.py", conanfile_content) test_package_dir = os.path.join(os.path.dirname(conanfile_path), "test_package") test_package_path = os.path.join(test_package_dir, "conanfile.py") if os.path.exists(test_package_path): test_package_content = tools.load(test_package_path) _check_private_imports("test_package/conanfile.py", test_package_content) @run_test("KB-H055", output) def test(out): for prefix in ["", "build_"]: if hasattr(conanfile, "{}requires".format(prefix)) and \ callable(getattr(conanfile, "{}requirements".format(prefix), None)): out.error( "Both '{0}requires' attribute and '{0}requirements()' method should not " "be declared at same recipe.".format(prefix))
def _get_version_from_dependency_file(): file_content = tools.load(DEPENDENCY_FILE_PATH) content = json.loads(file_content) return str(content['version'])
def patch_config_paths(self): """ changes references to the absolute path of the installed package and its dependencies in exported cmake config files to the appropriate conan variable. This makes most (sensible) cmake config files portable. For example, if a package foo installs a file called "fooConfig.cmake" to be used by cmake's find_package method, normally this file will contain absolute paths to the installed package folder, for example it will contain a line such as: SET(Foo_INSTALL_DIR /home/developer/.conan/data/Foo/1.0.0/...) This will cause cmake find_package() method to fail when someone else installs the package via conan. This function will replace such mentions to SET(Foo_INSTALL_DIR ${CONAN_FOO_ROOT}) which is a variable that is set by conanbuildinfo.cmake, so that find_package() now correctly works on this conan package. For dependent packages, if a package foo installs a file called "fooConfig.cmake" to be used by cmake's find_package method and if it depends to a package bar, normally this file will contain absolute paths to the bar package folder, for example it will contain a line such as: SET_TARGET_PROPERTIES(foo PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "/home/developer/.conan/data/Bar/1.0.0/user/channel/id/include") This function will replace such mentions to SET_TARGET_PROPERTIES(foo PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CONAN_BAR_ROOT}/include") If the install() method of the CMake object in the conan file is used, this function should be called _after_ that invocation. For example: def build(self): cmake = CMake(self) cmake.configure() cmake.build() cmake.install() cmake.patch_config_paths() """ if not self._conanfile.should_install: return if not self._conanfile.name: raise ConanException( "cmake.patch_config_paths() can't work without package name. " "Define name in your recipe") pf = self.definitions.get(cmake_install_prefix_var_name) replstr = "${CONAN_%s_ROOT}" % self._conanfile.name.upper() allwalk = chain(os.walk(self._conanfile.build_folder), os.walk(self._conanfile.package_folder)) for root, _, files in allwalk: for f in files: if f.endswith(".cmake"): path = os.path.join(root, f) tools.replace_in_file(path, pf, replstr, strict=False) # patch paths of dependent packages that are found in any cmake files of the # current package path_content = tools.load(path) for dep in self._conanfile.deps_cpp_info.deps: from_str = self._conanfile.deps_cpp_info[dep].rootpath # try to replace only if from str is found if path_content.find(from_str) != -1: dep_str = "${CONAN_%s_ROOT}" % dep.upper() self._conanfile.output.info( "Patching paths for %s: %s to %s" % (dep, from_str, dep_str)) tools.replace_in_file(path, from_str, dep_str, strict=False)
def package(self): header = tools.load(os.path.join(self._source_subfolder, "sqlite3.h")) license_content = header[3:header.find("***", 1)] tools.save(os.path.join(self.package_folder, "licenses", "LICENSE"), license_content) cmake = self._configure_cmake() cmake.install()
def _extract_license(self): header = tools.load(os.path.join( self._source_subfolder, "portable_endian.h")) license_contents = header[0:(header.find("#ifndef", 1))] tools.save("LICENSE", license_contents)
def set_version(self): content = load(os.path.join(self.recipe_folder, "CMakeLists.txt")) version = re.search(r"project\(cdsp VERSION (.*)\)", content).group(1) self.version = version.strip()
def configure(self): self.repo_revision = tools.load("revision")
def _create_components_file_from_cmake_target_file(self, target_file_path): components = {} target_content = tools.load(target_file_path) cmake_functions = re.findall( r"(?P<func>add_library|set_target_properties)[\n|\s]*\([\n|\s]*(?P<args>[^)]*)\)", target_content) for (cmake_function_name, cmake_function_args) in cmake_functions: cmake_function_args = re.split(r"[\s|\n]+", cmake_function_args, maxsplit=2) cmake_imported_target_name = cmake_function_args[0] cmake_target_nonamespace = cmake_imported_target_name.replace( "nmos-cpp::", "") component_name = cmake_target_nonamespace.lower() # Conan component name cannot be the same as the package name if component_name == "nmos-cpp": component_name = "nmos-cpp-lib" components.setdefault(component_name, {"cmake_target": cmake_target_nonamespace}) if cmake_function_name == "add_library": cmake_imported_target_type = cmake_function_args[1] if cmake_imported_target_type in ["STATIC", "SHARED"]: # library filenames are based on the target name by default lib_name = cmake_target_nonamespace # the filename may be changed by a straightforward command: # set_property(TARGET Bonjour PROPERTY OUTPUT_NAME dnssd) # but we'd have to read the nmos-cpp-targets-<config>.cmake files # and parse the IMPORTED_LOCATION_<CONFIG> values if lib_name == "Bonjour": lib_name = "dnssd" components[component_name]["libs"] = [lib_name] elif cmake_function_name == "set_target_properties": target_properties = re.findall( r"(?P<property>INTERFACE_[A-Z_]+)[\n|\s]+\"(?P<values>.+)\"", cmake_function_args[2]) for target_property in target_properties: property_type = target_property[0] # '\', '$' and '"' are escaped; '$' especially is important here # see https://github.com/conan-io/conan/blob/release/1.39/conans/client/generators/cmake_common.py#L43-L48 property_values = re.sub(r"\\(.)", r"\1", target_property[1]).split(";") if property_type == "INTERFACE_LINK_LIBRARIES": for dependency in property_values: match_private = re.fullmatch( r"\$<LINK_ONLY:(.+)>", dependency) if match_private: dependency = match_private.group(1) if "::" in dependency: dependency = dependency.replace( "nmos-cpp::", "") # Conan component name cannot be the same as the package name if dependency == "nmos-cpp": dependency = "nmos-cpp-lib" # Conan packages for Boost, cpprestsdk, websocketpp, OpenSSL and Avahi have component names that (except for being lowercase) match the CMake targets # json-schema-validator overrides cmake_find_package[_multi] names elif dependency == "nlohmann_json_schema_validator::nlohmann_json_schema_validator": dependency = "json-schema-validator::json-schema-validator" # mdnsresponder overrides cmake_find_package[_multi] names elif dependency == "DNSSD::DNSSD": dependency = "mdnsresponder::mdnsresponder" components[component_name].setdefault( "requires" if not match_private else "requires_private", []).append(dependency.lower()) elif "${_IMPORT_PREFIX}/lib/" in dependency: self.output.warn( "{} recipe does not handle {} {} (yet)". format(self.name, property_type, dependency)) else: components[component_name].setdefault( "system_libs", []).append(dependency) elif property_type == "INTERFACE_COMPILE_DEFINITIONS": for property_value in property_values: components[component_name].setdefault( "defines", []).append(property_value) elif property_type == "INTERFACE_COMPILE_FEATURES": for property_value in property_values: if property_value not in ["cxx_std_11"]: self.output.warn( "{} recipe does not handle {} {} (yet)". format(self.name, property_type, property_value)) elif property_type == "INTERFACE_COMPILE_OPTIONS": for property_value in property_values: # handle forced include (Visual Studio /FI, gcc -include) by relying on includedirs containing "include" property_value = property_value.replace( "${_IMPORT_PREFIX}/include/", "") components[component_name].setdefault( "cxxflags", []).append(property_value) elif property_type == "INTERFACE_INCLUDE_DIRECTORIES": for property_value in property_values: if property_value not in [ "${_IMPORT_PREFIX}/include" ]: self.output.warn( "{} recipe does not handle {} {} (yet)". format(self.name, property_type, property_value)) elif property_type == "INTERFACE_LINK_OPTIONS": for property_value in property_values: # workaround required because otherwise "/ignore:4099" gets converted to "\ignore:4099.obj" # thankfully the MSVC linker accepts both '/' and '-' for the option specifier and Visual Studio # handles link options appearing in Link/AdditionalDependencies rather than Link/AdditionalOptions # because the CMake generators put them in INTERFACE_LINK_LIBRARIES rather than INTERFACE_LINK_OPTIONS # see https://github.com/conan-io/conan/pull/8812 # and https://docs.microsoft.com/en-us/cpp/build/reference/linking?view=msvc-160#command-line property_value = re.sub(r"^/", r"-", property_value) components[component_name].setdefault( "linkflags", []).append(property_value) else: self.output.warn( "{} recipe does not handle {} (yet)".format( self.name, property_type)) # Save components informations in json file with open(self._components_helper_filepath, "w") as json_file: json.dump(components, json_file, indent=4)
def _extract_license(self): aaplus_header = tools.load( os.path.join(self._source_subfolder, "AA+.h")) begin = aaplus_header.find("Copyright") end = aaplus_header.find("*/", begin) return aaplus_header[begin:end]
def load_yml(path): if os.path.isfile(path): return yaml.safe_load(tools.load(path)) return None
def _extract_license(self): header = tools.load( os.path.join(self._source_subfolder, "angelscript", "include", "angelscript.h")) tools.save("LICENSE", header[header.find("/*", 1) + 3:header.find("*/", 1)])
def copy_file_to_source(self, name): file_content = tools.load(name) path_to_source = os.path.join(self.source_folder, self.folder_name, name) tools.save(path_to_source, file_content) print("Copied", name, "=>", path_to_source)
def _get_license(self): readme = tools.load(os.path.join(self.source_folder, self._source_subfolder, "README.md")) begin = readme.find("Copyright") end = readme.find("\n## Introduction", begin) return readme[begin:end]
def get_command(self, project_file, props_file_path=None, targets=None, upgrade_project=True, build_type=None, arch=None, parallel=True, toolset=None, platforms=None, use_env=False): targets = targets or [] command = [] if upgrade_project and not get_env("CONAN_SKIP_VS_PROJECTS_UPGRADE", False): command.append("devenv %s /upgrade &&" % project_file) else: self._output.info("Skipped sln project upgrade") build_type = build_type or self._settings.get_safe("build_type") arch = arch or self._settings.get_safe("arch") if not build_type: raise ConanException("Cannot build_sln_command, build_type not defined") if not arch: raise ConanException("Cannot build_sln_command, arch not defined") command.append("msbuild %s /p:Configuration=%s" % (project_file, build_type)) msvc_arch = {'x86': 'x86', 'x86_64': 'x64', 'armv7': 'ARM', 'armv8': 'ARM64'} if platforms: msvc_arch.update(platforms) msvc_arch = msvc_arch.get(str(arch)) try: sln = tools.load(project_file) pattern = re.compile(r"GlobalSection\(SolutionConfigurationPlatforms\)" r"(.*?)EndGlobalSection", re.DOTALL) solution_global = pattern.search(sln).group(1) lines = solution_global.splitlines() lines = [s.split("=")[0].strip() for s in lines] except Exception: pass else: config = "%s|%s" % (build_type, msvc_arch) if config not in "".join(lines): self._output.warn("***** The configuration %s does not exist in this solution *****" % config) self._output.warn("Use 'platforms' argument to define your architectures") if use_env: command.append('/p:UseEnv=true') if msvc_arch: command.append('/p:Platform="%s"' % msvc_arch) if parallel: command.append('/m:%s' % cpu_count()) if targets: command.append("/target:%s" % ";".join(targets)) if toolset: command.append("/p:PlatformToolset=%s" % toolset) if props_file_path: command.append('/p:ForceImportBeforeCppTargets="%s"' % props_file_path) return " ".join(command)
def package(self): self.output.warn("local cache: %s" % self.in_local_cache) self.output.warn("develop: %s" % self.develop) # Extract the License/s from the header to a file with tools.chdir(os.path.join(self.source_folder, self.ZIP_FOLDER_NAME)): tmp = tools.load("zlib.h") license_contents = tmp[2:tmp.find("*/", 1)] tools.save("LICENSE", license_contents) # Copy the license files self.copy("LICENSE", src=self.ZIP_FOLDER_NAME, dst=".") # Copy pc file self.copy("*.pc", dst="", keep_path=False) # Copying zlib.h, zutil.h, zconf.h self.copy("*.h", "include", "%s" % self.ZIP_FOLDER_NAME, keep_path=False) self.copy("*.h", "include", "%s" % "_build", keep_path=False) # Copying static and dynamic libs build_dir = os.path.join(self.ZIP_FOLDER_NAME, "_build") if self.settings.os == "Windows": if self.options.shared: build_dir = os.path.join(self.ZIP_FOLDER_NAME, "_build") self.copy(pattern="*.dll", dst="bin", src=build_dir, keep_path=False) build_dir = os.path.join(self.ZIP_FOLDER_NAME, "_build/lib") self.copy(pattern="*zlibd.lib", dst="lib", src=build_dir, keep_path=False) self.copy(pattern="*zlib.lib", dst="lib", src=build_dir, keep_path=False) self.copy(pattern="*zlib.dll.a", dst="lib", src=build_dir, keep_path=False) else: build_dir = os.path.join(self.ZIP_FOLDER_NAME, "_build/lib") if self.settings.os == "Windows": # MinGW self.copy(pattern="libzlibstaticd.a", dst="lib", src=build_dir, keep_path=False) self.copy(pattern="libzlibstatic.a", dst="lib", src=build_dir, keep_path=False) # Visual Studio self.copy(pattern="zlibstaticd.lib", dst="lib", src=build_dir, keep_path=False) self.copy(pattern="zlibstatic.lib", dst="lib", src=build_dir, keep_path=False) lib_path = os.path.join(self.package_folder, "lib") suffix = "d" if self.settings.build_type == "Debug" else "" if self.settings.compiler == "Visual Studio": current_lib = os.path.join(lib_path, "zlibstatic%s.lib" % suffix) os.rename(current_lib, os.path.join(lib_path, "zlib%s.lib" % suffix)) elif self.settings.compiler == "gcc": current_lib = os.path.join(lib_path, "libzlibstatic.a") os.rename(current_lib, os.path.join(lib_path, "libzlib.a")) else: if self.options.shared: if self.settings.os == "Macos": self.copy(pattern="*.dylib", dst="lib", src=build_dir, keep_path=False) else: self.copy(pattern="*.so*", dst="lib", src=build_dir, keep_path=False) else: self.copy(pattern="*.a", dst="lib", src=build_dir, keep_path=False)
def run(output, reply_dir, build_type, conanfile_name): message = '' for filename in os.listdir(reply_dir): if fnmatch.fnmatch(filename, "codemodel-v2-*.json"): codemodel = json.loads( tools.load(os.path.join(reply_dir, filename))) if 'configurations' not in codemodel: output.warn("codemodel doesn't have configurations") return for configuration in codemodel['configurations']: if 'name' not in configuration: output.warn("configuration doesn't have a name") continue if configuration['name'] == build_type: if 'projects' not in configuration: output.warn("configuration %s doesn't have projects" % configuration['name']) continue if 'targets' not in configuration: output.warn("configuration %s doesn't have targets" % configuration['name']) continue for project in configuration['projects']: if 'name' not in project: output.warn("project doesn't have a name") continue if project['name'] != 'cmake_wrapper': output.info('found CMake project: "%s"' % project['name']) if project['name'] != conanfile_name: name = project['name'] output.warn( 'project name "%s" is different from conanfile name "%s"' % (name, conanfile_name)) message += cmake_template.format(name=name) for target in configuration['targets']: if 'name' not in target: output.warn("target doesn't have a name") continue if target['name'] not in SKIP_TARGETS: target_js = json.loads( tools.load( os.path.join(reply_dir, target['jsonFile']))) if 'install' in target_js: if 'name' not in target_js: output.warn( "target.js doesn't have a name") continue if 'nameOnDisk' not in target_js: output.warn( "target.js doesn't have a nameOnDisk") continue if 'type' not in target_js: output.warn( "target.js doesn't have a type") continue name = target_js['name'] nameOnDisk = target_js['nameOnDisk'] type = target_js['type'] dependencies = target_js.get( 'dependencies', []) requires = [] for dependency in dependencies: if 'id' not in dependency: output.warn( "dependency doesn't have an id") continue id = dependency["id"] dependency_name, _ = id.split("::@") if dependency_name not in SKIP_TARGETS: requires.append(dependency_name) if len(requires): requires = ', '.join( ['"%s"' % r for r in requires]) requires = requires_template.format( component=name, requires=requires) else: requires = '' if type != 'EXECUTABLE': output.info( 'found CMake %s target: "%s" ("%s")' % (type, name, nameOnDisk)) link = nameOnDisk if fnmatch.fnmatch(nameOnDisk, '*.lib'): link = nameOnDisk[:-4] if fnmatch.fnmatch(nameOnDisk, '*.dll'): link = nameOnDisk[:-4] if fnmatch.fnmatch(nameOnDisk, 'lib*.a'): link = nameOnDisk[3:-2] if name != conanfile_name: output.warn( 'target name "%s" is different from conanfile name "%s"' % (name, conanfile_name)) message += component_template.format( name=name, component=name, link=link, requires=requires) if message: output.warn( 'consider adding the following code to the "package_info" method:' ) output.warn(message) break
def run(self): if self._config_url: ConfigManager(self._conan_api, self.printer).install(url=self._config_url) context = tools.no_op() compiler = self.settings.get("compiler", None) if not self._exclude_vcvars_precommand: if compiler == "Visual Studio" and "compiler.version" in self.settings: compiler_set = namedtuple("compiler", "version")(self.settings["compiler.version"]) mock_sets = namedtuple("mock_settings", "arch compiler get_safe")(self.settings["arch"], compiler_set, lambda x: self.settings.get(x, None)) context = tools.vcvars(mock_sets) with context: self.printer.print_rule() self.printer.print_profile(tools.load(self._profile_abs_path)) with self.printer.foldable_output("conan_create"): if client_version < Version("1.10.0"): name, version, user, channel = self._reference else: name, version, user, channel, _ = self._reference if self._build_policy: self._build_policy = [self._build_policy] # https://github.com/conan-io/conan-package-tools/issues/184 with tools.environment_append({"_CONAN_CREATE_COMMAND_": "1"}): params = {"name": name, "version": version, "user": user, "channel": channel, "build_modes": self._build_policy, "profile_name": self._profile_abs_path} self.printer.print_message("Calling 'conan create'") self.printer.print_dict(params) with tools.chdir(self._cwd): if Version(client_version) >= "1.8.0": from conans.errors import ConanInvalidConfiguration exc_class = ConanInvalidConfiguration else: exc_class = None try: if client_version < Version("1.12.0"): r = self._conan_api.create(".", name=name, version=version, user=user, channel=channel, build_modes=self._build_policy, profile_name=self._profile_abs_path, test_folder=self._test_folder) else: r = self._conan_api.create(".", name=name, version=version, user=user, channel=channel, build_modes=self._build_policy, profile_names=[self._profile_abs_path], test_folder=self._test_folder) except exc_class as e: self.printer.print_rule() self.printer.print_message("Skipped configuration by the recipe: " "%s" % str(e)) self.printer.print_rule() return for installed in r['installed']: if installed["recipe"]["id"] == str(self._reference): package_id = installed['packages'][0]['id'] if installed['packages'][0]["built"]: self._uploader.upload_packages(self._reference, self._upload, package_id) else: self.printer.print_message("Skipping upload for %s, " "it hasn't been built" % package_id)
def _extract_license(self): readme = tools.load(os.path.join(self._source_subfolder, "README")) match = next( re.finditer("\n[^\n]*license[^\n]*\n", readme, flags=re.I | re.A)) return readme[match.span()[1]:].strip("*").strip()
def package(self): self.output.warn("local cache: %s" % self.in_local_cache) self.output.warn("develop: %s" % self.develop) # Extract the License/s from the header to a file with tools.chdir( os.path.join(self.source_folder, self._source_subfolder)): tmp = tools.load("zlib.h") license_contents = tmp[2:tmp.find("*/", 1)] tools.save("LICENSE", license_contents) # Copy the license files self.copy("LICENSE", src=self._source_subfolder, dst="licenses") # Copy pc file self.copy("*.pc", dst="", keep_path=False) # Copy headers for header in ["*zlib.h", "*zconf.h"]: self.copy(pattern=header, dst="include", src=self._source_subfolder, keep_path=False) self.copy(pattern=header, dst="include", src="_build", keep_path=False) # Copying static and dynamic libs build_dir = os.path.join(self._source_subfolder, "_build") lib_path = os.path.join(self.package_folder, "lib") suffix = "d" if self.settings.build_type == "Debug" else "" if self.settings.os == "Windows": if self.options.shared: build_dir = os.path.join(self._source_subfolder, "_build") self.copy(pattern="*.dll", dst="bin", src=build_dir, keep_path=False) build_dir = os.path.join(self._source_subfolder, "_build/lib") self.copy(pattern="*zlibd.lib", dst="lib", src=build_dir, keep_path=False) self.copy(pattern="*zlib.lib", dst="lib", src=build_dir, keep_path=False) self.copy(pattern="*zlib.dll.a", dst="lib", src=build_dir, keep_path=False) if tools.os_info.is_linux: self.copy(pattern="*libz.dll.a", dst="lib", src=self._source_subfolder) if self.settings.compiler == "Visual Studio": current_lib = os.path.join(lib_path, "zlib%s.lib" % suffix) os.rename(current_lib, os.path.join(lib_path, "zlib.lib")) else: build_dir = os.path.join(self._source_subfolder, "_build/lib") if self.settings.os == "Windows": if tools.os_info.is_windows: # MinGW self.copy(pattern="libzlibstaticd.a", dst="lib", src=build_dir, keep_path=False) self.copy(pattern="libzlibstatic.a", dst="lib", src=build_dir, keep_path=False) # Visual Studio self.copy(pattern="zlibstaticd.lib", dst="lib", src=build_dir, keep_path=False) self.copy(pattern="zlibstatic.lib", dst="lib", src=build_dir, keep_path=False) elif not tools.os_info.is_linux: # MSYS/Cygwin build self.copy(pattern="*libz.a", dst="lib", src=self._source_subfolder, keep_path=False) if tools.os_info.is_linux: self.copy(pattern="libz.a", dst="lib", src=self._source_subfolder, keep_path=False) if self.settings.compiler == "Visual Studio": current_lib = os.path.join(lib_path, "zlibstatic%s.lib" % suffix) os.rename(current_lib, os.path.join(lib_path, "zlib.lib")) elif self.settings.compiler == "gcc": if tools.os_info.is_windows: current_lib = os.path.join(lib_path, "libzlibstatic.a") os.rename(current_lib, os.path.join(lib_path, "libzlib.a")) else: if self.options.shared: if self.settings.os == "Macos": self.copy(pattern="*.dylib", dst="lib", src=build_dir, keep_path=False, symlinks=True) else: self.copy(pattern="*.so*", dst="lib", src=build_dir, keep_path=False, symlinks=True) else: self.copy(pattern="*.a", dst="lib", src=build_dir, keep_path=False)
def _extract_license(self): file = os.path.join(self.package_folder, "include/cute_math2d.h") file_content = tools.load(file) return file_content[file_content.rfind('/*'):]
def read(filename, decode=True): ''' Reads the contents of a file ''' data = tools.load(filename, binary=True) return data.decode('utf-8') if decode == True else data
def package(self): self.copy('LICENSE.TXT', dst='licenses', src=self._source_subfolder) lib_path = os.path.join(self.package_folder, 'lib') cmake = self._configure_cmake() cmake.install() if not self.options.shared: for ext in ['.a', '.lib']: lib = '**/lib/*LLVMTableGenGlobalISel{}'.format(ext) self.copy(lib, dst='lib', keep_path=False) lib = '*LLVMTableGenGlobalISel{}'.format(ext) self.copy(lib, dst='lib', src='lib') CMake(self).configure(args=['--graphviz=graph/llvm.dot'], source_dir='.', build_dir='.') with tools.chdir('graph'): dot_text = tools.load('llvm.dot').replace('\r\n', '\n') dep_regex = re.compile(r'//\s(.+)\s->\s(.+)$', re.MULTILINE) deps = re.findall(dep_regex, dot_text) dummy_targets = defaultdict(list) for target, dep in deps: if not target.startswith('LLVM'): dummy_targets[target].append(dep) cmake_targets = { 'libffi::libffi': 'ffi', 'ZLIB::ZLIB': 'z', 'Iconv::Iconv': 'iconv', 'LibXml2::LibXml2': 'xml2' } components = defaultdict(list) for lib, dep in deps: if not lib.startswith('LLVM'): continue elif dep.startswith('-delayload:'): continue elif dep.startswith('LLVM'): components[dep] elif dep in cmake_targets: dep = cmake_targets[dep] elif os.path.exists(dep): dep = os.path.splitext(os.path.basename(dep))[0] dep = dep.replace('lib', '') dep = dep.replace('-l', '') if dep in dummy_targets.keys(): components[lib].extend(dummy_targets[dep]) components[lib] = list(set(components[lib])) else: components[lib].append(dep) tools.rmdir(os.path.join(self.package_folder, 'bin')) tools.rmdir(os.path.join(self.package_folder, 'lib', 'cmake')) tools.rmdir(os.path.join(self.package_folder, 'share')) for name in os.listdir(lib_path): if 'LLVM' not in name: os.remove(os.path.join(lib_path, name)) if not self.options.shared: if self.options.get_safe('with_zlib', False): if not 'z' in components['LLVMSupport']: components['LLVMSupport'].append('z') components_path = \ os.path.join(self.package_folder, 'lib', 'components.json') with open(components_path, 'w') as components_file: json.dump(components, components_file, indent=4) else: suffixes = ['.dylib', '.so'] for name in os.listdir(lib_path): if not any(suffix in name for suffix in suffixes): os.remove(os.path.join(lib_path, name))
def _extract_pffft_license(self): pffft_c = tools.load(os.path.join(self._source_subfolder, "src", "pffft.c")) license_contents = pffft_c[pffft_c.find("/* Copyright")+3:pffft_c.find("modern CPUs.")+13] tools.save(os.path.join(self.package_folder, "licenses", "LICENSE"), license_contents)
from cpt.packager import ConanMultiPackager from conans import tools if __name__ == "__main__": builder = ConanMultiPackager(username="******", reference="libvncserver/" + tools.load("version.txt"), channel="testing", stable_branch_pattern="release/*") builder.add_common_builds() builder.run()