Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Unified Diff: chrome/tools/mac_helpers/infoplist_strings_util.mm

Issue 171040: add the InfoPlist.strings generation based on GRD strings.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/tools/build/apply_locales.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/tools/mac_helpers/infoplist_strings_util.mm
===================================================================
--- chrome/tools/mac_helpers/infoplist_strings_util.mm (revision 0)
+++ chrome/tools/mac_helpers/infoplist_strings_util.mm (revision 0)
@@ -0,0 +1,296 @@
+// 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.
+
+// Helper tool that is built and run during a build to pull strings from
+// the GRD files and generate the InfoPlist.strings files needed for
+// Mac OS X app bundles.
+
+#import <Foundation/Foundation.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "base/data_pack.h"
+#include "base/file_path.h"
+#include "base/scoped_nsautorelease_pool.h"
+#include "base/scoped_ptr.h"
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "grit/chromium_strings.h"
+
+namespace {
+
+NSString* ApplicationVersionString(const char* version_file_path) {
+ NSError* error = nil;
+ NSString* path_string = [NSString stringWithUTF8String:version_file_path];
+ NSString* version_file =
+ [NSString stringWithContentsOfFile:path_string
+ encoding:NSUTF8StringEncoding
+ error:&error];
+ if (!version_file || error) {
+ fprintf(stderr, "Failed to load version file: %s\n",
+ [[error description] UTF8String]);
+ return nil;
+ }
+
+ int major = 0, minor = 0, build = 0, patch = 0;
+ NSScanner* scanner = [NSScanner scannerWithString:version_file];
+ if ([scanner scanString:@"MAJOR=" intoString:nil] &&
+ [scanner scanInt:&major] &&
+ [scanner scanString:@"MINOR=" intoString:nil] &&
+ [scanner scanInt:&minor] &&
+ [scanner scanString:@"BUILD=" intoString:nil] &&
+ [scanner scanInt:&build] &&
+ [scanner scanString:@"PATCH=" intoString:nil] &&
+ [scanner scanInt:&patch]) {
+ return [NSString stringWithFormat:@"%d.%d.%d.%d",
+ major, minor, build, patch];
+ }
+ fprintf(stderr, "Failed to parse version file\n");
+ return nil;
+}
+
+base::DataPack* LoadResourceDataPack(const char* dir_path,
+ const char* branding_strings_name,
+ const char* locale_name) {
+ base::DataPack* resource_pack = NULL;
+
+ NSString* resource_path = [NSString stringWithFormat:@"%s/%s_%s.pak",
+ dir_path, branding_strings_name, locale_name];
+ if (resource_path) {
+ FilePath resources_pak_path([resource_path fileSystemRepresentation]);
+ resource_pack = new base::DataPack;
+ bool success = resource_pack->Load(resources_pak_path);
+ if (!success) {
+ delete resource_pack;
+ resource_pack = NULL;
+ }
+ }
+
+ return resource_pack;
+}
+
+NSString* LoadStringFromDataPack(base::DataPack* data_pack,
+ const char* data_pack_lang,
+ uint32_t resource_id,
+ const char* resource_id_str) {
+ NSString* result = nil;
+ StringPiece data;
+ if (data_pack->Get(resource_id, &data)) {
+ // Data pack encodes strings as UTF16.
+ result =
+ [[[NSString alloc] initWithBytes:data.data()
+ length:data.length()
+ encoding:NSUTF16LittleEndianStringEncoding]
+ autorelease];
+ }
+ if (!result) {
+ fprintf(stderr, "ERROR: failed to load string %s for lang %s\n",
+ resource_id_str, data_pack_lang);
+ exit(1);
+ }
+ return result;
+}
+
+// Escape quotes, newlines, etc so there are no errors when the strings file
+// is parsed.
+NSString* EscapeForStringsFileValue(NSString* str) {
+ NSMutableString* worker = [NSMutableString stringWithString:str];
+
+ // Since this is a build tool, we don't really worry about making this
+ // the most efficient code.
+
+ // Backslash first since we need to do it before we put in all the others
+ [worker replaceOccurrencesOfString:@"\\"
+ withString:@"\\\\"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [worker length])];
+ // Now the rest of them.
+ [worker replaceOccurrencesOfString:@"\n"
+ withString:@"\\n"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [worker length])];
+ [worker replaceOccurrencesOfString:@"\r"
+ withString:@"\\r"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [worker length])];
+ [worker replaceOccurrencesOfString:@"\t"
+ withString:@"\\t"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [worker length])];
+ [worker replaceOccurrencesOfString:@"\""
+ withString:@"\\\""
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [worker length])];
+
+ return [[worker copy] autorelease];
+}
+
+// The valid types for the -t arg
+const char* kAppType_Main = "main"; // Main app
+const char* kAppType_Helper = "helper"; // Helper app
+
+} // namespace
+
+int main(int argc, char* const argv[]) {
+ base::ScopedNSAutoreleasePool autorelease_pool;
+
+ const char* version_file_path = NULL;
+ const char* grit_output_dir = NULL;
+ const char* branding_strings_name = NULL;
+ const char* output_dir = NULL;
+ const char* app_type = kAppType_Main;
+
+ // Process the args
+ int ch;
+ while ((ch = getopt(argc, argv, "t:v:g:b:o:")) != -1) {
+ switch (ch) {
+ case 't':
+ app_type = optarg;
+ break;
+ case 'v':
+ version_file_path = optarg;
+ break;
+ case 'g':
+ grit_output_dir = optarg;
+ break;
+ case 'b':
+ branding_strings_name = optarg;
+ break;
+ case 'o':
+ output_dir = optarg;
+ break;
+ default:
+ fprintf(stderr, "ERROR: bad command line arg\n");
+ exit(1);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+#define CHECK_ARG(a, b) \
+ do { \
+ if ((a)) { \
+ fprintf(stderr, "ERROR: " b "\n"); \
+ exit(1); \
+ } \
+ } while (false)
+
+ // Check our args
+ CHECK_ARG(!version_file_path, "Missing VERSION file path");
+ CHECK_ARG(!grit_output_dir, "Missing grit output dir path");
+ CHECK_ARG(!output_dir, "Missing path to write InfoPlist.strings files");
+ CHECK_ARG(!branding_strings_name, "Missing branding strings file name");
+ CHECK_ARG(argc == 0, "Missing language list");
+ CHECK_ARG((strcmp(app_type, kAppType_Main) != 0 &&
+ strcmp(app_type, kAppType_Helper) != 0),
+ "Unknown app type");
+
+ char* const* lang_list = argv;
+ int lang_list_count = argc;
+
+ // Parse the version file and build our string
+ NSString* version_string = ApplicationVersionString(version_file_path);
+ if (!version_string) {
+ fprintf(stderr, "ERROR: failed to get a version string");
+ exit(1);
+ }
+
+ NSFileManager* fm = [NSFileManager defaultManager];
+
+ for (int loop = 0; loop < lang_list_count; ++loop) {
+ const char* cur_lang = lang_list[loop];
+
+ // Open the branded string pak file
+ scoped_ptr<base::DataPack> branded_data_pack(
+ LoadResourceDataPack(grit_output_dir,
+ branding_strings_name,
+ cur_lang));
+ if (branded_data_pack.get() == NULL) {
+ fprintf(stderr, "ERROR: Failed to load branded pak for language: %s\n",
+ cur_lang);
+ exit(1);
+ }
+
+ uint32_t name_id = IDS_PRODUCT_NAME;
+ const char* name_id_str = "IDS_PRODUCT_NAME";
+ uint32_t short_name_id = IDS_SHORT_PRODUCT_NAME;
+ const char* short_name_id_str = "IDS_SHORT_PRODUCT_NAME";
+ if (strcmp(app_type, kAppType_Helper) == 0) {
+ name_id = IDS_HELPER_NAME;
+ name_id_str = "IDS_HELPER_NAME";
+ short_name_id = IDS_SHORT_HELPER_NAME;
+ short_name_id_str = "IDS_SHORT_HELPER_NAME";
+ }
+
+ // Fetch the strings
+ NSString* name =
+ LoadStringFromDataPack(branded_data_pack.get(), cur_lang,
+ name_id, name_id_str);
+ NSString* short_name =
+ LoadStringFromDataPack(branded_data_pack.get(), cur_lang,
+ short_name_id, short_name_id_str);
+ NSString* copyright =
+ LoadStringFromDataPack(branded_data_pack.get(), cur_lang,
+ IDS_ABOUT_VERSION_COPYRIGHT,
+ "IDS_ABOUT_VERSION_COPYRIGHT");
+
+ // For now, assume this is ok for all languages. If we need to, this could
+ // be moved into generated_resources.grd and fetched.
+ NSString *get_info = [NSString stringWithFormat:@"%@ %@, %@",
+ name, version_string, copyright];
+
+ // Generate the InfoPlist.strings file contents
+ NSString* strings_file_contents_string =
+ [NSString stringWithFormat:
+ @"CFBundleDisplayName = \"%@\";\n"
+ @"CFBundleGetInfoString = \"%@\";\n"
+ @"CFBundleName = \"%@\";\n"
+ @"NSHumanReadableCopyright = \"%@\";\n",
+ EscapeForStringsFileValue(name),
+ EscapeForStringsFileValue(get_info),
+ EscapeForStringsFileValue(short_name),
+ EscapeForStringsFileValue(copyright)];
+
+ // We set up Xcode projects expecting strings files to be UTF8, so make
+ // sure we write the data in that form. When Xcode copies them it will
+ // put them final runtime encoding.
+ NSData* strings_file_contents_utf8 =
+ [strings_file_contents_string dataUsingEncoding:NSUTF8StringEncoding];
+
+ if ([strings_file_contents_utf8 length] == 0) {
+ fprintf(stderr, "ERROR: failed to get the utf8 encoding of the strings "
+ "file for language: %s\n", cur_lang);
+ exit(1);
+ }
+
+ // Make sure the lproj we write to exists
+ NSString *output_path =
+ [[NSString stringWithUTF8String:output_dir]
+ stringByAppendingPathComponent:
+ [NSString stringWithFormat:@"%s.lproj", cur_lang]];
+ NSError* error = nil;
+ if (![fm fileExistsAtPath:output_path] &&
+ ![fm createDirectoryAtPath:output_path
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:&error]) {
+ fprintf(stderr, "ERROR: '%s' didn't exist or we failed to create it\n",
+ [output_path UTF8String]);
+ exit(1);
+ }
+
+ // Write out the file
+ output_path =
+ [output_path stringByAppendingPathComponent:@"InfoPlist.strings"];
+ if (![strings_file_contents_utf8 writeToFile:output_path
+ atomically:YES]) {
+ fprintf(stderr, "ERROR: Failed to write out '%s'\n",
+ [output_path UTF8String]);
+ exit(1);
+ }
+ }
+ return 0;
+}
Property changes on: chrome/tools/mac_helpers/infoplist_strings_util.mm
___________________________________________________________________
Name: svn:eol-style
+ LF
« no previous file with comments | « chrome/tools/build/apply_locales.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698