createSpmSourcesStructure function

void createSpmSourcesStructure(
  1. String baseDir,
  2. String platform,
  3. String className,
  4. String pluginName,
)

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 (_) {}
  }
}