145 lines
5.7 KiB
JavaScript
145 lines
5.7 KiB
JavaScript
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
/**
|
|
* Workaround für Xcode 16 + RN 0.79 + fmt 11.0.2:
|
|
* "Call to consteval function 'fmt::basic_format_string<...>' is not a constant expression"
|
|
*
|
|
* Grund: fmt/include/fmt/base.h definiert FMT_USE_CONSTEVAL UNCONDITIONAL —
|
|
* kein `#ifndef`-Guard. Daher hilft `-DFMT_USE_CONSTEVAL=0` als Compiler-Flag
|
|
* NICHT — fmt's eigener Header überschreibt es.
|
|
*
|
|
* Wir patchen daher direkt die Source-Datei nach `pod install`:
|
|
* - In ios/Pods/fmt/include/fmt/base.h einen Override-Block einfügen, der
|
|
* nach fmt's eigener Detection FMT_USE_CONSTEVAL auf 0 zwingt.
|
|
*
|
|
* Wirkung:
|
|
* - basic_format_string-Konstruktor ist nicht mehr consteval, sondern constexpr
|
|
* - FMT_STRING("{}{}") expansion compiliert wieder unter Apple Clang 16+
|
|
*
|
|
* Idempotent — markiert die Patch-Stelle mit einem Magic-Comment.
|
|
*/
|
|
const { withDangerousMod } = require('@expo/config-plugins');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const PATCH_MARKER = '/* REBREAK_FMT_CONSTEVAL_FIX */';
|
|
|
|
const SOURCE_PATCH = `
|
|
|
|
${PATCH_MARKER}
|
|
// Xcode 16 + Apple Clang 16+ haben einen consteval-Bug der fmt's
|
|
// FMT_STRING-basierte format_to-Calls bricht. Wir zwingen daher
|
|
// FMT_USE_CONSTEVAL=0 nach fmt's eigener Detection.
|
|
#undef FMT_USE_CONSTEVAL
|
|
#define FMT_USE_CONSTEVAL 0
|
|
#undef FMT_CONSTEVAL
|
|
#define FMT_CONSTEVAL
|
|
#undef FMT_CONSTEXPR20
|
|
#define FMT_CONSTEXPR20
|
|
${PATCH_MARKER}
|
|
`;
|
|
|
|
function patchFmtBaseHeader(podsDir) {
|
|
const baseHeader = path.join(podsDir, 'fmt', 'include', 'fmt', 'base.h');
|
|
if (!fs.existsSync(baseHeader)) {
|
|
console.warn('[with-fmt-consteval-fix] fmt/base.h not found at', baseHeader);
|
|
return false;
|
|
}
|
|
|
|
let content = fs.readFileSync(baseHeader, 'utf-8');
|
|
if (content.includes(PATCH_MARKER)) {
|
|
return false; // schon gepatcht
|
|
}
|
|
|
|
// Patch nach der Detection-Block einfügen, vor dem `#if FMT_USE_CONSTEVAL`
|
|
// Suche nach dem End-of-Detection (line endet mit `#endif` direkt vor
|
|
// `#if FMT_USE_CONSTEVAL`).
|
|
const anchor = '#if FMT_USE_CONSTEVAL';
|
|
const idx = content.indexOf(anchor);
|
|
if (idx === -1) {
|
|
console.warn('[with-fmt-consteval-fix] anchor not found in base.h');
|
|
return false;
|
|
}
|
|
|
|
// Patch direkt vor dem anchor einfügen
|
|
content = content.slice(0, idx) + SOURCE_PATCH + '\n' + content.slice(idx);
|
|
fs.writeFileSync(baseHeader, content);
|
|
console.log('[with-fmt-consteval-fix] patched', baseHeader);
|
|
return true;
|
|
}
|
|
|
|
module.exports = function withFmtConstevalFix(config) {
|
|
return withDangerousMod(config, [
|
|
'ios',
|
|
async (cfg) => {
|
|
const podsDir = path.join(cfg.modRequest.platformProjectRoot, 'Pods');
|
|
// Wenn Pods/ noch nicht existiert (= prebuild Phase, vor pod install):
|
|
// Patch wird automatisch beim nächsten Run angewendet sobald Pods da sind.
|
|
// Damit der User aber NICHT manuell nachpatchen muss, packen wir den
|
|
// Patch zusätzlich in einen Podfile-pre_install-Hook der bei JEDEM
|
|
// pod install läuft (auch beim ersten).
|
|
if (fs.existsSync(podsDir)) {
|
|
patchFmtBaseHeader(podsDir);
|
|
}
|
|
|
|
// Podfile pre_install-Hook injizieren — patched die fmt-Source bei
|
|
// jedem pod install (nachdem Pods/fmt/ bereits gedownloaded ist).
|
|
const podfilePath = path.join(cfg.modRequest.platformProjectRoot, 'Podfile');
|
|
let podfile = fs.readFileSync(podfilePath, 'utf-8');
|
|
|
|
// Alten Patch (frühere Plugin-Version) entfernen
|
|
const oldPatchRegex = /\s*# ─── Rebreak: fmt consteval fix[\s\S]*?# ───────────────────────────────────────────────────────/g;
|
|
podfile = podfile.replace(oldPatchRegex, '');
|
|
const oldPostInstallPatchRegex = /\s*# ═══ Rebreak: fmt consteval source-patch[\s\S]*?# ═══════════════════════════════════════════════════════/g;
|
|
podfile = podfile.replace(oldPostInstallPatchRegex, '');
|
|
|
|
// Neuen pre_install-Hook injizieren (vor `target` block).
|
|
// Wir patchen die fmt/base.h-Datei direkt im pre_install — pod install
|
|
// hat dann zu dem Zeitpunkt schon den Pod gedownloaded.
|
|
const PRE_INSTALL = `
|
|
# ═══ Rebreak: fmt consteval source-patch (Xcode 16 + RN 0.79) ═══
|
|
pre_install do |installer|
|
|
fmt_base_h = File.join(installer.sandbox.root, 'fmt', 'include', 'fmt', 'base.h')
|
|
if File.exist?(fmt_base_h)
|
|
content = File.read(fmt_base_h)
|
|
marker = '/* REBREAK_FMT_CONSTEVAL_FIX */'
|
|
unless content.include?(marker)
|
|
patch = <<~PATCH
|
|
|
|
#{marker}
|
|
// Xcode 16 + Apple Clang 16+ consteval-Bug Workaround
|
|
#undef FMT_USE_CONSTEVAL
|
|
#define FMT_USE_CONSTEVAL 0
|
|
#undef FMT_CONSTEVAL
|
|
#define FMT_CONSTEVAL
|
|
#undef FMT_CONSTEXPR20
|
|
#define FMT_CONSTEXPR20
|
|
#{marker}
|
|
PATCH
|
|
anchor = '#if FMT_USE_CONSTEVAL'
|
|
if content.include?(anchor)
|
|
content = content.sub(anchor, patch + "\\n" + anchor)
|
|
File.write(fmt_base_h, content)
|
|
Pod::UI.puts " -> Patched fmt/base.h with consteval workaround".green
|
|
end
|
|
end
|
|
end
|
|
end
|
|
# ═══════════════════════════════════════════════════════
|
|
`;
|
|
|
|
// Inject vor dem ersten `target` block (Top-level)
|
|
const targetMatch = podfile.match(/^target\s+['"][^'"]+['"]\s+do/m);
|
|
if (targetMatch) {
|
|
const insertAt = targetMatch.index;
|
|
podfile = podfile.slice(0, insertAt) + PRE_INSTALL + '\n' + podfile.slice(insertAt);
|
|
} else {
|
|
// Fallback: ans Ende anhängen
|
|
podfile += PRE_INSTALL;
|
|
}
|
|
|
|
fs.writeFileSync(podfilePath, podfile);
|
|
return cfg;
|
|
},
|
|
]);
|
|
};
|