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 {
|
||||
final Directory repoDir = Directory.fromUri(Platform.script.resolve("../gomuks"));
|
||||
|
||||
print("Generating FFI Bindings...");
|
||||
print("Generating FFI Bindings for ${Platform.operatingSystem}...");
|
||||
|
||||
int? parseVersion(String name) {
|
||||
final RegExpMatch? match = RegExp(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?$").firstMatch(name);
|
||||
|
|
@ -17,66 +16,148 @@ void main(List<String> args) async {
|
|||
final int major = int.tryParse(match.group(1)!) ?? 0;
|
||||
final int minor = int.tryParse(match.group(2) ?? "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");
|
||||
String? latestGccIncludePath;
|
||||
final List<String> systemIncludePaths = [];
|
||||
late String targetTriple;
|
||||
late String libclangName;
|
||||
|
||||
if (await gccBaseDir.exists()) {
|
||||
final Iterable<Directory> entries = gccBaseDir.listSync().whereType<Directory>();
|
||||
if (Platform.isLinux) {
|
||||
targetTriple = "x86_64-pc-linux-gnu";
|
||||
libclangName = "libclang.so";
|
||||
|
||||
final Directory gccBaseDir = Directory("/usr/lib/gcc/x86_64-pc-linux-gnu");
|
||||
|
||||
if (await gccBaseDir.exists()) {
|
||||
final List<Directory> dirs = gccBaseDir.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 Directory latest = dirs.first;
|
||||
final String inc = path.join(latest.path, "include");
|
||||
systemIncludePaths.add(inc);
|
||||
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");
|
||||
|
||||
final List<Directory> versionDirs = entries.where((dir) {
|
||||
final String name = path.basename(dir.path);
|
||||
return parseVersion(name) != null;
|
||||
}).toList();
|
||||
|
||||
if (versionDirs.isNotEmpty) {
|
||||
versionDirs.sort((a, b) {
|
||||
final int verA = parseVersion(path.basename(a.path))!;
|
||||
final int verB = parseVersion(path.basename(b.path))!;
|
||||
return verB.compareTo(verA); // Descending
|
||||
});
|
||||
|
||||
final Directory latestDir = versionDirs.first;
|
||||
latestGccIncludePath = path.join(latestDir.path, "include");
|
||||
print("Successfully detected GCC version: ${path.basename(latestDir.path)} -> Using: $latestGccIncludePath");
|
||||
} else {
|
||||
print("!Warning!: No GCC version directories found in ${gccBaseDir.path}");
|
||||
if (llvmDir.existsSync()) {
|
||||
systemIncludePaths.add(llvmDir.path);
|
||||
}
|
||||
|
||||
} else {
|
||||
print("!Warning!: GCC base directory not found at ${gccBaseDir.path}");
|
||||
|
||||
print("Error: Unsupported platform: ${Platform.operatingSystem}");
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
final List<String> systemIncludePaths = <String>[];
|
||||
|
||||
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",
|
||||
]);
|
||||
print("Target: $targetTriple");
|
||||
print("Include paths: ${systemIncludePaths.length} found");
|
||||
|
||||
final String? libclangPath = Platform.environment["LIBCLANG_PATH"];
|
||||
|
||||
|
||||
FfiGenerator(
|
||||
output: Output(
|
||||
dartFile: Platform.script.resolve("../lib/src/third_party/gomuks.g.dart"),
|
||||
|
|
@ -85,16 +166,30 @@ void main(List<String> args) async {
|
|||
entryPoints: [File(path.join(repoDir.path, "pkg", "ffi", "gomuksffi.h")).uri],
|
||||
compilerOptions: [
|
||||
"--no-warnings",
|
||||
"-target", "x86_64-pc-linux-gnu",
|
||||
...systemIncludePaths.map((path) => "-I$path"),
|
||||
"-target", targetTriple,
|
||||
...systemIncludePaths.map((p) => "-I$p"),
|
||||
],
|
||||
),
|
||||
functions: Functions.includeAll,
|
||||
).generate(
|
||||
libclangDylib: libclangPath == null
|
||||
? null
|
||||
: Uri.file(path.join(libclangPath, "libclang.so")),
|
||||
: Uri.file(path.join(libclangPath, libclangName)),
|
||||
);
|
||||
|
||||
|
||||
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