8

I would like a new entry to be added under "Header Search Paths" once my Cordova plugin is added to an Xcode project.

How can I config it in my Cordova plugin.xml file?

Thanks.

Alon Amir
  • 4,913
  • 9
  • 47
  • 86

3 Answers3

5

As far as I know, there's no way to do this on a project-wide basis.

However, there is a way to add to the search path for each of your source files, which accomplishes the same thing. The source-file element in plugin.xml supports a compiler-flags attribute. To this attribute, you may add any flags that the compiler (in this case the clang command) supports. The compiler flag to add to the header search path is -I<path>. Note that if you include a space (eg -I <path>), Cordova will produce a misformatted .xcodeproj folder, and you will not be able to open the project in Xcode, nor build the Cordova project from the command line. Note also that <path> in this case is relative to your .xcodeproj folder that Cordova generates.

So, for example, if you have these files in your plugin folder (let's call it ~/com.MyPlugin/):

myAngleHeader.h
mySource.m
mySource.h

where mySource.h contains the line #include <myAngleHeader.h> and mySource.m contains the line #include "mySource.h"

You would then want to put into your plugin.xml (~/com.MyPlugin/plugin.xml):

<source-file src="myAngleHeader.h" />
<source-file src="mySource.h" />
<source-file src="mySource.m" compiler-flags="-ImyApp/Plugins/com.MyPlugin/" />

where "myApp" is the name of your Cordova project. Note again that there must be no space after the -I flag.

This method unfortunately requires that the developer control both the plugin and the Cordova project. It won't be very useful if you want to publish a plugin for all to use. There is probably a better way to do this; I'd love to hear other solutions.

Hope that helps!

John Walthour
  • 786
  • 2
  • 9
  • 23
  • This is just what I have been searching so long for, thanks. I just wanted to ask if it is possible to add more than one complier flag? As I also need to add the compiler flag '-fno-objc-arc' to the same files. – kai Taylor Mar 02 '15 at 11:11
  • I bet you could, but I haven't tried it myself. Try putting the full list of compiler flags into that element - eg compiler-flags="-I/folder/ -fno-obj-arc" or something like that. It might produce issues due to the space though. – John Walthour Feb 26 '16 at 13:44
  • @JohnWalthour Hey I figured out a way, gave an answer below. Not sure if the @ replies work in posts. I'll share my plugin with you when it is complete, it's really close. – Ross Feb 26 '16 at 23:34
  • @AlonAmir Here is my cordova plugin that uses hooks to modify header search paths on plugin install/uninstall - https://github.com/rossmartin/cordova-plugin-instagram-assets-picker – Ross Feb 29 '16 at 04:53
2

@JohnWalthour

I needed to do this for a cordova plugin I am creating and with the "after plugin install" hook it is possible. I realized I could run a node.js script after install and modify the HEADER_SEARCH_PATHS in ${project}/platforms/ios/cordova/build.xcconfig.

It required getting dirty but it works great. One crucial part of this working is that the Bundle name is assigned to ${PRODUCT_NAME} in the info.plist so you can use ${PRODUCT_NAME} in your build.xcconfig and it will interpolate with your project/app name. Cordova already has the ${PRODUCT_NAME} variable set for you.

Here is the relevant code -

plugin.xml (shortened for brevity and the important stuff)

<platform name="ios">
  .....
  <hook type="after_plugin_install" src="hooks/AfterPluginInstall.js" />
  <hook type="before_plugin_uninstall" src="hooks/BeforePluginUninstall.js" />
  .....
</platform>

AfterPluginInstall.js

#!/usr/bin/env node
'use strict';

let cwd = process.cwd();
let fs = require('fs');
let path = require('path');

console.log('InstagramAssetsPicker AfterPluginInstall.js, attempting to modify build.xcconfig');

let xcConfigBuildFilePath = path.join(cwd, 'platforms', 'ios', 'cordova', 'build.xcconfig');
console.log('xcConfigBuildFilePath: ', xcConfigBuildFilePath);
let lines = fs.readFileSync(xcConfigBuildFilePath, 'utf8').split('\n');

let headerSearchPathLineNumber;
lines.forEach((l, i) => {
  if (l.indexOf('HEADER_SEARCH_PATHS') > -1) {
    headerSearchPathLineNumber = i;
  }
});

if (lines[headerSearchPathLineNumber].indexOf('InstagramAssetsPicker') > -1) {
  console.log('build.xcconfig already setup for InstagramAssetsPicker');
  return;
}

lines[headerSearchPathLineNumber] += ' "$(SRCROOT)/$(PRODUCT_NAME)/cordova-plugin-InstagramAssetsPicker/GPUImageHeaders"';

let newConfig = lines.join('\n');

fs.writeFile(xcConfigBuildFilePath, newConfig, function (err) {
  if (err) {
    console.log('error updating build.xcconfig, err: ', err);
    return;
  }
  console.log('successfully updated HEADER_SEARCH_PATHS in build.xcconfig');
});

BeforePluginUninstall.js

#!/usr/bin/env node
'use strict';

let cwd = process.cwd();
let fs = require('fs');
let path = require('path');

console.log('InstagramAssetsPicker BeforePluginInstall.js, attempting to modify build.xcconfig');

let xcConfigBuildFilePath = path.join(cwd, 'platforms', 'ios', 'cordova', 'build.xcconfig');
console.log('xcConfigBuildFilePath: ', xcConfigBuildFilePath);
let lines = fs.readFileSync(xcConfigBuildFilePath, 'utf8').split('\n');

let headerSearchPathLineNumber;
lines.forEach((l, i) => {
  if (l.indexOf('HEADER_SEARCH_PATHS') > -1) {
    headerSearchPathLineNumber = i;
  }
});

if (lines[headerSearchPathLineNumber].indexOf('InstagramAssetsPicker') === -1) {
  console.log('build.xcconfig does not have header path for InstagramAssetsPicker.');
  return;
}

let line = lines[headerSearchPathLineNumber];
lines[headerSearchPathLineNumber] = line.replace(/\ "\$\(SRCROOT\)\/\$\(PRODUCT_NAME\)\/cordova-plugin-InstagramAssetsPicker\/GPUImageHeaders\"/i, '');

let newConfig = lines.join('\n');

fs.writeFile(xcConfigBuildFilePath, newConfig, function (err) {
  if (err) {
    console.log('error updating build.xcconfig, err: ', err);
    return;
  }
  console.log('successfully updated HEADER_SEARCH_PATHS in build.xcconfig');
});
Ross
  • 3,335
  • 1
  • 19
  • 18
2

I wanted to update my header search paths via the config as it was always a manual task setting it on build day. I have since added this plugin:

Cordova-Custom-Plugin

I was then able to add these to my config and didn't have to worry about it again.

<platform name="ios">
   <!-- Set orientation on iPhone -->
   <config-file platform="ios" target="*-Info.plist" parent="UISupportedInterfaceOrientations">
     <array>
       <string>UIInterfaceOrientationPortrait</string>
       <string>UIInterfaceOrientationPortraitUpsideDown</string>
     </array>
   </config-file>
   <!-- Set orientation on iPad -->
   <config-file platform="ios" target="*-Info.plist" parent="UISupportedInterfaceOrientations~ipad">
     <array>
       <string>UIInterfaceOrientationLandscapeLeft</string>
       <string>UIInterfaceOrientationLandscapeRight</string>
     </array>
   </config-file>
   <!-- Set Header Search Paths-->
   <preference name="ios-XCBuildConfiguration-HEADER\_SEARCH\_PATHS" value="'$(TARGET_BUILD_DIR)/usr/local/lib/include' '$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include' '$(BUILT_PRODUCTS_DIR)'" buildType="release" xcconfigEnforce="true" />

tyler_mitchell
  • 1,727
  • 1
  • 19
  • 27