CMake - project

mohadang·2022년 8월 7일
0

CMake

목록 보기
15/24
post-thumbnail

project 명령을 사용하였다는 것은 프로젝트(.vcxproj, Makefile ...)를 하나 선언한 것으로 보면 된다. 프로젝트는 플랫폼에 따라 형태가 다르며 프로젝트의 출력 파일은 .so , .dll, .lib 등으로 생성된다고 보면 될것이다.
project와 add_subdirectory를 사용하면 CMakeLists.txt를 계층적으로 구조화 할 수 있다.

cmake_minimum_required 다음에는 project 명령이 기록되어 있어야 한다.
project는 가급적 CMaktLists.txt의 최상위에 있어야 하고 cmake_minimum_required 와 project 명령 사이에는 가급적이면 다른 작업이 포함되면 안된다.

project 실행 후 기본 컴파일러가 설정된다.

# project 명령 실행 전과 실행후 컴파일러 내역을 출력

cmake_minimum_required(VERSION 2.8)

message("Before 'project':")
message("  C: '${CMAKE_C_COMPILER}'")
message("  C++: '${CMAKE_CXX_COMPILER}'")

project(Foo)

message("After 'project':")
message("  C: '${CMAKE_C_COMPILER}'")
message("  C++: '${CMAKE_CXX_COMPILER}'")
[project-examples]> rm -rf _builds
[project-examples]> cmake -H set-compiler -B _builds
Before 'project':    # project 선언 전에는 어떤 컴파일러도 설정되어 있지 않음
  C: ''
  C++: ''
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc    # 사용자 시스템에서 C 컴파일러를 찾음
-- Check for working C compiler: /usr/bin/cc -- works 
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++    # 사용자 시스템에서 C++ 컴파일러를 찾음
-- Check for working CXX compiler: /usr/bin/c++ -- works  
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
After 'project':
  C: '/usr/bin/cc'      <-- C 설정됨
  C++: '/usr/bin/c++'   <-- C++ 설정됨
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds

  • project 명령은 컴파일러뿐만 아니라 다른 도구에 대해서도 테스트를 하기에 가급적이면 검사는 project 선언 후에 수행해야 한다.

기본 컴파일 언어를 명시적으로 지정

cmake_minimum_required(VERSION 2.8)

message("Before 'project':")
message("  C: '${CMAKE_C_COMPILER}'")
message("  C++: '${CMAKE_CXX_COMPILER}'")

project(Foo C)       # 기본 컴파일 언어를 C 로 설정하였다

message("After 'project':")
message("  C: '${CMAKE_C_COMPILER}'")
message("  C++: '${CMAKE_CXX_COMPILER}'")
[project-examples]> rm -rf _builds
[project-examples]> cmake -H c-compiler -B _builds
Before 'project':
  C: ''
  C++: ''
-- The C compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
After 'project':
  C: '/usr/bin/cc'
  C++: ''               # 기본 컴파일 언어 설정하는 순간 설정하지 다른 컴파일 언어 설정은 비어있게됨
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds

컴파일러 확인 과정을 제외하기

  • CMakeLists.txt에서 기본 컴파일 언어를 지정할 필요가 없는 경우 project에 NONE 인자를 사용하여 컴파일러 확인 과정을 제외할 수 있다. 이러면 cmake 실행 시간이 빨라진다.(cmake 명령어를 테스트 하고 싶을때 좋음)
cmake_minimum_required(VERSION 2.8)
project(foo NONE) # 3.0, project(foo LANGUAGES NONE)
[project-examples]> rm -rf _builds
[project-examples]> cmake -H no-language -B _builds
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds

project 명령어는 *_{SOURCE,BINARY}_DIR 변수를 선언한다.

  • 버전 3.0부터 *VERSION{MAJOR,MINOR,PATCH,TWEAK} 변수를 추가로 선언한다.
# CMakeLists.txt : project 실행시 선언되는 변수를 확인

cmake_minimum_required(VERSION 3.0)

message("Before project:")
message("  Source: ${PROJECT_SOURCE_DIR}")
message("  Binary: ${PROJECT_BINARY_DIR}")
message("  Version: ${PROJECT_VERSION}")
message("  Version (alt): ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")

project(Foo VERSION 1.2.7)

message("After project:")
message("  Source: ${PROJECT_SOURCE_DIR}")
message("  Binary: ${PROJECT_BINARY_DIR}")
message("  Version: ${PROJECT_VERSION}")
message("  Version (alt): ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
[project-examples]> rm -rf _builds
[project-examples]> cmake -H variables -B _builds
Before project:								# project 실행 전 
  Source:                                   # 출력 없음 ...
  Binary:
  Version:
  Version (alt): ..
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
After project:								# project 실행 후 
  Source: /.../project-examples/variables   # source
  Binary: /.../project-examples/_builds     # binary
  Version: 1.2.7                            # version
  Version (alt): 1.2.7                      # version
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds  
  • foo{SOURCE,BINARY}_DIRS/ foo_VERSION{MINOR,MAJOR,PATCH} 와 같이 project 이름을 조합하여 사용 가능하다. 이는 project가 계층화 되어 있을때 유용하다
    • 서브 디렉터리의 CMakeLists에서 최상위 CMakeLists 소스 디렉터리를 확인할 수 있다.
# CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo)

message("From top level:")
message("  Source (general): ${PROJECT_SOURCE_DIR}") # project의 소스 디렉터리 출력
message("  Source (foo): ${foo_SOURCE_DIR}") # foo project의 소스 디렉터리 출력

add_subdirectory(boo) # boo project를 추가한다.
# boo 서브 디렉터리에 있는 CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(boo)

message("From subdirectory 'boo':")
message("  Source (general): ${PROJECT_SOURCE_DIR}") # project의 소스 디렉터리 출력
message("  Source (foo): ${foo_SOURCE_DIR}") # foo project의 소스 디렉터리 출력
message("  Source (boo): ${boo_SOURCE_DIR}") # boo project의 소스 디렉터리 출력
[project-examples]> rm -rf _builds
[project-examples]> cmake -H hierarchy -B _builds
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
From top level:                                                 # root cmake에서
  Source (general): /.../project-examples/hierarchy             # source
  Source (foo): /.../project-examples/hierarchy                 # foo
From subdirectory 'boo':                                        # boo cmake에서
  Source (general): /.../project-examples/hierarchy/boo         # source
  Source (foo): /.../project-examples/hierarchy                 # foo
  Source (boo): /.../project-examples/hierarchy/boo             # boo
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds

CMakeLists.txt에 project 명령을 사용하지 않으면 발생되는 일

  • CMakeLists.txt에서 project 명령을 사용하지 않는다고 하여도 project 명령이 수행되지 않는 것은 아니다.
  • project 명령이 없으면 다른 어떤 명령보다(심지어 cmake_minimum_required) 먼저 project 명령을 자동으로 실행 시킨다.
# CMakeLists.txt : project 명령이 없음

message("Before 'minimum'")
cmake_minimum_required(VERSION 2.8)
message("After 'minimum'")
CMake Warning (dev) in CMakeLists.txt:
  No project() command is present.  The top-level CMakeLists.txt file must # 경고
  contain a literal, direct call to the project() command.  Add a line of
  code such as

    project(ProjectName)

  near the top of the file, but after cmake_minimum_required().

  CMake is pretending there is a "project(Project)" command on the first
  line.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Detecting C compiler ABI info                     # project 명령이 실행됨 
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Before 'minimum'                 # project 명령이 cmake_minimum_required 보다 먼저 실행됨
After 'minimum'
-- Configuring done
-- Generating done
-- Build files have been written to: /home/red/cgold/build

project 실행시 툴체인 파일을 읽는다

cmake_minimum_required(VERSION 2.8)
message("Before 'project'")
project(Foo)
message("After 'project'")
# toolchain.cmake

message("Processing toolchain")
# toolchin 파일 지정하여 cmake 실행

[project-examples]> cmake -B _builds -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
Before 'project'     # project 명령 실행전
Processing toolchain     # toolchin 읽음
Processing toolchain     # toolchin 읽음
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Detecting C compiler ABI info
Processing toolchain    # toolchin 읽음 
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
Processing toolchain    # toolchin 읽음
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
After 'project'     <-- projectt 명령 실행 후
-- Configuring done
-- Generating done
-- Build files have been written to: /home/red/cgold/build

프로젝트 에서 생성하는 것들

  • 프로젝트에서는 반드시 하나의 바이너리만을 생성하지 않는다. 하나의 프로젝트에서 여러 바이너리를 만들 수 있다.
cmake_minimum_required(VERSION 2.8)
project(foo)

add_library(bar bar.cpp)
add_library(boo boo.cpp)

add_executable(foo foo.cpp)
# 링크는 왼쪽에서 오른쪽 순으로 처리한다. 그래서 bar 부터 먼저 처리
target_link_libraries(foo PUBLIC bar boo)
# 소스 파일

[bar.cpp]
  int bar() {
    return 0x42;
  }

[boo.cpp]  
  int boo() {
    return 123;
  }

[foo.cpp]
  int boo();

  int main() {
    return boo();
  }
# 빌드
red@DESKTOP-G15ND3V:~/cgold$ cmake -B _build
red@DESKTOP-G15ND3V:~/cgold$ cmake --build _build/
# tree
ed@DESKTOP-G15ND3V:~/cgold$ tree _build/
_build/
├── CMakeCache.txt
├── CMakeFiles
....
├── foo   <-- 실행 파일 생성
├── libbar.a    <-- bar 라이브러리
└── libboo.a    <-- boo 라이브러리

10 directories, 54 files
profile
mohadang

0개의 댓글