| #!/usr/bin/env python3 |
| # Copyright 2016 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| |
| import glob |
| import hashlib |
| import os |
| import shutil |
| import sys |
| |
| script_dir = os.path.dirname(os.path.realpath(__file__)) |
| src_build_dir = os.path.abspath(os.path.join(script_dir, os.pardir)) |
| sys.path.insert(0, src_build_dir) |
| |
| import vs_toolchain |
| |
| |
| def _HexDigest(file_name): |
| hasher = hashlib.sha256() |
| afile = open(file_name, 'rb') |
| blocksize = 65536 |
| buf = afile.read(blocksize) |
| while len(buf) > 0: |
| hasher.update(buf) |
| buf = afile.read(blocksize) |
| afile.close() |
| return hasher.hexdigest() |
| |
| |
| def _CopyImpl(file_name, target_dir, source_dir, verbose=False): |
| """Copy |source| to |target| if it doesn't already exist or if it |
| needs to be updated. |
| """ |
| target = os.path.join(target_dir, file_name) |
| source = os.path.join(source_dir, file_name) |
| if (os.path.isdir(os.path.dirname(target)) and |
| ((not os.path.isfile(target)) or |
| _HexDigest(source) != _HexDigest(target))): |
| if verbose: |
| print('Copying %s to %s...' % (source, target)) |
| if os.path.exists(target): |
| os.unlink(target) |
| shutil.copy(source, target) |
| |
| |
| def _ConditionalMkdir(output_dir): |
| if not os.path.isdir(output_dir): |
| os.makedirs(output_dir) |
| |
| |
| def _CopyCDBToOutput(output_dir, target_arch): |
| """Copies the Windows debugging executable cdb.exe to the output |
| directory, which is created if it does not exist. The output |
| directory, and target architecture that should be copied, are |
| passed. Supported values for the target architecture are the GYP |
| values "ia32", "x64", "arm64" and the GN values "x86", "x64", "arm64". |
| """ |
| _ConditionalMkdir(output_dir) |
| vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs() |
| # If WINDOWSSDKDIR is not set use the default SDK path. This will be the case |
| # when DEPOT_TOOLS_WIN_TOOLCHAIN=0 and vcvarsall.bat has not been run. |
| win_sdk_dir = os.path.normpath( |
| os.environ.get('WINDOWSSDKDIR', |
| os.path.expandvars('%ProgramFiles(x86)%' |
| '\\Windows Kits\\10'))) |
| if target_arch == 'ia32' or target_arch == 'x86': |
| src_arch = 'x86' |
| elif target_arch in ['x64', 'arm64']: |
| src_arch = target_arch |
| else: |
| print('copy_cdb_to_output.py: unknown target_arch %s' % target_arch) |
| sys.exit(1) |
| # We need to copy multiple files, so cache the computed source directory. |
| src_dir = os.path.join(win_sdk_dir, 'Debuggers', src_arch) |
| # We need to copy some helper DLLs to get access to the !uniqstack |
| # command to dump all threads' stacks. |
| src_winext_dir = os.path.join(src_dir, 'winext') |
| dst_winext_dir = os.path.join(output_dir, 'winext') |
| src_winxp_dir = os.path.join(src_dir, 'winxp') |
| dst_winxp_dir = os.path.join(output_dir, 'winxp') |
| # Starting with the 10.0.17763 SDK the ucrt files are in a version-named |
| # directory - this handles both cases. |
| redist_dir = os.path.join(win_sdk_dir, 'Redist') |
| version_dirs = glob.glob(os.path.join(redist_dir, '10.*')) |
| if len(version_dirs) > 0: |
| version_dirs.sort(reverse=True) |
| redist_dir = version_dirs[0] |
| src_crt_dir = os.path.join(redist_dir, 'ucrt', 'DLLs', src_arch) |
| _ConditionalMkdir(dst_winext_dir) |
| _ConditionalMkdir(dst_winxp_dir) |
| # Note that the outputs from the "copy_cdb_to_output" target need to |
| # be kept in sync with this list. |
| _CopyImpl('cdb.exe', output_dir, src_dir) |
| _CopyImpl('dbgeng.dll', output_dir, src_dir) |
| _CopyImpl('dbghelp.dll', output_dir, src_dir) |
| _CopyImpl('dbgmodel.dll', output_dir, src_dir) |
| _CopyImpl('ext.dll', dst_winext_dir, src_winext_dir) |
| _CopyImpl('uext.dll', dst_winext_dir, src_winext_dir) |
| _CopyImpl('exts.dll', dst_winxp_dir, src_winxp_dir) |
| _CopyImpl('ntsdexts.dll', dst_winxp_dir, src_winxp_dir) |
| return 0 |
| |
| |
| def main(): |
| if len(sys.argv) < 2: |
| print('Usage: copy_cdb_to_output.py <output_dir> ' + \ |
| '<target_arch>', file=sys.stderr) |
| return 1 |
| return _CopyCDBToOutput(sys.argv[1], sys.argv[2]) |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |