@@ -1109,8 +1109,8 @@ async function buildPhp(config: BuildConfig): Promise<string> {
1109
1109
. map ( path => join ( path , 'include' ) )
1110
1110
. filter ( path => existsSync ( path ) )
1111
1111
1112
- // Add iconv paths back - we need the actual library for linking
1113
- if ( config . platform === 'darwin' ) {
1112
+ // Add iconv paths back - we need the actual library for linking (except for x86_64)
1113
+ if ( config . platform === 'darwin' && config . arch !== 'x86_64' ) {
1114
1114
const iconvPath = findLatestVersion ( `${ launchpadRoot } /gnu.org/libiconv` )
1115
1115
if ( iconvPath && existsSync ( iconvPath ) ) {
1116
1116
const iconvLibPath = join ( iconvPath , 'lib' )
@@ -1124,6 +1124,8 @@ async function buildPhp(config: BuildConfig): Promise<string> {
1124
1124
} else {
1125
1125
log ( '⚠️ iconv library not found, may cause linking issues' )
1126
1126
}
1127
+ } else if ( config . platform === 'darwin' && config . arch === 'x86_64' ) {
1128
+ log ( `🔧 ✅ Skipped GNU iconv for x86_64 to prevent dyld conflicts (using system iconv)` )
1127
1129
}
1128
1130
1129
1131
buildEnv . PKG_CONFIG_PATH = pkgConfigPaths . join ( ':' )
@@ -1190,8 +1192,8 @@ async function buildPhp(config: BuildConfig): Promise<string> {
1190
1192
. map ( path => join ( path , 'include' ) )
1191
1193
. filter ( path => existsSync ( path ) )
1192
1194
1193
- // Add iconv paths after dependency installation on macOS
1194
- if ( config . platform === 'darwin' ) {
1195
+ // Add iconv paths after dependency installation on macOS (except for x86_64)
1196
+ if ( config . platform === 'darwin' && config . arch !== 'x86_64' ) {
1195
1197
const iconvPath = findLatestVersion ( `${ launchpadRoot } /gnu.org/libiconv` )
1196
1198
if ( iconvPath && existsSync ( iconvPath ) ) {
1197
1199
const iconvLibPath = join ( iconvPath , 'lib' )
@@ -1271,31 +1273,31 @@ async function buildPhp(config: BuildConfig): Promise<string> {
1271
1273
// Add platform-specific linker flags with dynamic rpaths
1272
1274
if ( config . platform === 'darwin' ) {
1273
1275
// macOS: Use dynamic rpaths based on actual library locations, removing duplicates
1274
- const uniqueLibPaths = [ ...new Set ( libPaths ) ]
1275
- const rpathFlags = uniqueLibPaths . map ( path => `-Wl,-rpath, ${ path } ` ) . join ( ' ' )
1276
+ let uniqueLibPaths = [ ...new Set ( libPaths ) ]
1277
+ let uniqueIncludePaths = [ ... new Set ( includePaths ) ]
1276
1278
// Handle libiconv with architecture-specific linking to avoid dyld symbol conflicts
1277
- const iconvLibPath = uniqueLibPaths . find ( p => p . includes ( 'libiconv' ) )
1278
1279
let iconvFlag = ' -liconv' // fallback to system iconv
1279
1280
1280
- if ( iconvLibPath ) {
1281
- if ( config . arch === 'x86_64' ) {
1282
- // For x86_64, use static linking to avoid dyld symbol override conflicts
1283
- const staticLib = join ( iconvLibPath , 'libiconv.a' )
1284
- if ( existsSync ( staticLib ) ) {
1285
- iconvFlag = ` ${ staticLib } `
1286
- log ( `🔧 ✅ Using static iconv library for x86_64: ${ staticLib } ` )
1287
- } else {
1288
- // Fallback: use -liconv to link against system library
1289
- iconvFlag = ' -liconv'
1290
- log ( `🔧 ⚠️ Static iconv not found, using system iconv for x86_64` )
1291
- }
1292
- } else {
1293
- // ARM64 can use dynamic linking without dyld conflicts
1281
+ if ( config . arch === 'x86_64' ) {
1282
+ // For x86_64, completely avoid GNU libiconv to prevent dyld symbol conflicts
1283
+ // Use system iconv only
1284
+ iconvFlag = ' -liconv'
1285
+ log ( `🔧 ✅ Using system iconv for x86_64 (avoiding GNU libiconv dyld conflicts)` )
1286
+ // Remove iconv and libcups from library paths for x86_64 to prevent dyld interference
1287
+ uniqueLibPaths = uniqueLibPaths . filter ( p => ! p . includes ( 'libiconv' ) && ! p . includes ( 'libcups' ) )
1288
+ uniqueIncludePaths = uniqueIncludePaths . filter ( p => ! p . includes ( 'libiconv' ) && ! p . includes ( 'libcups' ) )
1289
+ log ( `🔧 ✅ Excluded libcups from x86_64 library paths to prevent dyld conflicts` )
1290
+ } else {
1291
+ // ARM64 can use GNU libiconv without issues
1292
+ const iconvLibPath = uniqueLibPaths . find ( p => p . includes ( 'libiconv' ) )
1293
+ if ( iconvLibPath ) {
1294
1294
iconvFlag = ` ${ iconvLibPath } /libiconv.2.dylib`
1295
- log ( `🔧 ✅ Using dynamic iconv library for ARM64: ${ iconvLibPath } ` )
1295
+ log ( `🔧 ✅ Using GNU iconv library for ARM64: ${ iconvLibPath } ` )
1296
1296
}
1297
1297
}
1298
1298
1299
+ const rpathFlags = uniqueLibPaths . map ( path => `-Wl,-rpath,${ path } ` ) . join ( ' ' )
1300
+
1299
1301
buildEnv . LDFLAGS += ` -lresolv${ iconvFlag } ${ rpathFlags } -Wl,-headerpad_max_install_names`
1300
1302
// Set up runtime library path for macOS (build-time only)
1301
1303
buildEnv . DYLD_LIBRARY_PATH = uniqueLibPaths . join ( ':' )
@@ -1450,11 +1452,21 @@ exec "$@"
1450
1452
const libraryMappings = [
1451
1453
{ flag : '--with-bz2' , basePath : 'sourceware.org/bzip2' } ,
1452
1454
{ flag : '--with-gettext' , basePath : 'gnu.org/gettext' } ,
1453
- // Re-enable iconv library mapping for proper linking
1454
- { flag : '--with-iconv' , basePath : 'gnu.org/libiconv' } ,
1455
+ // Conditionally include iconv library mapping based on architecture
1456
+ ... ( config . arch === 'x86_64' ? [ ] : [ { flag : '--with-iconv' , basePath : 'gnu.org/libiconv' } ] ) ,
1455
1457
{ flag : '--with-readline' , basePath : 'gnu.org/readline' } ,
1456
1458
]
1457
1459
1460
+ // For x86_64, remove --with-iconv=/path/to/gnu/libiconv to use system iconv instead
1461
+ // This prevents GNU libiconv dyld conflicts while still maintaining iconv functionality
1462
+ if ( config . arch === 'x86_64' ) {
1463
+ const iconvIndex = configureArgs . findIndex ( arg => arg . startsWith ( '--with-iconv' ) )
1464
+ if ( iconvIndex !== - 1 ) {
1465
+ configureArgs . splice ( iconvIndex , 1 )
1466
+ log ( `🔧 ✅ Removed GNU --with-iconv for x86_64, will use system iconv (required for Laravel/Composer)` )
1467
+ }
1468
+ }
1469
+
1458
1470
for ( const mapping of libraryMappings ) {
1459
1471
const libPath = findLatestVersion ( `${ homeDir } /.local/${ mapping . basePath } ` )
1460
1472
const argIndex = configureArgs . findIndex ( arg => arg === mapping . flag )
@@ -1988,14 +2000,16 @@ exec ./configure "$@"
1988
2000
]
1989
2001
1990
2002
const patches = [
1991
- // Fix "S" constraint (source register) - incompatible on macOS
1992
- 's/asm volatile("([^"]*)" :: "S" ([^)]*))/asm volatile("$1" : : "r" $2 : "memory")/g' ,
1993
- // Fix "D" constraint (destination register) issues
1994
- 's/asm volatile("([^"]*)" :: "D" ([^)]*))/asm volatile("$1" : : "r" $2 : "memory")/g' ,
1995
- // Fix mixed constraint issues
1996
- 's/asm volatile("([^"]*)" :: "([SD])" ([^)]*), "([^"]*)" ([^)]*))/asm volatile("$1" : : "r" $3, "r" $5 : "memory")/g' ,
1997
- // Fix memory operand issues in inline assembly
1998
- 's/__asm__ volatile("([^"]*)" :: "([SD])" ([^)]*))/asm volatile("$1" : : "r" $3 : "memory")/g' ,
2003
+ // Fix "S" constraint (source register) - incompatible on macOS - handle leading whitespace/tabs
2004
+ 's/^([[:space:]]*)asm volatile\\("([^"]*)"\\s*::\\s*"S"\\s*\\(([^)]*)\\)\\);/\\1asm volatile("\\2" : : "r" \\3 : "memory");/g' ,
2005
+ // Fix "D" constraint (destination register) issues - handle leading whitespace/tabs
2006
+ 's/^([[:space:]]*)asm volatile\\("([^"]*)"\\s*::\\s*"D"\\s*\\(([^)]*)\\)\\);/\\1asm volatile("\\2" : : "r" \\3 : "memory");/g' ,
2007
+ // Fix __asm__ variant with "S" constraint - handle leading whitespace/tabs
2008
+ 's/^([[:space:]]*)__asm__ volatile\\("([^"]*)"\\s*::\\s*"S"\\s*\\(([^)]*)\\)\\);/\\1asm volatile("\\2" : : "r" \\3 : "memory");/g' ,
2009
+ // Fix __asm__ variant with "D" constraint - handle leading whitespace/tabs
2010
+ 's/^([[:space:]]*)__asm__ volatile\\("([^"]*)"\\s*::\\s*"D"\\s*\\(([^)]*)\\)\\);/\\1asm volatile("\\2" : : "r" \\3 : "memory");/g' ,
2011
+ // Fix mixed constraint issues - handle leading whitespace/tabs
2012
+ 's/^([[:space:]]*)asm volatile\\("([^"]*)"\\s*::\\s*"([SD])"\\s*\\(([^)]*)\\),\\s*"([^"]*)"\\s*\\(([^)]*)\\)\\);/\\1asm volatile("\\2" : : "r" \\4, "r" \\6 : "memory");/g' ,
1999
2013
]
2000
2014
2001
2015
for ( const filePath of jitSourceFiles ) {
@@ -2004,7 +2018,7 @@ exec ./configure "$@"
2004
2018
log ( `Patching ${ filePath } ...` )
2005
2019
for ( const patch of patches ) {
2006
2020
try {
2007
- execSync ( `sed -i.jitpatch '${ patch } ' "${ fullFilePath } "` , {
2021
+ execSync ( `sed -E - i.jitpatch '${ patch } ' "${ fullFilePath } "` , {
2008
2022
cwd : phpSourceDir ,
2009
2023
stdio : 'pipe'
2010
2024
} )
@@ -2144,7 +2158,8 @@ exec ./configure "$@"
2144
2158
const readlinePath = findLatestVersion ( `${ homeDir } /.local/gnu.org/readline` )
2145
2159
2146
2160
if ( readlinePath ) dynamicLibPaths . push ( join ( readlinePath , 'lib' ) )
2147
- if ( iconvPath ) dynamicLibPaths . push ( join ( iconvPath , 'lib' ) )
2161
+ // Only add GNU iconv for non-x86_64 builds to prevent dyld conflicts
2162
+ if ( iconvPath && config . arch !== 'x86_64' ) dynamicLibPaths . push ( join ( iconvPath , 'lib' ) )
2148
2163
if ( gettextPath ) dynamicLibPaths . push ( join ( gettextPath , 'lib' ) )
2149
2164
if ( bz2Path ) dynamicLibPaths . push ( join ( bz2Path , 'lib' ) )
2150
2165
0 commit comments