Giter Site home page Giter Site logo

cordova-node-xcode's Introduction

cordova-node-xcode

NPM

Node CI

Parser utility for xcodeproj project files

Allows you to edit xcodeproject files and write them back out.

based on donated code from alunny / node-xcode

Example

// API is a bit wonky right now
var xcode = require('xcode'),
    fs = require('fs'),
    projectPath = 'myproject.xcodeproj/project.pbxproj',
    myProj = xcode.project(projectPath);

// parsing is async, in a different process
myProj.parse(function (err) {
    myProj.addHeaderFile('foo.h');
    myProj.addSourceFile('foo.m');
    myProj.addFramework('FooKit.framework');
   
    fs.writeFileSync(projectPath, myProj.writeSync());
    console.log('new project written');
});

Working on the parser

If there's a problem parsing, you will want to edit the grammar under lib/parser/pbxproj.pegjs. You can test it online with the PEGjs online thingy at https://pegjs.org/online - I have had some mixed results though.

Tests under the test/parser directory will compile the parser from the grammar. Other tests will use the prebuilt parser (lib/parser/pbxproj.js).

To rebuild the parser js file after editing the grammar, run:

npm run pegjs

(and be sure to restore the Apache license notice in lib/parser/pbxproj.js before committing)

License

Apache V2

cordova-node-xcode's People

Contributors

aabluedragon avatar alunny avatar appden avatar breautek avatar bshepherdson avatar dependabot[bot] avatar erisu avatar filmaj avatar freiserg avatar goya avatar imhotep avatar initialxy avatar ivankarpan avatar jdmcgrew avatar kelvinhokk avatar l3ender avatar mreinstein avatar n1ru4l avatar niklasmerz avatar robertoandrade avatar seobyeongky avatar sgrebnov avatar shazron avatar sidneys avatar stevengill avatar sundbry avatar timbru31 avatar vladimir-kotikov avatar wartech9 avatar zaubernerd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cordova-node-xcode's Issues

addFramework uses incorrect path for Swift libraries

The default path used in the PBXFileReference for frameworks with .tbd extensions is /usr/lib. However, I believe that Swift libraries with the same extension needs to have the path /usr/lib/swift.

For example, if you use addFramework to add libswiftAVFoundation.tbd it produces the following PBXFileReference in the project file:

27874A9BBF2444AABA64E8E0 /* libswiftAVFoundation.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswiftAVFoundation.tbd; path = usr/lib/libswiftAVFoundation.tbd; sourceTree = SDKROOT; };

This will ultimately result in a Crash on iOS versions 12.1 or lower, before the Swift runtime was bundled with the OS.

If you add the library manually in Xcode, the project file has the following `PBXFileReference' added:

5DBEA893249434B30034407A /* libswiftAVFoundation.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswiftAVFoundation.tbd; path = usr/lib/swift/libswiftAVFoundation.tbd; sourceTree = SDKROOT; };

Note the path difference:
cordova-node-xcode: usr/lib/libswiftAVFoundation.tbd
Xcode: usr/lib/swift/libswiftAVFoundation.tbd

I have an experimental patch here to work around this.

Assuming I'm on the right track here, I'll submit a pull request but I'm hoping that the maintainers can recommend if the approach I used is acceptable or if there's a more effective way to select the correct default path for these libraries than introducing another option.

Drop support for old Node.js versions

This should be done in a new major release. Some non-Cordova projects may be depending on support for old Node.js engines, maybe even back to 0.8.

ES6 classes

would be better than setting prototype functions, as part of new major release (#20)

I would personally favor a more functional approach, should be possible to make it more functional in a followup stage.

Unity `AddFileToBuild` How to achieve?

Unity AddFileToBuild How to achieve?

// https://docs.unity3d.com/ScriptReference/iOS.Xcode.PBXProject.html
proj.AddFileToBuild(target, proj.AddFile(fileName, fileName, PBXSourceTree.Source));

The documentation is too smal.

Travis CI build is too slow (was stuck)

I really do not understand it. I just pushed a new brodybits-travis-ci-multiple-os branch, Travis CI seems to be stuck too slow. I pushed the same branch to my fork, with Travis CI there, and quickly got a green build.

Cleanup

From review of PR #56 (watch2 support), I have a feeling that we should be able to clean up both the source code and all of the tests. I am raising this for future consideration and discussion.

Starting to add a list:

  • use const & let instead of var, especially in new code (noticed after merging PR #56)
  • look for ways to make the code easier to read & understand, especially the code added in PRs #56 & #76

/cc @l3ender

Convert to TypeScript?

Someone asked me by email if there would be any objections to converting this project to TypeScript in a pull request.

This kind of a contribution is always welcome for discussion and consideration. It would be best to first raise an issue for discussion.

My personal feelings about this idea are coming in a comment. I will also cast a vote on my own issue, based on my personal feelings coming up.

How to change Deployment Info?

Looking to update General -> Deployment Info -> Devices; how can I do this? Are there docs for this project anywhere?

Need some document/instruction for watch apps and app extensions

Hi guys, I am trying to create watch app with corodva app. Is there any place I could have a document/instruction on how to add watch2 apps and app extensions with cordova-node-xcode? I am sorry but don't know where is the correct place to ask this question. I greatly appreciate any help.

Internal filetypeForProducttype function not properly tested

The following possible mutation would not be detected by the existing test suite:

diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index 6466f47..c055e6a 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -1705,20 +1705,6 @@ function producttypeForTargettype (targetType) {
 
 function filetypeForProducttype (productType) {
 
-    FILETYPE_BY_PRODUCTTYPE = {
-            'com.apple.product-type.application': '"wrapper.application"',
-            'com.apple.product-type.app-extension': '"wrapper.app-extension"',
-            'com.apple.product-type.bundle': '"wrapper.plug-in"',
-            'com.apple.product-type.tool': '"compiled.mach-o.dylib"',
-            'com.apple.product-type.library.dynamic': '"compiled.mach-o.dylib"',
-            'com.apple.product-type.framework': '"wrapper.framework"',
-            'com.apple.product-type.library.static': '"archive.ar"',
-            'com.apple.product-type.bundle.unit-test': '"wrapper.cfbundle"',
-            'com.apple.product-type.application.watchapp': '"wrapper.application"',
-            'com.apple.product-type.watchkit-extension': '"wrapper.app-extension"'
-        };
-
-    return FILETYPE_BY_PRODUCTTYPE[productType]
 }
 
 pbxProject.prototype.getFirstProject = function() {

I think this test coverage should be added before we can finish adding WatchKit 2 as proposed in PR #56.

Mutation testing is done using Stryker as proposed in PR #61.

/cc @l3ender

Allow comma in buildSettings

when i try to set "TARGETED_DEVICE_FAMILY", it failed.
buildSettingsObj.TARGETED_DEVICE_FAMILY = '1,2'

While preparing Cordova project for platform iOS:
   SyntaxError: Expected ".", "/*", ";", or [0-9] but "," found.
   at peg$buildStructuredError (/Users/monsterstep/.meteor/packages/meteor-tool/.1.9.0.1eehdch.kfff++os.osx.x86_64+web.browser+web.browser.legacy+web.cordova/mt-os.osx.x86_64/dev_bundle/lib/node_modules/cordova-lib/node_modules/xcode/lib/parser/pbxproj.js:412:12)
   at Object.peg$parse [as parse] (/Users/monsterstep/.meteor/packages/meteor-tool/.1.9.0.1eehdch.kfff++os.osx.x86_64+web.browser+web.browser.legacy+web.cordova/mt-os.osx.x86_64/dev_bundle/lib/node_modules/cordova-lib/node_modules/xcode/lib/parser/pbxproj.js:1886:11)

the xcodeproj has value like this

image

image

#57

[META discuss] move this project out of Cordova?

This project which is published as xcode was "donated" to Cordova but seems to have some non-Cordova users (see #28 (comment) for example). Some recent changes such as PR #24 seem to come from non-Cordova users. There was also a question in apache/cordova-docs#921 (comment) on a blog post for this project.

I think it would be ideal to move this project into a non-Cordova organization so that we can start adding non-Cordova maintainers.

Automate "Notification Service Extension" (File > New > Target) step

Hi ✋ ,

I'm working with a Cordova based App, and I would like to automate the "Notification Service Extension" step (In Xcode: File > New > Target) (for example, in Jenkins pipeline) , since I saw that after doing it, remove platform, and add it again, the associated target is removed 😭

I've been searching through the docs, stack overflow and another issues and I haven't seen anything... (and trying to make a diff between platform without/with the extension seems impossible)... is this possible / or somebody can provide an example of something similar (since my knowledge over xcode is very limited) ?

Thanks a lot in advance!

PS: actually this is duplicate from (apache/cordova-ios#582) because I didn't know the existence of this project, if you think that the issue in the cordova-ios project should be closed let me know 🙏

PS: meanwhile I'm going to try myself with the library, if I achieve something I'll post here the solution for helping 👍

How to add system frameworks and custom frameworks?

Hi

I have been trying to use this module to add system and custom frameworks to automate adding a OneSignal Push Notification to our Ionic app.

We have managed to use the code snippet to generate the right NotificationService.h, NotificationService.m and .plist. That works very well indeed.

However we are stymed as we want to add in four system frameworks, UIKit.framework, WebKit.framework, SystemConfiguration.framework and CoreGraphics.framework as well as the OneSignal.framework. This is the last section to automating the whole of our build :)

We cannot see any documentation on how to use xcode.addframework here. We followed the link to the Swve plugins which were useful, we had a look at those and adapted them to work but as far as we can see, they don't add any frameworks.

Is this easy, have we not lookedf somewhere or is adding the frameworks a non-starter with this module.

Thanks for reading.

Rob

How do you define the target for Specific Build Settings or Adding Frameworks?

I've made an App Extension with the addTarget function but even though I have the target defined like so :

// (some global paths deliberately left out but they all point correctly)
    var extFiles = [
        'NotificationService.h',
        'NotificationService.m',
        `${extName}-Info.plist`,
        'appgroupconfig.json',
        'PushExtension.entitlements',
    ];

        const proj = xcode.project(projPath);
        proj.parseSync();

        // Copy in the extension files
        fs.mkdirSync(`${iosPath}${extName}`);
        extFiles.forEach(function (extFile) {
            let targetFile = `${iosPath}${extName}/${extFile}`;
            fs.createReadStream(`${sourceDir}${extFile}`)
                .pipe(fs.createWriteStream(targetFile));
        });
        
        // Add a target for the extension
        let extTarget = proj.addTarget(extName, 'app_extension');

I cannot seem to define any buildProperties for it specifically. For example, the function

pbxProject.prototype.updateBuildProperty = function(prop, value, build)

takes in the property key the value and the build but this will only update the main project and not any of the targets defined.

The target parameter in the addFramework function doesn't appear to work either. When digging into the pbxfile that it creates to addToFrameworkSearchPaths the target is not passed or accessed in the constructor. The following code doesn't add the Framework to the target:

var opt = {target: extTarget.uuid, embed: true, customFramework: true, sign: true}
proj.addFramework(`${custom_framework_path}`, opt);

Can somebody please point me to the right direction here? I don't know what I'm doing wrong.

'getBuildProperty' does not work as expected

In cordova-ios tests we have some failing tests because getBuildProperty behaves strangely.

It loops through all properties and returns the value of the last one. See code:

pbxProject.prototype.getBuildProperty = function(prop, build) {
    var target;
    var configs = this.pbxXCBuildConfigurationSection();
    for (var configName in configs) {
        if (!COMMENT_KEY.test(configName)) {
            var config = configs[configName];
            if ( (build && config.name === build) || (build === undefined) ) {
                if (config.buildSettings[prop] !== undefined) {
                    target = config.buildSettings[prop]; // <---- Here
                }
            }
        }
    }
    return target;
}

To me this does not make sense. In the cordova-ios test we update and check PRODUCT_BUNDLE_IDENTIFIER but we don't update all values. So getBuildProperty basically returns a random result.

Any ideas how we should handle this?

Internal pbxProject.prototype.addTargetDependency call not properly tested

From Stryker mutation testing (see PR #61) of WatchKit 2 support (PR #56), I discovered that the following change does not trigger a test failure:

diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index be9f473..5a7702a 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -1483,7 +1483,7 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) {
     this.addToPbxProjectSection(target);
 
     // Target: Add dependency for this target to first (main) target
-    this.addTargetDependency(this.getFirstTarget().uuid, [target.uuid]);
+    this.addTargetDependency(this.getFirstTarget().uuid, []);
 
 
     // Return target on success

I think test coverage of this possible mutation needs to be added before we merge PR #56, which moves this piece of code into the else clause of an if statement.

/cc @l3ender

Internal pbxProject.prototype.addTargetDependency function not properly tested

As discovered through Stryker mutation testing (PR #61), the following changes to pbxProject.prototype.addTargetDependency do not seem to trigger a test failure:

diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index be9f473..74b5f08 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -820,15 +820,6 @@ pbxProject.prototype.addTargetDependency = function(target, dependencyTargets) {
 
     var nativeTargets = this.pbxNativeTargetSection();
 
-    if (typeof nativeTargets[target] == "undefined")
-        throw new Error("Invalid target: " + target);
-
-    for (var index = 0; index < dependencyTargets.length; index++) {
-        var dependencyTarget = dependencyTargets[index];
-        if (typeof nativeTargets[dependencyTarget] == "undefined")
-            throw new Error("Invalid target: " + dependencyTarget);
-        }
-
     var pbxTargetDependency = 'PBXTargetDependency',
         pbxContainerItemProxy = 'PBXContainerItemProxy',
         pbxTargetDependencySection = this.hash.project.objects[pbxTargetDependency],
@@ -836,15 +827,15 @@ pbxProject.prototype.addTargetDependency = function(target, dependencyTargets) {
 
     for (var index = 0; index < dependencyTargets.length; index++) {
         var dependencyTargetUuid = dependencyTargets[index],
-            dependencyTargetCommentKey = f("%s_comment", dependencyTargetUuid),
+            dependencyTargetCommentKey = f("", dependencyTargetUuid),
             targetDependencyUuid = this.generateUuid(),
             targetDependencyCommentKey = f("%s_comment", targetDependencyUuid),
             itemProxyUuid = this.generateUuid(),
-            itemProxyCommentKey = f("%s_comment", itemProxyUuid),
+            itemProxyCommentKey = f("", itemProxyUuid),
             itemProxy = {
                 isa: pbxContainerItemProxy,
                 containerPortal: this.hash.project['rootObject'],
-                containerPortal_comment: this.hash.project['rootObject_comment'],
+                containerPortal_comment: this.hash.project[''],
                 proxyType: 1,
                 remoteGlobalIDString: dependencyTargetUuid,
                 remoteInfo: nativeTargets[dependencyTargetUuid].name
@@ -857,7 +848,7 @@ pbxProject.prototype.addTargetDependency = function(target, dependencyTargets) {
                 targetProxy_comment: pbxContainerItemProxy
             };
 
-        if (pbxContainerItemProxySection && pbxTargetDependencySection) {
+        {
             pbxContainerItemProxySection[itemProxyUuid] = itemProxy;
             pbxContainerItemProxySection[itemProxyCommentKey] = pbxContainerItemProxy;
             pbxTargetDependencySection[targetDependencyUuid] = targetDependency;

I discovered this while looking at the mutation testing results of PR #56 (watch2 support).

I think we should try to add the missing test coverage soon since this function is used to support the new watch2 functionality. However, I do not think this should block merge of PR #56.

This is also related to #73 (internal pbxProject.prototype.addTargetDependency call not properly tested).

/cc @l3ender

Unexpected error when xcode.project

Hi,

Currently I'm starting to use the library which seems to be very reliable but when I hit xcode.project('') the code stops with an exception.

I'm including this in a cordova hook to run a process after build and update some configuration.

The path is correct, I double check it, but the hook just stops when it gets to the load project line and doesn't return any message.

module.exports = function (context) {
    const fs = require('fs');
    const path = require('path');
    const fsExtra = require('fs-extra');
    const util = require('util')
    // The next library help us execute the cli(s) we require
    var glob = require('glob');
    var plist = require('plist');
    const cli = require('shelljs');
    try {
        // Only execute if we are dealing with iOS
        if (!context.opts.cordova.platforms || context.opts.cordova.platforms.indexOf('ios') === -1 || process.platform !== 'darwin') {
            console.log('HOOK_ERROR_PLATFORM_OR_OS_NOT_PRESENT');
            return;
        }

        // We require these libraries to manipulate files, directories and paths
        

        var rootdir = path.join(context.opts.projectRoot);

        cli.echo('START_HOOK_ENTITLEMENTS');

        // var pbxFiles = glob.sync("**/*.xcodeproj/project.pbxproj", {"cwd": rootdir});
        var pbxFiles = glob.sync("**/*.pbxproj", {"cwd": rootdir});
		pbxFiles.forEach(function(foundFile, idx, array){
			if(foundFile.indexOf("CordovaLib") == -1 
				&& foundFile.indexOf('node_modules') == -1
				&& foundFile.indexOf('plugins') == -1){
                    cli.echo('HOOK_ENTITLEMENTS_INITIATE_CHANGE');
				// Not the "CordovaLib" project
				var foundFileFull = path.join(rootdir, foundFile);
                cli.echo("Using project file " + foundFileFull);
                proj = xcode.project(foundFileFull);
                
                cli.echo('HERE');
                
			}
		});
    } catch(err) {
        cli.echo('HOOK_STOP_UNEXPECTEDLY');
        cli.echo(err);
        return;
    }
}

Any help will be appreciated

pbxProject hasFile returns false for existing file on Windows

We are running into an issue with this in our Expo CLI on Windows. After some investigation, it looks like there are some issues with Posix and Windows paths when detecting if files exists or not.

I created a repository with an example running on Ubuntu, MacOS and Windows that demonstrates this issue. The scenario it's testing is fairly simple:

const PBX_PROJECT_PATH = path.resolve('ios', 'testios2.xcodeproj', 'project.pbxproj');
const SPLASH_SCREEN_PATH = path.join('testios2', 'SplashScreen.storyboard');

// Create a new pbx project instance
const project = xcode.project(PBX_PROJECT_PATH);
// Now parse the project
project.parseSync();

// Determine if "SplashScreen.storyboard" exists
const file = project.hasFile(SPLASH_SCREEN_PATH);

You see that this is done successfully on both Linux and MacOS, but fails on Windows.

There is a workaround, you have to force the SPLASH_SCREEN_PATH to always be a posix formatted path. That works on Linux, MacOS, and Windows.

const SPLASH_SCREEN_PATH = path.join('testios2', 'SplashScreen.storyboard')
    // Force the path to always be a posix formatted path
    .replace(path.sep, path.posix.sep);

Internal pbxProject.prototype.addTarget function not properly tested

Through Stryker mutation testing (see PR #61) of watch2 support (PR #56), I discovered that the internal pbxProject.prototype.addTarget function is not properly tested. Here are some possible mutations that would not be detected by the existing test suite:

diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index be9f473..1693b74 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -1393,54 +1393,22 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) {
         targetSubfolder = subfolder || name,
         targetName = name.trim();
 
-    // Check type against list of allowed target types
-    if (!targetName) {
-        throw new Error("Target name missing.");
-    }
-
     // Check type against list of allowed target types
     if (!targetType) {
         throw new Error("Target type missing.");
     }
 
-    // Check type against list of allowed target types
-    if (!producttypeForTargettype(targetType)) {
-        throw new Error("Target type invalid: " + targetType);
-    }
-
     // Build Configuration: Create
-    var buildConfigurationsList = [
-        {
-            name: 'Debug',
-            isa: 'XCBuildConfiguration',
-            buildSettings: {
-                GCC_PREPROCESSOR_DEFINITIONS: ['"DEBUG=1"', '"$(inherited)"'],
-                INFOPLIST_FILE: '"' + path.join(targetSubfolder, targetSubfolder + '-Info.plist' + '"'),
-                LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"',
-                PRODUCT_NAME: '"' + targetName + '"',
-                SKIP_INSTALL: 'YES'
-            }
-        },
-        {
-            name: 'Release',
-            isa: 'XCBuildConfiguration',
-            buildSettings: {
-                INFOPLIST_FILE: '"' + path.join(targetSubfolder, targetSubfolder + '-Info.plist' + '"'),
-                LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"',
-                PRODUCT_NAME: '"' + targetName + '"',
-                SKIP_INSTALL: 'YES'
-            }
-        }
-    ];
+    var buildConfigurationsList = [];
 
     // Build Configuration: Add
-    var buildConfigurations = this.addXCConfigurationList(buildConfigurationsList, 'Release', 'Build configuration list for PBXNativeTarget "' + targetName +'"');
+    var buildConfigurations = this.addXCConfigurationList(buildConfigurationsList, '', '');
 
     // Product: Create
     var productName = targetName,
         productType = producttypeForTargettype(targetType),
         productFileType = filetypeForProducttype(productType),
-        productFile = this.addProductFile(productName, { group: 'Copy Files', 'target': targetUuid, 'explicitFileType': productFileType}),
+        productFile = this.addProductFile(productName, { group: '', 'explicitFileType': productFileType}),
         productFileName = productFile.basename;
 
 
@@ -1452,8 +1420,8 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) {
             uuid: targetUuid,
             pbxNativeTarget: {
                 isa: 'PBXNativeTarget',
-                name: '"' + targetName + '"',
-                productName: '"' + targetName + '"',
+                name: '"',
+                productName: '"',
                 productReference: productFile.fileRef,
                 productType: '"' + producttypeForTargettype(targetType) + '"',
                 buildConfigurationList: buildConfigurations.uuid,
@@ -1483,7 +1451,7 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) {
     this.addToPbxProjectSection(target);
 
     // Target: Add dependency for this target to first (main) target
-    this.addTargetDependency(this.getFirstTarget().uuid, [target.uuid]);
+    this.addTargetDependency(this.getFirstTarget().uuid, []);
 
 
     // Return target on success

Note that this diff includes the untested mutation that I reported in #73.

Considering that this function seems to play an important role in of the watch2 support, I would like to see it properly tested in the near future. However, I do not think that this should block merge of PR #56.

/cc @l3ender

[MAJOR] Drop support for Node.js 6 & 8

It is not desired to support outdated Node.js versions unless absolutely necessary.

For example, test coverage in PR #76 needed to be adapted to work on Node.js 6.

This kind of breaking change needs to be done in a major release. We would likely remove Node.js 8 at the same time since its EOL is December 2019.

allow setting empty path

When path is set to undefiend or null the following code is generated:

8E63D5C4EFE34B3BAE93815F /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				18285FBD1A3D4F05A3F47AC4 /* GoogleInterchangeUtilities.framework */,
			);
			name = Frameworks;
			path = undefined;
			sourceTree = "<group>";
		};

Since it is possible to create groups without a path it would be nice to not set a path when the path is undefined or null. Furthermore a path that equals undefined or null makes the Group appear red in xcode. This would also be fixed by simply dropping the path

How to use addResourceFile

I want to add localized content, use addResourceFile, but keep prompting Cannot read property 'path' of null
2
1

Code:
var languageResourceFile = myProj.addResourceFile("InfoPlist.strings");
if (languageResourceFile){
myProj.addToPbxResourcesBuildPhase(languageResourceFile);
myProj.addToPbxBuildFileSection(languageResourceFile);
fs.writeFileSync(projectPbxprojNamePath, myProj.writeSync());
}

Can we have a release? :)

There are some neat fixes that have happened since the last release. I'd be happy to become a contributor if you need somebody to do the grunt-work of shipping a release!

addBuildPhase corrupting project

I want to automate Crashlytics initialization by adding a build phase, as documented here:
https://firebase.google.com/docs/crashlytics/get-started#initialize

I added a cordova after_prepare hook to run the following script:

const xcode = require('xcode')
const path = require('path')
const fs = require('fs')

module.exports = function (context) {

  const projectDir = path.resolve(context.opts.projectRoot + '/platforms/ios')
  const dirContent = fs.readdirSync(projectDir)
  const matchingProjectFiles = dirContent.filter(filePath => /.*\.xcodeproj/gi.test(filePath) );
  const projectPath = projectDir + '/' + matchingProjectFiles[0] + '/project.pbxproj'

  const project = xcode.project(projectPath)

  project.parse(error => {
    if (error) console.error('failed to parse project', error)
    const options = {
      shellPath: '/bin/sh',
      shellScript: '${PODS_ROOT}/Fabric/run',
      // TODO: setting inputPaths corrupts the project file
      // inputPaths: ['$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)']
    }
    // TODO: Only add if not there yet
    project.addBuildPhase(
      [],
      'PBXShellScriptBuildPhase',
      'Initialize Crashlytics',
      project.getFirstTarget().uuid,
      options)
    fs.writeFileSync(projectPath, project.writeSync());
  })
}

The script as-is will create the build phase, but note the TODO comment above the commented-out configuration to set inputPaths. If I uncomment inputPaths, then the project file is corrupted, and I need to wipe out the platforms directory and start over.

Am I doing something wrong?

P.S. How can I check whether a build phase exists before adding it, in order to prevent duplicates?

Is there any documentation for this project?

I would like to ask if there is some sort of documentation for this project or perhaps can someone answer my questions?

I need to create "group" in the xcode project an add files in it. Then add these files into "compile sources" in "build phases". Is it possible to do this? I tried to create group with pbxCreateGroup() function and to add it in Xcode project I used addPbxGroupFunction(). But non of this seems to work. Also I tried to add the files directly to project with addFile() and addHeaderFile() / addSourceFile() functions but without success. I have to admit that first time I ran the script the files were added into "compile sources" in "build phases" but I wasn't able to do this again. Also I'm not really sure what the myProj.parse() does and how should I use it.

I know it is a lot of things but hopefully someone could help me.

script that I used:

project.parse(function(err) {
    if(err) console.log(err);

    var group = project.pbxCreateGroup("ASIHTTPRequest");

    files.forEach(file => {
        console.log(file);

        if (file.indexOf(".h") >= 0) {
                project.addFile(file, group);
                project.addHeaderFile(file);
                fs.writeFileSync(_PROJECT_FILE_PATH, project.writeSync());
        }
        else {
                project.addFile(file, group);
                project.addSourceFile(file);
                fs.writeFileSync(_PROJECT_FILE_PATH, project.writeSync());
        }
    })

    project.addPbxGroup([_PROJECT_FILE_PATH], "ASIHTTPRequest", _PROJECT_FILE_PATH);
    fs.writeFileSync(_PROJECT_FILE_PATH, project.writeSync());
})

pbxProject.prototype.addFramework: automatically create Frameworks Group if it does not exist

This is a feature proposal

Initial Situation:

Your xcode project tree looks like this:
bildschirmfoto 2018-12-09 um 22 28 11

You have a Xcode project without a Framworks group and you want to add a new framework using pbxProject.prototype.addFramework.

Current behaviour:

The Frameworks group is created but not added to the mainGroup of the project which references all files (that are not part of a subgroup) and all groups (that are no subgroups).

If you open the updated xcode project with xcode you see the following:

bildschirmfoto 2018-12-09 um 22 15 28

This is because xcode cannot find a reference to the Frameworks group on the mainGroup and therefore "autofixes" the project by adding the library added with pbxProject.prototype.addFramework to a newly generated group Recovered References.

Expected behaviour:

The Framework group is created and also automatically added to the mainGroup.

When you open the project in xcode it should look like this:

bildschirmfoto 2018-12-09 um 22 23 26

Current workaround:

Add the Frameworks group to mainGroupmanually:

  const project = xcode.project(projectPath);
  project.parseSync();

  project.addFramework(path.resolve(frameworksDirectory, 'GoogleInterchangeUtilities.framework'), {
    customFramework: true,
    embed: true,
    link: true,
  });

  const mainProject = project.getPBXGroupByKey(project.getFirstProject().firstProject.mainGroup);
  if (!mainProject.children.some(children => children.comment === 'Frameworks')) {
    const [groupKey] = Object.entries(project.hash.project.objects['PBXGroup']).find(
      ([, group]) => group.name === 'Frameworks',
    );
    project.addToPbxGroup(groupKey, project.getFirstProject().firstProject.mainGroup);
  }

If you are okay with this feature proposal I would love to implement it!

Build of `app_extension` target is not covered by test suite

The following changes would not be detected by the existing test suite:

1:

diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index 0e0f8f9..5894d91 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -1466,19 +1466,6 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) {
     // Target: Add to PBXNativeTarget section
     this.addToPbxNativeTargetSection(target)
 
-    // Product: Embed (only for "extension"-type targets)
-    if (targetType === 'app_extension') {
-
-        // Create CopyFiles phase in first target
-        this.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Copy Files', this.getFirstTarget().uuid,  targetType)
-
-        // Add product to CopyFiles phase
-        this.addToPbxCopyfilesBuildPhase(productFile)
-
-       // this.addBuildPhaseToTarget(newPhase.buildPhase, this.getFirstTarget().uuid)
-
-    };
-
     // Target: Add uuid to root project
     this.addToPbxProjectSection(target);
 

2:

diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index 0e0f8f9..d7e65da 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -1555,7 +1555,7 @@ function pbxCopyFilesBuildPhaseObj(obj, folderType, subfolderPath, phaseName) {
      // Add additional properties for 'CopyFiles' build phase
     var DESTINATION_BY_TARGETTYPE = {
         application: 'wrapper',
-        app_extension: 'plugins',
+        app_extension: '',
         bundle: 'wrapper',
         command_line_tool: 'wrapper',
         dynamic_library: 'products_directory',

3:

diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index 0e0f8f9..7301a16 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -1555,7 +1555,6 @@ function pbxCopyFilesBuildPhaseObj(obj, folderType, subfolderPath, phaseName) {
      // Add additional properties for 'CopyFiles' build phase
     var DESTINATION_BY_TARGETTYPE = {
         application: 'wrapper',
-        app_extension: 'plugins',
         bundle: 'wrapper',
         command_line_tool: 'wrapper',
         dynamic_library: 'products_directory',

I think the test coverage is needed to help ensure the functionality would not be broken by future changes.

Detected through mutation testing (PR #61) of watchkit2 updates (PR #56).

pbxProject.prototype.addToHeaderSearchPaths #13 issue, still appeared.

if (!buildSettings['HEADER_SEARCH_PATHS']) {
      buildSettings['HEADER_SEARCH_PATHS'] = [INHERITED];
}

This can be changed like this?

if (!buildSettings['HEADER_SEARCH_PATHS']
            || buildSettings['HEADER_SEARCH_PATHS'] === INHERITED) {
            buildSettings['HEADER_SEARCH_PATHS'] = [INHERITED];
        }

Adding support for ODR - On Demand Resources

Hello everyone :),

Our native team was in need to programmatically manage ODR tags in an Xcode project and found this project to be the best foundation for this we have found, hence the quite compact PR you can see here (
#87 ). Should the discussion continue here or in the PR itself?

Kind Regards,

Goffredo Marocchi - Native Area Gamesys

Allow asterisks in comments

Once the parser passes a /* token, it proceeds to search for a */ token, throwing a SyntaxError as soon as it encounter an asterisk not immediately followed by a slash. Comments can contain asterisks though. Many of these comments in project files are autogenerated, for example based on a file name which could have an asterisk in it.

Could the parser ignore * characters between /* and */, continuing its search without issue until it finds the closing */?

To reproduce the below, call the parser on any (file containing a) line such as /* Upload *.dSYM to Firebase */:

Thrown:
{ [SyntaxError: Expected "*/" or [^*] but "*" found.
]
  message: 'Expected "*/" or [^*] but "*" found.',
  expected:
   [ { type: 'class',
       parts: [Array],
       inverted: true,
       ignoreCase: false },
     { type: 'literal', text: '*/', ignoreCase: false },
     { type: 'class',
       parts: [Array],
       inverted: true,
       ignoreCase: false },
     { type: 'literal', text: '*/', ignoreCase: false } ],
  found: '*',
  location:
   { start: { offset: 697, line: 13, column: 35 },
     end: { offset: 698, line: 13, column: 36 } },
  name: 'SyntaxError' }

Remove addDataModelDocument function & drop simple-plist dependency

The addDataModelDocument does not seem to be used by Cordova, not sure if any other major dependents use this function or not.

I would personally favor moving addDataModelDocument & simple-plist dependency out, into an external utility package if anyone needs the functionality.

For consideration in a new major release (#20).

addBuildPhase keeps adding phases when they already exist

This is the build script line

xcodeProject.addBuildPhase(
              [], 'PBXShellScriptBuildPhase', 'Configure Crashlytics', undefined, options
            ).buildPhase;
            fs.writeFileSync(xcodeProjectPath, xcodeProject.writeSync());
            $logger.trace('Xcode project written');
          } else {
            $logger.error(xcodeProjectPath + ' is missing.');
            reject();
            return;
          }

So I guess everytime the CLI build runs it adds a NEW "Configure Crashlytics" to the build phase. Eventually my machine just outright died because the script was running hundreds of times.

Is there maybe a way before this I can check to see if it exists first before just adding it again?

Major update proposal

  • drop support for deprecated Node.js versions 0.8, 0.10, 0.12, and 4 (#17)
  • simple-plist@1 update
  • use ES2015 Object.assign as proposed in PR #14
  • consider committing package-lock.json
  • use ES6 classes instead of setting prototype functions
  • introduce some form of linting using eslint & prettier (#36, see discussion in PR #39)
  • cleanup code style issues, using prettier (ibid)
  • optional: it would also be ideal if we could port to a more currently maintained testing framework as well

We would need to increase the major version number to avoid breaking dependents that may need to support the older Node.js versions.

I would like to do the following before starting the major update:

  • uuid@3 update
  • introduce eslint that can be run as an npm script
  • cleanup major issues found by eslint
  • other possible cleanup that may be triggered by changes to resolve eslint issues
  • optional: it would also be ideal if we could port to a more currently maintained testing framework as well
  • publish minor 1.1.0 update

[Question] How to add file to PBXNativeTarget

I'm trying to add a file (GoogleServices-Info.plist) to my main project folder, but can't figure out what function to use. I've tried every one, and the best I can do is get it into my Plugins folder. Anyone know?

I thought these might work, but they didn't:

project.addToPbxGroupType(file, targetKey, 'PBXNativeTarget');
project.addToPbxFileReferenceSection(file);

// this one gives an error; sources is undefined
project.addToPbxCopyfilesBuildPhase(file);

Use JSDoc with tsc for strong static typing

It is possible to use JSDoc comments with the TypeScript compiler to enforce some strong typing, as documented in the following resources:

Here is the best example I have found: prettier/prettier#6313

I would personally favor this alternative over porting to TypeScript as proposed in #64.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.