사용자 정의 모듈이란?

사용자 정의 모듈은 CMake에서 기본 제공하는 모듈 외에 사용자가 직접 작성하여 추가적인 기능을 제공하는 모듈이다. 예를 들어, 특정 라이브러리의 경로를 자동으로 찾거나, 프로젝트에 맞춤형 명령어를 추가하는 등의 작업을 할 수 있다. 사용자 정의 모듈은 주로 .cmake 확장자를 가지며, CMake 프로젝트에서 필요에 따라 포함하여 사용한다.

사용자 정의 모듈 작성의 기본 구조

사용자 정의 모듈을 작성할 때에는 다음과 같은 기본 구조를 따른다.


if(NOT DEFINED MyCustomModule_LOADED)
  set(MyCustomModule_LOADED TRUE)

  # 모듈의 주요 내용
  function(MyFunction arg1 arg2)
    # 함수의 구현 내용
    message(STATUS "Argument 1: ${arg1}")
    message(STATUS "Argument 2: ${arg2}")
  endfunction()

  # 필요 시 다른 함수나 변수 정의

endif()

이러한 가드 조건을 사용함으로써, 모듈이 여러 번 포함되더라도 중복 정의로 인한 오류를 방지할 수 있다.

사용자 정의 모듈 사용하기

사용자 정의 모듈을 사용하려면 CMakeLists.txt 파일에 include() 명령어를 사용하여 모듈을 포함한다.


cmake_minimum_required(VERSION 3.10)
project(MyProject)

include(MyCustomModule.cmake)

MyFunction("Hello" "World")

이렇게 하면, MyCustomModule.cmake 파일에 정의된 모든 함수와 변수를 사용할 수 있다.

사용자 정의 모듈의 예제: 라이브러리 찾기

사용자 정의 모듈을 사용하여 특정 라이브러리를 찾는 방법을 예로 들어보자.


if(NOT DEFINED MyLibrary_FOUND)
  set(MyLibrary_FOUND FALSE)

  find_path(MyLibrary_INCLUDE_DIR mylibrary.h PATHS /usr/local/include /opt/include)
  find_library(MyLibrary_LIBRARIES NAMES mylibrary PATHS /usr/local/lib /opt/lib)

  if(MyLibrary_INCLUDE_DIR AND MyLibrary_LIBRARIES)
    set(MyLibrary_FOUND TRUE)
    set(MyLibrary_INCLUDE_DIRS ${MyLibrary_INCLUDE_DIR})
    set(MyLibrary_LIBRARIES ${MyLibrary_LIBRARIES})
  endif()

  if(MyLibrary_FOUND)
    message(STATUS "MyLibrary found")
  else()
    message(FATAL_ERROR "MyLibrary not found")
  endif()
endif()

위의 모듈은 mylibrary.h 헤더 파일과 mylibrary 라이브러리를 찾고, 찾으면 관련 변수를 설정한다. 이 모듈을 프로젝트에 포함시키면, 해당 라이브러리가 존재하는지 쉽게 확인하고, 필요한 경우 빌드 프로세스에서 사용하도록 설정할 수 있다.

함수 및 매크로의 활용

CMake에서 함수와 매크로는 중요한 역할을 한다. 함수는 로컬 스코프를 가지며, 호출된 위치에서만 영향을 미친다. 반면에, 매크로는 전역 스코프를 가지며, 호출된 위치뿐만 아니라 전체 CMake 파일에서 영향을 미친다.

function(MyFunction arg)
  message(STATUS "This is a function. Argument: ${arg}")
endfunction()

macro(MyMacro arg)
  message(STATUS "This is a macro. Argument: ${arg}")
endmacro()

함수는 주로 로컬 변수를 사용해야 하는 경우에 적합하며, 매크로는 전역 변수를 수정하거나 다수의 파일에서 재사용할 필요가 있는 경우에 유용하다.

모듈의 재사용성 극대화

모듈을 작성할 때는 최대한 재사용성을 염두에 두어야 한다. 이를 위해 입력 인자를 사용하여 모듈의 동작을 유연하게 만들고, 하드코딩을 피해야 한다. 또한, 모듈이 다른 프로젝트에서도 사용될 수 있도록 경로와 같은 환경 변수에 의존하지 않도록 설계하는 것이 좋다.

CMake의 메시지 및 오류 처리

CMake에서는 message() 명령어를 사용하여 정보를 출력하거나, 경고, 오류를 처리할 수 있다.

message(STATUS "This is a status message.")
message(WARNING "This is a warning message.")
message(FATAL_ERROR "This is a fatal error message.")

STATUS는 일반적인 정보를 출력할 때 사용되며, WARNING은 경고 메시지, FATAL_ERROR는 치명적인 오류 발생 시 사용된다. 오류 메시지를 출력하면 CMake는 즉시 종료된다.

모듈 내의 변수 스코프 관리

CMake에서 변수의 스코프는 중요하다. 함수 내에서 선언된 변수는 로컬 스코프를 가지며, 함수 외부에서는 접근할 수 없다. 반면, 전역 변수는 모든 CMake 파일에서 접근할 수 있다. set() 명령어를 사용할 때 PARENT_SCOPE 옵션을 사용하여 상위 스코프에서 변수를 설정할 수 있다.

function(MyFunction)
  set(MY_VARIABLE "Hello" PARENT_SCOPE)
endfunction()

이와 같이 설정된 변수는 함수 외부에서도 접근이 가능한다.


관련 자료: - CMake 공식 문서: https://cmake.org/documentation/ - Mastering CMake by Ken Martin and Bill Hoffman - CMake Tutorial: https://cmake.org/cmake/help/latest/guide/tutorial/index.html