[컴][LLVM] Visual Studio 에서 Clang tool 빌드 하기



Clang 의 AST 이용하기

c:\> clang hello.c
를 하면, a.exe 를 만들어 낸다. 우리는 이런 실행파일을 원하는 것은 아니다. clang 내부에서 쓰는 AST 자료를 사용할 것이다.
source code 가 있다면 CLang 이 preprocessor 를 실행해서 이 source code 를 parse 해서 AST(Abstract Syntax Tree) 를 만든다.[ref. 1]

이 AST 를 얻기위해서 아래처럼 하면 AST 를 console 에 뿌려준다.
c:\> clang -Xclang -ast-dump -fsyntax-only hello.c

이 AST 를 이용해서 source code 를 다루는 이유는 source code 자체에 대한 분석이 용이하기 때문이다. AST 를 보면 대략 알겠지만, 각 code 가 어떤 의미를 갖는지에 대한 정보를 다 만들어준다.(예를 들면, 함수인지 여부, 변수인지 여부 등등)



The Clang AST




CLang interface

CLang 에서 AST 를 이용할 수 있게 3가지 interface 를 제공하는데, "CLang 문서" 에서 대해 말해준다.

  1. LibClang : 대부분 Clang 을 쓴다면 이녀석을 사용하게 될 것이라고 한다. 다른 Clang 의 interface 는 LibClang 을 쓰지 말아야할 이유가 있을 경우에 사용하라고 한다.
    참고로 LibClang 은 AST 의 full control 을 제공하지 않는다.
  2. Clang Plugins : compile 할 때 만드는 AST 에 어떤 추가적인 작업을 넣고 싶을 때 이 interface 를 사용하면 된다.
  3. LibTooling : C++ interface 이다. ref. 1 에서는 이 LibTooling 이 처음에 사용하기에 가장 적합하다고 이야기한다.
개인적으로는 ref. 1 의 설명이 더 이해하기 좋다.






Visual Studio 에서 Clang tool 만들기

일단 위의 글(ref. 3)의 code 를 가지고 작업을 해보자.



Visual Studio project file 만들기

source 와 CMakeLists 만들기

아래처럼 구조를 만든다. 여기서 아마도 반드시 폴더 이름을 extra 로 해야할 것이다.

<llvm>\tools\clang\tools\extra
                   + CMakeLists.txt
                   + \loop-convert
                                  + CMakeLists.txt
                                  + LoopConvert.cpp

<llvm>\tools\clang\tools\CMakeLists.txt 에 아래와 같은 code 가 기본으로 들어가기 때문이다.
add_llvm_external_project(clang-tools-extra extra)

<llvm>\tools\clang\tools\extra\CMakeLists.txt
add_subdirectory(loop-convert)

<llvm>\tools\clang\tools\extra\loop-convert\CMakeLists.txt
set(LLVM_LINK_COMPONENTS support)

add_clang_executable(loop-convert
  LoopConvert.cpp
  )
target_link_libraries(loop-convert
  clangTooling
  clangBasic
  clangASTMatchers
  )

<llvm>\tools\clang\tools\extra\loop-convert\LoopConvert.cpp
// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"

using namespace clang::tooling;
using namespace llvm;

// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static llvm::cl::OptionCategory MyToolCategory("my-tool options");

// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);

// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...");

int main(int argc, const char **argv) {
  CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
  ClangTool Tool(OptionsParser.getCompilations(),
                 OptionsParser.getSourcePathList());
  return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
}


cmake-gui.exe

이 상황에서 linux 의 경우는 CMake 를 하면 될 것인데, VS 에서는 일단 필자는 cmake-gui.exe 를 이용했기 때문에, .proj 만 하나 따로 생성 하는 법을 모른다. ^^;;; 그래서 모든 .proj 를 다시 만드는 법을 택했다.(참고-LLVM 을 Windows Visual Studio Community 2015에서 build)

대신에 기존의 path 이름을 임시로 변경해 놓고 -> 새롭게 만들고 -> 필요한 부분만 옮겨놓고 -> 이름을 바꾸는 방식을 택했다.

그렇게 얻고나서 필요한 부분만 기존의 .sln/.proj 있는 곳을 copy 해주면 된다. 그러니까 여기서는 아래 부분이 되겠다. 아래 그림에서 왼쪽패널이 새롭게 만든것이고, 오른쪽으로 copy 한 것이다.
  • <llvm>\build\tools\clang\tools\extra\




project 추가

이렇게 하고, 다시 .sln 이 있는 곳의 folder 이름을 변경해 주고, LLVM.sln 을 열었다. 그리고 나서 아래처럼 solution explorer 에서 project 를 add 해주면 된다.



exe 위치

loop-convert 의 build 가 끝나면 아래 위치에서 exe 를 확인할 수 있다.
  • <llvm>\build\Debug\bin\loop-convert.exe

exe실행


f:\>c:\a\programming\llvm\llvm\build\Debug\bin\loop-convert.exe test.cpp --

이러면 test.cpp 를 분석해준다.

뒤에 "--" 표시는 "--" 뒤에 오는 "compiler 에 대한 추가적인 옵션"들을 사용해라. 라는 뜻이다. 즉 위의 경우는 아무런 옵션도 사용하지 않겠다는 뜻이 된다.

"--" 가 없는 경우에 compiler option 을 compilation database 에서 가져오게 된다.





이방법을 이용해서 ref. 2 의 예제를 한번 따라해 보면 될 듯 하다. 참고로  ref, 2 의 소스코드는 옛버전의 llvm 소스를 바탕으로 해서, 몇가지 수정해야 돌아간다.


References






댓글 2개:

  1. *.h 헤더파일과 *.lib 파일 형태로만 제공되는 라이브러리에서
    헤더파일의 클래스들을 추출하여 클래스 멤버 목록을 갖는 리플렉션(?) 기능을 만들고싶은데
    혹시 clang 으로 AST 를 생성하는 방법을 이용하면 헤더파일만 파싱하여 클래스의 멤버목록 추출이 가능한지 궁금합니다

    답글삭제
    답글
    1. 검색을 해보시면, 관련 정보들이 나오는 것 같습니다.

      https://stackoverflow.com/questions/41717457/extracting-function-declarations-from-a-c-c-header-file-using-clang

      삭제