CMake는 어떻게 사용됩니까? [닫은]


95

초보자로서 CMake에 대한 유용한 정보를 얻는 것은 악명이 높습니다. 지금까지 매우 기본적인 프로젝트 나 다른 프로젝트를 설정하는 방법에 대한 몇 가지 자습서를 보았습니다. 그러나 이것들 중 어느 것도 그 안에 표시된 모든 것의 추론을 설명하지 않으며 항상 많은 구멍을 채울 수 있습니다.

CMakeLists에서 CMake를 호출하는 것은 무엇을 의미 합니까? 빌드 트리 당 한 번 호출해야합니까? 모두 동일한 소스의 동일한 CMakeLists.txt 파일을 사용하는 경우 각 빌드에 대해 다른 설정을 사용하려면 어떻게해야합니까? 각 하위 디렉토리에 자체 CMakeLists 파일이 필요한 이유는 무엇입니까? 프로젝트의 루트가 아닌 CMakeLists.txt에서 CMake를 사용하는 것이 합리적입니까? 그렇다면 어떤 경우에? 자체 하위 디렉터리의 CMakeLists 파일에서 실행 파일 또는 라이브러리를 빌드하는 방법을 지정하는 방법과 모든 소스의 루트에있는 CMakeLists 파일에서 수행하는 방법의 차이점은 무엇입니까? -GCMake를 호출 할 때 옵션을 변경하여 Eclipse 용 프로젝트와 Visual Studio 용 프로젝트를 만들 수 있나요 ? 그것이 어떻게 사용 되는가?

지금까지 본 튜토리얼, 문서 페이지 또는 질문 / 답변 중 어느 것도 CMake 사용 방법을 이해하는 데 유용한 통찰력을 제공하지 않습니다. 예제는 완전하지 않습니다. 어떤 튜토리얼을 읽어도 중요한 것을 놓치고있는 것 같습니다.

저와 같은 CMake 초보자는 이것을 명시 적으로 묻지 않는 많은 질문이 있지만, 이는 초보자로서 CMake를 어떻게 처리해야하는지 또는 무엇을 만들어야하는지 전혀 모른다는 사실을 분명히합니다.


8
대신 블로그 게시물을 작성해야 할 수도 있습니다.
steveire 2014 년

2
나는 "너무 광범위하게"찬성 투표를하고 싶은데 ... 이것은 CMake에 대한 개인적인 에세이 같은 느낌이 스택 오버플로에 적합합니다. 이 모든 질문을 별도의 질문에 넣지 않은 이유는 무엇입니까? 그리고 얼마나 많은 사람들, 예로부터 질문 + 응답 다른 stackoverflow.com/q/20884380/417197 , stackoverflow.com/q/4745996/417197 , stackoverflow.com/q/4506193/417197은 ?
André

13
@Andre 왜이 질문 이냐 : 나는 CMake를 이해하기 위해 일주일을 보냈고 내가 찾은 튜토리얼이 완성되지 않았습니다. 지적한 링크는 좋지만 내부에 CMakeLists가 포함 된 프로젝트가 포함되어 CMake를 찾은 사람에게는 CMake가 작동하는 방식에 대해 자세히 설명하지 않습니다. 저는 솔직히 CMake를 배우기 시작했을 때 제 시간에 제 시간에 되돌릴 수 있기를 바라는 답을 작성하려고 노력했습니다. 그리고 하위 질문은 제가 실제로 그 의심을 가지지 않기 위해 알아야 할 것이 무엇인지 물어 보려고한다는 것을 보여주기위한 것입니다. 올바른 질문을하는 것은 어렵습니다.
leinaD_natipaC

2
대답은 아니지만 jaws.rootdirectory.de를 보도록 초대합니다 . CMake 문서 (및 허용 된 답변 ...)는 사용자가 할 수있는 작업 에 대한 작은 스 니펫을 많이 보여 주지만 , 전체적으로 주석을 포함하여 기본 설정을 작성했습니다. IMHO는 CMake (및 CTest 및 CPack 및 CDash ...)가 할 수있는 작업을 보여줍니다. 기본적으로 구축되며 프로젝트의 요구에 맞게 쉽게 조정 / 확장 할 수 있습니다.
DevSolar 2011

9
요즘 그런 질문이 닫히는 것은 부끄러운 일입니다. 답변과 같은 자습서가 필요하지만 문서화되지 않은 주제 (또 다른 예는 Torch7 C api)에 관한 광범위한 질문과 연구 수준의 질문은 계속 열려 있어야한다고 생각합니다. 그것들은 사이트를 괴롭히는 전형적인 "야, 장난감 프로젝트를 만들 때 세그 폴트가 있습니다"보다 훨씬 더 흥미 롭습니다.
Ash

답변:


137

CMake는 무엇입니까?

Wikipedia에 따르면 :

CMake는 컴파일러 독립적 인 방법을 사용하여 소프트웨어의 빌드 프로세스를 관리하는 [...] 소프트웨어입니다. 여러 라이브러리에 의존하는 디렉토리 계층 구조 및 애플리케이션을 지원하도록 설계되었습니다. make, Apple의 Xcode 및 Microsoft Visual Studio와 같은 기본 빌드 환경과 함께 사용됩니다.

CMake를 사용하면 더 이상 컴파일러 / 빌드 환경에 특정한 별도의 설정을 유지할 필요가 없습니다. 당신은 하나 개의 구성을하고, 그 작동 많은 환경.

CMake는 같은 파일에서 아무것도 변경하지 않고 동일한 파일 에서 Microsoft Visual Studio 솔루션, Eclipse 프로젝트 또는 Makefile 미로를 생성 할 수 있습니다.

코드가 포함 된 여러 디렉터리가있는 경우 CMake는 프로젝트를 컴파일하기 전에 수행해야하는 모든 종속성, 빌드 순서 및 기타 작업을 관리합니다. 실제로 아무것도 컴파일하지 않습니다. CMake를 사용하려면 CMakeLists.txt라는 구성 파일을 사용하여 컴파일해야하는 실행 파일, 링크 된 라이브러리, 프로젝트에있는 디렉터리 및 내부에있는 내용, 플래그와 같은 세부 정보를 알려야합니다. 또는 필요한 다른 것 (CMake는 매우 강력합니다).

이것이 올바르게 설정된 경우 CMake를 사용하여 선택한 "기본 빌드 환경"이 작업을 수행하는 데 필요한 모든 파일을 만듭니다. Linux에서는 기본적으로 Makefile을 의미합니다. 따라서 CMake를 실행하면 자체 사용을위한 파일과 Makefile. 그 후에해야 할 일은 코드 편집을 마칠 때마다 루트 폴더에서 콘솔에 "make"를 입력하는 것입니다. 그러면 컴파일되고 연결된 실행 파일이 만들어집니다.

CMake는 어떻게 작동합니까? 그것은 무엇을합니까?

다음은 전체적으로 사용할 프로젝트 설정의 예입니다.

simple/
  CMakeLists.txt
  src/
    tutorial.cxx
    CMakeLists.txt
  lib/
    TestLib.cxx
    TestLib.h
    CMakeLists.txt
  build/

각 파일의 내용은 나중에 표시되고 설명됩니다.

CMake는 프로젝트의 루트 CMakeLists.txt 에 따라 프로젝트 cmake를 설정하고 콘솔에서 실행 한 모든 디렉터리 에서 수행 합니다. 프로젝트의 루트가 아닌 폴더에서이 작업을 수행하면 소스 외부 빌드 라고 불리는 것이 생성됩니다. 즉, 컴파일 중에 생성 된 파일 (obj 파일, lib 파일, 실행 파일)이 해당 폴더에 배치됩니다. , 실제 코드와 별도로 유지됩니다. 혼란을 줄이는 데 도움이되며 다른 이유로도 선호됩니다.

cmake루트 이외의 다른 곳에서 실행하면 어떻게되는지 모르겠습니다 CMakeLists.txt.

이 예제에서는 모든 build/파일을 폴더 안에 배치하기를 원하므로 먼저 거기로 이동 한 다음 루트가있는 디렉터리를 CMake에 전달해야 CMakeLists.txt합니다.

cd build
cmake ..

기본적으로 이것은 내가 말했듯이 Makefile을 사용하여 모든 것을 설정합니다. 다음은 빌드 폴더의 모습입니다.

simple/build/
  CMakeCache.txt
  cmake_install.cmake
  Makefile
  CMakeFiles/
    (...)
  src/
    CMakeFiles/
      (...)
    cmake_install.cmake
    Makefile
  lib/
    CMakeFiles/
      (...)
    cmake_install.cmake
    Makefile

이 모든 파일은 무엇입니까? 걱정해야 할 것은 Makefile과 프로젝트 폴더뿐입니다 .

통지 src/lib/폴더를. 이것들은 simple/CMakeLists.txt명령을 사용하여 그들을 가리 키기 때문에 만들어졌습니다 add_subdirectory(<folder>). 이 명령은 CMake에게 해당 폴더에서 다른 CMakeLists.txt파일 을 찾고 해당 스크립트를 실행하도록 지시하므로이 방식으로 추가 된 모든 하위 디렉토리 에는 파일 이 있어야합니다CMakeLists.txt . 이 프로젝트에서는 simple/src/CMakeLists.txt실제 실행 파일 simple/lib/CMakeLists.txt을 빌드하는 방법 과 라이브러리를 빌드하는 방법을 설명합니다. CMakeLists.txt설명 하는 모든 대상은 기본적으로 빌드 트리 내의 하위 디렉터리에 배치됩니다. 그래서, 잠시 후

make

에서 완료된 콘솔 build/에 일부 파일이 추가되었습니다.

simple/build/
  (...)
  lib/
    libTestLib.a
    (...)
  src/
    Tutorial
    (...)

프로젝트가 빌드되고 실행 파일을 실행할 준비가되었습니다. 실행 파일을 특정 폴더에 넣으려면 어떻게해야합니까? 적절한 CMake 변수를 설정하거나 특정 대상의 속성을 변경합니다 . 나중에 CMake 변수에 대해 자세히 알아보십시오.

내 프로젝트를 빌드하는 방법을 CMake에 어떻게 알릴 수 있습니까?

다음은 소스 디렉토리에있는 각 파일의 내용입니다.

simple/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6)

project(Tutorial)

# Add all subdirectories in this project
add_subdirectory(lib)
add_subdirectory(src)

필요한 최소 버전은 항상 설정해야합니다. 그렇지 않은 경우 CMake에서 발생하는 경고에 따라 설정해야합니다. CMake의 버전을 사용하십시오.

프로젝트 이름은 나중에 사용할 수 있으며 동일한 CMake 파일에서 둘 이상의 프로젝트를 관리 할 수 ​​있다는 사실을 알려줍니다. 그래도 자세히 다루지는 않겠습니다.

이전에 언급했듯이 add_subdirectory()프로젝트에 폴더를 추가합니다. 즉, CMake는 폴더에 CMakeLists.txt내부 가있을 것으로 예상하고 계속하기 전에 실행됩니다. 그런데 CMake 함수를 정의한 경우 CMakeLists.txt하위 디렉터리의 다른 함수에서 사용할 수 있지만 사용하기 전에 정의해야 add_subdirectory()합니다. 그렇지 않으면 찾을 수 없습니다. CMake는 라이브러리에 대해 더 똑똑하므로 이런 종류의 문제가 발생하는 유일한 경우 일 것입니다.

simple/lib/CMakeLists.txt:

add_library(TestLib TestLib.cxx)

나만의 라이브러리를 만들려면 이름을 지정한 다음 빌드 된 모든 파일을 나열합니다. 똑바로. foo.cxx컴파일 할 다른 파일이 필요 하면 대신 add_library(TestLib TestLib.cxx foo.cxx). 이것은 예를 들어 다른 디렉토리의 파일에도 적용됩니다 add_library(TestLib TestLib.cxx ${CMAKE_SOURCE_DIR}/foo.cxx). 나중에 CMAKE_SOURCE_DIR 변수에 대해 자세히 알아보십시오.

이것으로 할 수있는 또 다른 일은 공유 라이브러리를 원하도록 지정하는 것입니다. 예 : add_library(TestLib SHARED TestLib.cxx). 두려워하지 마세요. CMake가 여러분의 삶을 더 쉽게 만들어주는 곳입니다. 공유 여부에 관계없이 이제 이런 방식으로 생성 된 라이브러리를 사용하기 위해 처리해야 할 것은 여기에 지정한 이름뿐입니다. 이 라이브러리의 이름은 이제 TestLib이며 프로젝트의 어느 곳에서나 참조 할 수 있습니다 . CMake가 찾을 것입니다.

종속성을 나열하는 더 좋은 방법이 있습니까? 확실히 그렇습니다 . 이에 대한 자세한 내용은 아래를 확인하십시오.

simple/lib/TestLib.cxx:

#include <stdio.h>

void test() {
  printf("testing...\n");
}

simple/lib/TestLib.h:

#ifndef TestLib
#define TestLib

void test();

#endif

simple/src/CMakeLists.txt:

# Name the executable and all resources it depends on directly
add_executable(Tutorial tutorial.cxx)

# Link to needed libraries
target_link_libraries(Tutorial TestLib)

# Tell CMake where to look for the .h files
target_include_directories(Tutorial PUBLIC ${CMAKE_SOURCE_DIR}/lib)

이 명령 은 물론 실행 파일을 대신 생성한다는 점을 제외 add_executable()하면과 정확히 동일하게 작동 add_library()합니다. 이 실행 파일은 이제 target_link_libraries(). tutorial.cxx는 TestLib 라이브러리에있는 코드를 사용하므로 다음과 같이 CMake를 가리 킵니다.

마찬가지로, 어떤 소스에 의해 #include하는 모든 .H 파일 add_executable()이 있습니다 하지 소스가 어떻게 든 추가 할 필요가 같은 디렉토리에. 을 위해하지 않으면 target_include_directories()명령, lib/TestLib.h전체 있도록 튜토리얼을 컴파일 할 때 찾을 수없는 것 lib/폴더에 추가됩니다은 #include를 검색 할 디렉토리를 포함한다. include_directories()모든 실행 파일에 대해 전체적으로 대상을 설정하므로 대상을 지정할 필요가 없다는 점을 제외하면 유사한 방식으로 작동 하는 명령 을 볼 수도 있습니다 . 다시 한번 CMAKE_SOURCE_DIR에 대해 설명하겠습니다.

simple/src/tutorial.cxx:

#include <stdio.h>
#include "TestLib.h"
int main (int argc, char *argv[])
{
  test();
  fprintf(stdout, "Main\n");
  return 0;
}

"TestLib.h"파일이 어떻게 포함되어 있는지 확인하십시오. 전체 경로를 포함 할 필요가 없습니다. CMake는 target_include_directories().

기술적으로 당신은없이 할 다음과 같이 간단한 소스 트리에, 수 말하기 CMakeLists.txt에서의 lib/src/및처럼 뭔가를 추가 add_executable(Tutorial src/tutorial.cxx)simple/CMakeLists.txt. 그것은 당신과 당신의 프로젝트의 필요에 달려 있습니다.

CMake를 올바르게 사용하려면 그 밖에 무엇을 알아야합니까?

(이해와 관련된 일명 주제)

패키지 찾기 및 사용 : 이 질문에 대한 대답 은 내가 할 수있는 것보다 더 잘 설명합니다.

변수 및 함수 선언, 제어 흐름 사용 등 : CMake가 제공하는 기본 사항을 설명하고 일반적으로 좋은 소개가되는 이 자습서 를 확인하십시오 .

CMake 변수 : 많은 것이 있으므로 다음은 올바른 방향으로 나아 가기위한 단기 집중 과정입니다. CMake wiki는 변수 및 표면적으로는 다른 것들 에 대한 더 자세한 정보를 얻을 수있는 좋은 장소 입니다.

빌드 트리를 다시 빌드하지 않고 일부 변수를 편집 할 수 있습니다. 이를 위해 ccmake를 사용하십시오 ( CMakeCache.txt파일을 편집 합니다). 에 기억 c변경 한 후 함께 할 때 onfigure g업데이트 된 구성 enerate 메이크.

변수 사용에 대해 배우 려면 이전에 참조한 자습서 를 읽으십시오. 그러나 변수 set(<variable name> value)를 변경하거나 생성하는 방법은 짧습니다 . ${<variable name>}그것을 사용합니다.

  • CMAKE_SOURCE_DIR: 소스의 루트 디렉토리입니다. 이전 예에서 이것은 항상 다음과 같습니다./simple
  • CMAKE_BINARY_DIR: 빌드의 루트 디렉토리입니다. 이전 예에서 이것은 simple/build/과 같지만 cmake simple/과 같은 폴더에서 실행 한 경우 해당 빌드 트리의 foo/bar/etc/모든 참조 CMAKE_BINARY_DIR/foo/bar/etc.
  • CMAKE_CURRENT_SOURCE_DIR: 전류 CMakeLists.txt가있는 디렉토리 . 이것은 전체적으로 변경됨을 의미합니다. simple/CMakeLists.txtyields /simple에서 인쇄하고 simple/src/CMakeLists.txtyields 에서 인쇄합니다 /simple/src.
  • CMAKE_CURRENT_BINARY_DIR: 당신은 아이디어를 얻습니다. 이 경로는 빌드가있는 폴더뿐만 아니라 현재 CMakeLists.txt스크립트의 위치 에 따라 다릅니다 .

이것이 왜 중요한가요? 소스 파일은 분명히 빌드 트리에 있지 않습니다. 당신이 뭔가하려고하면 target_include_directories(Tutorial PUBLIC ../lib)앞의 예를, 해당 경로는 쓰기와 같은 것 말을하는 것입니다 빌드 트리를 기준으로 할 것이다 ${CMAKE_BINARY_DIR}/lib내부 볼 것이다, simple/build/lib/. 거기에는 .h 파일이 없습니다. 기껏해야 libTestLib.a. ${CMAKE_SOURCE_DIR}/lib대신 원합니다 .

  • CMAKE_CXX_FLAGS: 컴파일러 (이 경우 C ++ 컴파일러)에 전달할 플래그입니다. 또한 이 DEBUG로 설정되어 CMAKE_CXX_FLAGS_DEBUG있으면 대신 사용됩니다 CMAKE_BUILD_TYPE. 이와 같은 것이 더 있습니다. CMake wiki를 확인하십시오 .
  • CMAKE_RUNTIME_OUTPUT_DIRECTORY: 빌드시 모든 실행 파일을 저장할 위치를 CMake에 알립니다. 이것은 글로벌 설정입니다. 예를 들어로 설정하고 bin/모든 것을 깔끔하게 배치 할 수 있습니다. EXECUTABLE_OUTPUT_PATH유사하지만 우연히 발견 될 경우를 대비하여 더 이상 사용되지 않습니다.
  • CMAKE_LIBRARY_OUTPUT_DIRECTORY: 마찬가지로 모든 라이브러리 파일을 저장할 위치를 CMake에 알리는 전역 설정입니다.

대상 속성 : 실행 파일이나 라이브러리 (또는 아카이브 ... 아이디어를 얻을 수 있음) 등 하나의 대상에만 영향을주는 속성을 설정할 수 있습니다. 다음은 사용 방법에 대한 좋은 예 입니다 set_target_properties().

소스를 대상에 자동으로 추가하는 쉬운 방법이 있습니까? GLOB사용 하여 동일한 변수 아래 주어진 디렉토리의 모든 항목을 나열합니다. 구문 예는 FILE(GLOB <variable name> <directory>/*.cxx).

다른 빌드 유형을 지정할 수 있습니까? 예, 이것이 어떻게 작동하는지 또는 이것의 한계에 대해 잘 모르겠습니다. 아마도 약간의 if / then'ning이 필요할 수 있지만 CMake는 CMAKE_CXX_FLAGS_DEBUG예를 들어 기본값과 같은 아무것도 구성하지 않고 몇 가지 기본 지원을 제공 합니다. CMakeLists.txt를 통해 파일 내에서 빌드 유형을 설정 set(CMAKE_BUILD_TYPE <type>)하거나 적절한 플래그를 사용하여 콘솔에서 CMake를 호출 하여 설정할 수 있습니다 ( 예 : cmake -DCMAKE_BUILD_TYPE=Debug.

CMake를 사용하는 프로젝트의 좋은 예가 있습니까? Wikipedia에는 ​​CMake를 사용하는 오픈 소스 프로젝트 목록이 있습니다. 온라인 자습서는 지금까지 이와 관련하여 저에게 실망 스러웠지만 이 Stack Overflow 질문 에는 꽤 멋지고 이해하기 쉬운 CMake 설정이 있습니다. 한 번 볼 가치가 있습니다.

코드에서 CMake의 변수 사용 : 다음은 빠르고 더러운 예제입니다 ( 다른 자습서에서 수정 됨 ).

simple/CMakeLists.txt:

project (Tutorial)

# Setting variables
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 1)

# Configure_file(<input> <output>)
# Copies a file <input> to file <output> and substitutes variable values referenced in the file content.
# So you can pass some CMake variables to the source code (in this case version numbers)
configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_SOURCE_DIR}/src/TutorialConfig.h"
)

simple/TutorialConfig.h.in:

// Configured options and settings
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

CMake에 의해 생성 된 결과 파일 simple/src/TutorialConfig.h:

// Configured options and settings
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 1

이것들을 영리하게 사용하면 라이브러리를 끄는 것과 같은 멋진 일을 할 수 있습니다. 조만간 더 큰 프로젝트에서 매우 유용하게 될 약간 더 고급 기능이 있기 때문에이 튜토리얼 을 살펴 보는 것이 좋습니다 .

그 밖의 모든 것에 대해 Stack Overflow는 특정 질문과 간결한 답변으로 넘쳐나 며 초보자를 제외한 모든 사람에게 좋습니다.


2
나는이 대답을 받아들이지 만 다른 누군가가 더 좋고 짧은 대답을 쓰면 나는 그것을 선택할 것입니다. 나는 그것을 스스로 할 것이지만 나는 이미 CMake로 충분히 고통 받았다.
leinaD_natipaC

6
이 놀라운 작업에 감사드립니다. 이것이 더 많은 투표를 얻길 바랍니다! :)
LETs

4
오히려 절제된 요점 : CMake를 사용하면 더 이상 컴파일러 / 빌드 환경에 특정한 별도의 설정을 유지할 필요가 없습니다. 당신은 하나 개의 구성을, 그것은 (다양한 버전) 비주얼 스튜디오, 코드 블록, 일반 유닉스 메이크, 그리고 많은 다른 환경에서 작동합니다. 이것이 제가 처음에 CMake를 살펴본 이유입니다. Autoconf, MSVC 2005/32 비트 및 MSVC 2010/64 비트 구성을 동기화 상태로 유지하는 것이 큰 고통이되었습니다. 그리고 일단 익숙해지면 문서 생성, 테스트, 패키징 등과 같은 많은 것들을 플랫폼 간 방식으로 추가했습니다.
DevSolar 2011

1
@DevSolar 사실입니다. 나는 위키피디아보다 그 줄이 더 마음에 들기 때문에 괜찮다면 대답에 추가하겠습니다. 나는 CMake를 그 효과에 올바르게 사용하는 방법에 대해서는 아무것도 다루지 않을 것입니다. 이것은 단지 무슨 일이 일어나고 있는지 말할 수있는 것에 관한 것입니다.
leinaD_natipaC

1
@RichieHH 예제에 따라 먼저 Makefile을 사용하도록 CMake를 구성한 다음 CMake를 사용하여 프로젝트를 빌드해야하는 파일을 생성하고 마지막으로 여기에서 작업이 완료되었으므로 CMake에 대한 걱정을 멈 춥니 다. 따라서 이제부터는 make프로젝트를 만들기 위해 bash에서 사용해야한다는 점에서 Makefile에 대해 "걱정" 합니다.
leinaD_natipaC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.