본문 바로가기
CMake

[CMake] Compiler and Linker 설정

by 별준 2021. 11. 6.

References

  • Professional CMake : A Practical Guide

Contents

  • Traget Properties
  • Directory Properties / Command
  • Compiler / Linker Variables

이전 게시글에서 빌드 타입과 이와 관련된 특정 컴파일러와 링커 선택에 관련하여 알아봤습니다.

2021.11.05 - [CMake] - [CMake] Build Type / Custom Build Type

 

이번에는 컴파일러와 링커 동작을 제어하는 기본적인 방법에 대해서 알아보겠습니다.

 

Target Properties

CMake의 속성 시스템에서 Traget 속성은 컴파일러와 링커 플래그를 제어하는 기본 메커니즘을 가지고 있습니다.

일부 속성은 임의의 플래그를 지정할 수 있는 기능을 제공하는 반면, 어떤 속성은 플랫폼 또는 컴파일의 차이를 추상화할 수 있는 특정 기능에 중점을 둡니다. 이 글에서는 일반적으로 사용되는 범용적인 속성에 대해서 알아보도록 하겠습니다.

 

Compiler Flags

컴파일러 플래그를 제어하기 위한 가장 기본적인 Target 속성은 다음과 같습니다. 각 속성은 리스트입니다.

  • INCLUDE_DIRECTORIES : 헤더 검색 경로로 사용할 디렉토리 리스트이며, 모든 항목들이 절대경로이어야 합니다. CMake는 각 경로에 컴파일러 플래그를 추가합니다(일반적으로 -I 또는 /I). Target이 생성되면, 이 Target 속성의 기본값은 같은 이름의 Directory 속성에서 가져와서 설정됩니다.
  • COMPILE_DEFINITIONS : 컴파일 커맨드 라인에서 설정되는 definitions(정의) 리스트입니다. VAR 또는 VAR=VALUE의 형태로 이루어지면, CMake는 사용되는 컴파일러에 대한 적절한 형식으로 변환합니다. 일반적으로 -DVAR 또는 /DVAR 의 형태입니다.
  • COMPILE_OPTIONS : 헤더 검색 경로나 심볼 정의가 아닌 모든 컴파일러 플래그는 이 속성을 통해 전달됩니다. Target이 생성될 때, 이 속성의 초기값은 같은 이름의 디렉토리 속성으로부터 설정됩니다. 
    (이와 비슷한 COMPILE_FLAGS가 있는데 이 속성은 deprecated 되었습니다.)

INCLUDE_DIRECTORIES와 COMPILE_DEFINITIONS 속성은 프로젝트에서 자주 설정하는 일반적인 특정 플래그를 처리하는데 매우 편리합니다. 그 이외의 모든 컴파일러 관련 플래그는 COMPILE_OPTIONS 속성으로 설정합니다.

 

위의 3개의 속성에는 각각 'INTERFACE_' 가 붙은 동일한 이름의 Target 속성이 있습니다.

(INTERFACE_INCLUDE_DIRECTORIES, INTERFACE_COMPILE_DEFINITIONS, INTERFACE_COMPILE_OPTIONS)

이런 인터페이스 속성은 이 Target을 링크하는 다른 Target에도 플래그를 적용해주는 역할을 합니다. 이 속성들은 target_compile_directories(definitions, options) 커맨드에서 PUBLIC / INTERFACE 키워드를 추가하여서 설정할 수 있습니다. INTERFACE가 붙은 속성들은 디렉토리 속성으로부터 초기화되지 않습니다. 이 속성들은 다른 타겟에 전달되어야하는 플래그들을 가지고 있어야 하므로 빈 값으로 초기화됩니다.

 

위의 모든 속성들은 Generator Expression도 지원합니다. 이는 COMPILE_OPTIONS 속성에 특히 유용한데, 특정 컴파일러에 대해서와 같은 특정 조건이 만족하는 경우에만 특정 플래그를 추가할 수 있기 때문입니다. 또 다른 일반적인 사용법으로 다른 Target의 경로를 가져와서 include path의 일부로 사용하는 방법이 있습니다.

 

만약 컴파일러 플래그를 소스 파일 수준으로 조작하고 싶은 경우, Target 속성으로는 충분하지 않습니다. 이런 경우에는 CMake에서 제공하는 소스 파일 속성인 COMPILE_DEFINITIONS, COMPILE_FLAGS, COMPILE_OPTIONS 를 설정해야합니다 (COMPILE_OPTIONS 소스 파일 속성은 CMake 3.11에서 추가됨). 이들은 개별 소스 파일에만 적용된다는 점을 제외하고는 각각 동일한 이름의 Target 속성과 유사합니다. 

 

Linker Flags

링커 플래그와 관련된 Target 속성은 컴파일러 플래그의 속성과 유사하지만 그 숫자는 더 적습니다.

  • LINK_LIBRARIES : 이 속성은 대상이 직접 링크해야하는 모든 라이브러리의 리스트입니다. Target이 생성될 때 처음에는 비어 있으며, Generator Expression을 지원합니다. 이 리스트의 항목들은 다음 중의 하나일 수 있습니다.
    1. 라이브러리의 경로(보통 절대 경로로 구체화됨)
    2. 경로가 없는 단순 라이브러리 이름.
    3. CMake의 라이브러리 Target 이름. CMake는 플랫폼에 적절하게 해당 Target 이름에 접두사(lib) 또는 접미사(.a, .so, .dll)을 붙여서 링커 커맨드를 생성할 때 이를 빌드된 라이브러리에 대한 경로로 변환함.
  • LINK_FLAGS : 이 속성에는 실행 파일, 공유 라이브러리 및 모듈 라이브러리인 Target에 대해 링커로 전달될 플래그가 리스트로 추가됩니다. 정적 라이브러리로 빌드되는 대상에 대해서는 무시됩니다. 이 속성은 링크할 다른 라이브러리를 지정하는 플래그가 아닌 일반 링커 플래그입니다. Generator Expression은 지원되지 않으며, Target이 생성될 때 이 속성은 빈 값으로 초기화됩니다.
  • STATIC_LIBRARY_FLAGS : 이는 LINK_FLAGS에 대응되는 것으로, 정적 라이브러리로 빌드되는 Target에만 적용됩니다.

컴파일러 속성과 달리 LINK_LIBRARIES에만 인터페이스 속성인 INTERFACE_LINK_LIBRARIES가 존재합니다. 일부 이전 버전을 사용하는 프로젝트에서는 INTERFACE_LINK_LIBARIES의 이전 버전인 LINK_INTERFACE_LIBRARIES 라는 속성을 가끔 확인할 수 있습니다. 이 속성은 CMake 2.8.12부터 더 이상 사용되지 않지만 필요한 경우 policy CPM0022를 사용하여 이전 속성에 대해 우선 순위를 부여할 수 있습니다.

또한, LINK_FLAGS 및 STATIC_LIBRARY_FLAGS 속성은 Generator Expression을 지원하지 않지만, 관련 빌드 configuration별 속성이 있습니다.

이 플래그들은 현재 빌드 중인 빌드 타입이 <CONFIG>(ex, DEBUG, RELEASE, ...)와 일치할 때 추가됩니다.

 

Target Property Command

위에서 설명한 Target 속성들은 보통 직접적으로 조작되지는 않습니다. CMake에서는 이 속성들을 조작하는 보다 편리하고 강력한 전용 함수들을 제공하는데, Target 간의 종속성 및 transitive behavior(전이 동작)을 명확하게 지정하도록 권장합니다. 

이전 글(2021.10.28 - [CMake] - [CMake] Tutorial (2) - Library 추가)에서 target_link_libraries() 커맨드가 링크 타입인 PRIVATE, PUBLIC, INTERFACE 키워드를 사용하여 대상 간 종속성을 나타낸다고 말씀드렸습니다.

이번에는 Target 속성과 관련하여, 이 키워드의 정확한 효과를 알아보도록 하겠습니다.

  • PRIVATE : PRIVATE 뒤에 나열되는 항목들은 targetName 자체의 동작에만 영향을 줍니다. 즉, INTERFACE_가 붙지 않는 LINK_LIBRARIES나 LINK_FLAGS, STATIC_LIBRARY_FLAGS 속성만 수정됩니다.
  • INTERFACE : 이 키워드는 PRIVATE를 보완하는 키워드로, INTERFACE 키워드 뒤에 위치하는 항목은 targetName에 링크된 Target에만 영향을 미칩니다. 즉, targetName의 INTERFACE_... 속성만 수정됩니다. (ex, INTERFACE_LINK_LIBRARIES)
  • PUBLIC : PUBLIC은 PRIVATE와 INTERFACE의 효과를 합친 것과 동일합니다.

다른 target_...() 커맨드의 PRIVATE/INTERFACE/PUBLIC 키워드는 위와 같은 패턴을 따르고, 동일한 방식으로 이 키워드를 적용합니다.

 

target_include_directories() 커맨드는 INCLUDE_DIRECTORIES 및 INTERFACE_INCLUDE_DIRECTORIES 속성에 헤더 검색 경로를 추가합니다. PRIVATE 뒤에 오는 디렉토리는 INCLUDE_DIRECTORIES 속성에 추가되고, INTERFACE 키워드 뒤에 오는 디렉토리는 INTERFACE_INCLUDE_DIRECTORIES 속성에 추가됩니다. PUBLIC 키워드에 오는 디렉토리는 두 속성에 모두 추가됩니다.

 

일반적으로 target_include_directories()가 호출될 때마다 지정된 디렉토리가 기존 Target 속성 값 뒤에 추가됩니다. 이는 여러 경로들을 자연스럽게 진행하면서 추가할 수 있습니다. 필요한 경우 BEFORE 키워드를 사용하여 target 속성의 기존 내용에 앞에 나열된 디렉토리를 덧붙일 수 있습니다.

 

SYSTEM 키워드가 지정되면 컴파일러는 일부 플랫폼에서 나열된 디렉토리를 시스템 include path로 처리합니다. 이로 인해서 특정 컴파일러 경로를 스킵하거나 파일 종속성을 처리하는 방법이 변경될 수 있습니다. 또한, 컴파일러가 헤더 경로를 검색하는 순서에 영향을 미칠 수 있습니다. 

 

target_include_directories() 커맨드를 사용하면 상대경로를 입력해도 자동으로 절대경로로 변환하여 속성에 추가하므로, 직접 속성을 설정하는 것보다 더 편리합니다.

 

target_compile_definitions() 커맨드에서 각 item은 VAR 또는 VAR=VALUE의 형태입니다. 

PRIVATE 키워드는 각 항목을 COMPILE_DEFINITIONS 속성에 추가하고, INTERFACE 키워드는 INTERFACE_COMPILE_DEFINITIONS 속성에 추가하고, PUBLIC은 항상 두 속성에 모두 추가합니다. 이 속성에 대해서 Generator Expression을 사용할 수 있는데, 일반적으로 빌드와 인스톨 상황을 다르게 처리할 필요는 없습니다.

 

target_compile_options() 커맨드 또한 간단합니다. PRIVATE는 각 item을 COMPILE_OPTIONS 속성에 추가하고, INTERFACE 키워드는 INTERFACE_COMPILE_OPTIONS 속성에 추가하고, PUBLIC은 두 속성 모두에 추가합니다. target_include_directories() 와 마찬가지로 BEFORE 키워드가 제공되는데, 기본적으로 기존 Target 속성 값에 뒤에 추가되지만, BEFORE 키워드를 사용하면 기존 속성 값 앞 쪽에 추가할 수 있습니다.


Directory Properties And Commands

CMake 3.0 이상에서는 컴파일러 및 링커 플래그를 설정할 때, Target 속성이 서로 링크되는 대상과 상호작용하도록 정의하는 방식이 선호됩니다. 이전 버전의 CMake에서는 Target 속성이 아닌 디렉토리 수준에서 속성이 지정되는 경우가 많았습니다. 이러한 디렉토리 수준의 속성과 커맨드는 Target 수준의 속성과 커맨드에서 보여주는 일관성이 부족합니다. 가능하면 프로젝트에서 일반적으로 디렉토리 수준의 속성과 커맨드를 피해야 하지만, 아직 많은 프로젝트에서 사용되고 있으므로 최소한의 디렉토리 수준의 속성과 커맨드는 알고 있어야 합니다.

 

include_directories

간단하게, include_directories() 커맨드는 현재 디렉토리 범위(하위 디렉토리 포함)에서 생성된 Target에 헤더 검색 경로를 추가합니다. 기본적으로 추가되는 경로들은 기존 디렉토리 목록 뒤에 추가되지만, CMAKE_INCLUDE_DIRECTORIES_BEFORE 변수를 ON으로 설정하여 디렉토리 목록의 기본값을 변경할 수 있습니다.

또한, BEFORE / AFTER 옵션을 사용하여 기존 값의 앞이나 뒤에 추가하도록 설정할 수 있습니다. SYSTEM 키워드는 target_include_directories()의 경우와 동일합니다.

 

include_directories()로 설정되는 경로는 상대경로, 절대경로 둘 다 허용됩니다. 상대경로는 현재 디렉토리 기준이며, 자동으로 절대경로로 변경됩니다. 경로에는 genrator expression 또한 허용됩니다.

 

사실 include_directoreis()가 실제로 하는 일은 위의 설명보다는 조금 더 복잡합니다.

  • include_directories()에 나열된 경로는 현재 CMakeLists.txt 파일의 INCLUDE_DIRECTORIES 속성에 추가됩니다. 이는 현재 디렉토리와 그 하위 디렉토리에서 생성된 모든 Target이 INCLUDE_DIRECTORIES 속성에 추가되는 디렉토리를 include 합니다.
  • 현재 디렉토리와 그 하위 디렉토리에서 생성된 모든 Target에는 INCLUDE_DIRECTORIES 속성에 추가된 경로가 추가되는데, 이는 Target이 include_directories()를 호출하기 전에 생성된 경우도 마찬가지 입니다. 

두 번째 기능 때문에 혼란이 발생할 수 있는데, 이 상황을 방지하기 위해 include_directories() 커맨드를 사용해야하는 경우 Target이 생성되거나 include() 또는 add_subdirectory()를 호출하기 전에 먼저 include_directories() 커맨드를 사용하는 것이 추천됩니다.

 

add_definitions / remove_definitions

add_defintions() 와 remove_definitions() 커맨드는 COMPILE_DEFINITIONS 디렉토리 속성의 항목을 추가하거나 제거하는 역할을 합니다. 각 항목은 대부분의 컴파일러에서 사용되는 플래그 형식인 -D 또는 /D로 시작해야 합니다. 이 플래그 접두사는 definition이 COMPILE_DEFINITIONS 디렉토리 속성에 추가되기 전에 CMake에 의해서 제거되므로 프로젝트가 빌드되는 컴파일러나 플랫폼에 관계없이 어떤 접두사를 사용해도 무관합니다.

 

include_directories()와 마찬가지로 위 두 커맨드가 호출 전에 생성된 Target이더라도 현재 디렉토리에서 생성된 Target이라면 모두 영향을 받습니다. 대신, include_directories()와는 달리 하위 디렉토리에서 생성된 Target은 add_definitions()나 remove_definitions()가 호출된 후에 생성된 Target에만 적용됩니다.

 

위 방법들이 권장되지는 않지만, 이 커맨드들을 통해서 컴파일러 플래그나 definition을 지정할 수 있습니다. 만약 CMake가 compiler define처럼 보이는 항목을 인식하지 못한다면, 해당 항목은 수정되지 않은 상태로 COMPILE_OPTIONS 디렉토리 속성에 추가됩니다. 이 커맨드는 레거시로 남아있는데, 사용을 하지 않는 것을 권장합니다.

 

이 두 커맨드들 또한, generator expression을 지원하는데, 몇 가지 주의사항이 있습니다. 

하나는 generator expression은 definition의 이름이 아닌 값 부분에만 사용해야 합니다 ("-DVAR=VALUE"에서 VALUE에만 사용해야함). 이는 CMake가 각 항목을 컴파일러 definition인지 아닌지 체크하는 것에 관련이 있습니다. 또한 이 커맨드들은 오직 디렉토리 속성만 수정하여 COMPILE_DEFINITIONS Target 속성에는 영향을 미치지 않습니다.

 

add_definitions() 커맨드에는 여러가지 단점이 존재하는데, 각 항목에 -D나 /D를 붙여야 합니다. 이 접두사를 생략하면 커맨드는 해당 항목을 definition이 아닌 일반 옵션으로 취급합니다. 따라서 커맨드 이름과 일치하는 동작도 아닙니다. 또한 generator expression을 VALUE에만 적용되는 것도 접두사 때문입니다. 이러한 이유들로 CMake 3.12에서 add_compile_definitions()가 도입되었습니다.

 

add_compile_definitions

add_compile_definitions() 커맨드는 각 항목에 접두사가 붙이지 않고 definition을 추가할 수 있으며, generator expression도 VALUE에 국한되지 않습니다. 이 커맨드는 target_compile_definitions() 커맨드와 동일하게 처리되지만, 디렉토리 속성으로 여전히 동일한 디렉토리 범위에서 생성된 모든 Target에 영향을 미칩니다. 이는 커맨드가 설정하는 COMPILE_DEFINITIONS가 디렉토리 속성이기 때문입니다.

 

add_compile_options

add_compile_options() 커맨드는 임의의 컴파일러 옵션을 제공하는 데 사용됩니다. include_directories(), add_definitions(), remove_definitions() 및 add_compile_definitions() 커맨드와는 달리 그 동작은 매우 간단합니다. add_compile_options() 에 주어진 각 옵션은 COMPILE_OPTIONS라는 디렉토리 속성에 추가됩니다. 이후에 현재 디렉토리 및 하위 디렉토리에서 생성된 모든 Target은 Target의 COMPILE_OPTIONS 속성에 이 속성을 상속받습니다. 이 커맨드가 호출되기 전에 생성된 Target은 영향을 받지 않습니다. generator expression 또한 지원합니다.

 

link_libraries / link_directories

초기 CMake 버전에서 위 두 커맨드(link_libraries(), link_directories())는 라이브러리를 다른 Target에 링크하는 기본 커맨드였습니다. 커맨드가 호출된 후 현재 디렉토리와 그 하위 디렉토리에서 생성된 모든 Target에 영향을 주지만 기존 Target(호출 전에 설정된)은 영향을 받지 않습니다.

 

link_libraries() 커맨드에 지정된 항목은 CMake Target, 라이브러리 이름, 라이브러리에 대한 전체 경로 또는 링커 플래그일 수 있습니다. debug 키워드를 항목 앞에 사용하여 디버그 빌드에만 적용하거나 optimized 키워드를 사용하여 디버그를 제외한 모든 빌드 타입에 적용하도록 할 수 있습니다. 모든 빌드 타입에 적용하려면 general 키워드가 올 수 있지만, general이 기본값입니다.

주의할 점은 이 세 가지 키워드는 다음 키워드까지의 모든 항목이 아닌 단일 항목에만 영향을 줍니다.

 

link_directories()에 추가된 디렉토리는 CMake에 링크할 bare 라이브러리의 이름이 지정될 때만 효과가 있습니다. CMake는 제공된 디렉토리를 링커 커맨드에 추가하고 링커가 자체적으로 이러한 라이브러리를 찾도록 합니다. 만약 상대경로가 주어지면 현재 소스 디렉토리에 상대적인 것으로 취급합니다. 일반적으로 전체경로 또는 CMake Target 이름 사용을 권장합니다. 게다가 link_directories() 커맨드에 의해 링커 검색 디렉토리가 추가되면 필요한 경우 해당 경로를 제거할 방법이 없습니다. 이러한 이유로 링커 검색 디렉토리 추가는 가능한 피해야합니다.


Compiler and Linker Variables

CMake는 다양한 디렉토리, 타겟, 소스 파일 속성에서 제공하는 컴파일 및 링커 플래그에 추가할 수 있는 몇 가지 변수들을 제공합니다. 일반적으로 사용자가 쉽게 확인하고 수정할 수 있도록 캐시 변수로 설정되어 있지만, CMakeLists.txt에서 일반적인 CMake 변수로 설정할 수도 있습니다. CMake는 빌드 디렉토리에서 처음 실행할 때 이러한 캐시 변수들의 값에 적절한 기본값을 설정합니다.

 

CMAKE_<LANG>_FLAGS / CMAKE_<LANG>_FLAGS_<CONFIG>

컴파일러 플래그에 직접 영향을 미치는 기본 변수의 형식은 다음과 같습니다.

이 변수들에서 <LANG>은 컴파일되는 언어에 해당하며 일반적으로 C, CXX, Fortran, Swift 등 입니다. <CONFIG>는 DEBUG, RELEASE, RELWITHDEBINFO 또는 MINSIZEREL과 같은 빌드 타입 중 하나에 해당하는 대문자 문자열입니다. CMAKE_<LANG>_FLAGS는 빈 CMAKE_BUILD_TYPE을 가지는 single configuration generator를 포함하여 모든 빌드 타입에 적용되는 반면, CMAKE_<LANG>_FLAGS_<CONFIG>는 지정된 빌드 타입에만 적용됩니다. 따라서 디버그로 빌드되는 C++ 파일에는 CMAKE_CXX_FLAGS 및 CMAKE_CXX_FLAGS_DEBUG, 두 개의 컴파일러 플래그가 있습니다.

 

간단하게 설명하자면, 처음 호출되는 project() 커맨드에서는 캐시 변수가 아직 존재하지 않는 경우 이를 위한 캐시 변수를 생성합니다. 예를 들어, C++ 언어에서 기본적으로 설정되는 값은 다음과 같습니다.

 

링커 플래그의 처리도 유사합니다. 링커 플래그는 다음 변수들에 의해 제어됩니다.

  • CMAKE_<TARGETTYPE>_LINKER_FLAGS
  • CMAKE_<TARGETTYPE>_LINKER_FLAGS_<CONFIG>

이 변수들은 특정 타입의 타겟에만 해당되며, <TARGETTYPE>은 다음 중의 하나이어야 합니다.

  • EXE : add_excutable() 로 생성된 타겟
  • SHARED : add_library(name SHARED ...) 생성되거나 또는 SHARED 키워드가 생략되었지만, BUILD_SHARED_LIBS가 true로 설정되어서 생성된 타겟
  • STATIC : add_library(name STATIC ...) 또는 STATIC 키워드가 생략되고 BUILD_SHARED_LIBS가 false거나 정의되지 않은 채로 생성된 타겟
  • MODULE : add_library(name MODULE) 로 생성된 타겟

컴파일러 플래그와 마찬가지로 CMAKE_<TARGETTYPE>_LINKER_FLAGS는 build configuration을 링킹할 때 사용되는 반면, CMAKE_<TARGETTYPE>_LINKER_FLAGS_<CONFIG>는 해당 CONFIG에만 추가됩니다. 

 

CMake 튜토리얼이나 예제코드들은 이 변수들을 자주 사용하여 컴파일러 및 링커 플래그를 설정합니다. 이는 CMake 3.0 이전에는 일반적인 방법이었으나, CMake 3.0 이상에서는 타겟 중심 모델로 중심이 이동되면서 이러한 예시들은 더 이상 좋은 모델이라고는 할 수 없습니다. 이러한 예시들은 종종 실수를 유발하기도 합니다.

 

몇 가지 예시들을 살펴보고 마무리하도록 하겠습니다 !

 

- 컴파일러/링커 변수가 리스트가 아닌 하나의 문자열인 경우

 

- 캐시 및 비-캐시 변수 구별

 

- 플래그를 교체하는 것보다 추가하는 것을 선호해야함

위의 경우 캐시 변수에 저장되어 있는 값을 모조리 지워버릴 수 있습니다. 가능한 경우 기존 값에 플래그를 추가하는 것을 선호해야 합니다.

 

 

- 언제 변수값이 사용되는지에 대한 이해

위의 경우에 strictReq 라이브러리는 -Wall -Werror 플래그로 빌드되지 않습니다. 직관적으로는 add_library() 호출 시 CMAKE_CXX_FLAGS 변수 값이 CMake가 사용한다라고 예상할 수 있지만, 실제로 사용되는 CMAKE_CXX_FLAGS의 값은 해당 디렉토리 범위가 끝났을 때의 값입니다. 즉, 중요한 것은 해당 디렉토리의 CMakeLists.txt 파일 끝에서 CMAKE_CXX_FLAGS의 값입니다. 위와 같은 경우는 무의식적으로 다양항 상황에서 예상치 못한 결과를 초래할 수 있습니다.

 

위와 같은 상황을 피하는 주요 방법 중 하나는 컴파일러와 링커 변수가 생성된 모든 타겟에 즉시 적용되는 것처럼 처리하는 것입니다. 문제 발생할 수 있는 주요 함정은 타겟이 생성되고, 컴파일러 또는 링커 변수를 수정한 후에 include()나 add_subdirectory()가 사용되는 경우입니다. 컴파일러 및 링커 변수가 지연되어 적용되는 특성으로 인해 문제가 발생할 수 있으므로, 이러한 상황을 최소화하기 위해 프로젝트의 최상위 CMakeLists.txt 파일의 초기에서만 수정하는 것을 권장합니다.

'CMake' 카테고리의 다른 글

[CMake] Target Types  (0) 2021.11.14
[CMake] Language Requirements  (0) 2021.11.09
[CMake] Build Type / Custom Build Type  (0) 2021.11.05
[CMake] Policy  (0) 2021.11.04
[CMake] Modules  (6) 2021.11.04

댓글