def replace_path_in_file(file_path, search, replace, strict=True, windows_paths=None, output=None): output = default_output(output, 'conans.client.tools.files.replace_path_in_file') if windows_paths is False or (windows_paths is None and platform.system() != "Windows"): return replace_in_file(file_path, search, replace, strict=strict, output=output) def normalized_text(text): return text.replace("\\", "/").lower() content = load(file_path) normalized_content = normalized_text(content) normalized_search = normalized_text(search) index = normalized_content.find(normalized_search) if index == -1: return _manage_text_not_found(search, file_path, strict, "replace_path_in_file", output=output) while index != -1: content = content[:index] + replace + content[index + len(search):] normalized_content = normalized_text(content) index = normalized_content.find(normalized_search) content = content.encode("utf-8") with open(file_path, "wb") as handle: handle.write(content) return True
def replace_in_file(file_path, search, replace, strict=True, output=None, encoding=None): output = default_output(output, 'conans.client.tools.files.replace_in_file') encoding_in = encoding or "auto" encoding_out = encoding or "utf-8" content = load(file_path, encoding=encoding_in) if -1 == content.find(search): _manage_text_not_found(search, file_path, strict, "replace_in_file", output=output) content = content.replace(search, replace) content = content.encode(encoding_out) save(file_path, content, only_if_modified=False, encoding=encoding_out)
def build_sln_command(settings, sln_path, targets=None, upgrade_project=True, build_type=None, arch=None, parallel=True, toolset=None, platforms=None, output=None): """ Use example: build_command = build_sln_command(self.settings, "myfile.sln", targets=["SDL2_image"]) command = "%s && %s" % (tools.vcvars_command(self.settings), build_command) self.run(command) """ from conans.client.build.msbuild import MSBuild tmp = MSBuild(settings) output = default_output( output, fn_name='conans.client.tools.win.build_sln_command') tmp._output = output # Generate the properties file props_file_contents = tmp._get_props_file_contents() tmp_path = os.path.join(mkdir_tmp(), ".conan_properties") save(tmp_path, props_file_contents) # Build command command = tmp.get_command(sln_path, tmp_path, targets=targets, upgrade_project=upgrade_project, build_type=build_type, arch=arch, parallel=parallel, toolset=toolset, platforms=platforms, use_env=False) return command
def vcvars_command(settings, arch=None, compiler_version=None, force=False, vcvars_ver=None, winsdk_version=None, output=None): output = default_output(output, 'conans.client.tools.win.vcvars_command') arch_setting = arch or settings.get_safe("arch") compiler = settings.get_safe("compiler") if compiler == 'Visual Studio': compiler_version = compiler_version or settings.get_safe( "compiler.version") else: # vcvars might be still needed for other compilers, e.g. clang-cl or Intel C++, # as they might be using Microsoft STL and other tools # (e.g. resource compiler, manifest tool, etc) # in this case, use the latest Visual Studio available on the machine last_version = latest_vs_version_installed(output=output) compiler_version = compiler_version or last_version os_setting = settings.get_safe("os") if not compiler_version: raise ConanException( "compiler.version setting required for vcvars not defined") # https://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx arch_setting = arch_setting or 'x86_64' arch_build = settings.get_safe("arch_build") or detected_architecture() if arch_build == 'x86_64': # Only uses x64 tooling if arch_build explicitly defines it, otherwise # Keep the VS default, which is x86 toolset # This will probably be changed in conan 2.0 if ((settings.get_safe("arch_build") or os.getenv("PreferredToolArchitecture") == "x64") and int(compiler_version) >= 12): x86_cross = "amd64_x86" else: x86_cross = "x86" vcvars_arch = { 'x86': x86_cross, 'x86_64': 'amd64', 'armv7': 'amd64_arm', 'armv8': 'amd64_arm64' }.get(arch_setting) elif arch_build == 'x86': vcvars_arch = { 'x86': 'x86', 'x86_64': 'x86_amd64', 'armv7': 'x86_arm', 'armv8': 'x86_arm64' }.get(arch_setting) if not vcvars_arch: raise ConanException('unsupported architecture %s' % arch_setting) existing_version = os.environ.get("VisualStudioVersion") if existing_version: command = ["echo Conan:vcvars already set"] existing_version = existing_version.split(".")[0] if existing_version != compiler_version: message = "Visual environment already set to %s\n " \ "Current settings visual version: %s" % (existing_version, compiler_version) if not force: raise ConanException("Error, %s" % message) else: output.warn(message) else: vs_path = vs_installation_path(str(compiler_version)) if not vs_path or not os.path.isdir(vs_path): raise ConanException( "VS non-existing installation: Visual Studio %s" % str(compiler_version)) else: if int(compiler_version) > 14: vcvars_path = os.path.join(vs_path, "VC/Auxiliary/Build/vcvarsall.bat") command = [ 'set "VSCMD_START_DIR=%%CD%%" && ' 'call "%s" %s' % (vcvars_path, vcvars_arch) ] else: vcvars_path = os.path.join(vs_path, "VC/vcvarsall.bat") command = ['call "%s" %s' % (vcvars_path, vcvars_arch)] if int(compiler_version) >= 14: if winsdk_version: command.append(winsdk_version) if vcvars_ver: command.append("-vcvars_ver=%s" % vcvars_ver) if os_setting == 'WindowsStore': os_version_setting = settings.get_safe("os.version") if os_version_setting == '8.1': command.append('store 8.1') elif os_version_setting == '10.0': windows_10_sdk = find_windows_10_sdk() if not windows_10_sdk: raise ConanException( "cross-compiling for WindowsStore 10 (UWP), " "but Windows 10 SDK wasn't found") command.append('store %s' % windows_10_sdk) else: raise ConanException('unsupported Windows Store version %s' % os_version_setting) return " ".join(command)
def __init__(self, output=None): self._output = default_output(output, 'conans.client.tools.system_pm.BaseTool')
def unzip(filename, destination=".", keep_permissions=False, pattern=None, output=None): """ Unzip a zipped file :param filename: Path to the zip file :param destination: Destination folder (or file for .gz files) :param keep_permissions: Keep the zip permissions. WARNING: Can be dangerous if the zip was not created in a NIX system, the bits could produce undefined permission schema. Use this option only if you are sure that the zip was created correctly. :param pattern: Extract only paths matching the pattern. This should be a Unix shell-style wildcard, see fnmatch documentation for more details. :param output: output :return: """ output = default_output(output, 'conans.client.tools.files.unzip') if (filename.endswith(".tar.gz") or filename.endswith(".tgz") or filename.endswith(".tbz2") or filename.endswith(".tar.bz2") or filename.endswith(".tar")): return untargz(filename, destination, pattern) if filename.endswith(".gz"): import gzip with gzip.open(filename, 'rb') as f: file_content = f.read() target_name = filename[:-3] if destination == "." else destination save(target_name, file_content) return if filename.endswith(".tar.xz") or filename.endswith(".txz"): if six.PY2: raise ConanException( "XZ format not supported in Python 2. Use Python 3 instead") return untargz(filename, destination, pattern) import zipfile full_path = os.path.normpath(os.path.join(get_cwd(), destination)) if hasattr(sys.stdout, "isatty") and sys.stdout.isatty(): def print_progress(the_size, uncomp_size): the_size = (the_size * 100.0 / uncomp_size) if uncomp_size != 0 else 0 txt_msg = "Unzipping %d %%" if the_size > print_progress.last_size + 1: output.rewrite_line(txt_msg % the_size) print_progress.last_size = the_size if int(the_size) == 99: output.rewrite_line(txt_msg % 100) output.writeln("") else: def print_progress(_, __): pass with zipfile.ZipFile(filename, "r") as z: if not pattern: zip_info = z.infolist() else: zip_info = [ zi for zi in z.infolist() if fnmatch(zi.filename, pattern) ] uncompress_size = sum((file_.file_size for file_ in zip_info)) if uncompress_size > 100000: output.info("Unzipping %s, this can take a while" % human_size(uncompress_size)) else: output.info("Unzipping %s" % human_size(uncompress_size)) extracted_size = 0 print_progress.last_size = -1 if platform.system() == "Windows": for file_ in zip_info: extracted_size += file_.file_size print_progress(extracted_size, uncompress_size) try: z.extract(file_, full_path) except Exception as e: output.error("Error extract %s\n%s" % (file_.filename, str(e))) else: # duplicated for, to avoid a platform check for each zipped file for file_ in zip_info: extracted_size += file_.file_size print_progress(extracted_size, uncompress_size) try: z.extract(file_, full_path) if keep_permissions: # Could be dangerous if the ZIP has been created in a non nix system # https://bugs.python.org/issue15795 perm = file_.external_attr >> 16 & 0xFFF os.chmod(os.path.join(full_path, file_.filename), perm) except Exception as e: output.error("Error extract %s\n%s" % (file_.filename, str(e)))
def vcvars_command(conanfile=None, arch=None, compiler_version=None, force=False, vcvars_ver=None, winsdk_version=None, output=None, settings=None): # Handle input arguments (backwards compatibility with 'settings' as first argument) # TODO: This can be promoted to a decorator pattern for any function if conanfile and settings: raise ConanException( "Do not set both arguments, 'conanfile' and 'settings'," " to call 'vcvars_command' function") from conans.model.conan_file import ConanFile if conanfile and not isinstance(conanfile, ConanFile): return vcvars_command(settings=conanfile, arch=arch, compiler_version=compiler_version, force=force, vcvars_ver=vcvars_ver, winsdk_version=winsdk_version, output=output) if settings: warnings.warn( "argument 'settings' has been deprecated, use 'conanfile' instead") if not conanfile: # TODO: If Conan is using 'profile_build' here we don't have any information about it, # we are falling back to the old behavior (which is probably wrong here) conanfile = namedtuple('_ConanFile', ['settings'])(settings) del settings # Here starts the actual implementation for this function output = default_output(output, 'conans.client.tools.win.vcvars_command') arch_setting = arch or conanfile.settings.get_safe("arch") compiler = conanfile.settings.get_safe("compiler") compiler_base = conanfile.settings.get_safe("compiler.base") if compiler == 'Visual Studio': compiler_version = compiler_version or conanfile.settings.get_safe( "compiler.version") elif compiler_base == "Visual Studio": compiler_version = compiler_version or conanfile.settings.get_safe( "compiler.base.version") else: # vcvars might be still needed for other compilers, e.g. clang-cl or Intel C++, # as they might be using Microsoft STL and other tools # (e.g. resource compiler, manifest tool, etc) # in this case, use the latest Visual Studio available on the machine last_version = latest_vs_version_installed(output=output) compiler_version = compiler_version or last_version os_setting = conanfile.settings.get_safe("os") if not compiler_version: raise ConanException( "compiler.version setting required for vcvars not defined") # https://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx vcvars_arch = None arch_setting = arch_setting or 'x86_64' _, settings_arch_build = get_build_os_arch(conanfile) arch_build = settings_arch_build if not hasattr(conanfile, 'settings_build'): arch_build = arch_build or detected_architecture() if os_setting == 'WindowsCE': vcvars_arch = "x86" elif arch_build == 'x86_64': # Only uses x64 tooling if arch_build explicitly defines it, otherwise # Keep the VS default, which is x86 toolset # This will probably be changed in conan 2.0 if ((settings_arch_build or os.getenv("PreferredToolArchitecture") == "x64") and int(compiler_version) >= 12): x86_cross = "amd64_x86" else: x86_cross = "x86" vcvars_arch = { 'x86': x86_cross, 'x86_64': 'amd64', 'armv7': 'amd64_arm', 'armv8': 'amd64_arm64' }.get(arch_setting) elif arch_build == 'x86': vcvars_arch = { 'x86': 'x86', 'x86_64': 'x86_amd64', 'armv7': 'x86_arm', 'armv8': 'x86_arm64' }.get(arch_setting) if not vcvars_arch: raise ConanException('unsupported architecture %s' % arch_setting) existing_version = os.environ.get("VisualStudioVersion") if existing_version: command = ["echo Conan:vcvars already set"] existing_version = existing_version.split(".")[0] if existing_version != compiler_version: message = "Visual environment already set to %s\n " \ "Current settings visual version: %s" % (existing_version, compiler_version) if not force: raise ConanException("Error, %s" % message) else: output.warn(message) else: vs_path = vs_installation_path(str(compiler_version)) if not vs_path or not os.path.isdir(vs_path): raise ConanException( "VS non-existing installation: Visual Studio %s" % str(compiler_version)) else: if int(compiler_version) > 14: vcvars_path = os.path.join(vs_path, "VC/Auxiliary/Build/vcvarsall.bat") command = [ 'set "VSCMD_START_DIR=%%CD%%" && ' 'call "%s" %s' % (vcvars_path, vcvars_arch) ] else: vcvars_path = os.path.join(vs_path, "VC/vcvarsall.bat") command = ['call "%s" %s' % (vcvars_path, vcvars_arch)] if int(compiler_version) >= 14: if winsdk_version: command.append(winsdk_version) if vcvars_ver: command.append("-vcvars_ver=%s" % vcvars_ver) if os_setting == 'WindowsStore': os_version_setting = conanfile.settings.get_safe("os.version") if os_version_setting == '8.1': winsdk_version = winsdk_version or "8.1" command.append('store %s' % winsdk_version) elif os_version_setting == '10.0': winsdk_version = winsdk_version or find_windows_10_sdk() if not winsdk_version: raise ConanException( "cross-compiling for WindowsStore 10 (UWP), " "but Windows 10 SDK wasn't found") command.append('store %s' % winsdk_version) else: raise ConanException('unsupported Windows Store version %s' % os_version_setting) return " ".join(command)
def download(url, filename, verify=True, out=None, retry=None, retry_wait=None, overwrite=False, auth=None, headers=None, requester=None, md5='', sha1='', sha256=''): """Retrieves a file from a given URL into a file with a given filename. It uses certificates from a list of known verifiers for https downloads, but this can be optionally disabled. :param url: URL to download. It can be a list, which only the first one will be downloaded, and the follow URLs will be used as mirror in case of download error. :param filename: Name of the file to be created in the local storage :param verify: When False, disables https certificate validation :param out: An object with a write() method can be passed to get the output. stdout will use if not specified :param retry: Number of retries in case of failure. Default is overriden by general.retry in the conan.conf file or an env variable CONAN_RETRY :param retry_wait: Seconds to wait between download attempts. Default is overriden by general.retry_wait in the conan.conf file or an env variable CONAN_RETRY_WAIT :param overwrite: When True, Conan will overwrite the destination file if exists. Otherwise it will raise an exception :param auth: A tuple of user and password to use HTTPBasic authentication :param headers: A dictionary with additional headers :param requester: HTTP requests instance :param md5: MD5 hash code to check the downloaded file :param sha1: SHA-1 hash code to check the downloaded file :param sha256: SHA-256 hash code to check the downloaded file :return: None """ out = default_output(out, 'conans.client.tools.net.download') requester = default_requester(requester, 'conans.client.tools.net.download') from conans.tools import _global_config as config # It might be possible that users provide their own requester retry = retry if retry is not None else config.retry retry = retry if retry is not None else 1 retry_wait = retry_wait if retry_wait is not None else config.retry_wait retry_wait = retry_wait if retry_wait is not None else 5 checksum = sha256 or sha1 or md5 download_cache = config.download_cache if checksum else None def _download_file(file_url): # The download cache is only used if a checksum is provided, otherwise, a normal download run_downloader(requester=requester, output=out, verify=verify, user_download=True, download_cache=download_cache, url=file_url, file_path=filename, retry=retry, retry_wait=retry_wait, overwrite=overwrite, auth=auth, headers=headers, md5=md5, sha1=sha1, sha256=sha256) out.writeln("") if not isinstance(url, (list, tuple)): _download_file(url) else: # We were provided several URLs to try for url_it in url: try: _download_file(url_it) break except Exception as error: message = "Could not download from the URL {}: {}.".format( url_it, str(error)) out.warn(message + " Trying another mirror.") else: raise ConanException( "All downloads from ({}) URLs have failed.".format(len(url)))
def download(url, filename, verify=True, out=None, retry=None, retry_wait=None, overwrite=False, auth=None, headers=None, requester=None, md5='', sha1='', sha256=''): out = default_output(out, 'conans.client.tools.net.download') requester = default_requester(requester, 'conans.client.tools.net.download') from conans.tools import _global_config as config # It might be possible that users provide their own requester retry = retry if retry is not None else config.retry retry = retry if retry is not None else 1 retry_wait = retry_wait if retry_wait is not None else config.retry_wait retry_wait = retry_wait if retry_wait is not None else 5 downloader = FileDownloader(requester=requester, output=out, verify=verify, config=config) checksum = sha256 or sha1 or md5 # The download cache is only used if a checksum is provided, otherwise, a normal download if config and config.download_cache and checksum: downloader = CachedFileDownloader(config.download_cache, downloader, user_download=True) downloader.download(url, filename, retry=retry, retry_wait=retry_wait, overwrite=overwrite, auth=auth, headers=headers, md5=md5, sha1=sha1, sha256=sha256) else: downloader.download(url, filename, retry=retry, retry_wait=retry_wait, overwrite=overwrite, auth=auth, headers=headers) if md5: check_md5(filename, md5) if sha1: check_sha1(filename, sha1) if sha256: check_sha256(filename, sha256) out.writeln("")