Skip to content

Commit 81ddc4a

Browse files
authored
fix(addBuildPhase): adding of PBXBuildFile entries to lookup table (#174)
* fix(addBuildPhase): adding of PBXBuildFile entries to lookup table - Add PBXBuildFile entry to filePathToBuildFile lookup table when a valid identifier is present. - Valid identifier is determined when the fileReference has either a path or name property value. - The path property takes priority when both path and name are defined. - When the path and name properties are not defined the entry is not added to the lookup table. * doc(addBuildPhase): add notes & supporting typedef
1 parent 04fc2dd commit 81ddc4a

1 file changed

Lines changed: 96 additions & 6 deletions

File tree

lib/pbxProject.js

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,56 @@ const parser = require('./parser/pbxproj');
3030
const plist = require('simple-plist');
3131
const COMMENT_KEY = /_comment$/;
3232

33+
// MARK: Start of Typings
34+
35+
/**
36+
* A list of known build phase types.
37+
* @typedef {'PBXCopyFilesBuildPhase' |
38+
* 'PBXResourcesBuildPhase' |
39+
* 'PBXFrameworksBuildPhase' |
40+
* 'PBXHeadersBuildPhase' |
41+
* 'PBXShellScriptBuildPhase' |
42+
* 'PBXSourcesBuildPhase'
43+
* } BuildPhaseType
44+
*/
45+
46+
/**
47+
* The result object returned when adding a build phase.
48+
* @typedef {object} AddBuildPhaseResults
49+
* @property {string} uuid Build Phase UUID
50+
* @property {object} buildPhase Build Phase object
51+
*/
52+
53+
/**
54+
* A list of valid target types used for copy files build configurations.
55+
* @typedef {'application'
56+
* | 'app_extension'
57+
* | 'bundle'
58+
* | 'command_line_tool'
59+
* | 'dynamic_library'
60+
* | 'framework'
61+
* | 'frameworks'
62+
* | 'static_library'
63+
* | 'unit_test_bundle'
64+
* | 'watch_app'
65+
* | 'watch2_app'
66+
* | 'watch_extension'
67+
* | 'watch2_extension'
68+
* } CopyFilesTargetType
69+
*/
70+
71+
/**
72+
* Options used when adding a PBXShellScriptBuildPhase.
73+
* @typedef {object} ShellScriptOptions
74+
* @property {string[]} inputPaths input paths
75+
* @property {string[]} outputPaths output Paths
76+
* @property {string} shellPath shell paths
77+
* @property {0 | 1} runOnlyForDeploymentPostprocessing run script for install builds only
78+
* @property {1} [alwaysOutOfDate] disables dependency analysis when set to true
79+
*/
80+
81+
// MARK: End of Typings
82+
3383
function PBXProject (filename) {
3484
if (!(this instanceof PBXProject)) { return new PBXProject(filename); }
3585

@@ -851,6 +901,25 @@ PBXProject.prototype.addTargetDependency = function (target, dependencyTargets)
851901
return { uuid: target, target: nativeTargets[target] };
852902
};
853903

904+
/**
905+
* Add files to specific build phase by defining the build phase type.
906+
*
907+
* @example
908+
* // Adding a file to Resource Build Phase.
909+
* myProject.addBuildPhase(
910+
* ['MyAssets.xcassets'],
911+
* 'PBXResourcesBuildPhase',
912+
* 'Resources'
913+
* );
914+
*
915+
* @param {string[]} filePathsArray collection of file paths
916+
* @param {BuildPhaseType} buildPhaseType target build phase
917+
* @param {string} comment name of the build phase. (e.g. "Copy My Files")
918+
* @param {string} target UUID of the PBXNativeTarget (defaults to first target)
919+
* @param {CopyFilesTargetType|ShellScriptOptions} optionsOrFolderType either sell script options or copy files target type
920+
* @param {string} subfolderPath copy files subfolder path (default: "")
921+
* @returns {AddBuildPhaseResults} object containing the build phase & uuid
922+
*/
854923
PBXProject.prototype.addBuildPhase = function (filePathsArray, buildPhaseType, comment, target, optionsOrFolderType, subfolderPath) {
855924
let buildPhaseSection;
856925
const fileReferenceSection = this.pbxFileReferenceSection();
@@ -896,18 +965,33 @@ PBXProject.prototype.addBuildPhase = function (filePathsArray, buildPhaseType, c
896965
const buildFile = buildFileSection[buildFileKey];
897966
const fileReference = fileReferenceSection[buildFile.fileRef];
898967

899-
if (!fileReference) continue;
968+
// If a file reference does not define either the name or path property,
969+
// it will not be included to the filePathToBuildFile lookup table.
970+
// If the file reference defines both properies, the path property will
971+
// take priority.
972+
const fileIdentifier = fileReference?.path || fileReference?.name;
900973

901-
const pbxFileObj = new PBXFile(fileReference.path);
974+
if (!fileIdentifier) {
975+
continue;
976+
}
902977

903-
filePathToBuildFile[fileReference.path] = { uuid: buildFileKey, basename: pbxFileObj.basename, group: pbxFileObj.group };
978+
const pbxFileObj = new PBXFile(fileIdentifier);
979+
980+
// Creates a lookup table of existing PBXBuildFile entries keyed by fileIdentifier.
981+
// Used later when adding files to the build phase to reuse the existing PBXBuildFile
982+
// instead of generating new PBXBuildFile.
983+
filePathToBuildFile[fileIdentifier] = {
984+
uuid: buildFileKey,
985+
basename: pbxFileObj.basename,
986+
group: pbxFileObj.group
987+
};
904988
}
905989

906990
for (let index = 0; index < filePathsArray.length; index++) {
907991
const filePath = filePathsArray[index];
908992
const filePathQuoted = '"' + filePath + '"';
909-
const file = new PBXFile(filePath);
910993

994+
// Checks for an existing PBXBuildFile entry from the filePathToBuildFile lookup table.
911995
if (filePathToBuildFile[filePath]) {
912996
buildPhase.files.push(pbxBuildPhaseObj(filePathToBuildFile[filePath]));
913997
continue;
@@ -916,10 +1000,16 @@ PBXProject.prototype.addBuildPhase = function (filePathsArray, buildPhaseType, c
9161000
continue;
9171001
}
9181002

1003+
// If no PBXBuildFile entry is found in the lookup table, a new entry is created
1004+
// with a new UUID. It is then:
1005+
// 1. Added to the PBXFileReferenceSection
1006+
// 2. Added to the PBXBuildFileSection
1007+
// 3. Pushed onto the build phase file list.
1008+
const file = new PBXFile(filePath);
9191009
file.uuid = this.generateUuid();
9201010
file.fileRef = this.generateUuid();
921-
this.addToPbxFileReferenceSection(file); // PBXFileReference
922-
this.addToPbxBuildFileSection(file); // PBXBuildFile
1011+
this.addToPbxFileReferenceSection(file);
1012+
this.addToPbxBuildFileSection(file);
9231013
buildPhase.files.push(pbxBuildPhaseObj(file));
9241014
}
9251015

0 commit comments

Comments
 (0)