expo-plugin-ios-static-libraries
Version:
Expo Config Plugin to set specific iOS libraries to use static build type
168 lines (167 loc) • 6.55 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeLibraries = normalizeLibraries;
exports.patchPodfile = patchPodfile;
const config_plugins_1 = require("@expo/config-plugins");
const fs = __importStar(require("fs"));
const path_1 = __importDefault(require("path"));
const pluginComment = "# Added by expo-plugin-ios-static-libraries";
/**
* Normalizes the library entries into separate arrays for static libraries and modular headers
*/
function normalizeLibraries(libraries) {
const allLibraries = [];
const modularHeaderLibraries = [];
for (const lib of libraries) {
if (typeof lib === 'string') {
allLibraries.push(lib);
}
else {
allLibraries.push(lib.name);
if (lib.modularHeaders) {
modularHeaderLibraries.push(lib.name);
}
}
}
return { allLibraries, modularHeaderLibraries };
}
/**
* Generates Ruby code to enable modular headers for specified libraries
*/
function generateModularHeadersCode(libraries, indent = '') {
if (libraries.length === 0) {
return '';
}
const escapedLibs = libraries
.map(lib => `'${lib.replace(/'/g, "\\'")}'`)
.join(', ');
return `${indent}# Enable modular headers for Swift compatibility
${indent}[${escapedLibs}].each do |lib_name|
${indent} installer.podfile.target_definitions.each do |name, target_def|
${indent} target_def.set_use_modular_headers_for_pod(lib_name, true)
${indent} end
${indent}end
`;
}
/**
* Patches a Podfile string to add static library configuration for specified libraries
* This function is exported for testing purposes
*/
function patchPodfile(podfileContent, libraries = [], modularHeaderLibraries = []) {
// Skip if no libraries to configure
if (libraries.length === 0) {
return podfileContent;
}
// If there is already a match for this plugins comment, skip adding.
if (podfileContent.indexOf(pluginComment) !== -1) {
return podfileContent;
}
// Create condition for libraries, escaping single quotes to prevent injection
const libraryConditions = libraries
.map(lib => `pod.name.eql?('${lib.replace(/'/g, "\\'")}')`)
.join(' || ');
// Generate modular headers code if needed
const modularHeadersCode = generateModularHeadersCode(modularHeaderLibraries, ' ');
// Check if pre_install block already exists
const preInstallRegex = /pre_install\s+do\s+\|installer\|([\s\S]*?)end/;
const preInstallMatch = podfileContent.match(preInstallRegex);
let newPodfileContent = podfileContent;
if (preInstallMatch) {
// There's an existing pre_install block, add our code to the end of it
const existingContent = preInstallMatch[0];
const insertPoint = existingContent.lastIndexOf('end');
const codeToAdd = `
${pluginComment}
${modularHeadersCode} installer.pod_targets.each do |pod|
if ${libraryConditions}
def pod.build_type
Pod::BuildType.static_library
end
end
end
`;
// Insert our code before the last 'end'
const newContent = existingContent.slice(0, insertPoint) + codeToAdd + existingContent.slice(insertPoint);
newPodfileContent = podfileContent.replace(existingContent, newContent);
}
else {
// No existing pre_install block, create a new one
const preInstallBlock = `
${pluginComment}
pre_install do |installer|
${modularHeadersCode} installer.pod_targets.each do |pod|
if ${libraryConditions}
def pod.build_type
Pod::BuildType.static_library
end
end
end
end
`;
// Append the pre_install hook to the end of the Podfile
newPodfileContent += `\n${preInstallBlock}\n`;
}
return newPodfileContent;
}
/**
* Config plugin that adds pre_install hook to the iOS Podfile to set
* specific libraries to use static build type and optionally enable modular headers
*/
const withIosStaticLibraries = (config, { libraries = [] }) => {
const { allLibraries, modularHeaderLibraries } = normalizeLibraries(libraries);
return (0, config_plugins_1.withDangerousMod)(config, [
'ios',
async (config) => {
const { platformProjectRoot } = config.modRequest;
const podfilePath = path_1.default.join(platformProjectRoot, 'Podfile');
if (!fs.existsSync(podfilePath)) {
console.warn('[expo-plugin-ios-static-libraries] Podfile not found at', podfilePath);
return config;
}
const podfileContent = fs.readFileSync(podfilePath, 'utf-8');
const newPodfileContent = patchPodfile(podfileContent, allLibraries, modularHeaderLibraries);
// Only write the file if changes were made
if (newPodfileContent !== podfileContent) {
fs.writeFileSync(podfilePath, newPodfileContent);
}
return config;
},
]);
};
exports.default = withIosStaticLibraries;