diff options
author | mark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-27 19:28:52 +0000 |
---|---|---|
committer | mark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-27 19:28:52 +0000 |
commit | 4c8c60ee58cf2f22fcdc0cf3b30f1f5e8884f0ff (patch) | |
tree | ced48dcb1b9f9d4ecf8305ad4647122abe2c3fdd | |
parent | 691519839a22b371f53b4f7b2b7c6e553c252591 (diff) | |
download | chromium_src-4c8c60ee58cf2f22fcdc0cf3b30f1f5e8884f0ff.zip chromium_src-4c8c60ee58cf2f22fcdc0cf3b30f1f5e8884f0ff.tar.gz chromium_src-4c8c60ee58cf2f22fcdc0cf3b30f1f5e8884f0ff.tar.bz2 |
Ensure classes only referenced by .xib files end up in the executable
Review URL: http://codereview.chromium.org/27277
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10619 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-x | build/mac/make_ib_classes.py | 146 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.h | 2 | ||||
-rw-r--r-- | chrome/chrome.gyp | 43 |
3 files changed, 185 insertions, 6 deletions
diff --git a/build/mac/make_ib_classes.py b/build/mac/make_ib_classes.py new file mode 100755 index 0000000..78b3509 --- /dev/null +++ b/build/mac/make_ib_classes.py @@ -0,0 +1,146 @@ +#!/usr/bin/python + +# Copyright (c) 2009 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. + +# Usage: make_ib_classes.py output.mm input.xib [...] +# +# Generates an Objective-C++ file at output.mm referencing each class described +# in input.xib. +# +# This script is useful when building an application containing .nib or .xib +# files that reference Objective-C classes that may not be referenced by other +# code in the application. The intended use case is when the .nib and .xib +# files refer to classes that are built into a static library that gets linked +# into the main executable. If nothing in the main executable references those +# classes, the linker will not include them in its output (without -all_load or +# -ObjC). Using this script, references to such classes are created, such that +# if output.mm is compiled into the application itself, it will provide the +# class references and cause the linker to bring the required code into the +# executable. +# +# If your application is structured in the above way, and you're plagued with +# messages like: +# app[12345:101] Unknown class `MyApp' in nib file, using `NSObject' instead. +# then this script may be right for you. + + +import errno +import os +import os.path +import re +import subprocess +import sys + + +# Patterns used by ListIBClasses + +# A pattern that matches the line preceding a class name. +_class_re = re.compile('<key>class</key>$') + +# A pattern that matches the line with a class name; match group 1 should be +# the class name. +_class_name_re = re.compile('<string>(.*)</string>$') + +# A pattern that matches class names to exclude from the output. This includes +# various Cocoa classes. +_forbidden_class_re = re.compile('^(NS|IB|FirstResponder$|WebView$)') + +def ListIBClasses(ib_path, class_names=None): + """Returns a list of class names referenced by ib_path. + + ib_path is a path to an Interface Builder document. It may be a .nib or a + .xib. + + This function calls "ibtool --classes" to get the list of class names. + ibtool's output is in XML plist format. Rather than doing proper structured + plist scanning, this function relies on the fact that plists are serialized + to XML in a consistent way, and simply takes the string value names of any + dictionary key named "class" as class names. + + class_names may be specified as an existing list to use. This is helpful + when this function will be called several times for multiple nib/xib files. + """ + if class_names == None: + class_names = [] + + # When running within an Xcode build, use the tools from that Xcode + # installation. + developer_tools_dir = os.getenv('DEVELOPER_BIN_DIR', '/usr/bin') + ibtool_path = os.path.join(developer_tools_dir, 'ibtool') + ibtool_command = [ibtool_path, '--classes', ib_path] + + ibtool = subprocess.Popen(ibtool_command, stdout=subprocess.PIPE) + + ibtool_output = ibtool.communicate()[0] + + ibtool_rv = ibtool.returncode + assert ibtool_rv == 0 + + # Loop through the output, looking for "class" keys. The string value on + # any line following a "class" key is taken as a class name. + is_class_name = False + for line in ibtool_output.splitlines(): + if is_class_name: + class_name = _class_name_re.search(line).group(1) + is_class_name = False + if not class_name in class_names and \ + not _forbidden_class_re.search(class_name): + class_names.append(class_name) + elif _class_re.search(line): + is_class_name = True + + return class_names + + +def main(args): + assert len(args) > 2 + (script_path, output_path) = args[0:2] + assert output_path.endswith('.mm') + input_paths = args[2:] + + try: + os.unlink(output_path) + except OSError, e: + if e.errno != errno.ENOENT: + raise + + class_names = [] + + # Get the class names for all desired files. + for input_path in input_paths: + ListIBClasses(input_path, class_names) + + class_names.sort() + + # Write the requested output file. Each class is referenced simply by + # calling its +class function. In order to do this, each class needs a + # bogus @interface to tell the compiler that it's an NSObject subclass. + # #import NSObject.h to get the definition of NSObject without bringing in + # other headers that might provide real declarations. + + output_file = open(output_path, 'w') + print >>output_file, \ +"""// This file was generated by %s. Do not edit. + +#import <Foundation/NSObject.h> +""" % os.path.basename(script_path) + + for class_name in class_names: + print >>output_file, '@interface %s : NSObject\n@end' % class_name + + print >>output_file, '\nnamespace {\n\nvoid IBClasses() {' + + for class_name in class_names: + print >>output_file, ' [%s class];' % class_name + + print >>output_file, '}\n\n} // namespace' + + output_file.close() + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h index db91e5a..0e6b15f 100644 --- a/chrome/browser/cocoa/browser_window_controller.h +++ b/chrome/browser/cocoa/browser_window_controller.h @@ -12,6 +12,8 @@ class Browser; class BrowserWindow; +class LocationBar; +class TabContents; @class TabStripView; @class TabContentsController; @class TabStripController; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index c0dc19c..32c8e74 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -331,8 +331,8 @@ 'browser/autocomplete/autocomplete_edit.h', 'browser/autocomplete/autocomplete_popup_model.cc', 'browser/autocomplete/autocomplete_popup_model.h', - 'browser/autocomplete/autocomplete_popup_view_win.cc', 'browser/autocomplete/autocomplete_popup_view.h', + 'browser/autocomplete/autocomplete_popup_view_win.cc', 'browser/autocomplete/edit_drop_target.cc', 'browser/autocomplete/edit_drop_target.h', 'browser/autocomplete/history_contents_provider.cc', @@ -1163,7 +1163,6 @@ 'browser/autocomplete/autocomplete_accessibility.cc', 'browser/autocomplete/autocomplete_edit.cc', 'browser/autocomplete/autocomplete_popup_model.cc', - 'browser/autocomplete/autocomplete_popup_view_win.cc', 'browser/autocomplete/edit_drop_target.cc', 'browser/bookmarks/bookmark_context_menu.cc', 'browser/bookmarks/bookmark_drop_info.cc', @@ -1304,7 +1303,25 @@ 'browser', 'renderer', ], + 'variables': { + 'conditions': [ + ['OS=="mac"', { + 'mac_xib_files': [ + # Use .xib files only, because .nibs are bundles and these files + # need to be used as an input to rules. Rule dependency checking + # only works on files, not directories as .nib bundles are. + 'app/nibs/English.lproj/BrowserWindow.xib', + 'app/nibs/English.lproj/MainMenu.xib', + 'app/nibs/English.lproj/TabContents.xib', + ], + }, { # else: OS!="mac" + 'mac_xib_files': [], + }], + ], + }, 'sources': [ + '<@(mac_xib_files)', + # All .cc, .h, and .mm files under app except for tests. 'app/breakpad.cc', 'app/breakpad.h', @@ -1322,9 +1339,7 @@ 'app/scoped_ole_initializer.h', ], 'mac_bundle_resources': [ - 'app/nibs/English.lproj/BrowserWindow.xib', - 'app/nibs/English.lproj/MainMenu.xib', - 'app/nibs/English.lproj/TabContents.xib', + '<@(mac_xib_files)', 'app/theme/chromium/chromium.icns', 'app/theme/back.pdf', 'app/theme/forward.pdf', @@ -1347,7 +1362,23 @@ 'INFOPLIST_FILE': 'app/app-Info.plist', }, 'conditions': [ - ['OS=="mac"', {'product_name': 'Chromium'}], + ['OS=="mac"', { + 'product_name': 'Chromium', + 'rules': [ + { + 'rule_name': 'ib_classes', + 'extension': 'xib', + 'outputs': [ + '<(INTERMEDIATE_DIR)/ib_classes/<(RULE_INPUT_ROOT)IBClasses.mm', + ], + 'inputs': [ + '../build/mac/make_ib_classes.py', + ], + 'action': ['python', '<@(_inputs)', '<@(_outputs)', '<(RULE_INPUT_PATH)'], + 'process_outputs_as_sources': 1, + }, + ], + }], ['OS!="win"', { 'variables': { 'repack_path': '../tools/data_pack/repack.py', |