0

[Mac/GN] Fix rebuilds when changing framework_version of a mac_framework_bundle.

Write the current framework_version to a file at gen-time, and clobber the
entire framework bundle if it differs from the current value in the file.

This has to be done at gen-time because it is not possible to run a script at
the create_bundle stage before any other dependencies in its tree run. Take
this sample graph:

                       bundle_data --> shared_library
                      /
  mac_framework_bundle
                      \
                       action("clean_framework_version")

It is not possible, from a mac_framework_bundle, to force the
clean_framework_version action to run before the shared_library. When the
action does run, its stamp will have a newer mtime than the shared_library.
Because bundle_data are hard linked into place, the link source file will
have an older mtime than the action, and the build will never stabilize.

BUG=648757
R=dpranke@chromium.org

Originally Committed: https://crrev.com/fed4fc1df8bab7159f19e04ed658c1f417e4e499
Reverted: https://crrev.com/d76ba00e6cc2625000d495e79bdc8d747645405e

Review-Url: https://codereview.chromium.org/2453043002
Cr-Commit-Position: refs/heads/master@{#428366}
This commit is contained in:
rsesek
2016-10-28 07:42:10 -07:00
committed by Commit bot
parent 38a720804f
commit a74b313db5
3 changed files with 60 additions and 2 deletions

1
.gn

@ -227,6 +227,7 @@ exec_script_whitelist = [
"//build/config/linux/pkg_config.gni",
"//build/config/linux/atk/BUILD.gn",
"//build/config/mac/mac_sdk.gni",
"//build/config/mac/rules.gni",
"//build/config/posix/BUILD.gn",
"//build/config/sysroot.gni",
"//build/config/win/BUILD.gn",

@ -0,0 +1,42 @@
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import shutil
import sys
# Ensures that the current version matches the last-produced version, which is
# stored in the version_file. If it does not, then the framework_root_dir is
# obliterated.
# Usage: python prepare_framework_version.py out/obj/version_file \
# out/Framework.framework \
# 'A'
def PrepareFrameworkVersion(version_file, framework_root_dir, version):
# Test what the current framework version is. Stop if it is up-to-date.
try:
with open(version_file, 'r') as f:
current_version = f.read()
if current_version == version:
return
except IOError:
pass
# The framework version has changed, so clobber the framework.
if os.path.exists(framework_root_dir):
shutil.rmtree(framework_root_dir)
# Write out the new framework version file, making sure its containing
# directory exists.
dirname = os.path.dirname(version_file)
if not os.path.isdir(dirname):
os.makedirs(dirname, 0700)
with open(version_file, 'w+') as f:
f.write(version)
if __name__ == '__main__':
PrepareFrameworkVersion(sys.argv[1], sys.argv[2], sys.argv[3])
sys.exit(0)

@ -258,11 +258,13 @@ template("mac_framework_bundle") {
# the versioned directory structure.
_framework_target = _target_name
_framework_name = _output_name + ".framework"
_framework_root_dir = "$root_out_dir/$_framework_name"
_framework_base_dir = "$root_out_dir/$_framework_name"
if (defined(invoker.framework_version) && invoker.framework_version != "") {
_framework_version = invoker.framework_version
_framework_root_dir += "/Versions/$_framework_version"
_framework_root_dir = _framework_base_dir + "/Versions/$_framework_version"
_framework_target = _target_name + "_create_bundle"
} else {
_framework_root_dir = _framework_base_dir
}
_link_shared_library_target = target_name + "_shared_library"
@ -302,6 +304,19 @@ template("mac_framework_bundle") {
]
}
# Clean the entire framework if the framework_version changes.
_version_arg = ""
if (defined(_framework_version)) {
_version_arg = _framework_version
}
_version_file = "$target_out_dir/${target_name}_version"
exec_script("//build/config/mac/prepare_framework_version.py",
[
rebase_path(_version_file),
rebase_path(_framework_base_dir),
"'$_version_arg'",
])
_framework_public_config = _target_name + "_public_config"
config(_framework_public_config) {
# TODO(sdefresne): should we have a framework_dirs similar to lib_dirs