linkMacosPodspec function

void linkMacosPodspec(
  1. String pluginName,
  2. List<String> moduleLibs, {
  3. String baseDir = '.',
  4. List<ModuleInfo>? moduleInfos,
})

Implementation

void linkMacosPodspec(
  String pluginName,
  List<String> moduleLibs, {
  String baseDir = '.',
  List<ModuleInfo>? moduleInfos,
}) {
  final nitroNativePath = resolveNitroNativePath(baseDir);
  final podspecFile = File(p.join(baseDir, 'macos', '$pluginName.podspec'));
  if (!podspecFile.existsSync()) return;
  var content = podspecFile.readAsStringSync();
  bool modified = false;
  // Normalize source_files to 'Classes/**/*' (same fix as linkIosPodspec).
  final sourceFilesMatchMacos = RegExp(r"s\.source_files\s*=\s*'([^']+)'").firstMatch(content);
  if (sourceFilesMatchMacos != null && sourceFilesMatchMacos.group(1) != 'Classes/**/*') {
    final badPath = sourceFilesMatchMacos.group(1)!;
    // Fix any non-Classes path regardless of whether the first directory exists —
    // for SPM-layout plugins the directory exists but the glob still matches nothing.
    final firstSegment = badPath.split('/').first;
    if (firstSegment != 'Classes') {
      content = content.replaceFirst(
        sourceFilesMatchMacos.group(0)!,
        "s.source_files = 'Classes/**/*'",
      );
      modified = true;
    }
  }
  if (!content.contains("s.swift_version = '${BuildVersions.podSwiftVersion}'")) {
    content = content.replaceFirst(
      RegExp(r"s\.swift_version\s*=\s*'.+?'"),
      "s.swift_version = '${BuildVersions.podSwiftVersion}'",
    );
    modified = true;
  }
  final macosDeployment = BuildVersions.macosDeployment.replaceAll('_', '.');
  if (!content.contains("s.platform = :osx, '$macosDeployment'")) {
    if (RegExp(r"s\.platform\s*=\s*:osx").hasMatch(content)) {
      content = content.replaceFirst(
        RegExp(r"s\.platform\s*=\s*:osx,\s*'.+?'"),
        "s.platform = :osx, '$macosDeployment'",
      );
    } else {
      // Insert platform line after the spec name line
      content = content.replaceFirst(
        RegExp(r"(s\.name\s*=.+\n)"),
        "\$1  s.platform = :osx, '$macosDeployment'\n",
      );
    }
    modified = true;
  }
  final xcResult = _patchApplePodspecXcconfig(content, isMacos: true);
  content = xcResult.content;
  if (xcResult.modified) modified = true;
  // Sync generated Swift bridges into macos/Classes/ so Xcode compiles them
  // in the same module scope as the plugin's other Swift files.
  if (modified) podspecFile.writeAsStringSync(content);
  createSharedHeaders(nitroNativePath, baseDir: baseDir);
  final classesDir = Directory(p.join(baseDir, 'macos', 'Classes'))..createSync(recursive: true);
  File(
    p.join(classesDir.path, 'dart_api_dl.c'),
  ).writeAsStringSync(classesDartApiDlForwarder);
  syncBridgeFiles(baseDir, platform: 'macos');
  _copySwiftBridgesToClasses(classesDir, baseDir, platform: 'macos');
  _removeSwiftGlobFromPodspec(podspecFile);

  // Link the main project source files.
  final cppInSrc = File(p.join(baseDir, 'src', '$pluginName.cpp'));
  if (cppInSrc.existsSync()) {
    cleanRedundantIncludes(cppInSrc);
    File(p.join(classesDir.path, '$pluginName.cpp')).writeAsStringSync(
      managedCppForwarder('../../src/$pluginName.cpp'),
    );
  }
  final cInSrc = File(p.join(baseDir, 'src', '$pluginName.c'));
  if (cInSrc.existsSync()) {
    cleanRedundantIncludes(cInSrc);
    File(
      p.join(classesDir.path, '$pluginName.c'),
    ).writeAsStringSync(classesCForwarder(pluginName));
  }

  // Link C++ module implementation files for macOS — same logic as iOS above.
  // Only macos:NativeImpl.cpp modules get a Hybrid*.cpp forwarder in macos/Classes/.
  _writeAppleModuleForwarders(moduleInfos, classesDir, baseDir, isMacosCppModule);
}