More Modern CMake - Common Problems and Solutions

 

일반적인 문제 및 해결 방법

Overview

  • 질문
    • 무엇이 잘못될 수 있나?
  • 목표
    • 몇 가지 일반적인 실수 식별하기
    • 일반적인 실수 피하기

이제 CMake 코드 및 빌드와 관련된 몇 가지 일반적인 문제를 살펴보자.

1: 낮은 최소 CMake 버전

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)

어떤 경우에는 이 숫자를 올리는 것만으로도 문제가 해결된다. 예를 들어 3.0 이하에서는 맥OS에서 링크할 때 잘못된 동작하는 경향이 있다.

해결책: 최소 버전을 높게 설정하거나 버전 범위 기능과 CMake 3.12 이상을 사용한다. 극도로 보수적인 프로젝트라도 선택해야 할 가장 낮은 버전은 3.4 이다; 해당 버전에서는 몇 가지 일반적인 이슈가 해결되었다.

2: 내부 폴더에서 빌드

CMake를 소스 디렉토리에서 빌드할 때 사용해서는 안되지만 실수하기 쉽다. 그리고 일단 발생하면, 소스 외부에서 다시 빌드하기 전에 디렉토리를 수동으로 정리해야 한다. 이 때문에 초기 실행 후 빌드 디렉토리에서 cmake .을 실행할 수 있지만, 소스 디렉토리에서 잊어버리고 실행할 경우를 대비하여 이 방법은 피하는 것이 좋다. 또한 CMakeLists.txt에 다음 체크를 추가할 수 있다:

### 소스 외부에서 빌드 필요
file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH)
if(EXISTS "${LOC_PATH}")
    message(FATAL_ERROR "You cannot build in a source directory (or any directory with "
                        "CMakeLists.txt file). Please make a build subdirectory. Feel free to "
                        "remove CMakeCache.txt and CMakeFiles.")
endif()

한 두 개의 생성된 파일을 피할 수는 없지만, 맨 위에 두면 생성된 대부분의 파일을 피할 수 있을 뿐만 아니라, 사용자(아마도 당신)에게 실수를 했다는 것을 즉시 알릴 수 있다.

3: 컴파일러 선택하기

CMake는 여러 컴파일러가 있는 시스템에서 잘못된 컴파일러를 선택할 수 있다. 처음 구성할 때 환경 변수 CCCXX를 사용하거나 CMake 변수 CMAKE_CXX_COMPILER 등을 사용할 수 있지만 - 첫 실행 시 컴파일러를 선택해야만 한다; 새로운 컴파일러를 얻기 위해 재구성만 할 수는 없다.

4: 경로의 공백이 있을 때

CMake의 목록 및 인자 시스템은 매우 조잡하다(매크로 언어다); 이를 유리하게 사용할 수 있지만 문제가 발생할 수 있다(이것이 Python의 f( args )처럼 CMake에 “splat” 연산자가 없는 이유이기도 하다). 항목이 여러 개일 경우 목록(고유 인자)이다:

set(VAR a b v)

VAR의 값은 세 개의 요소가 있는 목록이거나 문자열 “a;b;c”이다(두 항목은 정확히 동일하다). 따라서 이렇게 하면:

set(MY_DIR "/path/with spaces/")
target_include_directories(target PRIVATE ${MY_DIR})

아래 것과 동일하다.

target_include_directories(target PRIVATE /path/with spaces/)

두 개의 별도 인자이기 때문에, 원하는 바가 전혀 아니다. 해결책은 원래 값을 큰 따옴표로 묶는 것이다:

set(MY_DIR "/path/with spaces/")
target_include_directories(target PRIVATE "${MY_DIR}")

이제 공백을 포함한 단일 디렉터리가 올바르게 설정된다.

핵심사항

  • CMake 버전을 너무 낮게 설정했다.
  • 소스 안에서 빌드하면 안된다.
  • 컴파일러를 선택하는 방법.
  • 경로에서 공백을 사용하는 방법.