================================================
make ( makefile ), cmake ( CMakeLists.txt ) 에 대하여
1. make (makefile) 기초 https://bahk33.tistory.com/193
2. cmake ( CMakeLists.txt ) 기초, 간단 예제 - 본글 https://bahk33.tistory.com/195
================================================
================================================
1. 들머리
> cmake 라는 프로그램은 간단히 말하여 CMakeLists.txt 를 읽어 makefile(.txt) 을 만들어 주는 것 입니다.
make 프로그램이 makefile을 읽어 소스(.c)들을 빌드하여 최종 실행 파일을 만듭 니다.
cmake 는 빌드때
1) makefile 이 나름 복잡하여 이를 쉽게 만들기 위한것과,
2) 빌드시간을 간단히 ( 수정 된것만 재컴파일 ) 하기 위한 것
등을 제공 하기 위하여 씁니다.
> 즉 makefile 을 만들때 쓰는 것 이므로, 소스 파일 내용이 변경되더라도, 다른 소스 파일이 추가 된다든지, 빠지지 않는다면, cmake 는 최초 1번만 실행 하면 됩니다. 거꾸로 말하면, 소스 파일이 추가 또는 빠진다면 그때 마다 실행 해야겠지요.
> make, makefile 에 대하여는 ( https://bahk33.tistory.com/193 ) 를 참고 하시고, 여기서는 cmake, CMakeLists.txt 에 대한 기초적인것을 다룹니다. cmake 에 대하여 자세한 것은 공식 사이트( https://cmake.org/ ) 를 보시면 됩니다.
CMake는 소프트웨어를 빌드, 테스트, 패키징하도록 설계된 오픈 소스, 크로스 플랫폼 도구 제품군입니다.
CMake는 간단한 독립적인 구성 파일을 사용하여 소프트웨어 컴파일 프로세스를 제어할 수 있도록 합니다.
많은 크로스 플랫폼 시스템과 달리 CMake는 네이티브 빌드 환경과 함께 사용하도록 설계되었습니다.
2. cmake 사용 보기
1) 간단한 더하기 함수 파일 만들기 add.c, add.h
2) 간단한 곱하기 함수 파일 만들기 mul.c, mul.h
// mul.h
3) 주 함수 main.c 만들기
main.c는 헤더 파일 add.h, mul.h를 참조한다.
return 0; // 메인문 종료
4) CMakeLists.txt 작성
> 간단히 한줄만 기술 하면 된다 ( 사실 기본 2줄 포함 3줄 )
> 사실 반드시 들어가야할 기본 2줄이 들어 간 3줄이면 됩니다.
- cmake_minimum_required ( VERSION <버전> ) 빌드에 필요한 cmake 최소 버전
- project( ) 프로젝트 정보
cmake_minimum_required ( VERSION 2.9) #cmake 최소 요구 버전
project (test) #프로젝트 정보: 이름: test
add_excutable(add_mul add.c mul.c main.c) #빌드: 실행파일 add_mul 만들기
> ADD_EXECUTABLE은 실행할 파일을 생성하는 명령입니다. 대소문자 가리지 않읍니다.
첫 번째 매개변수는 실행 파일 이름이고, 나머지는 그 실행 파일을 생성하기 위한 소스 파일들 이다.
실행 파일(Excutable File)을 만들어 내는 것이 목표이므로 명령어에 executable이 사용된 것이다.
즉, add.c, mul.c, main.c를 이용해 add_mul이라는 실행 파일을 만들라는 의미이다.
5) 실행 1 : cmake 로 CMakeLists.txt 에서 makefile 만들기
> "cmake CMakeLists.txt" 하면 makefile 이 만들어진다.
6) 실행 2 : make 로 빌드 하기
> "make" 하면 빌드가 된다.
7) CMakeLists.txt 문법
> 설명, 코멘트 는 "#" 으로 시작 합니다.
# CMakeLists.txt , 설명은 # 로 시작 하면 됩니다.
> 문장 ( command ) 은
- commnad_name ( arg1 arg2 ... ) 와 같읍니다.
- cmd_name 은 대소문자 가리지 않읍니다.
즉 ADD_EXECUTABLE(add_mul main.c) 과 add_executable(add_mul main.c) 은 같읍니다.
- arguments 는 0개 이상 입니다. 즉 명령에 따라 없는거도 있고, 있는것도 있읍니다
add_executable(add_mul add.c mul.c main.c) #빌드: 실행파일 add_mul 만들기
보기, if 문
if(<condition>)
<commands>
elseif(<condition>) # optional block, can be repeated
<commands>
else() # optional block
<commands>
endif()
3. sub dirctory 처리
1). 파일 구조를 다음 과 같이 해 보자
$ tree
.
├── CMakeLists.txt
├── inc
│ ├── add.h
│ └── mul.h
├── Module1
│ └── add.c
├── Module2
│ └── mul.c
└── src
├── version.c
└── main.c
2). CMakeLists.txt 파일의 내용은 다음과 같다.
# 최소 cmake 버전 설정
cmake_minimum_required(VERSION 3.30.3)
# 프로젝트 이름 및 버전 설정
project(projectSub VERSION 1.0.0 LANGUAGES CXX)
# C++17 표준을 사용
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 소스 파일 목록 설정
set(
SOURCES
src/*.c
Module1/add.c
Module2/*.c
)
# 실행 파일 생성
add_executable( ${PROJECT_NAME} ${SOURCES} )
# compile 옵션
target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -O2)
# include 디렉토리 추가 (헤더 파일 경로)
target_include_directories(${PROJECT_NAME} BEFORE inc)
위의 경우 실행 파일을 빌드할 때 컴파일 옵션으로 -Wall (모든 경고 표시)과 -Werror (경고는 컴파일 오류로 간주)를 준다는 의미이다.
3). 실행 순서는 다음과 같다.
$ mkdir build
$ cd build
$ cmake -S .. -B .
$ make -j$(nproc)
* cmake -S .. -B . 명령은, 상위 디렉토리에 있는 CMakeLists.txt를 찾아 현재 디렉토리에 빌드 파일을 생성하라는 의미이다.
4). Makefile을 만들어 냈던 cmake -S .. -B . 명령을 살펴보자.
- -S
- 이 옵션은 소스 디렉토리(Source Directory)를 지정하는 옵션이다. 여기서 쓰인 ".."은 현재 디렉토리의 상위 디렉토리를 소스 디렉토리로 지정하고 있다.
- 즉, cmake가 CMakeLists.txt 파일을 찾기 위해 상위 디렉토리를 소스 디렉토리로 사용한다.
- -B
- 빌드 디렉토리(Build Directory)를 지정하는 옵션이다. 여기서 쓰인 "." 현재 디렉토리를 빌드 디렉토리로 설정하고 있다.
- 즉, 컴파일된 파일들과 중간 파일들이 현재 디렉토리에 생성된다.
- -D
- 특정 변수 설정을 할 수 있도록 해준다. 이 옵션은 -D<변수>=<값> 형식으로 사용되며, 프로젝트의 빌드 과정에서 변수 값을 정의하거나 특정 옵션을 활성화/비활성화하는 데 유용하다.
- 보기)
- cmake -DCMAKE_BUILD_TYPE=Release
- cmake -DCMAKE_INSTALL_PREFIX=/usr/local
- cmake -DENABLE_TESTS=ON
5) include 경로 지정
CMake에서는 컴파일 시에 헤더 파일들을 찾을 경로의 위치를 지정할 수 있다.
보통 컴파일러는
> #include <>의 형태로 include되는 헤더 파일들은 시스템 경로에서 찾고,
> #include ""의 형태로 include된 헤더 파일의 경우는 따로 지정하지 않는 이상 현재 코드의 위치를 기준으로 찾는다.
하지만 경우에 따라서 (특히 라이브러리를 만들 시) 헤더 파일들을 다른 곳에 위치시키는 경우가 있는데, 컴파일러가 해당 파일들을 찾기 위해서는 컴파일 시에 따로 경로를 지정해줘야 한다. 따라서 CMakeLists.txt에 include 디렉토리를 헤더 파일 경로 탐색 시 어디에서 확인해라 라고 알려줘야 한다.
target_include_directories(MyTarget PUBLIC ${CMAKE_SOURCE_DIR}/include)
사용 방법은 아래와 같다.
target_include_directories(<실행 파일 이름> PUBLIC <경로 1> <경로 2> ...)
위의 경우 ${CMAKE_SOURCE_DIR}/include 를 헤더 파일 탐색 경로에 추가하고 있다. 한 가지 중요한 점은 CMake에서 디렉토리의 경로를 지정할 때, 왠만하면 절대 경로를 쓰지 않는 것이 중요하다. 그 이유는 CMake의 가장 큰 장점이 여러 플랫폼에서 사용할 수 있는 것인데, 절대 경로로 설정하면 다른 시스템에서 사용할 수 없기 때문이다.
${CMAKE_SOURCE_DIR}은 CMake에서 기본으로 제공하는 변수로, 최상위 CMakeLists.txt, 즉 cmake .. 할 때 읽어들이는 CMakeLists.txt의 경로를 의미한다. 다시 말해 프로젝트의 경로라고 볼 수 있다. 따라서 ${CMAKE_SOURCE_DIR}/include 는 현재 프로젝트 경로 안에 include 디렉토리라고 보면 된다.
6) 컴파일 옵션 지정하기
> target_compile_options 명령을 사용합니다.
보기로
라면, program 을 빌드할 때 컴파일 옵션으로 -Wall (모든 경고 표시) 과 -Werror (경고는 컴파일 오류로 간주) 을 준다는 의미 입니다. 중간에 PUBLIC 은 실행 파일을 빌드할 때에는 그닥 중요하지 않습니다. (PUBLIC 말고도 INTERFACE 와 PRIVATE 도 있는데 사실 어느 옵션을 사용하도 큰 상관은 없습니다.)
4.
5. 자주 쓰이는 명령들
- project( )
- 프로젝트 이름
- cmake_minimum_required ( VERSION <버전> )
- 빌드에 필요한 cmake 최소 버전
- set
- set ( <변수 이름> <값> )
- set ( <목록 변수 이름> <항목> <항목> ... )
- 보기) set ( SRC_FILES main.cpp A_Module.cpp B_Module.cpp )
- set ( CMAKE_CXX_STANDARD <버전> )
- C++ 표준 버전 설정
- set ( RUNTIME_OUTPUT_DIRECTORY 디렉토리1 )
- 빌드된 실행 바이너리를 저장할 디렉토리 지정
- target_include_directories (디렉토리1, 디렉토리2, ...)
- 헤더 파일 경로 포함 (컴파일러가 찾을 수 있도록 경로 설정)
- 특정 타겟(target)에만 헤더 디렉토리를 적용
- 즉, 지정한 타겟(target)에만 영향을 미치므로 더 명시적이고 권장되는 방식이다.
- 보기) target_include_directories(my_target PUBLIC ${CMAKE_SOURCE_DIR}/include)
- 이 경우, my_target 타겟에만 해당 디렉토리가 포함된다.
- 또한, target_include_directories는 접근 제어(PRIVATE, PUBLIC, INTERFACE) 옵션을 제공하여 헤더 디렉토리의 가시성을 제어할 수 있다.
- PRIVATE
- 해당 타겟 내에서만 사용
- PUBLIC
- 해당 타겟과 이를 링크하는 다른 타겟도 사용 가능
- INTERFACE
- 타겟 자신은 사용하지 않지만 이를 링크하는 타겟에서만 사용
- PRIVATE
- add_compile_options ( 옵션1, 옵션2, ... )
- 프로젝트 내의 모든 타겟에 동일한 컴파일 옵션 추가
- 프로젝트 전역 옵션으로 사용 가능. 즉, 특정 타겟이 아닌 전체 프로젝트의 빌드 설정에 영향을 미친다.
- 보기 ) add_compile_options ( -g -Wall -O2 )
- target_compile_options ( <실행 파일 이름> PRIVATE | INTERFACE | PUBLIC <컴파일 옵션1> <컴파일 옵션2> ... )
- 특정 타겟에 대해서만 컴파일 옵션을 추가
- 타겟별로 세밀하게 컴파일러 옵션을 관리할 때 유용
- Options
- PRIVATE
- 타겟 내부에서만 적용. 즉, PRIVATE로 지정된 컴파일 옵션은 해당 타겟에만 적용되고, 이 타겟을 의존하는 다른 타겟에는 전파되지 않는다.
- PUBLIC
- 해당 타겟과 의존하는 다른 타겟에도 적용. 즉, PUBLIC으로 지정된 옵션은 해당 타겟뿐만 아니라, 이 타겟을 의존하는 다른 타겟에도 동일하게 적용된다.
- INTERFACE
- 의존하는 타겟에만 적용. 즉, INTERFACE로 지정된 옵션은 해당 타겟 자체에는 적용되지 않고, 오직 이 타겟을 의존하는 타겟에만 적용된다.
- PRIVATE
- 보기 ) target_compile_options(test.out PRIVATE -Wall -O2)
- add_executable ( <실행 파일 이름> <소스 파일> ... )
- 빌드의 최종 결과물 생성 (binary 파일 생성)
- 보기 ) add_executable ( test.out main.cpp A_Module.cpp B_Module.cpp)
- 보기 ) add_executable ( test.out ${SRC_FILES} )
- 빌드의 최종 결과물 생성 (binary 파일 생성)
- add_library ( <라이브러리 이름> [STATIC | SHARED | MODULE] <소스파일> )
- 빌드의 최종 결과물로 라이브러리 생성
- 라이브러리의 링킹(Linking)의 형태를 명시하지 않는다면, 여기서 생성되는 라이브러리는 프로젝트 생성 시, BUILD_SHARED_LIBS 변수에 따라서 결정된다.
- add_subdirectory ( <디렉토리 경로> [binary_dir][EXCLUDE_FROM_ALL] )
- Options
- <디렉토리 경로>
- 서브 디렉토리의 경로 (이 경로에 CMakeLists.txt 파일이 존재해야 한다)
- [binary_dir]
- 빌드 아티팩트가 생성될 디렉토리 경로 (옵션)
- [EXCLUDE_FROM_ALL]
- 이 플래그를 사용하면 make all 명령어를 실행할 때, 해당 디렉토리의 target을 제외 함
- <디렉토리 경로>
- 서브 디렉토리를 추가하여 해당 디렉토리안의 CMakeLists.txt파일을 호출하고 빌드 시스템에 통합할 때 사용
- 즉, 다중 디렉토리로 이루어진 프로젝트에서 모듈화된 빌드 지원
- add_subdirectory는 디렉토리마다 독립적인 CMakeLists.txt 파일을 정의하고, 이를 상위 프로젝트에서 통합할 때 사용
- 여러 팀이 함께 개발하는 큰 프로젝트에서 자주 사용 됨
- Options
- add_dependencies
- 프로젝트 내에서 여러 라이브러리를 빌드할 때, 의존성을 제어할 때 사용한다.
- cmake_c_compiler
- 컴파일 및 링크 과정에서 사용할 컴파일러의 경로 지정
- 보기 ) set (cmake_c_compiler "gcc")
- 컴파일 및 링크 과정에서 사용할 컴파일러의 경로 지정
- message( )
- 콘솔에 메시지 출력
- install( )
- make install 실행 시, 동작 지정
- target_link_libraries ( <target> <item1> <item2> ... )
- Options
- <target>
- 라이브러리를 링크할 대상(target), 실행 파일 또는 라이브러리 이름
- <item1>, <item2>
- 링크할 라이브러리나 target 이름들
- <target>
- 컴파일 된 실행 파일이나 라이브러리에 외부 라이브버리 또는 다른 타겟을 링크할 때 사용
- Options
'개발 > embed' 카테고리의 다른 글
make (makefile) 기초 (0) | 2025.02.06 |
---|---|
CMakeCache.txt: Error: unrecognized option '--major-image-version' (0) | 2025.01.21 |
gcc 로 nuvoton source 직접 build(compile) 하기 (0) | 2025.01.20 |
Nuvoton 제공 Sample Code를 Keil 에서 Compile 하기 (0) | 2025.01.10 |
win11에 JTAGICE mkII driver설치 ( ATMega AVR Studio 4.19 ) (0) | 2024.12.10 |