본문 바로가기
장인으로의 여정

[Build System] CMake

by 유기농프로그래밍 2016. 3. 31.
반응형

CMake


Makefile은 개발하는 사람들이라면 들어봤을 것이다.

Makefile을 보면 대개 복잡하고 읽기 쉽지 않다. 그래서 auto make나 기타 등등의 Makefile을 만들어 주는 툴을 만들어 사용한다.


이번에 소개할 것은 CMake라는 것이다. CMake는 환경에 맞는 빌드시스템이다.


새로운 빌드 시스템에 대한 요구사항

1. 시스템에 설치된 C++컴파일러에만 의존한다.

2. Visual Studio IDE 입력 파일을 생성할 수 있어야 한다.

3. 정적 라이브러리, 공유 라이브러리, 실행 파일, 플러그인 등 기본 빌드 시스템 타깃을 생성하기 쉬워야 한다.

4. 빌드 타임 코드 생성기를 사용할 수 있어야 한다.

5. 소스 트리에 따라 다양한 빌드 트리를 지원해야 한다.

6. 시스템 분석을 수행할 수 있어야 한다. 예를 들어 타깃 시스템이 할 수 있는 일과 없는 일을 자동으로 판단할 수 있어야 한다.

7. C/C++ 헤더 파일의 의존성 탐색을 자동으로 할 수 있어야 한다.

8. 모든 기능은 지원하는 모든 플랫폼에서 일관적이고 동일하게 잘 동작해야 한다.


CMake 프로세스

환경변수(혹은 다른 변수)

프로젝트에 소스트리의 루트를 가리키는 PROJECT_ROOT 환경 변수 등이 있다. CMake는 빌드할 때 필요한 모든 변수를 한 곳에 저장하는캐시 파일을 제공한다. 이때 변수들은 shell이나 환경 변수가 아닌 CMake 변수이다. 맨 처음에 CMakeCache.txt 파일 생성한다. 이 파일이 빌드 트리에 포함되기 때문에 CMake는 매번 실행할 때마다 항상 변수를 사용할 수 있게 된다.


크게 두단계가 있다.

1. 설정(configure) 단계

- 이전 실행의 CMakeCache.txt 파일이 존재하면 우선 이 파일을 읽는다. 그리고 CMake는 처리해야 하는 소스 트리의 루트에 위치한 CMakeLists.txt 파일을 읽는다.

설정 단계에서 CMakeLists.txt 파일을 CMake 언어 파서에 의해 해석하며 파일에 적힌 각 CMake 커맨드는 커맨드 패턴 객체(command pattern object)에 의해 하나씩 실행된다. include나 add_subdirectory라는 CMake 커맨드를 통해 추가적인 CMakeLists.txt 파일도 이 단계에서 해석할 수 있다.(즉, 하위 폴더에 있는 CMakeLists.txt 파일도 함께 해석할 수 있다)


커맨드의 예 : add_library, if, add_executable, add_subdirectory, include 등


파서의 역할 : 단순히 CMake 입력 파일을 커맨드 호출과 커맨드의 매개변수로 사용할 문자열 리스트로 변환한다.


설정 단계는 특히 사용자가 제공한 CMake 코드를 실행한다. 모든 코드 실행 후 모든 캐시변수 값이 계산되고 CMake는 빌드할 프로젝트 내용을 메모리상에 만든다.

(라이브러리, 실행 가능 파일, 커스텀 커맨드, 선택한 생성기가 마지막 빌드 파일을 생성하는데 필요한 모든 정보 등)


이 시점에서 CMakeCache.txt 파일이 디스크에 저장된다.


메모리 상에 있는 프로젝트 내용은 타깃 집합으로 라이브러리나 실행 가능 파일처럼 단순히 빌드될 대상을 의미한다.

CMake는 각 타깃을 cmTarget 객체에 저장한다. 이 객체는 소스트리의 해당 디렉터리에서 발견되는 모든 타깃이 저장되는 cmMakefile 객체에 차례로 저장된다. cmTarget 객체의 맵을 가지고 있는 cmMakefile 객체의 트리가 마지막 결과로 만들어진다.


2. 생성(generate) 단계

설정 단계가 완료되면 생성 단계가 시작된다. 이 시점의 타깃(라이브러리, 실행 가능 파일, 커스텀 타깃)의 내용은 Visual Studio 같은 IDE 빌드 툴의 입력이나 make로 실행되는 Makefile의 집합으로 변환된다. 설정 단계가 끝난 후 CMake 의 내용은 가능한 한 범용적인 형태를 보이는데, 코드와 데이터 구조를 다른 빌드 툴에서도 최대한 공유할 수 있어야 하기 때문이다.







CMake 객체

CMake는 상속, 디자인 패턴, 캡슐화의 개념을 차용한 객체 지향 시스템이다.

주요 클래스 : cmCommand

모든 커맨드 구현체의 기본 클래스이다. 각각의 서브클래스는 커맨드의 구현뿐만 아니라 문서화까지 담당하고 있다.


의존성 분석

CMake는 포트란, C, C++ 소스 코드 파일에 대한 강력한 의존성 분석 기능으르 내장하고 있다. 하지만 통합개발 환경(IDE)도 파일 의존 관계를 관리해주기 때문에, CMake는 이런 빌드 시스템에 대해서는 의존성 분석을 하지 않는다.

Makefile은 의존성분석을 스스로 못하기 때문에 CMake에서 알아서 의존관계를 계산한다.


각 타깃의 의존관계 파일은 depend.make, flags.make, DependInfo.cmake, build.make라는 네개의 파일에 저장된다.

depend.make

- 디렉터리의 모든 객체 파일에 대한 의존 관계가 저장

flags.make

- 이 타깃 소스 파일에 사용되는 컴파일 플래그가 저장, 이게 변경되면 다시 컴파일한다.

DependInfo.cmake

- 의존관계를 최신으로 유지하는 데 사용, 어떤 언어의 어떤 파일이 이 프로젝트에 속해 있는지에 대한 정보가 담겨있다.

build.make

- 의존 관계를 구성하는 규칙 저장







반응형

'장인으로의 여정' 카테고리의 다른 글

애자일 프렉티스[1]  (0) 2016.04.07
[linux] 파일링크 ln (Hard Link, Soft Link)  (2) 2016.03.12
[linux] jdk 설치  (0) 2016.03.12

댓글