본문 바로가기
컴퓨터/내가 공부한 것

CMake study

by 빵케잌 2023. 2. 15.

1.

cmake는 Makefile을 추상화/직관화하기 위한 meta-Makefile이라고 할 수 있으며 결국 최종 빌드는 make로 수행한다.

2.

cmake CMakeLists.txt를 입력하면 Makefile이 생성된다.

3.

CMakeLists.txt 를 수정하면 make했을 때 자동으로 수정여부를 판단하고 Makefile로 만들어 빌드한다.

4.

Object 파일(.o)는 CMakeFiles 디렉토리 안에 생성된다.

5.

cmake CMakeLists.txt를 하면 생성되는 결과물은 4가지다.

Makefile    CMakeCache.txt    cmake_install.cmake    [CMakeFiles]

6.

위의 파일들은 삭제해도 무방하며 make를 하면 다시 생성한다. 즉, cmake는 최초 한번 이후 다시 할 필요 없다
-> 3. 과 같은 동작이며, 다른 관점의 이야기.

7.

(의문) cmake로 CMakeLists.txt -> Makefile이 가능하다면, 역방향은 불가능한가?

8.

cmake 시, 내부 directory 등의 Sub-Makefile이 생성되는데 이들은 [CMakefiles] 디렉토리에 저장된다.

9.

[CMakefiles]에 있는 Sub-Makefile들은 기존에 존재하는 것이 있으면 재활용한다.
-> 다시 한번 3.과 같은 이야기

10.

여기서부터는 CMake 명령어를 기술한다.

11.

Set(변수 정의)
SET ( <변수명> <값> )
-> 공백이 포함될 경우 큰따옴표로 둘러준다.

12.

Set(List 변수 정의)
SET ( <List_변수명> <항목> <항목> <항목> ... )
-> 각 항목들은 세미콜론(;)으로 구분되어 저장된다.

13.

변수 참조
$변수명
${<변수명>}

2가지 방법 모두 가능하다.

사용 예시)
set(src_files main.c foo.c bar.c)
add_executable (app.out ${src_files})

14.

예약 변수
CMake에 내장되어 있는 변수를 말한다. 사용자 변수처럼 set으로 변경 가능하다.
Set 명령어로 반드시 지정해줘야 하는 변수도 있다. 
빌드 스크립트 디버깅 목적으로 설정이 제대로 되었는지 확인하기도 한다.

15.

message(콘솔 출력)

message ( [<Type>] <메시지> )

콘솔에 메시지나 변수를 출력한다.

<Type>은 생략가능하며, 다음 중 하나로 선택할 수 있다.
STATUS : 상태 메시지 출력
WARNING : 경고 메시지를 출력하고, 계속 진행
AUTHOR_WARNING : 프로젝트 개발자용 경고 메시지를 출력하고, 계속 진행
SEND_ERROR : 오류 메시지를 출력하고 계속 진행, 그러나 Makefile 생성하지 않음
FATAL_ERROR : 오류 메시지 출력하고 즉시 중단

16.

프로젝트 전반적인 명령어
16-1.

cmake_minimum_required ( VERSION <버전> ) : 필요 CMake 최소 버전 명시
16-2.

project(<프로젝트명>) : 프로젝트 이름 설정
16-3.

(변수) CMAKE_PROJECT_NAME : project 명령어로 설정한 프로젝트 이름이 담김
16-4.

(변수) CMAKE_BUILD_TYPE : 빌드 형상. 다음 중 하나의 값이 담긴다.
    - Debug : 디버깅 목적의 빌드
    - Release : 배포 목적의 빌드
    - RelWithDebInfo : 배포 목적의 빌드, 디버깅 정보 포함
    - MinSizeRel : 최소 크기로 최적화한 배포 목적의 빌드
16-5.

(변수) CMAKE_VERBOSE_MAKEFILE : Verbose Makefile 작성 여부
true / false 중 값을 가지며, true 시 CMake 과정에서 빌드 상세 과정을 모두 출력하는 Makefile을 생성한다.

17.

Target이란 모든 빌드가 끝나고 최종적으로 출력되는 실행 파일과 라이브러리를 의미한다.

18.

Target 관련 명령어
18-1.

add_executable ( <실행_파일명> <소스_파일> <소스_파일> ... ) : 빌드 대상 바이너리 추가
18-2.

add_library ( <라이브러리_명> [STATIC|SHARED|MODULE] <소스_파일> <소스_파일> ... ) : 빌드 대상 라이브러리 추가
    - lib~.a  lib~.so 형태로 라이브러리를 생성한다. 
    예) add_library ( app STATIC main.c) -> libapp.a
18-3.

add_custom_target : 사용자 정의 target 추가
위의 두가지 방법으로 빌드할 수 없는 target을 생성할 때 쓴다. 쉽게 말해 customized build command이다.
add_custom_target ( <이름> [ALL] [COMMENT <출력_메시지>] [DEPENDS <의존_대상_목록>] 
        [WORKING_DIRECTORY <작업_디렉토리>] COMMAND <명령> 
        [COMMAND <명령>] [VERBATIM] ... )
<이름> : Target 이름
[ALL] : make(또는 make all) 명령에서 기본 빌드 대상에 포함할 지 여부
<출력_메시지> : 명령 실행 전에 콘솔에 출력할 메시지
<의존_대상_목록> : 이 Target이 의존하는 대상 목록
<작업_디렉토리> : 명령을 실행할 위치(pwd)
<명령> : Target을 생성하기 위한 명령(Recipe)
[VERBATIM] : <명령>을 Escape하지 않고 그대로 사용하려는 경우 추가

사용 예시) 다음 구문은 app.bin을 flashing하기 위한 make flash 매크로를 정의한다.
ADD_CUSTOM_TARGET ( flash
COMMENT "Flashing binary"
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMAND python esptool.py write_flash app.bin
DEPENDS app.out
)

18-4.

add_dependencies( <Target_이름> <의존_대상> <의존_대상> ... ) : Target 간 의존성 정의
Target이 해당 대상을 의존하고 있는지를 지정한다. 그러면 의존 대상이 빌드가 되었을 때 Target을 빌드한다.
add_executable이나 add_library에서 지정한 소스 파일과의 의존성을 명시할 필요는 없다.

18-5.

install() : 설치 매크로(make install) 정의
Makefile에서 make install을 하면 일반적으로 빌드 완료된 실행 바이너리와 라이브러리 및 기타 부속물(헤더 파일, 리소스 등)들을 적절한 위치로 복사하는 동작을 한다.
이러한 동작을 지정해주기 위한 명령어이다. 
INSTALL ( TARGETS <Target_목록>
        RUNTIME DESTINATION <바이너리_설치_경로>
        LIBRARY DESTINATION <라이브러리_설치_경로>
        ARCHIVE DESTINATION <아카이브_설치_경로>
)
사용 예시) app.out은 /usr/local/bin에, libapp.a는 /usr/local/lib에 설치하는 install target을 추가한다.

INSTALL ( TARGETS app.out app
        RUNTIME DESTINATION /usr/local/bin
        ARCHIVE DESTINATION /usr/local/lib
        )

18-6.

(변수) CMAKE_INSTALL_PREFIX : 설치 디렉토리
make install에서 최종 생성물을 복사할 설치 디렉토리를 지정한다. install 명령어에서 상대 경로를 사용할 때의 base가 되기도 한다.
기본값은 /usr/local이다.

19.

전역 빌드 설정 관련.
모든 Target에 공통으로 적용되는 빌드 옵션을 지정하는 변수와 커맨드이다.
주의할 점은, 명령어 선언 이후에 정의되는 Target에만 적용이 된다.

19-1.

(변수) CMAKE_C_COMPILER : 컴파일 및 링크 과정에서 사용할 컴파일러의 경로를 지정한다.

19-2.

ADD_COMPILE_OPTIONS ( <옵션> <옵션> ... ) : 컴파일러에 전달할 옵션(플래그)를 추가한다.

19-3.

(변수) CMAKE_C_FLAGS_<빌드_형상> : 빌드 형상별 컴파일 옵션

예시) Release 빌드시에 CONFIG_RELEASE 매크로를 정의하고 O3 최적화로 지정한다.

SET ( CMAKE_C_FLAGS_RELEASE "-DCONFIG_RELEASE -O3" )

(참고) 옵션이 여러 개인 경우 쌍따옴표로 하나의 문자열로 정의해야 한다.

19-4.

ADD_DEFINITIONS() : 전처리기 매크로 추가
컴파일러 옵션 중 -D에 해당한다.

예시) ICACHE_FLASH 매크로 변수를 정의하고, MY_DEBUG라는 이름의 전처리 매크로 값을 1로 정의한다.
ADD_DEFINITIONS( -DICACHE_FLASH -DMY_DEBUG=1 )

19-5.

INCLUDE_DIRECTORIES() : 헤더 디렉토리 추가 (-I)
소스 파일에서 헤더 파일을 찾을 디렉토리 목록을 추가한다. 컴파일러 옵션 중 -I에 해당된다.

예시) include 디렉토리와 driver/include 디렉토리에서 헤더 파일을 찾게 한다.
INCLUDE_DIRECTORIES ( include driver/include )

19-6.

19-7.

19-8.

(변수) CMAKE_EXE_LINKER_FLAGS_<빌드_형상> - 빌드 형상별 링크 옵션

예시) Debug 빌드시에만 CONFIG_DEBUG 매크로를 정의하고 모든 Symbol을 포함하도록 링크 옵션을 지정한다.
SET ( CMAKE_EXE_LINKER_FLAGS_DEBUG "-DCONFIG_DEBUG -Wl, -whole-archive" )

19-9.

(변수) RUNTIME_OUTPUT_DIRECTORY - 실행 바이너리 출력 디렉토리
빌드 완료한 실행 바이너리를 저장할 디렉토리를 지정한다.

19-10.

(변수) LIBRARY_OUTPUT_DIRECTORY - 라이브러리 출력 디렉토리
빌드 완료한 라이브러리를 저장할 디렉토리를 지정한다.

19-11.

(변수) ARCHIVE_OUTPUT_DIRECTORY - 아카이브 출력 디렉토리
빌드 완료한 아카이브(Static 라이브러리)를 저장할 디렉토리를 지정한다.

20.

특정 Target 한정 빌드 설정 관련
Target이 여러 개일 때, Target마다 빌드 옵션을 별개로 지정할 때 사용한다.
대상 Target은 이미 선언되어야 있어야 한다.
공통적으로 모든 커맨드는 Target으로 시작하고, 첫 번째 인수는 대상 Target이름이다.

20-1.

TARGET_COMPILE_OPTIONS( <Target_이름> PUBLIC <옵션> <옵션> .. ) : Target 컴파일 옵션 추가

20-2.

TARGET_COMPILE_DEFINITIONS() - Target 전처리 매크로 정의 (-D)

20-3.

TARGET_INCLUDE_DIRECTORIES() - Target 헤더 디렉토리 추가 (-I)

20-4.

21.

빌드 절차 관련

21-1.

CONFIGURE_FILE( <템플릿_파일명> <출력_파일명> ) - 템플릿 파일로부터 파일 자동 생성
템플릿 파일 내용 중 $변수명 @변수명을 치환하여 출력 파일로 저장한다. 전전처리 과정으로 볼 수 있다.
주로 프로그램 버전을 명시하는 헤더 파일을 자동 생성하는 경우 사용한다.

21-2.

ADD_CUSTOM_COMMAND(OUTPUT) - 사용자 정의 출력 파일 추가
출력 파일의 Recipe를 직접 지정해야 하는 경우 유용하게 활용할 수 있다.
ADD_CUSTOM_TARGET과의 차이점은 1. 출력 파일이 최소하나 있어야 한다는 점(OUTPUT 인수로 명시), 2. 생성하는 출력 파일들의 최신 여부를 파악하므로 시간을 줄여줄 수 있다는 점이다.

예시) app.out을 빌드 완료한 뒤, 임베디드 프로세서에 flashing하기 위한 app.bin을 생성하는 명령이다.

ADD_CUSTOM_COMMAND (
                OUTPUT app.bin
                COMMENT "Generating binary from executable"
                DEPENDS app.out
                COMMAND python tools/elf2bin.py app.out app.bin
)

21-3.

ADD_CUSTOM_COMMAND(TARGET) - 빌드 과정 명령 추가
특정 Target의 빌드 전/빌드 중/빌드 후에 수행할 명령을 추가한다.

ADD_CUSTOM_COMMAND (
                TARGET <대상_Target_이름>
                <PRE_BUILD|PRE_LINK|POST_BUILD>
                [COMMENT <출력_메시지>]
                [WORKING_DIRECTORY <작업_디렉토리>]
                COMMAND <명령>
                [COMMAND <명령>]
                [VERBATIM]
                ...
)

예시) app.out을 빌드 완료한 뒤, 임베디드 프로세서에 flashing하기 위한 app.bin을 생성하는 명령이다. 21-2.의 예시와 동일한 동작

ADD_CUSTOM_COMMAND (
                TARGET app.out
                POST_BUILD
                COMMENT "Generating binary from executable"
                COMMAND python tools/elf2bin.py app.out app.bin
)

 

출처 : https://www.tuwlab.com/27260