Rework win_toolchains a bit and copy the vs runtime DLLs as needed.
In order to run both the visual studio tools and the binaries built by them (and ninja), we need to ensure that the VS runtime DLLs are available in the path. In the GYP build, we accomplish this by copying them into the Debug and Debug_x64 dirs as appropriate inside the gyp_chromium script. In the pure-GN build, then, things would be broken, so we need to modify the GN build to do the copy as well, or we need to inject a step somewhere that happens after GN runs but before Ninja tries to run (since none of the toolchain binaries will work). This patch accomplishes this by calling out to vs_toolchain.py to copy the DLLs as neede when the toolchain is defined. This is somewhat less than ideal (makes 'gn gen' slower) but seems better than forcing devs to have to run an additional command. In addition, the GYP build writes targets into Debug and Debug_x64 concurrently. This doesn't really carry over into GN correctly, and we probably only ever want to write targets into Debug and Debug/64 (or some such). However, the way the toolchains are currently implemented, it's not clear if this really works and the interplay between 32-bit and 64-bit is weird (we apparently normally "force" 32-bit even if we set cpu_arch to 64-bit, and require you to specify force_win64). To work around this and make sure that we copy the right DLLs for the right arch into the outer Debug/ directory, this patch temporarily disables the cross-arch part of the build, forcing the host_toolchain to match the target_toolchain. This likely means that 'cpu_arch="x86"' works (the default), but the 'host' binaries like image_diff and mksnapshot will be compiled in 32-bit mode, not 64-bit mode. 'cpu_arch="x64" force_win64=true' should also work, and produce all-64-bit binaries. 'cpu_arch="x64"' does not work at all and won't until we can clean up the above stuff. R=scottmg@chromium.org, brettw@chromium.org BUG=430661 Review URL: https://codereview.chromium.org/722723004 Cr-Original-Commit-Position: refs/heads/master@{#304310} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 0b95195e49489b7a4d87048d2ce4b747173a5b8a
This commit is contained in:
Родитель
34a19a3ac9
Коммит
7265358749
|
@ -34,15 +34,6 @@ declare_args() {
|
|||
# to configure warnings.
|
||||
is_clang = (os == "mac" || os == "ios" || os == "linux" || os == "chromeos")
|
||||
|
||||
# Forces a 64-bit build on Windows. Does nothing on other platforms. Normally
|
||||
# we build 32-bit on Windows regardless of the current host OS bit depth.
|
||||
# Setting this flag will override this logic and generate 64-bit toolchains.
|
||||
#
|
||||
# Normally this would get set automatically when you specify a target using
|
||||
# the 64-bit toolchain. You can also set this on the command line to convert
|
||||
# the default toolchain to 64-bit.
|
||||
force_win64 = false
|
||||
|
||||
# Selects the desired build flavor. Official builds get additional
|
||||
# processing to prepare for release. Normally you will want to develop and
|
||||
# test with this flag off.
|
||||
|
@ -174,16 +165,6 @@ is_desktop_linux = is_linux && !is_chromeos
|
|||
# CPU ARCHITECTURE
|
||||
# =============================================================================
|
||||
|
||||
if (is_win) {
|
||||
# Always use 32-bit on Windows, even when compiling on a 64-bit host OS,
|
||||
# unless the override flag is specified.
|
||||
if (force_win64) {
|
||||
cpu_arch = "x64"
|
||||
} else {
|
||||
cpu_arch = "x86"
|
||||
}
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
# TODO(cjhopman): enable this assert once bots are updated to not set
|
||||
# cpu_arch.
|
||||
|
@ -495,19 +476,14 @@ set_defaults("test") {
|
|||
# default toolchain.
|
||||
|
||||
if (is_win) {
|
||||
# TODO(brettw) name the toolchains the same as cpu_arch as with Linux below
|
||||
# to eliminate these conditionals.
|
||||
if (build_cpu_arch == "x64") {
|
||||
# On windows we use the same toolchain for host and target by default.
|
||||
# TODO(dpranke): rename the toolchains to x64 and x86 to match cpu_arch.
|
||||
if (cpu_arch == "x64") {
|
||||
host_toolchain = "//build/toolchain/win:64"
|
||||
} else if (build_cpu_arch == "x86") {
|
||||
} else if (cpu_arch == "x86") {
|
||||
host_toolchain = "//build/toolchain/win:32"
|
||||
}
|
||||
|
||||
if (cpu_arch == "x64") {
|
||||
set_default_toolchain("//build/toolchain/win:64")
|
||||
} else if (cpu_arch == "x86") {
|
||||
set_default_toolchain("//build/toolchain/win:32")
|
||||
}
|
||||
set_default_toolchain("$host_toolchain")
|
||||
} else if (is_android) {
|
||||
# Use clang for the x86/64 Linux host builds.
|
||||
if (build_cpu_arch == "x86" || build_cpu_arch == "x64") {
|
||||
|
|
|
@ -24,7 +24,6 @@ concurrent_links = exec_script("../get_concurrent_links.py", [], "value")
|
|||
# Parameters:
|
||||
# cpu_arch: cpu_arch to pass as a build arg
|
||||
# environment: File name of environment file.
|
||||
# force_win64 (optional): value for this build arg.
|
||||
template("msvc_toolchain") {
|
||||
if (defined(invoker.concurrent_links)) {
|
||||
concurrent_links = invoker.concurrent_links
|
||||
|
@ -32,6 +31,16 @@ template("msvc_toolchain") {
|
|||
|
||||
env = invoker.environment
|
||||
|
||||
if (is_debug) {
|
||||
configuration = "Debug"
|
||||
} else {
|
||||
configuration = "Release"
|
||||
}
|
||||
exec_script("../../vs_toolchain.py", ["copy_dlls",
|
||||
rebase_path(root_build_dir),
|
||||
configuration,
|
||||
invoker.cpu_arch])
|
||||
|
||||
toolchain(target_name) {
|
||||
# Make these apply to all tools below.
|
||||
lib_switch = ""
|
||||
|
@ -154,23 +163,24 @@ template("msvc_toolchain") {
|
|||
# passed to the build. They are ignored when this is the default toolchain.
|
||||
toolchain_args() {
|
||||
cpu_arch = invoker.cpu_arch
|
||||
|
||||
# Normally the build config resets the CPU architecture to 32-bits. Setting
|
||||
# this flag overrides that behavior.
|
||||
if (defined(invoker.force_win64)) {
|
||||
force_win64 = invoker.force_win64
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msvc_toolchain("32") {
|
||||
environment = "environment.x86"
|
||||
cpu_arch = "x64"
|
||||
# TODO(dpranke): Declare both toolchains all of the time when we
|
||||
# get it sorted out how we want to support them both in a single build.
|
||||
# Right now only one of these can be enabled at a time because the
|
||||
# runtime libraries get copied to root_build_dir and would collide.
|
||||
if (cpu_arch == "x86") {
|
||||
msvc_toolchain("32") {
|
||||
environment = "environment.x86"
|
||||
cpu_arch = "x86"
|
||||
}
|
||||
}
|
||||
|
||||
msvc_toolchain("64") {
|
||||
environment = "environment.x64"
|
||||
cpu_arch = "x64"
|
||||
force_win64 = true
|
||||
if (cpu_arch == "x64") {
|
||||
msvc_toolchain("64") {
|
||||
environment = "environment.x64"
|
||||
cpu_arch = "x64"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,29 @@ def SetEnvironmentAndGetRuntimeDllDirs():
|
|||
return vs2013_runtime_dll_dirs
|
||||
|
||||
|
||||
def _CopyRuntimeImpl(target, source):
|
||||
"""Copy |source| to |target| if it doesn't already exist or if it
|
||||
needs to be updated.
|
||||
"""
|
||||
if (os.path.isdir(os.path.dirname(target)) and
|
||||
(not os.path.isfile(target) or
|
||||
os.stat(target).st_mtime != os.stat(source).st_mtime)):
|
||||
print 'Copying %s to %s...' % (source, target)
|
||||
if os.path.exists(target):
|
||||
os.unlink(target)
|
||||
shutil.copy2(source, target)
|
||||
|
||||
|
||||
def _CopyRuntime(target_dir, source_dir, dll_pattern):
|
||||
"""Copy both the msvcr and msvcp runtime DLLs, only if the target doesn't
|
||||
exist, but the target directory does exist."""
|
||||
for which in ('p', 'r'):
|
||||
dll = dll_pattern % which
|
||||
target = os.path.join(target_dir, dll)
|
||||
source = os.path.join(source_dir, dll)
|
||||
_CopyRuntimeImpl(target, source)
|
||||
|
||||
|
||||
def CopyVsRuntimeDlls(output_dir, runtime_dirs):
|
||||
"""Copies the VS runtime DLLs from the given |runtime_dirs| to the output
|
||||
directory so that even if not system-installed, built binaries are likely to
|
||||
|
@ -73,27 +96,6 @@ def CopyVsRuntimeDlls(output_dir, runtime_dirs):
|
|||
"""
|
||||
assert sys.platform.startswith(('win32', 'cygwin'))
|
||||
|
||||
def copy_runtime_impl(target, source):
|
||||
"""Copy |source| to |target| if it doesn't already exist or if it need to be
|
||||
updated.
|
||||
"""
|
||||
if (os.path.isdir(os.path.dirname(target)) and
|
||||
(not os.path.isfile(target) or
|
||||
os.stat(target).st_mtime != os.stat(source).st_mtime)):
|
||||
print 'Copying %s to %s...' % (source, target)
|
||||
if os.path.exists(target):
|
||||
os.unlink(target)
|
||||
shutil.copy2(source, target)
|
||||
|
||||
def copy_runtime(target_dir, source_dir, dll_pattern):
|
||||
"""Copy both the msvcr and msvcp runtime DLLs, only if the target doesn't
|
||||
exist, but the target directory does exist."""
|
||||
for which in ('p', 'r'):
|
||||
dll = dll_pattern % which
|
||||
target = os.path.join(target_dir, dll)
|
||||
source = os.path.join(source_dir, dll)
|
||||
copy_runtime_impl(target, source)
|
||||
|
||||
x86, x64 = runtime_dirs
|
||||
out_debug = os.path.join(output_dir, 'Debug')
|
||||
out_debug_nacl64 = os.path.join(output_dir, 'Debug', 'x64')
|
||||
|
@ -106,12 +108,12 @@ def CopyVsRuntimeDlls(output_dir, runtime_dirs):
|
|||
os.makedirs(out_debug_nacl64)
|
||||
if os.path.exists(out_release) and not os.path.exists(out_release_nacl64):
|
||||
os.makedirs(out_release_nacl64)
|
||||
copy_runtime(out_debug, x86, 'msvc%s120d.dll')
|
||||
copy_runtime(out_release, x86, 'msvc%s120.dll')
|
||||
copy_runtime(out_debug_x64, x64, 'msvc%s120d.dll')
|
||||
copy_runtime(out_release_x64, x64, 'msvc%s120.dll')
|
||||
copy_runtime(out_debug_nacl64, x64, 'msvc%s120d.dll')
|
||||
copy_runtime(out_release_nacl64, x64, 'msvc%s120.dll')
|
||||
_CopyRuntime(out_debug, x86, 'msvc%s120d.dll')
|
||||
_CopyRuntime(out_release, x86, 'msvc%s120.dll')
|
||||
_CopyRuntime(out_debug_x64, x64, 'msvc%s120d.dll')
|
||||
_CopyRuntime(out_release_x64, x64, 'msvc%s120.dll')
|
||||
_CopyRuntime(out_debug_nacl64, x64, 'msvc%s120d.dll')
|
||||
_CopyRuntime(out_release_nacl64, x64, 'msvc%s120.dll')
|
||||
|
||||
# Copy the PGO runtime library to the release directories.
|
||||
if os.environ.get('GYP_MSVS_OVERRIDE_PATH'):
|
||||
|
@ -121,11 +123,31 @@ def CopyVsRuntimeDlls(output_dir, runtime_dirs):
|
|||
pgo_runtime_dll = 'pgort120.dll'
|
||||
source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll)
|
||||
if os.path.exists(source_x86):
|
||||
copy_runtime_impl(os.path.join(out_release, pgo_runtime_dll), source_x86)
|
||||
_CopyRuntimeImpl(os.path.join(out_release, pgo_runtime_dll), source_x86)
|
||||
source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll)
|
||||
if os.path.exists(source_x64):
|
||||
copy_runtime_impl(os.path.join(out_release_x64, pgo_runtime_dll),
|
||||
source_x64)
|
||||
_CopyRuntimeImpl(os.path.join(out_release_x64, pgo_runtime_dll),
|
||||
source_x64)
|
||||
|
||||
|
||||
def CopyDlls(target_dir, configuration, cpu_arch):
|
||||
"""Copy the VS runtime DLLs into the requested directory as needed.
|
||||
|
||||
configuration is one of 'Debug' or 'Release'.
|
||||
cpu_arch is one of 'x86' or 'x64'.
|
||||
|
||||
The debug configuration gets both the debug and release DLLs; the
|
||||
release config only the latter.
|
||||
"""
|
||||
vs2013_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
|
||||
if not vs2013_runtime_dll_dirs:
|
||||
return
|
||||
|
||||
x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
|
||||
runtime_dir = x64_runtime if cpu_arch == 'x64' else x86_runtime
|
||||
_CopyRuntime(target_dir, runtime_dir, 'msvc%s120.dll')
|
||||
if configuration == 'Debug':
|
||||
_CopyRuntime(target_dir, runtime_dir, 'msvc%s120d.dll')
|
||||
|
||||
|
||||
def _GetDesiredVsToolchainHashes():
|
||||
|
@ -188,13 +210,12 @@ def main():
|
|||
commands = {
|
||||
'update': Update,
|
||||
'get_toolchain_dir': GetToolchainDir,
|
||||
# TODO(scottmg): Add copy_dlls for GN builds (gyp_chromium calls
|
||||
# CopyVsRuntimeDlls via import, currently).
|
||||
'copy_dlls': CopyDlls,
|
||||
}
|
||||
if len(sys.argv) < 2 or sys.argv[1] not in commands:
|
||||
print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands)
|
||||
return 1
|
||||
return commands[sys.argv[1]]()
|
||||
return commands[sys.argv[1]](*sys.argv[2:])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Загрузка…
Ссылка в новой задаче