@@ -221,6 +221,7 @@ private async Task<TargetAuditResult> AuditTargetAsync(
221221
222222 try
223223 {
224+ PrepareStagedXcframeworkForTarget ( target , stagedFrameworkPath ) ;
224225 var projectFile = CreateSwiftBindingProject ( projectDirectory , projectName , stagedFrameworkPath , options . GeneratorVersion ) ;
225226 var buildResult = await BuildTargetProjectAsync ( projectFile , projectDirectory , dotnetEnvironment , cancellationToken ) ;
226227 WriteLogs ( logsDirectory , $ "{ target . Id } -build", buildResult ) ;
@@ -1208,6 +1209,96 @@ private static void StageXcframeworks(string repoRoot, string destinationDirecto
12081209 }
12091210 }
12101211
1212+ internal static void PrepareStagedXcframeworkForTarget ( AuditTargetDefinition target , string stagedXcframeworkPath )
1213+ {
1214+ if ( target . ObjcUmbrellaHeaderImports . Length == 0 )
1215+ {
1216+ return ;
1217+ }
1218+
1219+ MaterializeStagedDirectory ( stagedXcframeworkPath ) ;
1220+ AddObjcUmbrellaHeaderImports ( stagedXcframeworkPath , target . ObjcUmbrellaHeaderImports ) ;
1221+ }
1222+
1223+ private static void MaterializeStagedDirectory ( string stagedDirectoryPath )
1224+ {
1225+ var directoryInfo = new DirectoryInfo ( stagedDirectoryPath ) ;
1226+ if ( ! directoryInfo . Exists || ( directoryInfo . Attributes & FileAttributes . ReparsePoint ) == 0 )
1227+ {
1228+ return ;
1229+ }
1230+
1231+ var linkTarget = directoryInfo . LinkTarget ;
1232+ if ( string . IsNullOrWhiteSpace ( linkTarget ) )
1233+ {
1234+ throw new InvalidOperationException ( $ "Unable to resolve symlink target for '{ stagedDirectoryPath } '.") ;
1235+ }
1236+
1237+ var sourcePath = Path . IsPathRooted ( linkTarget )
1238+ ? linkTarget
1239+ : Path . GetFullPath ( Path . Combine ( directoryInfo . Parent ? . FullName ?? Directory . GetCurrentDirectory ( ) , linkTarget ) ) ;
1240+ if ( ! Directory . Exists ( sourcePath ) )
1241+ {
1242+ throw new InvalidOperationException ( $ "Symlink target '{ sourcePath } ' does not exist for '{ stagedDirectoryPath } '.") ;
1243+ }
1244+
1245+ Directory . Delete ( stagedDirectoryPath ) ;
1246+ CopyDirectory ( sourcePath , stagedDirectoryPath ) ;
1247+ }
1248+
1249+ private static void AddObjcUmbrellaHeaderImports ( string xcframeworkPath , IReadOnlyList < string > imports )
1250+ {
1251+ var importLines = imports
1252+ . Select ( NormalizeObjcImportLine )
1253+ . Distinct ( StringComparer . Ordinal )
1254+ . ToList ( ) ;
1255+ if ( importLines . Count == 0 )
1256+ {
1257+ return ;
1258+ }
1259+
1260+ foreach ( var umbrellaHeaderPath in Directory . EnumerateFiles ( xcframeworkPath , "*-umbrella.h" , SearchOption . AllDirectories ) )
1261+ {
1262+ var content = File . ReadAllText ( umbrellaHeaderPath ) ;
1263+ var additions = importLines
1264+ . Where ( importLine => ! content . Contains ( importLine , StringComparison . Ordinal ) )
1265+ . ToList ( ) ;
1266+ if ( additions . Count == 0 )
1267+ {
1268+ continue ;
1269+ }
1270+
1271+ var builder = new StringBuilder ( content ) ;
1272+ if ( builder . Length > 0 && builder [ ^ 1 ] != '\n ' )
1273+ {
1274+ builder . AppendLine ( ) ;
1275+ }
1276+
1277+ foreach ( var addition in additions )
1278+ {
1279+ builder . AppendLine ( addition ) ;
1280+ }
1281+
1282+ File . WriteAllText ( umbrellaHeaderPath , builder . ToString ( ) ) ;
1283+ }
1284+ }
1285+
1286+ private static string NormalizeObjcImportLine ( string import )
1287+ {
1288+ var trimmedImport = import . Trim ( ) ;
1289+ if ( trimmedImport . StartsWith ( "#import " , StringComparison . Ordinal ) )
1290+ {
1291+ return trimmedImport ;
1292+ }
1293+
1294+ if ( trimmedImport . StartsWith ( "<" , StringComparison . Ordinal ) || trimmedImport . StartsWith ( "\" " , StringComparison . Ordinal ) )
1295+ {
1296+ return $ "#import { trimmedImport } ";
1297+ }
1298+
1299+ return $ "#import <{ trimmedImport } >";
1300+ }
1301+
12111302 private static void StageSharpieFrameworkSlices (
12121303 string stagedFrameworksDirectory ,
12131304 string destinationDirectory ,
0 commit comments