[모던 CMake] C++ 표준 버전 설정 방법 비교

모던 CMake를 활용하여 효율적인 C++ 프로젝트 빌드 시스템을 구축하는 방법을 계속해서 알아보겠습니다. 이번 글에서는 C++ 표준 버전 설정에 대한 다양한 방법을 소개하고, 각 방법의 차이점과 장단점을 설명하겠습니다.

C++ 표준 버전 설정의 중요성

C++ 언어는 C++11, C++14, C++17, C++20 등 지속적으로 새로운 표준이 발표되고 있습니다. 프로젝트에서 사용하는 C++ 표준 버전을 명시적으로 설정하면 다음과 같은 이점이 있습니다:

  • 코드 호환성 보장: 팀원 간 동일한 언어 기능을 사용하여 일관성 있는 코드베이스를 유지할 수 있습니다.
  • 컴파일러 최적화: 컴파일러가 표준에 맞는 최적화를 적용하여 성능 향상을 기대할 수 있습니다.
  • 미래 대비: 최신 표준을 사용하여 최신 언어 기능과 라이브러리를 활용할 수 있습니다.

1. 전통적인 방법

초기에는 CMake에서 C++ 표준을 설정하기 위해 컴파일러 플래그를 직접 지정하는 방법을 사용했습니다.

1.1. add_definitions() 사용

add_definitions(-std=c++11)

장점

  • 간단함: 간단하게 컴파일러 플래그를 추가할 수 있습니다.
  • 즉각적인 적용: 모든 타겟에 플래그가 적용됩니다.

단점

  • 유연성 부족: 특정 타겟에만 적용하기 어렵습니다.
  • 언어별 설정 어려움: C와 C++의 컴파일 옵션을 구분하기 어렵습니다.
  • 플랫폼 종속성: 컴파일러에 따라 플래그가 다를 수 있습니다.

1.2. set(CMAKE_CXX_FLAGS ...) 사용

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

장점

  • 전역 적용: 프로젝트의 모든 C++ 파일에 플래그가 적용됩니다.

단점

  • 유연성 부족: 특정 타겟에만 적용하기 어렵습니다.
  • 누적 관리 어려움: 여러 곳에서 CMAKE_CXX_FLAGS를 수정하면 추적이 어렵습니다.
  • 컴파일러 호환성 문제: 다른 컴파일러나 언어에 영향을 줄 수 있습니다.

2. 모던 CMake 방법

모던 CMake에서는 타겟 기반의 설정을 통해 C++ 표준을 보다 명확하고 유연하게 설정할 수 있습니다.

2.1. CMAKE_CXX_STANDARD와 CMAKE_CXX_STANDARD_REQUIRED 사용

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

장점

  • 간편함: 전역 변수로 C++ 표준을 설정할 수 있습니다.
  • 컴파일러 독립적: CMake가 컴파일러에 맞는 플래그를 자동으로 설정합니다.
  • 가독성 향상: 코드에서 명시적으로 표준 버전을 확인할 수 있습니다.

단점

  • 타겟별 설정 어려움: 모든 타겟에 동일한 표준이 적용됩니다.
  • 다중 프로젝트 관리 어려움: 서브 디렉토리에서 다른 표준을 사용하기 어렵습니다.

2.2. 타겟 프로퍼티 CXX_STANDARD 사용

add_executable(MyApp main.cpp)
set_target_properties(MyApp PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)

사용 가능한 값들은 여기에서 확인할 수 있다.

장점

  • 타겟별 설정 가능: 각 타겟마다 다른 C++ 표준을 설정할 수 있습니다.
  • 유연성 증가: 라이브러리와 실행 파일에 다른 표준 적용이 가능합니다.

단점

  • 코드 중복: 여러 타겟에 동일한 설정을 반복해야 할 수 있습니다.
  • 복잡성 증가: 타겟 수가 많아질 경우 관리가 어려울 수 있습니다.

2.3. target_compile_features() 사용

add_executable(MyApp main.cpp)
target_compile_features(MyApp PRIVATE cxx_std_17)

사용 가능한 값들은 여기에서 확인할 수 있다.

장점

  • 모던 CMake 방식: 필요한 C++ 표준 기능을 선언적으로 지정합니다.
  • 컴파일러 자동 설정: CMake가 컴파일러에 맞는 플래그를 자동으로 설정합니다.
  • 인터페이스 전파: PUBLIC 또는 INTERFACE로 설정하면 의존 타겟에 표준이 전파됩니다.

단점

  • 학습 곡선: 기존 방식에 익숙한 개발자에게는 다소 생소할 수 있습니다.
  • 명시적 버전 확인 필요: 코드에서 설정한 C++ 표준 버전을 한눈에 파악하기 어려울 수 있습니다.

방법별 비교 및 장단점

방법  장점  단점
add_definitions(-std=c++11) 간단하고 즉각적인 적용 유연성 부족, 언어별 구분 어려움, 플랫폼 종속성
set(CMAKE_CXX_FLAGS ...) 전역 적용 유연성 부족, 관리 어려움, 컴파일러 호환성 문제
CMAKE_CXX_STANDARD 설정 간편하고 컴파일러 독립적 타겟별 설정 어려움, 다중 프로젝트 관리 어려움
set_target_properties() 사용 타겟별 설정 가능 코드 중복 가능성, 복잡성 증가
target_compile_features() 사용 모던 방식, 선언적 설정, 인터페이스 전파 가능 학습 필요, 명시적 버전 확인 어려움

추천 방법 및 실전 예제

모던 CMake에서는 target_compile_features()를 사용하는 것을 권장합니다. 이를 통해 타겟별로 필요한 C++ 표준 기능을 선언하고, 컴파일러에 맞는 설정을 자동으로 적용할 수 있습니다.

예제: target_compile_features() 사용

CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(MyProject)

add_executable(MyApp main.cpp)

target_compile_features(MyApp PRIVATE cxx_std_17)

설명

  • CMake 최소 요구 버전을 3.8로 설정합니다. (target_compile_features는 CMake 3.8 이상에서 안정적으로 지원)
  • MyApp 타겟에 cxx_std_17 기능을 PRIVATE 범위로 설정합니다.
  • CMake는 컴파일러에 맞는 플래그를 자동으로 추가합니다. 예를 들어, GCC의 경우 -std=gnu++17을 추가합니다.

예제: 라이브러리와 실행 파일에 적용

add_library(MyLib mylib.cpp)
target_compile_features(MyLib PUBLIC cxx_std_17)

add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE MyLib)
  • MyLib 라이브러리에 cxx_std_17을 PUBLIC 범위로 설정하여, 이를 링크하는 MyApp에도 표준이 전파됩니다.
  • MyApp은 별도로 표준을 설정할 필요가 없습니다.

주의사항

  • 컴파일러 최소 버전 확인: 프로젝트에서 사용하는 C++ 표준을 지원하는 컴파일러 버전을 확인해야 합니다.
  • CMake 최소 버전 설정: 사용하려는 CMake 기능이 지원되는 최소 버전을 cmake_minimum_required()로 지정해야 합니다.
  • 플랫폼 호환성 고려: Windows, macOS, Linux 등 다양한 플랫폼에서의 컴파일러 동작을 테스트해야 합니다.

결론

이번 글에서는 C++ 표준 버전을 설정하는 다양한 방법을 소개하고, 각 방법의 차이점과 장단점을 살펴보았습니다. 모던 CMake에서는 target_compile_features()를 사용하는 것이 권장되며, 이를 통해 타겟별로 유연하고 선언적으로 C++ 표준을 관리할 수 있습니다.

반응형