linkCMake function
void
linkCMake(})
Implementation
void linkCMake(
String pluginName,
List<String> moduleLibs,
String nitroNativePath, {
String baseDir = '.',
List<ModuleInfo>? moduleInfos,
}) {
createSharedHeaders(nitroNativePath, baseDir: baseDir);
final cmakeFile = File(p.join(baseDir, 'src', 'CMakeLists.txt'));
if (!cmakeFile.existsSync()) {
generateCMake(
pluginName,
moduleLibs,
nitroNativePath,
baseDir: baseDir,
moduleInfos: moduleInfos,
);
return;
}
var content = cmakeFile.readAsStringSync();
bool modified = false;
const defaultCmakeNitro =
r'${CMAKE_CURRENT_SOURCE_DIR}/../../packages/nitro/src/native';
final desiredNitroValue =
nitroNativePathExists(defaultCmakeNitro, p.join(baseDir, 'src'))
? defaultCmakeNitro
: nitroNativePath.replaceAll(r'\', '/');
final nitroNativeSetLine = 'set(NITRO_NATIVE "$desiredNitroValue")';
if (!content.contains('NITRO_NATIVE')) {
content = '$nitroNativeSetLine\n\n$content';
modified = true;
} else {
final staleMatch = RegExp(
r'set\(NITRO_NATIVE\s+"([^"]+)"\)',
).firstMatch(content);
if (staleMatch != null &&
!nitroNativePathExists(staleMatch.group(1)!, p.join(baseDir, 'src')) &&
staleMatch.group(1) != desiredNitroValue) {
content = content.replaceFirst(staleMatch.group(0)!, nitroNativeSetLine);
modified = true;
}
}
if (!content.contains('CMAKE_CXX_STANDARD')) {
// Inject C++17 standard after the project() declaration.
content = content.replaceFirstMapped(
RegExp(r'project\([^)]+\)\s*\n'),
(m) =>
'${m.group(0)!}\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\n',
);
modified = true;
}
if (!content.contains(r'${NITRO_NATIVE}')) {
content = content.replaceFirst(
'target_include_directories($pluginName PRIVATE',
'target_include_directories($pluginName PRIVATE\n "\${NITRO_NATIVE}"',
);
modified = true;
}
if (!content.contains('dart_api_dl.c')) {
content = content.replaceFirst(
'add_library($pluginName SHARED',
'add_library($pluginName SHARED\n "dart_api_dl.c"',
);
modified = true;
}
final bridgeRel = '../lib/src/generated/cpp/$pluginName.bridge.g.cpp';
if (!content.contains(bridgeRel)) {
content = content.replaceFirst(
'add_library($pluginName SHARED',
'add_library($pluginName SHARED\n "\${CMAKE_CURRENT_SOURCE_DIR}/$bridgeRel"',
);
modified = true;
}
// Add the main plugin's HybridXxx.cpp impl file when:
// • the module uses NativeImpl.cpp on android/linux (isNativeCpp) — the
// src/ CMakeLists is for Android/Linux only; macOS/iOS are handled by SPM/CocoaPods.
// • the file exists in src/, and
// • it is not already listed in the cmake (either inline or in a NOT ANDROID guard).
//
// When android uses Kotlin (isAndroidCpp=false) but linux uses C++, wrap in
// `if(NOT ANDROID)` so the NDK build skips the C++ impl stub.
if (moduleInfos != null) {
final mainInfo = moduleInfos.firstWhere(
(m) => m.lib == pluginName,
orElse: () => ModuleInfo(lib: pluginName, module: pluginName, isCpp: false),
);
if (mainInfo.isNativeCpp) {
final className = _toPascalCase(
mainInfo.module.isNotEmpty ? mainInfo.module : pluginName,
);
final implName = 'Hybrid$className.cpp';
final implFile = File(p.join(baseDir, 'src', implName));
if (implFile.existsSync() && !content.contains('"$implName"')) {
if (mainInfo.isAndroidCpp) {
// Android uses C++ directly — embed impl in add_library.
content = content.replaceFirst(
'add_library($pluginName SHARED',
'add_library($pluginName SHARED\n "$implName"',
);
} else {
// Linux-only C++ — exclude from Android NDK builds.
content = content.replaceFirst(
'target_include_directories($pluginName PRIVATE',
'if(NOT ANDROID)\n target_sources($pluginName PRIVATE "$implName")\nendif()\ntarget_include_directories($pluginName PRIVATE',
);
}
modified = true;
}
}
}
for (final lib in moduleLibs) {
if (lib != pluginName && !content.contains('add_library($lib ')) {
final info = moduleInfos?.firstWhere(
(m) => m.lib == lib,
orElse: () => ModuleInfo(lib: lib, module: lib, isCpp: false),
);
// Use isNativeCpp (android/linux) — only those platforms put
// HybridXxx.cpp into src/CMakeLists.txt. Windows-only cpp uses
// windows/CMakeLists.txt instead.
content += ct.cmakeModuleTarget(
lib,
isCpp: info?.isNativeCpp ?? false,
isAndroidCpp: info?.isAndroidCpp ?? false,
);
modified = true;
}
}
if (modified) cmakeFile.writeAsStringSync(content);
}