UNPKG

react-native-integrate

Version:

Automate integration of additional code into React Native projects

311 lines (310 loc) 13.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.patchXcodeProject = patchXcodeProject; exports.patchXcodeHasFile = patchXcodeHasFile; exports.pbxBuildPhaseObj = pbxBuildPhaseObj; exports.longComment = longComment; exports.normalizeBundleId = normalizeBundleId; exports.unquote = unquote; const path_1 = __importDefault(require("path")); const xcode_1 = __importDefault(require("xcode")); const pbxFile_1 = __importDefault(require("xcode/lib/pbxFile")); const COMMENT_KEY = /_comment$/; function patchXcodeProject(opts) { // fixes a bug in pbxGroupByName const pbxGroupByNameOriginal = xcode_1.default.project.prototype.pbxGroupByName; xcode_1.default.project.prototype.pbxGroupByName = function (name) { const result = pbxGroupByNameOriginal.call(this, name); if (name == 'Resources' && result == null) return { path: null }; return result; }; // makes files to be added on top // eslint-disable-next-line @typescript-eslint/unbound-method const arrayPushOriginal = Array.prototype.push; Array.prototype.push = function (item) { return opts.push(this, item, arrayPushOriginal); }; return () => { xcode_1.default.project.prototype.pbxGroupByName = pbxGroupByNameOriginal; Array.prototype.push = arrayPushOriginal; }; } function patchXcodeHasFile() { // force add file const hasFileOriginal = xcode_1.default.project.prototype.hasFile; xcode_1.default.project.prototype.hasFile = function () { return false; }; return () => { xcode_1.default.project.prototype.hasFile = hasFileOriginal; }; } /* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return*/ // noinspection JSUnusedGlobalSymbols xcode_1.default.project.prototype.addExtensionTarget = function (name, type, subfolder, opts) { // Setup uuid and name of new target const targetUuid = this.generateUuid(), targetType = type, targetSubfolder = subfolder || name, targetName = name.trim(), targetBundleId = opts.bundleId, targetTeam = opts.team, targetCodeSign = opts.codeSign; // Build Configuration: Create let buildConfigurationsList = [ { name: 'Debug', isa: 'XCBuildConfiguration', buildSettings: { CLANG_ANALYZER_NONNULL: 'YES', CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION: 'YES_AGGRESSIVE', CLANG_CXX_LANGUAGE_STANDARD: '"gnu++20"', CLANG_ENABLE_OBJC_WEAK: 'YES', CLANG_WARN_DOCUMENTATION_COMMENTS: 'YES', CLANG_WARN_UNGUARDED_AVAILABILITY: 'YES_AGGRESSIVE', CODE_SIGN_STYLE: 'Automatic', CURRENT_PROJECT_VERSION: '1', DEBUG_INFORMATION_FORMAT: 'dwarf', GCC_C_LANGUAGE_STANDARD: 'gnu11', GENERATE_INFOPLIST_FILE: 'YES', INFOPLIST_FILE: `"${path_1.default.join(targetSubfolder, 'Info.plist')}"`, INFOPLIST_KEY_CFBundleDisplayName: `"${targetSubfolder}"`, INFOPLIST_KEY_NSHumanReadableCopyright: '""', IPHONEOS_DEPLOYMENT_TARGET: '16.4', LD_RUNPATH_SEARCH_PATHS: [ '"$(inherited)"', '"@executable_path/Frameworks"', '"@executable_path/../../Frameworks"', ], MARKETING_VERSION: '1.0', MTL_ENABLE_DEBUG_INFO: 'INCLUDE_SOURCE', MTL_FAST_MATH: 'YES', PRODUCT_NAME: '"$(TARGET_NAME)"', SKIP_INSTALL: 'YES', SWIFT_EMIT_LOC_STRINGS: 'YES', TARGETED_DEVICE_FAMILY: '"1,2"', }, }, { name: 'Release', isa: 'XCBuildConfiguration', buildSettings: { CLANG_ANALYZER_NONNULL: 'YES', CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION: 'YES_AGGRESSIVE', CLANG_CXX_LANGUAGE_STANDARD: '"gnu++20"', CLANG_ENABLE_OBJC_WEAK: 'YES', CLANG_WARN_DOCUMENTATION_COMMENTS: 'YES', CLANG_WARN_UNGUARDED_AVAILABILITY: 'YES_AGGRESSIVE', CODE_SIGN_STYLE: 'Automatic', COPY_PHASE_STRIP: 'NO', CURRENT_PROJECT_VERSION: '1', DEBUG_INFORMATION_FORMAT: '"dwarf-with-dsym"', GCC_C_LANGUAGE_STANDARD: 'gnu11', GENERATE_INFOPLIST_FILE: 'YES', INFOPLIST_FILE: `"${path_1.default.join(targetSubfolder, 'Info.plist')}"`, INFOPLIST_KEY_CFBundleDisplayName: `"${targetSubfolder}"`, INFOPLIST_KEY_NSHumanReadableCopyright: '""', IPHONEOS_DEPLOYMENT_TARGET: '16.4', LD_RUNPATH_SEARCH_PATHS: [ '"$(inherited)"', '"@executable_path/Frameworks"', '"@executable_path/../../Frameworks"', ], MARKETING_VERSION: '1.0', MTL_FAST_MATH: 'YES', PRODUCT_NAME: '"$(TARGET_NAME)"', SKIP_INSTALL: 'YES', SWIFT_EMIT_LOC_STRINGS: 'YES', TARGETED_DEVICE_FAMILY: '"1,2"', }, }, ]; // Add optional bundleId to build configuration buildConfigurationsList = buildConfigurationsList.map(elem => { if (targetBundleId) { elem.buildSettings.PRODUCT_BUNDLE_IDENTIFIER = '"' + targetBundleId + '"'; } if (targetTeam) { elem.buildSettings.DEVELOPMENT_TEAM = '"' + targetTeam + '"'; } if (targetCodeSign) { elem.buildSettings.CODE_SIGN_IDENTITY = '"' + targetCodeSign + '"'; } return elem; }); // Build Configuration: Add const buildConfigurations = this.addXCConfigurationList(buildConfigurationsList, 'Release', 'Build configuration list for PBXNativeTarget "' + targetName + '"'); // Product: Create const productName = targetName, productType = 'com.apple.product-type.app-extension', productFileType = '"wrapper.app-extension"', productFile = this.addProductFile(productName, { group: 'Embed Foundation Extensions', target: targetUuid, explicitFileType: productFileType, }); productFile.settings = { ATTRIBUTES: ['RemoveHeadersOnCopy'], }; // Product: Add to build file list this.addToPbxBuildFileSection(productFile); // Target: Create const target = { uuid: targetUuid, pbxNativeTarget: { isa: 'PBXNativeTarget', name: '"' + targetName + '"', productName: '"' + targetName + '"', productReference: productFile.fileRef, productType: `"${productType}"`, buildConfigurationList: buildConfigurations.uuid, buildPhases: [], buildRules: [], dependencies: [], }, }; // Target: Add to PBXNativeTarget section this.addToPbxNativeTargetSection(target); // Create CopyFiles phase in first target let sources = this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Foundation Extensions', productFile.target); if (!sources) { this.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Embed Foundation Extensions', this.getFirstTarget().uuid, targetType); // Add product to Embed Foundation Extensions phase sources = this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Foundation Extensions', productFile.target); } // eslint-disable-next-line @typescript-eslint/no-unsafe-argument sources.files.push(pbxBuildPhaseObj(productFile)); // Target: Add uuid to root project this.addToPbxProjectSection(target); // Target: Add dependency for this target to other targets this.addTargetDependency(this.getFirstTarget().uuid, [target.uuid]); // Return target on success return target; }; // noinspection JSUnusedGlobalSymbols xcode_1.default.project.prototype.addExtensionSourceFile = function (path, opt, group) { const file = this.addFile(path, group, opt); file.target = opt.target; file.uuid = this.generateUuid(); this.addToPbxBuildFileSection(file); // PBXBuildFile // this.addToPbxSourcesBuildPhase(file); // PBXSourcesBuildPhase return file; }; // noinspection JSUnusedGlobalSymbols xcode_1.default.project.prototype.addExtensionResourceFile = function (path, opt, group) { // noinspection JSPotentiallyInvalidConstructorUsage const file = new pbxFile_1.default(path, opt); file.uuid = this.generateUuid(); file.target = opt.target; file.fileRef = this.generateUuid(); this.addToPbxFileReferenceSection(file); // PBXFileReference if (this.getPBXVariantGroupByKey(group)) { this.addToPbxVariantGroup(file, group); // PBXVariantGroup } return file; }; // noinspection JSUnusedGlobalSymbols xcode_1.default.project.prototype.addExtensionLocalizationVariantGroup = function (name, target) { const groupKey = this.pbxCreateVariantGroup(name); const resourceGroupKey = this.findPBXGroupKey({ name: 'Resources' }); this.addToPbxGroup(groupKey, resourceGroupKey); const localizationVariantGroup = { uuid: this.generateUuid(), fileRef: groupKey, basename: name, group: 'Resources', target, }; this.addToPbxBuildFileSection(localizationVariantGroup); // PBXBuildFile this.addToPbxResourcesBuildPhase(localizationVariantGroup); //PBXResourcesBuildPhase return localizationVariantGroup; }; xcode_1.default.project.prototype.findPBXGroupKeyByAny = function (nameOrPath) { const groups = this.hash.project.objects['PBXGroup']; let target; for (const key in groups) { // only look for comments if (COMMENT_KEY.test(key)) continue; const group = groups[key]; if (nameOrPath) { if (nameOrPath === group.path || nameOrPath === group.name) { target = key; break; } } } return target; }; xcode_1.default.project.prototype.getBuildPropertyByTarget = function (prop, build, target) { let value; const validConfigs = []; if (target) { const targetBuildConfigs = target.buildConfigurationList; const xcConfigList = this.pbxXCConfigurationList(); // Collect the UUID's from the configuration of our target for (const configName in xcConfigList) { if (!COMMENT_KEY.test(configName) && targetBuildConfigs === configName) { const buildVariants = xcConfigList[configName].buildConfigurations; for (const item of buildVariants) { validConfigs.push(item.value); } break; } } } const configs = this.pbxXCBuildConfigurationSection(); for (const configName in configs) { if (!COMMENT_KEY.test(configName)) { if (target && !validConfigs.includes(configName)) continue; const config = configs[configName]; if ((build && config.name === build) || build === undefined) { if (config.buildSettings[prop] !== undefined) { value = config.buildSettings[prop]; } } } } return value; }; xcode_1.default.project.prototype.updateBuildPropertyByTarget = function (prop, value, build, target) { const validConfigs = []; if (target) { const targetBuildConfigs = target.buildConfigurationList; const xcConfigList = this.pbxXCConfigurationList(); // Collect the UUID's from the configuration of our target for (const configName in xcConfigList) { if (!COMMENT_KEY.test(configName) && targetBuildConfigs === configName) { const buildVariants = xcConfigList[configName].buildConfigurations; for (const item of buildVariants) { validConfigs.push(item.value); } break; } } } const configs = this.pbxXCBuildConfigurationSection(); for (const configName in configs) { if (!COMMENT_KEY.test(configName)) { if (target && !validConfigs.includes(configName)) continue; const config = configs[configName]; if ((build && config.name === build) || !build) { config.buildSettings[prop] = value; } } } }; function pbxBuildPhaseObj(file) { const obj = Object.create(null); obj.value = file.uuid; obj.comment = longComment(file); return obj; } function longComment(file) { return `${file.basename} in ${file.group}`; } function normalizeBundleId(bundleId, opts) { return bundleId .replace(/"/g, '') .replace(/\$\(PRODUCT_NAME.*?\)/g, opts.productName); } function unquote(str) { return str?.replace(/^"(.*)"$/, '$1'); }