From be0f756a001842ee3db1a80ffeae89a6f19adb66 Mon Sep 17 00:00:00 2001 From: lordAtticus Date: Fri, 20 Jun 2014 16:44:15 +0300 Subject: [PATCH 1/3] new functions for adding folders recursively MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add folder and its content recursively. Creates pbxgroup for each sub folder to resolve header inclusion across project. Equivalent with Xcode IDE add files… with create groups for folders option. --- lib/pbxFile.js | 12 +++++ lib/pbxProject.js | 130 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/lib/pbxFile.js b/lib/pbxFile.js index 3235d1b..faa5a57 100644 --- a/lib/pbxFile.js +++ b/lib/pbxFile.js @@ -1,5 +1,8 @@ var path = require('path'), M_EXTENSION = /[.]m$/, SOURCE_FILE = 'sourcecode.c.objc', + C_EXTENSION = /[.]c$/, C_FILE = 'sourcecode.c.c', + CPP_EXTENSION = /[.]cpp$/, CPP_FILE = 'sourcecode.cpp.cpp', + ASM_EXTENSION = /[.]s$/, ASM_FILE = 'sourcecode.asm', H_EXTENSION = /[.]h$/, HEADER_FILE = 'sourcecode.c.h', BUNDLE_EXTENSION = /[.]bundle$/, BUNDLE = '"wrapper.plug-in"', XIB_EXTENSION = /[.]xib$/, XIB_FILE = 'file.xib', @@ -12,6 +15,15 @@ var path = require('path'), function detectLastType(path) { if (M_EXTENSION.test(path)) return SOURCE_FILE; + + if (C_EXTENSION.test(path)) + return C_FILE; + + if (CPP_EXTENSION.test(path)) + return CPP_FILE; + + if (ASM_EXTENSION.test(path)) + return ASM_FILE; if (H_EXTENSION.test(path)) return HEADER_FILE; diff --git a/lib/pbxProject.js b/lib/pbxProject.js index 608c0fa..abdc622 100644 --- a/lib/pbxProject.js +++ b/lib/pbxProject.js @@ -13,8 +13,8 @@ var util = require('util'), function pbxProject(filename) { if (!(this instanceof pbxProject)) return new pbxProject(filename); - - this.filepath = path.resolve(filename) + + this.filepath = path.resolve(filename); } util.inherits(pbxProject, EventEmitter) @@ -108,6 +108,116 @@ pbxProject.prototype.removePluginFile = function (path, opt) { return file; } + + +pbxProject.prototype.addHeaderPath = function (path) { + var configurations = nonComments(this.pbxXCBuildConfigurationSection()), + INHERITED = '"$(inherited)"', + config, buildSettings, searchPaths; + + for (config in configurations) { + buildSettings = configurations[config].buildSettings; + + if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) + continue; + + if (!buildSettings['HEADER_SEARCH_PATHS']) { + buildSettings['HEADER_SEARCH_PATHS'] = [INHERITED]; + } + + buildSettings['HEADER_SEARCH_PATHS'].push('"'+path+'"'); + } +} + +pbxProject.prototype.addLibraryPath = function (path) { + var configurations = nonComments(this.pbxXCBuildConfigurationSection()), + config, buildSettings, searchPaths; + + for (config in configurations) { + buildSettings = configurations[config].buildSettings; + + if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) + continue; + + if (!buildSettings['LIBRARY_SEARCH_PATHS']) { + buildSettings['LIBRARY_SEARCH_PATHS'] = []; + } + + buildSettings['LIBRARY_SEARCH_PATHS'].push('"'+path+'"'); + } +} + +// relative paths are considered from source root +pbxProject.prototype.addFolder = function (dir) { + // solve paths + var pathToFolder = dir; + var pathToGroup = path.dirname(this.filepath); + pathToGroup = pathToGroup.substr(0, pathToGroup.lastIndexOf('.'))+"/Classes"; + if (path.resolve(dir) !== dir) pathToFolder = path.join(pathToGroup, "../../", pathToFolder); + var pathRelative = path.relative(pathToGroup, pathToFolder); + var name = dir.split('/').pop(); + // link to Classes group + var file = new pbxFile(name); + file.fileRef = this.generateUuid(); + this.addToClassesPbxGroup(file); + // create pbxgroup for parent folder + var commentKey = f("%s_comment", file.fileRef); + var entry = { "isa": 'PBXGroup', "children": [], "name": name, "path": pathRelative, "sourceTree": '""'}; + var groups = this.hash.project.objects['PBXGroup']; + groups[file.fileRef] = entry; + groups[commentKey] = name; + console.log('Adding folder: '+pathToFolder); + + this.readFolder(pathToFolder, file.fileRef); +} + +pbxProject.prototype.readFolder = function (dir, uuid) { + var files = fs.readdirSync(dir); + var groups = this.hash.project.objects['PBXGroup']; + for(var i in files){ + //if (!files.hasOwnProperty(i)) continue; + var folder = dir+'/'+files[i]; + var name = files[i]; + var format = path.extname(name); + // parse directories, but don't bother with repository + if ( (fs.statSync(folder).isDirectory()) && + (files[i] != '.git') && (files[i] != '.svn') ) { + //console.log('Sub folder: '+folder); + var fp = new pbxFile(files[i]); + fp.fileRef = this.generateUuid(); + // create pbxgroup for parent folder + var commentKey = f("%s_comment", fp.fileRef); + var entry = { "isa": 'PBXGroup', "children": [], "name": name, "path": name, "sourceTree": '""'}; + groups[fp.fileRef] = entry; + groups[commentKey] = name; + groups[uuid].children.push(pbxGroupChild(fp)); + this.readFolder(folder, fp.fileRef); + } + // add source + else if ((format == '.m') || + (format == '.c') || + (format == '.cpp') || + (format == '.s')) { + //console.log('Source: '+name); + var fp = new pbxFile(files[i]); + fp.fileRef = this.generateUuid(); + fp.uuid = this.generateUuid(); + this.addToPbxFileReferenceSection(fp); // PBXFileReference + this.addToPbxBuildFileSection(fp); // PBXBuildFile + this.addToPbxSourcesBuildPhase(fp); // PBXSourcesBuildPhase + groups[uuid].children.push(pbxGroupChild(fp)); + } + // add header + else if (path.extname(name) == '.h') { + //console.log('Header: '+name); + var fp = new pbxFile(files[i]); + fp.fileRef = this.generateUuid(); + this.addToPbxFileReferenceSection(fp); // PBXFileReference + groups[uuid].children.push(pbxGroupChild(fp)); + } + } +} + pbxProject.prototype.addSourceFile = function (path, opt) { var file = this.addPluginFile(path, opt); @@ -291,6 +401,22 @@ pbxProject.prototype.removeFromPbxFileReferenceSection = function (file) { return file; } +pbxProject.prototype.addToClassesPbxGroup = function (file) { + var pluginsGroup = this.pbxGroupByName('Classes'); + pluginsGroup.children.push(pbxGroupChild(file)); +} + +pbxProject.prototype.removeFromClassesPbxGroup = function (file) { + var pluginsGroupChildren = this.pbxGroupByName('Classes').children, i; + for(i in pluginsGroupChildren) { + if(pbxGroupChild(file).value == pluginsGroupChildren[i].value && + pbxGroupChild(file).comment == pluginsGroupChildren[i].comment) { + pluginsGroupChildren.splice(i, 1); + break; + } + } +} + pbxProject.prototype.addToPluginsPbxGroup = function (file) { var pluginsGroup = this.pbxGroupByName('Plugins'); pluginsGroup.children.push(pbxGroupChild(file)); From fb98d92ab1fd6e428fc23e98e5e9ef22ee1d6c8e Mon Sep 17 00:00:00 2001 From: lordAtticus Date: Fri, 27 Jun 2014 14:16:40 +0300 Subject: [PATCH 2/3] addStaticLibrary fixed for Xcode 5.1 Xcode 5.1 requires static libraries added to framework group as well --- lib/pbxProject.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pbxProject.js b/lib/pbxProject.js index abdc622..1a9f86b 100644 --- a/lib/pbxProject.js +++ b/lib/pbxProject.js @@ -348,6 +348,7 @@ pbxProject.prototype.addStaticLibrary = function (path, opt) { this.addToPbxBuildFileSection(file); // PBXBuildFile this.addToPbxFrameworksBuildPhase(file); // PBXFrameworksBuildPhase + this.addToFrameworksPbxGroup(file); this.addToLibrarySearchPaths(file); // make sure it gets built! return file; From 2b798df9c77a30d25ab602b7034074a728affdb4 Mon Sep 17 00:00:00 2001 From: lordAtticus Date: Thu, 26 Feb 2015 17:08:50 +0200 Subject: [PATCH 3/3] Added quotes to handle folders with whitespace chars --- lib/pbxProject.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pbxProject.js b/lib/pbxProject.js index 1a9f86b..6343013 100644 --- a/lib/pbxProject.js +++ b/lib/pbxProject.js @@ -187,7 +187,7 @@ pbxProject.prototype.readFolder = function (dir, uuid) { fp.fileRef = this.generateUuid(); // create pbxgroup for parent folder var commentKey = f("%s_comment", fp.fileRef); - var entry = { "isa": 'PBXGroup', "children": [], "name": name, "path": name, "sourceTree": '""'}; + var entry = { "isa": 'PBXGroup', "children": [], "name": '"'+name+'"', "path": '"'+name+'"', "sourceTree": '""'}; groups[fp.fileRef] = entry; groups[commentKey] = name; groups[uuid].children.push(pbxGroupChild(fp));