ClangWrapper.Swift icon indicating copy to clipboard operation
ClangWrapper.Swift copied to clipboard

Clang C API wrapper for Swift.

Eonil/ClangWrapper

2015/01/21 Hoon H.

Provides a set of wrappers around libclang library API. (C API, not C++ API)

How to Use

Here's a quick example. (a part of Workbench example)

let	path		=	NSBundle.mainBundle().pathForResource("Sample", ofType: "c")!

let	idx			=	Index(excludeDeclarationsFromPCH: false, displayDiagnostics: false)
let	transunit	=	idx.parseTranslationUnit(path)

transunit.diagnostics.map { (d:Diagnostic)->() in
println(d.spelling)
}

println(transunit)

Above code should print something like this.

implicitly declaring library function 'printf' with type 'int (const char *, ...)'
main (FunctionDecl, 1:1~11:1)
   (CompoundStmt, 4:1~7:2)
	printf (CallExpr, 4:12~7:2)
	  printf (FirstExpr/UnexposedExpr, 5:2~5:32)
		printf (DeclRefExpr, 5:2~5:8)
	   (FirstExpr/UnexposedExpr, 5:2~5:32)
		 (FirstExpr/UnexposedExpr, 5:9~5:15)
		  "%s\n" (StringLiteral, 5:9~5:15)
	   (FirstExpr/UnexposedExpr, 5:2~5:32)
		"Hello world!" (StringLiteral, 5:17~5:31)
	 (ReturnStmt, 4:12~7:2)
	   (IntegerLiteral, 6:2~6:10)

Some points.

If you want to force specific language mode, use this method.

let	transunit	=	idx.parseTranslationUnit(path, commandLineArguments: ["-std=c++11"])

Usually compiler needs more parameters to locate proper platform support. Here's an example.

let	args	=	[
	"-x", "c++",
	"-std=c++11",
	"-stdlib=libc++",
	"-isysroot", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk",
	"-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
]

Requirements

  • OS X 10.11 El Capitan
  • Xcode 7.1
  • Swift 2.1

Cautions

  • This framework is designed for Swift.

  • This framework links to libclang.dylib included in Xcode.

    $(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib
    

    That will be resolved to

    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib
    

    Ths library path is hardcoded in LD_RUNPATH_SEARCH_PATHS. Change this if you want to use your own binary.

  • This framework is using Clang's C API that is intended to be stable. Linking to Xcode bonary should be fine.

  • This framework does not fully cover C API (yet? well...).

  • Compiler assumes some missing types to int silently, and I know no good way to determine this is missing or not. Anyway, TranslationUnit provides diagnostics, so always check it for any issues before you proceed.

Design Choices

  • All strings are passed by copy. Performance can be decreased.
  • An extra method like stringBuffer can be added later for efficiency.
  • Index class serves as local proxy root container. It manages all the proxy objects connected over C API. You have to keep a reference to Index object to keep any of its object.
  • Uses C-like tree (unique-ownership) manual resource management. That means you need to call dispose manually on them to free up allocated resources. If an object does not support dispose, it means it does not allocate resources internally.
  • For your safety and convenience, all proxy objects are tracked and disposed by Index class when it deinitializes if the proxy objects has not been disposed.
  • Enums constant values are copied from libclang headers if they're explicitly defined.
  • Using of C++ API has been avoided becuase it's a fast moving target and does not seem to be stable for at least in a few years. Maybe forever.

References

License

Portion of my work is licensed under "MIT license". This project contains some header files from LLVM project. That is licensed under "University of Illinois/NCSA Open Source License". The portion of LLVM project is all header files in /ClangWrapper/include directory. This project contains some header files from LLDB project. That is licensed under "University of Illinois/NCSA Open Source License". The portion of LLDB project is all header files in /ClangWrapper/ClangASTViewer/SampleData directory. The product of this project will be linked to a component of Xcode. That is a intellectual property of Apple. You can avoid this by changing link parameters. I don't redistribute any code from Xcode, so I believe this linking is fine. But please let me know if something is wrong.