createSpmSourcesStructure function
void
createSpmSourcesStructure()
Creates the SPM Sources directory structure for a platform.
Automatically detects whether to use the Flutter 3.41+ nested layout
(ios/<pluginName>/Sources/) or the legacy flat layout (ios/Sources/).
When the nested package directory already exists (created by
_createPackageSwift), it places Sources inside it; otherwise it falls
back to the flat layout.
Implementation
void createSpmSourcesStructure(
String baseDir,
String platform,
String className,
String pluginName,
) {
final platformDir = Directory(p.join(baseDir, platform));
if (!platformDir.existsSync()) return;
// Detect layout: nested (Flutter 3.41+) vs flat
final nestedPackageDir = Directory(p.join(platformDir.path, pluginName));
final bool useNested = nestedPackageDir.existsSync();
final packageRoot = useNested ? nestedPackageDir.path : platformDir.path;
// Symlink depth: nested → 3 levels up (ios/<plugin>/Sources/<Target>/ → ios/Classes/)
// flat → 2 levels up (ios/Sources/<Target>/ → ios/Classes/)
final String classesRelPath = useNested ? '../../../Classes' : '../../Classes';
final sourcesDir = Directory(p.join(packageRoot, 'Sources'));
final swiftDir = Directory(p.join(sourcesDir.path, className));
final cppDir = Directory(p.join(sourcesDir.path, '${className}Cpp'));
swiftDir.createSync(recursive: true);
cppDir.createSync(recursive: true);
// Create symlinks in Swift target
final swiftSymlinks = [
'Swift${className}Plugin.swift',
'${className}Impl.swift',
'$pluginName.bridge.g.swift',
];
for (final name in swiftSymlinks) {
final lnk = Link(p.join(swiftDir.path, name));
if (!lnk.existsSync()) {
try {
lnk.createSync('$classesRelPath/$name');
} catch (_) {
// Symlink may fail on Windows, ignore
}
}
}
// Create symlinks in Cpp target
final cppSymlinks = ['$pluginName.cpp', 'dart_api_dl.c'];
for (final name in cppSymlinks) {
final lnk = Link(p.join(cppDir.path, name));
if (!lnk.existsSync()) {
try {
lnk.createSync('$classesRelPath/$name');
} catch (_) {}
}
}
// Create include symlink
final includeLink = Link(p.join(cppDir.path, 'include'));
if (!includeLink.existsSync()) {
try {
includeLink.createSync(classesRelPath);
} catch (_) {}
}
}