From cc8621c61b66f6668a17ab3819a05add85dd3c44 Mon Sep 17 00:00:00 2001 From: Aapo Alasuutari Date: Sun, 15 Jan 2023 13:07:54 +0200 Subject: [PATCH] fix: Type exports, missing README.md, OS X support --- build/build.ts | 10 +++++----- deno.json | 2 +- lib/README.md | 39 +++++++++++++++++++++++++++++++++++++++ lib/ffi.ts | 49 ++++++++++++++++++++++++++++++++++++++----------- lib/mod.ts | 26 ++++++++++++++------------ 5 files changed, 97 insertions(+), 29 deletions(-) create mode 100644 lib/README.md diff --git a/build/build.ts b/build/build.ts index 70936d1..d4a91ea 100644 --- a/build/build.ts +++ b/build/build.ts @@ -83,7 +83,7 @@ HEADER_FILES.forEach((fileName) => { name = name.substring("enum ".length); } if (!TYPE_MEMORY.has(name)) { - const type = toAnyType(TYPE_MEMORY, cx.getType()); + const type = toAnyType(TYPE_MEMORY, cx.getType()!); TYPE_MEMORY.set(name, type); } break; @@ -93,7 +93,7 @@ HEADER_FILES.forEach((fileName) => { if (!TYPE_MEMORY.has(typedefName)) { const originalTypeDeclaration = cx - .getTypedefDeclarationOfUnderlyingType(); + .getTypedefDeclarationOfUnderlyingType()!; let structDeclAnyType = toAnyType( TYPE_MEMORY, originalTypeDeclaration, @@ -217,11 +217,11 @@ HEADER_FILES.forEach((fileName) => { } case CXCursorKind.CXCursor_FunctionDecl: { const parameters: FunctionParameter[] = []; - const resultAnyType = toAnyType(TYPE_MEMORY, cx.getResultType()); + const resultAnyType = toAnyType(TYPE_MEMORY, cx.getResultType()!); const length = cx.getNumberOfArguments(); for (let i = 0; i < length; i++) { - const argument = cx.getArgument(i); - const argumentAnyType = toAnyType(TYPE_MEMORY, argument.getType()); + const argument = cx.getArgument(i)!; + const argumentAnyType = toAnyType(TYPE_MEMORY, argument.getType()!); parameters.push({ comment: commentToJSDcoString( argument.getParsedComment(), diff --git a/deno.json b/deno.json index 5319fdc..6c51696 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,6 @@ { "lock": true, "tasks": { - "build": "./deno run --unstable --allow-env=LIBCLANG_PATH --allow-run=deno --allow-ffi --allow-write=lib/include build/build.ts" + "build": "deno run --unstable --allow-env=LIBCLANG_PATH --allow-run=deno --allow-ffi --allow-write=lib/include build/build.ts" } } diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..0eee07f --- /dev/null +++ b/lib/README.md @@ -0,0 +1,39 @@ +## libclang + +Deno bindings for [Clang](https://clang.llvm.org/)'s C API `libclang`. Full +project details are found on the +[libclang-deno GitHub page](https://github.com/aapoalas/libclang-deno). + +### Startup + +To use `libclang` in your Deno program, import the `mod.ts` file into your +program: + +```ts +import * as libclang from "https://deno.land/x/libclang@1.0.0-beta.3/mod.ts"; +``` + +You must run your program with the `LIBCLANG_PATH` environment variable set to +either the direct path to your `libclang.so` / `libclang.dll` / `libclang.dylib` +shared library or to the folder in which the shared library resides. If the +environment variable is not set, the import will fail. + +### Basic usage + +The following code will walk through all the cursors in a given header and log +their kind and spelling: + +```ts +import * as libclang from "https://deno.land/x/libclang@1.0.0-beta.3/mod.ts"; + +const index = new libclang.CXIndex(); + +const tu = index.parseTranslationUnit("/path/to/header.h", [ + "-I/path/to/include", +]); + +tu.getCursor().visitChildren((cursor) => { + console.log(`${cursor.getKindSpelling()}: ${cursor.getSpelling()}`); + return libclang.CXChildVisitResult.CXChildVisit_Recurse; +}); +``` diff --git a/lib/ffi.ts b/lib/ffi.ts index 3b7c3c4..a0f2658 100644 --- a/lib/ffi.ts +++ b/lib/ffi.ts @@ -33,26 +33,53 @@ if (!libclangPath) { let libclang: ReturnType>; -if (libclangPath.includes(".so") || libclangPath.endsWith(".dll")) { - // Explicit path, try without catching - libclang = Deno.dlopen(libclangPath, IMPORTS); -} else if (Deno.build.os === "windows") { +if (Deno.build.os === "windows") { + if (libclangPath.includes(".dll")) { + try { + libclang = Deno.dlopen(libclangPath, IMPORTS); + } catch { + // Ignore + } + } libclang = Deno.dlopen( join(libclangPath, "libclang.dll"), IMPORTS, ); +} else if (Deno.build.os === "darwin") { + if (libclangPath.includes(".dylib")) { + try { + libclang = Deno.dlopen(libclangPath, IMPORTS); + } catch { + // Ignore + } + } + libclang = Deno.dlopen( + join(libclangPath, "libclang.dylib"), + IMPORTS, + ); } else { - // Try 14.0.6 first, then 14, then 13 + if (libclangPath.includes(".so")) { + try { + libclang = Deno.dlopen(libclangPath, IMPORTS); + } catch { + // Ignore + } + } + // Try plain libclang first, then 14.0.6, then 14, and finally try 13. try { - libclang = Deno.dlopen( - join(libclangPath, "libclang.so.14.0.6"), - IMPORTS, - ); + libclang = Deno.dlopen(join(libclangPath, "libclang.so"), IMPORTS); } catch { try { - libclang = Deno.dlopen(join(libclangPath, "libclang.so.14"), IMPORTS); + libclang = Deno.dlopen( + join(libclangPath, "libclang.so.14.0.6"), + IMPORTS, + ); } catch { - libclang = Deno.dlopen(join(libclangPath, "libclang.so.13"), IMPORTS); + try { + libclang = Deno.dlopen(join(libclangPath, "libclang.so.14"), IMPORTS); + } catch { + libclang = Deno.dlopen(join(libclangPath, "libclang.so.13"), IMPORTS); + } } } } diff --git a/lib/mod.ts b/lib/mod.ts index 1af143c..46cf437 100644 --- a/lib/mod.ts +++ b/lib/mod.ts @@ -55,57 +55,59 @@ import { } from "./utils.ts"; export * from "./BuildSystem.ts"; export * from "./CXCompilationDatabase.ts"; -export type { +export { CX_CXXAccessSpecifier, CX_StorageClass, CXAvailabilityKind, CXCallingConv, CXChildVisitResult, CXCodeComplete_Flags, - CXCodeCompleteResults, CXCommentInlineCommandRenderKind, CXCommentKind, CXCommentParamPassDirection, CXCompletionChunkKind, CXCompletionContext, - CXCompletionString, CXCursor_ExceptionSpecificationKind, CXCursorKind, CXDiagnosticDisplayOptions, CXDiagnosticSeverity, CXErrorCode, - CXEvalResult, CXEvalResultKind, CXGlobalOptFlags, - CXIndexAction, CXLanguageKind, CXLinkageKind, CXLoadDiag_Error, - CXModule, CXNameRefFlags, CXObjCDeclQualifierKind, CXObjCPropertyAttrKind, - CXPrintingPolicy, CXPrintingPolicyProperty, CXRefQualifierKind, CXReparse_Flags, CXResult, - CXRewriter, CXSaveError, - CXSourceRangeList, CXTemplateArgumentKind, CXTLSKind, - CXToken, CXTokenKind, CXTranslationUnit_Flags, - CXTUResourceUsage, - CXType, CXTypeKind, CXTypeLayoutError, CXTypeNullabilityKind, CXVisibilityKind, CXVisitorResult, }; +export type { + CXCodeCompleteResults, + CXCompletionString, + CXEvalResult, + CXIndexAction, + CXModule, + CXPrintingPolicy, + CXRewriter, + CXSourceRangeList, + CXToken, + CXTUResourceUsage, + CXType, +}; const CONSTRUCTOR = Symbol("[[constructor]]"); const POINTER = Symbol("[[pointer]]");