You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by mu...@apache.org on 2015/05/18 23:55:25 UTC

cordova-windows git commit: CB-8486 Support for signing and build.json for Windows

Repository: cordova-windows
Updated Branches:
  refs/heads/master 48ced3f0f -> ca820841f


CB-8486 Support for signing and build.json for Windows


Project: http://git-wip-us.apache.org/repos/asf/cordova-windows/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-windows/commit/ca820841
Tree: http://git-wip-us.apache.org/repos/asf/cordova-windows/tree/ca820841
Diff: http://git-wip-us.apache.org/repos/asf/cordova-windows/diff/ca820841

Branch: refs/heads/master
Commit: ca820841f05be6fe48fa4793cb9fa92c0296de2a
Parents: 48ced3f
Author: Murat Sutunc <su...@gmail.com>
Authored: Mon Apr 13 18:17:07 2015 -0700
Committer: Murat Sutunc <su...@gmail.com>
Committed: Mon May 18 14:08:42 2015 -0700

----------------------------------------------------------------------
 template/CordovaApp.Phone.jsproj     |   7 +-
 template/CordovaApp.Windows.jsproj   |   7 +-
 template/CordovaApp.Windows80.jsproj |   5 +-
 template/CordovaApp.projitems        |   2 +
 template/CordovaApp.shproj           |  36 ++++-
 template/CordovaApp.sln              |   2 +-
 template/cordova/lib/build.js        | 222 +++++++++++++++++++++---------
 template/cordova/lib/prepare.js      | 147 +++++++++++++-------
 8 files changed, 293 insertions(+), 135 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/ca820841/template/CordovaApp.Phone.jsproj
----------------------------------------------------------------------
diff --git a/template/CordovaApp.Phone.jsproj b/template/CordovaApp.Phone.jsproj
index 43e4fe2..2c65b1c 100644
--- a/template/CordovaApp.Phone.jsproj
+++ b/template/CordovaApp.Phone.jsproj
@@ -71,9 +71,6 @@
     <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
   </PropertyGroup>
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).props" />
-  <PropertyGroup>
-    <DefaultLanguage>en-US</DefaultLanguage>
-  </PropertyGroup>
   <ItemGroup>
     <AppxManifest Include="package.phone.appxmanifest">
       <SubType>Designer</SubType>
@@ -83,10 +80,10 @@
   <ItemGroup>
     <SDKReference Include="Microsoft.Phone.WinJS.2.1, Version=1.0" />
   </ItemGroup>
-  <Import Project="CordovaApp.projitems" Label="Shared" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).targets" />
+  <Import Project="CordovaApp.projitems" Label="Shared" />
   <!-- To modify your build process, add your task inside one of the targets below then uncomment
-       that target and the DisableFastUpToDateCheck PropertyGroup. 
+       that target and the DisableFastUpToDateCheck PropertyGroup.
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">
   </Target>

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/ca820841/template/CordovaApp.Windows.jsproj
----------------------------------------------------------------------
diff --git a/template/CordovaApp.Windows.jsproj b/template/CordovaApp.Windows.jsproj
index 6905ba6..570a4b9 100644
--- a/template/CordovaApp.Windows.jsproj
+++ b/template/CordovaApp.Windows.jsproj
@@ -70,23 +70,20 @@
     <TargetPlatformVersion>8.1</TargetPlatformVersion>
     <RequiredPlatformVersion>8.1</RequiredPlatformVersion>
     <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
-    <DefaultLanguage>en-US</DefaultLanguage>
-    <PackageCertificateKeyFile>CordovaApp_TemporaryKey.pfx</PackageCertificateKeyFile>
   </PropertyGroup>
   <ItemGroup>
     <AppxManifest Include="package.windows.appxmanifest">
       <SubType>Designer</SubType>
     </AppxManifest>
     <Content Include="images\*.png" Exclude="images\*.scale-240.*" />
-    <None Include="CordovaApp_TemporaryKey.pfx" />
   </ItemGroup>
   <ItemGroup>
     <SDKReference Include="Microsoft.WinJS.2.0, Version=1.0" />
   </ItemGroup>
-  <Import Project="CordovaApp.projitems" Label="Shared" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).targets" />
+  <Import Project="CordovaApp.projitems" Label="Shared" />
   <!-- To modify your build process, add your task inside one of the targets below then uncomment
-       that target and the DisableFastUpToDateCheck PropertyGroup. 
+       that target and the DisableFastUpToDateCheck PropertyGroup.
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">
   </Target>

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/ca820841/template/CordovaApp.Windows80.jsproj
----------------------------------------------------------------------
diff --git a/template/CordovaApp.Windows80.jsproj b/template/CordovaApp.Windows80.jsproj
index 34d1985..56a6553 100644
--- a/template/CordovaApp.Windows80.jsproj
+++ b/template/CordovaApp.Windows80.jsproj
@@ -68,20 +68,16 @@
   <PropertyGroup>
     <TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
     <TargetPlatformVersion>8.0</TargetPlatformVersion>
-    <DefaultLanguage>en-US</DefaultLanguage>
-    <PackageCertificateKeyFile>CordovaApp_TemporaryKey.pfx</PackageCertificateKeyFile>
   </PropertyGroup>
   <ItemGroup>
     <AppxManifest Include="package.windows80.appxmanifest">
       <SubType>Designer</SubType>
     </AppxManifest>
     <Content Include="images\*.png" Exclude="images\*.scale-240.*" />
-    <None Include="CordovaApp_TemporaryKey.pfx" />
   </ItemGroup>
   <ItemGroup>
     <SDKReference Include="Microsoft.WinJS.1.0, Version=1.0" />
   </ItemGroup>
-  <Import Project="CordovaApp.projitems" Label="Shared" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).targets" />
   <PropertyGroup>
     <BuildFromCordovaTooling>false</BuildFromCordovaTooling>
@@ -90,4 +86,5 @@
       node -e "require('./cordova/lib/prepare.js').applyPlatformConfig()"
     </PreBuildEvent>
   </PropertyGroup>
+  <Import Project="CordovaApp.projitems" Label="Shared" />
 </Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/ca820841/template/CordovaApp.projitems
----------------------------------------------------------------------
diff --git a/template/CordovaApp.projitems b/template/CordovaApp.projitems
index 972a1a4..c408373 100644
--- a/template/CordovaApp.projitems
+++ b/template/CordovaApp.projitems
@@ -29,4 +29,6 @@
   <ItemGroup>
     <Content Include="$(MSBuildThisFileDirectory)config.xml" />
   </ItemGroup>
+  <Import Project="CordovaAppDebug.projitems" Condition="Exists('$(MSBuildThisFileDirectory)CordovaAppDebug.projitems') And '$(Configuration)'=='Debug'" />
+  <Import Project="CordovaAppRelease.projitems" Condition="Exists('$(MSBuildThisFileDirectory)CordovaAppRelease.projitems') And '$(Configuration)'!='Debug'" />
 </Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/ca820841/template/CordovaApp.shproj
----------------------------------------------------------------------
diff --git a/template/CordovaApp.shproj b/template/CordovaApp.shproj
index 08b59df..9c2f3bc 100644
--- a/template/CordovaApp.shproj
+++ b/template/CordovaApp.shproj
@@ -21,10 +21,44 @@
   <PropertyGroup Label="Globals">
     <ProjectGuid>{9ebdb27f-d75b-4d8c-b53f-7be4a1fe89f9}</ProjectGuid>
   </PropertyGroup>
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|AnyCPU">
+      <Configuration>Debug</Configuration>
+      <Platform>AnyCPU</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|ARM">
+      <Configuration>Debug</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x86">
+      <Configuration>Debug</Configuration>
+      <Platform>x86</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|AnyCPU">
+      <Configuration>Release</Configuration>
+      <Platform>AnyCPU</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|ARM">
+      <Configuration>Release</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x86">
+      <Configuration>Release</Configuration>
+      <Platform>x86</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
   <PropertyGroup />
-  <Import Project="CordovaApp.projitems" Label="Shared" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.CodeSharing.JavaScript.targets" />
+  <Import Project="CordovaApp.projitems" Label="Shared" />
 </Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/ca820841/template/CordovaApp.sln
----------------------------------------------------------------------
diff --git a/template/CordovaApp.sln b/template/CordovaApp.sln
index 808a6aa..31a66ee 100644
--- a/template/CordovaApp.sln
+++ b/template/CordovaApp.sln
@@ -37,7 +37,7 @@ Global
 	GlobalSection(SharedMSBuildProjectFiles) = preSolution
 		CordovaApp.projitems*{58950fb6-2f93-4963-b9cd-637f83f3efbf}*SharedItemsImports = 5
 		CordovaApp.projitems*{efffab2f-bfc5-4eda-b545-45ef4995f55a}*SharedItemsImports = 5
-		CordovaApp.projitems*{9ebdb27f-d75b-4d8c-b53f-7be4a1fe89f9}*SharedItemsImports = 13
+		CordovaApp.projitems*{9ebdb27f-d75b-4d8c-b53f-7be4a1fe89f9}*SharedItemsImports = 14
 		CordovaApp.projitems*{f9b0ae20-c91c-42b9-9c6e-d3bc28b4509e}*SharedItemsImports = 5
 		CordovaApp.projitems*{31b67a35-9503-4213-857e-f44eb42ae549}*SharedItemsImports = 5
 	EndGlobalSection

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/ca820841/template/cordova/lib/build.js
----------------------------------------------------------------------
diff --git a/template/cordova/lib/build.js b/template/cordova/lib/build.js
index 55f1cd0..e567192 100644
--- a/template/cordova/lib/build.js
+++ b/template/cordova/lib/build.js
@@ -24,7 +24,8 @@ var Q     = require('Q'),
     utils = require('./utils'),
     prepare = require('./prepare'),
     MSBuildTools = require('./MSBuildTools'),
-    ConfigParser = require('./ConfigParser');
+    ConfigParser = require('./ConfigParser'),
+    fs = require('fs');
 
 // Platform project root folder
 var ROOT = path.join(__dirname, '..', '..');
@@ -34,97 +35,184 @@ var projFiles = {
     win80: 'CordovaApp.Windows80.jsproj',
     win10: 'CordovaApp.Windows10.jsproj'
 };
-// parsed nopt arguments
-var args;
-// build type (Release vs Debug)
-var buildType;
-// target chip architectures to build for
-var buildArchs;
-// MSBuild Tools available on this development machine
-var msbuild;
-// Override windows-target-version for all devices
-var projVerOverride;
 
 // builds cordova-windows application with parameters provided.
 // See 'help' function for args list
 module.exports.run = function run (argv) {
+    // MSBuild Tools available on this development machine
+    var msbuild;
+
     if (!utils.isCordovaProject(ROOT)){
         return Q.reject('Could not find project at ' + ROOT);
     }
 
-    try {
-        // thows exception if something goes wrong
-        parseAndValidateArgs(argv);
-    } catch (error) {
-        return Q.reject(error);
-    }
-
-    // update platform as per configuration settings
-    prepare.applyPlatformConfig();
-    return MSBuildTools.findAvailableVersion().then(
-        function(msbuildTools) {
+    return Q.all([parseAndValidateArgs(argv), MSBuildTools.findAvailableVersion()])
+        .spread(function(buildConfig, msbuildTools) {
+            // update platform as per configuration settings
+            prepare.applyPlatformConfig(buildConfig);
             cleanIntermediates();
             msbuild = msbuildTools;
             console.log('MSBuildToolsPath: ' + msbuild.path);
-            return buildTargets();
+            return buildTargets(msbuild, buildConfig);
+        }, function(error) {
+            return Q.reject(error);
         });
 };
 
 // help/usage function
 module.exports.help = function help() {
     console.log('');
-    console.log('Usage: build [ --debug | --release ] [--archs="<list of architectures...>""] [--phone | --win]');
-    console.log('    --help    : Displays this dialog.');
-    console.log('    --debug   : Builds project in debug mode. (Default)');
-    console.log('    --release : Builds project in release mode.');
-    console.log('    -r        : Shortcut :: builds project in release mode.');
-    console.log('    --archs   : Builds project binaries for specific chip architectures ("anycpu", "arm", "x86", "x64").');
+    console.log('Usage: build [--debug | --release] [--archs="<list of architectures...>"]');
+    console.log('             [--phone | --win] [--packageCertificateKeyFile="key path"]');
+    console.log('             [--packageThumbprint="thumbprint"] [--publisherId]');
+    console.log('             [--buildConfig="file path"]');
+    console.log('    --help                      : Displays this dialog.');
+    console.log('    --debug                     : Builds project in debug mode. (Default).');
+    console.log('    --release                   : Builds project in release mode.');
+    console.log('    -r                          : (shortcut) Builds project in release mode.');
+    console.log('    --archs                     : Builds project binaries for specific chip');
+    console.log('                                  architectures (`anycpu`, `arm`, `x86`, `x64`).');
     console.log('    --phone, --win');
-    console.log('              : Specifies, what type of project to build');
+    console.log('                                : Specifies, what type of project to build.');
     console.log('    --appx=<8.1-win|8.1-phone|uap>');
-    console.log('              : Overrides windows-target-version to build Windows 8.1, Windows Phone 8.1, or Windows 10 Universal.');
+    console.log('                                : Overrides windows-target-version to build');
+    console.log('                                  Windows 8.1, Windows Phone 8.1, or');
+    console.log('                                  Windows 10 Universal.');
+    console.log('    --packageCertificateKeyFile : Builds the project using provided certificate.');
+    console.log('    --packageThumbprint         : Thumbprint associated with the certificate.');
+    console.log('    --publisherId               : Sets publisher id field in manifest.');
+    console.log('    --buildConfig               : Sets build settings from configuration file.');
+    console.log('');
     console.log('examples:');
     console.log('    build ');
     console.log('    build --debug');
     console.log('    build --release');
     console.log('    build --release --archs="arm x86"');
     console.log('    build --appx=8.1-phone -r');
+    console.log('    build --packageCertificateKeyFile="CordovaApp_TemporaryKey.pfx"');
+    console.log('    build --publisherId="CN=FakeCorp, C=US"');
+    console.log('    build --buildConfig="build.json"');
     console.log('');
 
     process.exit(0);
 };
 
 function parseAndValidateArgs(argv) {
-    // parse and validate args
-    args = nopt({'debug': Boolean, 'release': Boolean, 'archs': [String], 'appx': String,
-        'phone': Boolean, 'win': Boolean}, {'-r': '--release'}, argv);
-    // Validate args
-    if (args.debug && args.release) {
-        throw 'Only one of "debug"/"release" options should be specified';
-    }
-    if (args.phone && args.win) {
-        throw 'Only one of "phone"/"win" options should be specified';
+    return Q.promise(function(resolve, reject) {
+        // parse and validate args
+        var args = nopt({
+            'debug': Boolean,
+            'release': Boolean,
+            'archs': [String],
+            'appx': String,
+            'phone': Boolean,
+            'win': Boolean,
+            'packageCertificateKeyFile': String,
+            'packageThumbprint': String,
+            'publisherId': String,
+            'buildConfig': String
+            }, {'-r': '--release'}, argv);
+
+        var config = {};
+        var buildConfig = {};
+
+        // Validate args
+        if (args.debug && args.release) {
+            reject('Only one of "debug"/"release" options should be specified');
+            return;
+        }
+        if (args.phone && args.win) {
+            reject('Only one of "phone"/"win" options should be specified');
+            return;
+        }
+
+        // get build options/defaults
+        config.buildType = args.release ? 'release' : 'debug';
+        config.buildArchs = args.archs ? args.archs.split(' ') : ['anycpu'];
+        config.phone = args.phone ? true : false;
+        config.win = args.win ? true : false;
+        config.projVerOverride = args.appx;
+
+        // if build.json is provided, parse it
+        var buildConfigPath = args.buildConfig;
+        if (buildConfigPath) {
+            buildConfig = parseBuildConfig(buildConfigPath, config);
+            for (var prop in buildConfig) { config[prop] = buildConfig[prop]; }
+        }
+
+        // CLI arguments override build.json config
+        if (args.packageCertificateKeyFile) {
+            args.packageCertificateKeyFile = path.resolve(process.cwd(), args.packageCertificateKeyFile);
+            config.packageCertificateKeyFile = args.packageCertificateKeyFile;
+        }
+
+        config.packageThumbprint = config.packageThumbprint || args.packageThumbprint;
+        config.publisherId = config.publisherId || args.publisherId;
+
+        resolve(config);
+    });
+}
+
+function parseBuildConfig(buildConfigPath, config) {
+    var buildConfig, result = {};
+    console.log('Reading build config file: '+ buildConfigPath);
+    try {
+        var contents = fs.readFileSync(buildConfigPath, 'utf8');
+        buildConfig = JSON.parse(contents);
+    } catch (e) {
+        if (e.code === 'ENOENT') {
+            throw Error('Specified build config file does not exist: ' + buildConfigPath);
+        } else {
+            throw e;
+        }
     }
 
-    if (args.appx) {
-        projVerOverride = args.appx;
+    if (buildConfig.windows && buildConfig.windows[config.buildType]) {
+        var windowsInfo = buildConfig.windows[config.buildType];
+
+        // If provided assume it's a relative path
+        if(windowsInfo.packageCertificateKeyFile) {
+            var buildPath = path.dirname(fs.realpathSync(buildConfigPath));
+            result.packageCertificateKeyFile = path.resolve(buildPath, windowsInfo.packageCertificateKeyFile);
+        }
+
+        if(windowsInfo.packageThumbprint) {
+            result.packageThumbprint = windowsInfo.packageThumbprint;
+        }
+
+        if(windowsInfo.publisherId) {
+            // Quickly validate publisherId
+            var publisherRegexStr = '(CN|L|O|OU|E|C|S|STREET|T|G|I|SN|DC|SERIALNUMBER|(OID\\.(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))+))=' +
+                                    '(([^,+="<>#;])+|".*")(, (' +
+                                    '(CN|L|O|OU|E|C|S|STREET|T|G|I|SN|DC|SERIALNUMBER|(OID\\.(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))+))=' +
+                                    '(([^,+="<>#;])+|".*")))*';
+
+            var publisherRegex = new RegExp(publisherRegexStr);
+
+            if (!publisherRegex.test(windowsInfo.publisherId)) {
+                throw Error('Invalid publisher id: ' + windowsInfo.publisherId);
+            }
+
+            result.publisherId = windowsInfo.publisherId;
+        }
     }
-    
-    // get build options/defaults
-    buildType = args.release ? 'release' : 'debug';
-    buildArchs = args.archs ? args.archs.split(' ') : ['anycpu'];
-}
 
-function buildTargets() {
+    return result;
+}
 
+function buildTargets(msbuild, config) {
     // filter targets to make sure they are supported on this development machine
-    var myBuildTargets = filterSupportedTargets(getBuildTargets(), msbuild);
+    var myBuildTargets = filterSupportedTargets(getBuildTargets(config), msbuild);
+
     var buildConfigs = [];
 
     // collect all build configurations (pairs of project to build and target architecture)
     myBuildTargets.forEach(function(buildTarget) {
-        buildArchs.forEach(function(buildArch) {
-            buildConfigs.push({target:buildTarget, arch: buildArch});
+        config.buildArchs.forEach(function(buildArch) {
+            buildConfigs.push({
+                target:buildTarget,
+                arch: buildArch
+            });
         });
     });
 
@@ -139,18 +227,19 @@ function buildTargets() {
             if (msbuild.version == '4.0' && build.target == projFiles.win80) {
                 build.target = 'CordovaApp.vs2012.sln';
             }
-            return msbuild.buildProject(path.join(ROOT, build.target), buildType,  build.arch);
+            return msbuild.buildProject(path.join(ROOT, build.target), config.buildType,  build.arch);
          });
-    }, Q()); 
+    }, Q());
 }
 
-function getBuildTargets() {
-    var config = new ConfigParser(path.join(ROOT, 'config.xml'));
+function getBuildTargets(buildConfig) {
+    var configXML = new ConfigParser(path.join(ROOT, 'config.xml'));
     var targets = [];
-    var noSwitches = !(args.phone || args.win);
+    var noSwitches = !(buildConfig.phone || buildConfig.win);
+
     // Windows
-    if (args.win || noSwitches) { // if --win or no arg
-        var windowsTargetVersion = config.getWindowsTargetVersion();
+    if (buildConfig.win || noSwitches) { // if --win or no arg
+        var windowsTargetVersion = configXML.getWindowsTargetVersion();
         switch(windowsTargetVersion) {
         case '8':
         case '8.0':
@@ -167,18 +256,19 @@ function getBuildTargets() {
             throw new Error('Unsupported windows-target-version value: ' + windowsTargetVersion);
         }
     }
+
     // Windows Phone
-    if (args.phone || noSwitches) { // if --phone or no arg
-        var windowsPhoneTargetVersion = config.getWindowsPhoneTargetVersion();
+    if (buildConfig.phone || noSwitches) { // if --phone or no arg
+        var windowsPhoneTargetVersion = configXML.getWindowsPhoneTargetVersion();
         switch(windowsPhoneTargetVersion) {
         case '8.1':
             targets.push(projFiles.phone);
             break;
         case '10.0':
         case 'UAP':
-            if (!args.win && !noSwitches) { 
+            if (!buildConfig.win && !noSwitches) {
                 // Already built due to --win or no switches
-                // and since the same thing can be run on Phone as Windows, 
+                // and since the same thing can be run on Phone as Windows,
                 // we can skip this one.
                 targets.push(projFiles.win10);
             }
@@ -189,8 +279,8 @@ function getBuildTargets() {
     }
 
     // apply build target override if one was specified
-    if (projVerOverride) {
-        switch (projVerOverride) {
+    if (buildConfig.projVerOverride) {
+        switch (buildConfig.projVerOverride) {
             case '8.1-phone':
                 targets = [projFiles.phone];
                 break;
@@ -201,7 +291,7 @@ function getBuildTargets() {
                 targets = [projFiles.win10];
                 break;
             default:
-                console.warn('Unrecognized --appx parameter passed to build: "' + projVerOverride + '", ignoring.');
+                console.warn('Unrecognized --appx parameter passed to build: "' + buildConfig.projVerOverride + '", ignoring.');
                 break;
         }
     }
@@ -225,7 +315,7 @@ function msBuild14TargetsFilter(target) {
     return target === projFiles.win || target === projFiles.phone || target === projFiles.win10;
 }
 
-function filterSupportedTargets (targets) {
+function filterSupportedTargets (targets, msbuild) {
     if (!targets || targets.length === 0) {
         console.warn('\r\nNo build targets are specified.');
         return [];

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/ca820841/template/cordova/lib/prepare.js
----------------------------------------------------------------------
diff --git a/template/cordova/lib/prepare.js b/template/cordova/lib/prepare.js
index da3ff24..485f2d8 100644
--- a/template/cordova/lib/prepare.js
+++ b/template/cordova/lib/prepare.js
@@ -32,47 +32,56 @@ var ROOT = path.join(__dirname, '..', '..'),
     MANIFEST_WINDOWS    = 'package.windows.appxmanifest',
     MANIFEST_PHONE      = 'package.phone.appxmanifest',
     MANIFEST_WINDOWS10  = 'package.windows10.appxmanifest',
-    JSPROJ_WINDOWS8     = 'CordovaApp.Windows80.jsproj',
-    JSPROJ_WINDOWS      = 'CordovaApp.Windows.jsproj',
-    JSPROJ_PHONE        = 'CordovaApp.Phone.jsproj',
-    JSPROJ_WINDOWS10    = 'CordovaApp.Windows10.jsproj',
     BASE_UAP_VERSION    = new Version(10, 0, 10030, 0),
-    UAP_RESTRICTED_CAPS = ['enterpriseAuthentication', 'sharedUserCertificates', 
-                           'documentsLibrary', 'musicLibrary', 'picturesLibrary', 
-                           'videosLibrary', 'removableStorage', 'internetClientClientServer', 
+    UAP_RESTRICTED_CAPS = ['enterpriseAuthentication', 'sharedUserCertificates',
+                           'documentsLibrary', 'musicLibrary', 'picturesLibrary',
+                           'videosLibrary', 'removableStorage', 'internetClientClientServer',
                            'privateNetworkClientServer'],
     // UAP namespace capabilities come from the XSD type ST_Capability_Uap from AppxManifestTypes.xsd
-    CAPS_NEEDING_UAPNS  = ['documentsLibrary', 'picturesLibrary', 'videosLibrary', 
-                           'musicLibrary', 'enterpriseAuthentication', 'sharedUserCertificates', 
+    CAPS_NEEDING_UAPNS  = ['documentsLibrary', 'picturesLibrary', 'videosLibrary',
+                           'musicLibrary', 'enterpriseAuthentication', 'sharedUserCertificates',
                            'removableStorage', 'appointments', 'contacts', 'userAccountInformation',
                            'phoneCall', 'blockedChatMessages', 'objects3D'];
 
-module.exports.applyPlatformConfig = function () {
+var TEMPLATE =
+    '<?xml version="1.0" encoding="utf-8"?>\n' +
+    '<!--\n    This file is automatically generated.\n' +
+    '    Do not modify this file - YOUR CHANGES WILL BE ERASED!\n-->\n';
+
+module.exports.applyPlatformConfig = function(buildConfig) {
     console.log('Applying Platform Config...');
 
     var config = new ConfigParser(path.join(ROOT, 'config.xml'));
-
     var isTargetingWin10 = false;
     var winTargetVersion = config.getWindowsTargetVersion();
     if (winTargetVersion === '10.0' || winTargetVersion === 'UAP') {
         isTargetingWin10 = true;
     }
 
+    // if no buildConfig is provided dont do anything
+    buildConfig = buildConfig || {};
+
+    // Merge buildConfig with config
+    for (var attr in buildConfig) {
+        config[attr] = buildConfig[attr];
+    }
+
     // Apply appxmanifest changes
-    [{ fileName: MANIFEST_WINDOWS,   namespacePrefix: 'm2:' }, 
+    [{ fileName: MANIFEST_WINDOWS,   namespacePrefix: 'm2:' },
      { fileName: MANIFEST_WINDOWS8,  namespacePrefix: '' },
      { fileName: MANIFEST_PHONE,     namespacePrefix: 'm3:' }].forEach(
         function(manifestFile) {
             updateManifestFile(config, path.join(ROOT, manifestFile.fileName), manifestFile.namespacePrefix, null);
     });
 
-    // Apply jsproj changes
-    [JSPROJ_PHONE, JSPROJ_WINDOWS, JSPROJ_WINDOWS8, JSPROJ_WINDOWS10].forEach(
-        function(jsprojFile) {
-            updatejsprojFile(config, path.join(ROOT, jsprojFile));
-    });
+    // Apply build related configs
+    if (config.buildType === 'debug') {
+        updateBuildConfig(config, path.join(ROOT, 'CordovaAppDebug.projitems'));
+    } else if(config.buildType === 'release') {
+        updateBuildConfig(config, path.join(ROOT, 'CordovaAppRelease.projitems'));
+    }
 
-    // Break out Windows 10-specific functionality because we also need to 
+    // Break out Windows 10-specific functionality because we also need to
     // apply UAP versioning to Windows 10 appx-manifests.
     var uapVersionInfo = getUAPVersions(config);
 
@@ -88,18 +97,47 @@ module.exports.applyPlatformConfig = function () {
     copyImages(config);
 };
 
-function updatejsprojFile(config, jsProjFilePath) {
-    var defaultLocale = config.defaultLocale() || 'en-US';
 
-    var contents = fs.readFileSync(jsProjFilePath, 'utf-8');
-    // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
-    if (contents.charCodeAt(0) === 0xFEFF) {
-        contents = contents.slice(1);
+function updateBuildConfig(config, buildConfigFileName) {
+    var root = new et.Element('Project');
+    root.set('xmlns', 'http://schemas.microsoft.com/developer/msbuild/2003');
+    var buildConfigXML =  new et.ElementTree(root);
+    var propertyGroup = new et.Element('PropertyGroup');
+    var itemGroup = new et.Element('ItemGroup');
+
+    // Append PropertyGroup and ItemGroup
+    buildConfigXML.getroot().append(propertyGroup);
+    buildConfigXML.getroot().append(itemGroup);
+
+    // packageCertificateKeyFile - defaults to 'CordovaApp_TemporaryKey.pfx'
+    var packageCertificateKeyFile = config.packageCertificateKeyFile || 'CordovaApp_TemporaryKey.pfx';
+
+    if (config.packageCertificateKeyFile) {
+        // Convert packageCertificateKeyFile from absolute to relative path
+        packageCertificateKeyFile = path.relative(ROOT, packageCertificateKeyFile);
+    }
+
+    var certificatePropertyElement = new et.Element('PackageCertificateKeyFile');
+    certificatePropertyElement.text = packageCertificateKeyFile;
+    propertyGroup.append(certificatePropertyElement);
+
+    var certificateItemElement = new et.Element('None', { 'Include': packageCertificateKeyFile });
+    itemGroup.append(certificateItemElement);
+
+    // packageThumbprint
+    if (config.packageThumbprint) {
+        var thumbprintElement = new et.Element('PackageCertificateThumbprint');
+        thumbprintElement.text = config.packageThumbprint;
+        propertyGroup.append(thumbprintElement);
     }
-    var jsProjXML =  new et.ElementTree(et.XML(contents));
-    var jsProjDefaultLocale = jsProjXML.find('./PropertyGroup/DefaultLanguage');
-    jsProjDefaultLocale.text = defaultLocale;
-    fs.writeFileSync(jsProjFilePath, jsProjXML.write({indent: 2}), 'utf-8');
+
+    // DefaultLanguage - defaults to 'en-US'
+    var defaultLocale = config.defaultLocale() || 'en-US';
+    var defaultLocaleElement = new et.Element('DefaultLanguage');
+    defaultLocaleElement.text = defaultLocale;
+    propertyGroup.append(defaultLocaleElement);
+
+    fs.writeFileSync(buildConfigFileName, TEMPLATE + buildConfigXML.write({indent: 2, xml_declaration: false}), 'utf-8');
 }
 
 function updateManifestFile (config, manifestPath, namespacePrefix, uapVersionInfo) {
@@ -111,10 +149,10 @@ function updateManifestFile (config, manifestPath, namespacePrefix, uapVersionIn
 
     var manifest =  new et.ElementTree(et.XML(contents));
 
-    applyCoreProperties(config, manifest, manifestPath, namespacePrefix, !!uapVersionInfo); 
+    applyCoreProperties(config, manifest, manifestPath, namespacePrefix, !!uapVersionInfo);
     // sort Capability elements as per CB-5350 Windows8 build fails due to invalid 'Capabilities' definition
     sortCapabilities(manifest);
-    applyAccessRules(config, manifest, !!uapVersionInfo); 
+    applyAccessRules(config, manifest, !!uapVersionInfo);
     applyBackgroundColor(config, manifest, namespacePrefix);
     applyToastCapability(config, manifest, namespacePrefix);
 
@@ -146,12 +184,17 @@ function applyCoreProperties(config, manifest, manifestPath, xmlnsPrefix, target
         (identityNode.attrib.Version = version);
     }
 
+    // Update publisher id (identity)
+    if (config.publisherId && identityNode.attrib.Publisher !== config.publisherId) {
+        identityNode.attrib.Publisher = config.publisherId;
+    }
+
     // Update name (windows8 has it in the Application[@Id] and Application.VisualElements[@DisplayName])
     var app = manifest.find('.//Application');
     if(!app) {
         throw new Error('Invalid manifest file (no <Application> node): ' + manifestPath);
     }
-    
+
     if (pkgName) {
         // 64 symbols restriction goes from manifest schema definition
         // http://msdn.microsoft.com/en-us/library/windows/apps/br211415.aspx
@@ -159,10 +202,10 @@ function applyCoreProperties(config, manifest, manifestPath, xmlnsPrefix, target
         app.attrib.Id = appId;
     }
 
-    applyStartPage(app, config, targetWin10); 
+    applyStartPage(app, config, targetWin10);
 
-    var visualElementsName = './/' + xmlnsPrefix + 'VisualElements'; 
-    var visualElems = manifest.find(visualElementsName); 
+    var visualElementsName = './/' + xmlnsPrefix + 'VisualElements';
+    var visualElems = manifest.find(visualElementsName);
 
     if(!visualElems) {
         throw new Error('Invalid manifest file (no <' + xmlnsPrefix + 'VisualElements> node): ' + manifestPath);
@@ -242,7 +285,7 @@ function applyStartPage(appNode, config, targetingWin10) {
 
     var uriPrefix = '';
     if (targetingWin10) {
-        // for Win10, we respect config options such as WindowsDefaultUriPrefix and default to 
+        // for Win10, we respect config options such as WindowsDefaultUriPrefix and default to
         // ms-appx-web:// as the homepage.  Set those here.
 
         // Only add a URI prefix if the start page doesn't specify a URI scheme
@@ -251,7 +294,7 @@ function applyStartPage(appNode, config, targetingWin10) {
             if (!uriPrefix) {
                 uriPrefix = 'ms-appx-web://';
             }
-            else if (/^ms\-appx\:\/\/$/i.test(uriPrefix)) { 
+            else if (/^ms\-appx\:\/\/$/i.test(uriPrefix)) {
                 // Explicitly ignore the ms-appx:// scheme because it doesn't validate
                 // in the Windows 10 build schema (treat it as the root).
                 uriPrefix = '';
@@ -260,7 +303,7 @@ function applyStartPage(appNode, config, targetingWin10) {
     }
 
     var startPagePrefix = 'www/';
-    if ((uriPrefix && uriPrefix.toLowerCase().substring(0, 4) === 'http') || 
+    if ((uriPrefix && uriPrefix.toLowerCase().substring(0, 4) === 'http') ||
         startPage.toLowerCase().substring(0, 4) === 'http') {
         startPagePrefix = '';
     }
@@ -295,7 +338,6 @@ function applyAccessRules (config, manifest, isTargetingWin10) {
         return applyNavigationWhitelist(config, manifest);
     }
 
-    
     var accessRules = config.getAccessRules().filter(function(rule) {
         // https:// rules are always good, * rules are always good
         if (rule.indexOf('https://') === 0 || rule === '*') {
@@ -314,7 +356,7 @@ function applyAccessRules (config, manifest, isTargetingWin10) {
     createApplicationContentUriRules(manifest, AppContentUriRulesElementName, RuleElementName, accessRules, { Type: 'include' });
 }
 
-/** 
+/**
  * Windows 10-based whitelist-plugin-compatible support for the enhanced navigation whitelist.
  * Allows WinRT access to origins specified by <allow-navigation href="origin" /> elements.
  */
@@ -342,8 +384,8 @@ function applyNavigationWhitelist(config, manifest) {
         }
     }
 
-    createApplicationContentUriRules(manifest, AppContentUriRulesElementName, RuleElementName, whitelistRules, { 
-        Type: 'include', 
+    createApplicationContentUriRules(manifest, AppContentUriRulesElementName, RuleElementName, whitelistRules, {
+        Type: 'include',
         WindowsRuntimeAccess: 'all'
     });
 }
@@ -439,12 +481,12 @@ function copyImages(config) {
         var srcDir = path.dirname(src),
             srcExt = path.extname(src),
             srcFileName = path.basename(src, srcExt);
-     
+
         var destExt = path.extname(dest),
             destFileName = path.basename(dest, destExt);
 
         // all MRT images: logo.png, logo.scale-100.png, logo.scale-200.png, etc
-        var images = fs.readdirSync(srcDir).filter(function(e) { 
+        var images = fs.readdirSync(srcDir).filter(function(e) {
             return e.match('^'+srcFileName + '(.scale-[0-9]+)?' + srcExt);
         });
         // warn if no images found
@@ -460,7 +502,6 @@ function copyImages(config) {
             }
             copyImage(path.join(srcDir, img), destFileName+scale+destExt);
         });
-        
     }
 
     // Platform default images
@@ -485,7 +526,7 @@ function copyImages(config) {
 
     function findPlatformImage(width, height) {
         if (!width && !height){
-            // this could be default image, 
+            // this could be default image,
             // Windows requires specific image dimension so we can't apply it
             return null;
         }
@@ -597,12 +638,12 @@ function getUAPVersions(config) {
     };
 }
 
-/** 
+/**
  * Gets min/max UAP versions from the configuration.  If no version preferences are
  * in the configuration file, this will provide Windows.Universal at BASE_UAP_VERSION for both min and max.
  * This will always return a rational object or will fail; for example, if a platform expects
  * a higher min-version than max-version, it will raise the max version to the min version.
- * 
+ *
  * @param config {ConfigParser} The configuration parser
  * @return An object in the shape of: { 'Windows.Mobile': {'MinVersion': Version, 'MaxVersion': Version } } (where Version is a Version object)
  * @exception {RangeError} Thrown if a Version string is badly formed.
@@ -643,7 +684,7 @@ function getAllMinMaxUAPVersions(config) {
         else if (!versionPref.MinVersion && !versionPref.MaxVersionTested) { // neither are set
             versionPref.MinVersion = BASE_UAP_VERSION;
             versionPref.MaxVersionTested = BASE_UAP_VERSION;
-        } 
+        }
         else { // both are set
             if (versionPref.MinVersion.gt(versionPref.MaxVersionTested)) {
                 versionPref.MaxVersionTested = versionPref.MinVersion;
@@ -659,7 +700,7 @@ function getAllMinMaxUAPVersions(config) {
 }
 
 /**
- * Checks to see whether access rules or 
+ * Checks to see whether access rules or
  * @param config {ConfigParser} The configuration parser
  * @return {boolean} True if the config specifies remote URIs for access or start; false otherwise.
  */
@@ -676,7 +717,7 @@ function checkForRemoteModeUris(config) {
     return hasRemoteUri;
 }
 
-/** 
+/**
  * Checks for capabilities which are Restricted in Windows 10 UAP.
  * @param appxManifestCapabilitiesElement {ElementTree.Element} The appx manifest element for <capabilities>
  * @return {string[]|false} An array of restricted capability names, or false.
@@ -732,14 +773,14 @@ function ensureUapPrefixedCapabilities(appxManifestCapabilitiesElement) {
 function applyToastCapability(config, manifest, namespacePrefix) {
     var isToastCapable = config.getPreference('WindowsToastCapable');
     isToastCapable = (isToastCapable && isToastCapable.toString().toLowerCase() === 'true');
-    
+
     var visualElementsName = './/' + namespacePrefix + 'VisualElements';
     var visualElems = manifest.find(visualElementsName);
-    
+
     if (isToastCapable) {
         visualElems.attrib.ToastCapable = 'true';
     }
     else {
         delete visualElems.attrib.ToastCapable;
-    } 
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org