WIP: More dynmaic path searching for generating bindings. #30
1 changed files with 146 additions and 51 deletions
Changed generate.dart script to dynamically look for needed files for linux/windows/macos with newest version
commit
de97890634
|
|
@ -4,8 +4,7 @@ import "package:path/path.dart" as path;
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
final Directory repoDir = Directory.fromUri(Platform.script.resolve("../gomuks"));
|
final Directory repoDir = Directory.fromUri(Platform.script.resolve("../gomuks"));
|
||||||
|
print("Generating FFI Bindings for ${Platform.operatingSystem}...");
|
||||||
print("Generating FFI Bindings...");
|
|
||||||
|
|
||||||
int? parseVersion(String name) {
|
int? parseVersion(String name) {
|
||||||
final RegExpMatch? match = RegExp(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?$").firstMatch(name);
|
final RegExpMatch? match = RegExp(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?$").firstMatch(name);
|
||||||
|
|
@ -17,63 +16,145 @@ void main(List<String> args) async {
|
||||||
final int major = int.tryParse(match.group(1)!) ?? 0;
|
final int major = int.tryParse(match.group(1)!) ?? 0;
|
||||||
final int minor = int.tryParse(match.group(2) ?? "0") ?? 0;
|
final int minor = int.tryParse(match.group(2) ?? "0") ?? 0;
|
||||||
final int patch = int.tryParse(match.group(3) ?? "0") ?? 0;
|
final int patch = int.tryParse(match.group(3) ?? "0") ?? 0;
|
||||||
return major * 10000 + minor * 100 + patch; //Single number to compare versions based on integer math
|
return major * 10000 + minor * 100 + patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Directory gccBaseDir = Directory("/usr/lib/gcc/x86_64-pc-linux-gnu");
|
final List<String> systemIncludePaths = [];
|
||||||
String? latestGccIncludePath;
|
late String targetTriple;
|
||||||
|
late String libclangName;
|
||||||
|
|
||||||
if (await gccBaseDir.exists()) {
|
if (Platform.isLinux) {
|
||||||
final Iterable<Directory> entries = gccBaseDir.listSync().whereType<Directory>();
|
targetTriple = "x86_64-pc-linux-gnu";
|
||||||
|
libclangName = "libclang.so";
|
||||||
|
|
||||||
final List<Directory> versionDirs = entries.where((dir) {
|
final Directory gccBaseDir = Directory("/usr/lib/gcc/x86_64-pc-linux-gnu");
|
||||||
final String name = path.basename(dir.path);
|
|
||||||
return parseVersion(name) != null;
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
if (versionDirs.isNotEmpty) {
|
if (await gccBaseDir.exists()) {
|
||||||
versionDirs.sort((a, b) {
|
final List<Directory> dirs = gccBaseDir.listSync().whereType<Directory>().toList();
|
||||||
final int verA = parseVersion(path.basename(a.path))!;
|
|
||||||
final int verB = parseVersion(path.basename(b.path))!;
|
dirs.sort((a, b) {
|
||||||
return verB.compareTo(verA); // Descending
|
final int va = parseVersion(path.basename(a.path)) ?? 0;
|
||||||
|
final int vb = parseVersion(path.basename(b.path)) ?? 0;
|
||||||
|
return vb.compareTo(va);
|
||||||
});
|
});
|
||||||
|
|
||||||
final Directory latestDir = versionDirs.first;
|
if (dirs.isNotEmpty) {
|
||||||
latestGccIncludePath = path.join(latestDir.path, "include");
|
final Directory latest = dirs.first;
|
||||||
print("Successfully detected GCC version: ${path.basename(latestDir.path)} -> Using: $latestGccIncludePath");
|
final String inc = path.join(latest.path, "include");
|
||||||
} else {
|
systemIncludePaths.add(inc);
|
||||||
print("!Warning!: No GCC version directories found in ${gccBaseDir.path}");
|
systemIncludePaths.add(path.dirname(inc));
|
||||||
|
print("Using GCC: ${path.basename(latest.path)}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Directory clangDir = Directory("/usr/lib/clang");
|
||||||
|
|
||||||
|
if (await clangDir.exists()) {
|
||||||
|
final List<Directory> dirs = clangDir.listSync().whereType<Directory>().toList();
|
||||||
|
dirs.sort((a, b) {
|
||||||
|
final int va = parseVersion(path.basename(a.path)) ?? 0;
|
||||||
|
final int vb = parseVersion(path.basename(b.path)) ?? 0;
|
||||||
|
return vb.compareTo(va);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dirs.isNotEmpty) {
|
||||||
|
systemIncludePaths.add(path.join(dirs.first.path, "include"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
systemIncludePaths.addAll(["/usr/include", "/usr/include/x86_64-linux-gnu", "/usr/local/include"]);
|
||||||
|
|
||||||
|
} else if (Platform.isMacOS) {
|
||||||
|
final String arch = _detectMacArch();
|
||||||
|
targetTriple = "$arch-apple-darwin";
|
||||||
|
libclangName = "libclang.dylib";
|
||||||
|
|
||||||
|
final String? sdkPath = _runCommand("xcrun", ["--show-sdk-path"]);
|
||||||
|
if (sdkPath != null) {
|
||||||
|
systemIncludePaths.add(path.join(sdkPath, "usr", "include"));
|
||||||
|
print("Using Xcode SDK: $sdkPath");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String? clangResDir = _runCommand("clang", ["-print-resource-dir"]);
|
||||||
|
if (clangResDir != null) {
|
||||||
|
final String inc = path.join(clangResDir, "include");
|
||||||
|
|
||||||
|
if (Directory(inc).existsSync()) {
|
||||||
|
systemIncludePaths.add(inc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final String brewPrefix = arch == "arm64" ? "/opt/homebrew" : "/usr/local";
|
||||||
|
final Directory brewGcc = Directory(path.join(brewPrefix, "opt", "gcc", "lib", "gcc", "current", "include"));
|
||||||
|
|
||||||
|
if (brewGcc.existsSync()) {
|
||||||
|
systemIncludePaths.add(brewGcc.path);
|
||||||
|
print("Using Homebrew GCC");
|
||||||
|
}
|
||||||
|
|
||||||
|
systemIncludePaths.addAll(["$brewPrefix/include", "/usr/local/include"]);
|
||||||
|
|
||||||
|
} else if (Platform.isWindows) {
|
||||||
|
|
||||||
|
targetTriple = "x86_64-pc-windows-msvc";
|
||||||
|
libclangName = "libclang.dll";
|
||||||
|
|
||||||
|
final String vswhere = r"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe";
|
||||||
|
final String? vsPath = _runCommand(vswhere, ["-latest", "-property", "installationPath"]);
|
||||||
|
|
||||||
|
if (vsPath != null) {
|
||||||
|
final Directory msvcDir = Directory(path.join(vsPath, "VC", "Tools", "MSVC"));
|
||||||
|
|
||||||
|
if (msvcDir.existsSync()) {
|
||||||
|
final List<Directory> dirs = msvcDir.listSync().whereType<Directory>().toList();
|
||||||
|
dirs.sort((a, b) {
|
||||||
|
final int va = parseVersion(path.basename(a.path)) ?? 0;
|
||||||
|
final int vb = parseVersion(path.basename(b.path)) ?? 0;
|
||||||
|
return vb.compareTo(va);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dirs.isNotEmpty) {
|
||||||
|
systemIncludePaths.add(path.join(dirs.first.path, "include"));
|
||||||
|
print("Using MSVC: ${path.basename(dirs.first.path)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Directory sdkDir = Directory(r"C:\Program Files (x86)\Windows Kits\10\Include");
|
||||||
|
if (sdkDir.existsSync()) {
|
||||||
|
final List<Directory> dirs = sdkDir.listSync().whereType<Directory>().toList();
|
||||||
|
|
||||||
|
dirs.sort((a, b) {
|
||||||
|
final int va = parseVersion(path.basename(a.path)) ?? 0;
|
||||||
|
final int vb = parseVersion(path.basename(b.path)) ?? 0;
|
||||||
|
return vb.compareTo(va);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dirs.isNotEmpty) {
|
||||||
|
final String sdkVer = dirs.first.path;
|
||||||
|
for (final String sub in ["um", "ucrt", "shared"]) {
|
||||||
|
final String p = path.join(sdkVer, sub);
|
||||||
|
if (Directory(p).existsSync()) systemIncludePaths.add(p);
|
||||||
|
}
|
||||||
|
print("Using Windows SDK: ${path.basename(sdkVer)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Directory llvmDir = Directory(r"C:\Program Files\LLVM\include");
|
||||||
|
|
||||||
|
if (llvmDir.existsSync()) {
|
||||||
|
systemIncludePaths.add(llvmDir.path);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
print("!Warning!: GCC base directory not found at ${gccBaseDir.path}");
|
|
||||||
|
print("Error: Unsupported platform: ${Platform.operatingSystem}");
|
||||||
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<String> systemIncludePaths = <String>[];
|
print("Target: $targetTriple");
|
||||||
|
print("Include paths: ${systemIncludePaths.length} found");
|
||||||
if (latestGccIncludePath != null) {
|
|
||||||
systemIncludePaths.add(latestGccIncludePath);
|
|
||||||
systemIncludePaths.add(path.dirname(latestGccIncludePath));
|
|
||||||
}
|
|
||||||
|
|
||||||
final Directory clangDir = Directory("/usr/lib/clang");
|
|
||||||
if (await clangDir.exists()) {
|
|
||||||
final List<Directory> clangEntries = clangDir.listSync().whereType<Directory>().toList();
|
|
||||||
if (clangEntries.isNotEmpty) {
|
|
||||||
clangEntries.sort((a, b) {
|
|
||||||
final verA = parseVersion(path.basename(a.path)) ?? 0;
|
|
||||||
final verB = parseVersion(path.basename(b.path)) ?? 0;
|
|
||||||
return verB.compareTo(verA);
|
|
||||||
});
|
|
||||||
systemIncludePaths.add(path.join(clangEntries.first.path, "include"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Standard Paths
|
|
||||||
systemIncludePaths.addAll([
|
|
||||||
"/usr/include",
|
|
||||||
"/usr/include/x86_64-linux-gnu",
|
|
||||||
"/usr/local/include",
|
|
||||||
]);
|
|
||||||
|
|
||||||
final String? libclangPath = Platform.environment["LIBCLANG_PATH"];
|
final String? libclangPath = Platform.environment["LIBCLANG_PATH"];
|
||||||
|
|
||||||
|
|
@ -85,16 +166,30 @@ void main(List<String> args) async {
|
||||||
entryPoints: [File(path.join(repoDir.path, "pkg", "ffi", "gomuksffi.h")).uri],
|
entryPoints: [File(path.join(repoDir.path, "pkg", "ffi", "gomuksffi.h")).uri],
|
||||||
compilerOptions: [
|
compilerOptions: [
|
||||||
"--no-warnings",
|
"--no-warnings",
|
||||||
"-target", "x86_64-pc-linux-gnu",
|
"-target", targetTriple,
|
||||||
...systemIncludePaths.map((path) => "-I$path"),
|
...systemIncludePaths.map((p) => "-I$p"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
functions: Functions.includeAll,
|
functions: Functions.includeAll,
|
||||||
).generate(
|
).generate(
|
||||||
libclangDylib: libclangPath == null
|
libclangDylib: libclangPath == null
|
||||||
? null
|
? null
|
||||||
: Uri.file(path.join(libclangPath, "libclang.so")),
|
: Uri.file(path.join(libclangPath, libclangName)),
|
||||||
);
|
);
|
||||||
|
|
||||||
print("Done!");
|
print("Done!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _detectMacArch() {
|
||||||
|
final String? res = _runCommand("uname", ["-m"]);
|
||||||
|
return res?.trim() == "arm64" ? "arm64" : "x86_64";
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _runCommand(String exe, List<String> args) {
|
||||||
|
try {
|
||||||
|
final ProcessResult res = Process.runSync(exe, args);
|
||||||
|
return res.exitCode == 0 ? (res.stdout as String).trim() : null;
|
||||||
|
} catch (_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue