mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 16:05:39 +00:00
86 lines
3.6 KiB
JavaScript
86 lines
3.6 KiB
JavaScript
// Gives an extension target (plugins/ios-push, plugins/ios-widget) its own
|
|
// group of files in the Xcode project, and compiles its sources in its own
|
|
// Sources build phase.
|
|
//
|
|
// Written against the project objects directly: the `xcode` package's
|
|
// addPbxGroup and addBuildPhase reuse any file reference or build file with
|
|
// the same path, so two extensions that each carry SharedKeychain.swift ended
|
|
// up sharing one file reference (in both groups) and one build file (in both
|
|
// Sources phases). CocoaPods' xcodeproj then fails to save the project in
|
|
// pod install ("Consistency issue: no parent for object SharedKeychain.swift").
|
|
|
|
const FILE_TYPES = {
|
|
swift: 'sourcecode.swift',
|
|
m: 'sourcecode.c.objc',
|
|
h: 'sourcecode.c.h',
|
|
plist: 'text.plist.xml',
|
|
entitlements: 'text.plist.entitlements',
|
|
};
|
|
|
|
const quote = (value) => `"${value}"`;
|
|
const unquote = (value) => (typeof value === 'string' ? value.replace(/^"(.*)"$/, '$1') : value);
|
|
|
|
/**
|
|
* Whether the project has a target `name`. pbxTargetByName misses targets
|
|
* that addTarget made: it stores the name in quotes, so prebuild without
|
|
* --clean added the extension targets a second time.
|
|
*/
|
|
function hasTarget(project, name) {
|
|
return Object.entries(project.pbxNativeTargetSection() ?? {}).some(
|
|
([key, target]) => !key.endsWith('_comment') && unquote(target.name) === name,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Adds a group `name` (folder ios/<name>) under the project's main group,
|
|
* with a new file reference for each of `files` and `sources`, and a Sources
|
|
* build phase on the target that compiles `sources` from that group.
|
|
*
|
|
* @param project the `xcode` project (cfg.modResults of withXcodeProject)
|
|
* @param {{ name: string, targetUuid: string, sources: string[], files?: string[] }} options
|
|
* files: other files to show in the group (Info.plist, entitlements), not compiled
|
|
* @returns {{ groupUuid: string, phaseUuid: string }}
|
|
*/
|
|
function addTargetFiles(project, { name, targetUuid, sources, files = [] }) {
|
|
const objects = project.hash.project.objects;
|
|
objects.PBXFileReference = objects.PBXFileReference || {};
|
|
objects.PBXBuildFile = objects.PBXBuildFile || {};
|
|
objects.PBXGroup = objects.PBXGroup || {};
|
|
|
|
const groupUuid = project.generateUuid();
|
|
const group = { isa: 'PBXGroup', children: [], name: quote(name), path: quote(name), sourceTree: '"<group>"' };
|
|
objects.PBXGroup[groupUuid] = group;
|
|
objects.PBXGroup[`${groupUuid}_comment`] = name;
|
|
const mainGroup = objects.PBXGroup[project.getFirstProject().firstProject.mainGroup];
|
|
mainGroup.children.push({ value: groupUuid, comment: name });
|
|
|
|
const refs = {};
|
|
for (const file of [...sources, ...files]) {
|
|
if (refs[file]) throw new Error(`plugins/ios-target-files: ${file} listed twice for ${name}`);
|
|
const uuid = project.generateUuid();
|
|
const type = FILE_TYPES[file.split('.').pop()];
|
|
objects.PBXFileReference[uuid] = {
|
|
isa: 'PBXFileReference',
|
|
...(type ? { lastKnownFileType: type } : {}),
|
|
name: quote(file),
|
|
path: quote(file),
|
|
sourceTree: '"<group>"',
|
|
};
|
|
objects.PBXFileReference[`${uuid}_comment`] = file;
|
|
group.children.push({ value: uuid, comment: file });
|
|
refs[file] = uuid;
|
|
}
|
|
|
|
const { uuid: phaseUuid, buildPhase } = project.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', targetUuid);
|
|
for (const file of sources) {
|
|
const uuid = project.generateUuid();
|
|
const comment = `${file} in Sources`;
|
|
objects.PBXBuildFile[uuid] = { isa: 'PBXBuildFile', fileRef: refs[file], fileRef_comment: file };
|
|
objects.PBXBuildFile[`${uuid}_comment`] = comment;
|
|
buildPhase.files.push({ value: uuid, comment });
|
|
}
|
|
return { groupUuid, phaseUuid };
|
|
}
|
|
|
|
module.exports = { addTargetFiles, hasTarget };
|