summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-27 19:28:52 +0000
committermark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-27 19:28:52 +0000
commit4c8c60ee58cf2f22fcdc0cf3b30f1f5e8884f0ff (patch)
treeced48dcb1b9f9d4ecf8305ad4647122abe2c3fdd
parent691519839a22b371f53b4f7b2b7c6e553c252591 (diff)
downloadchromium_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-xbuild/mac/make_ib_classes.py146
-rw-r--r--chrome/browser/cocoa/browser_window_controller.h2
-rw-r--r--chrome/chrome.gyp43
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',