CMake를 사용하여 포함 디렉토리를 올바르게 추가하는 방법


243

약 1 년 전에 CMake의 헤더 종속성에 대해 물었습니다 .

최근에 CMake가 해당 헤더 파일을 프로젝트 외부 에 있다고 생각한 것이 문제라는 것을 깨달았습니다 . 적어도 Code :: Blocks 프로젝트를 생성 할 때 헤더 파일은 프로젝트 내에 나타나지 않습니다 (소스 파일은). 따라서 CMake는 해당 헤더를 프로젝트 외부 에있는 것으로 간주 하고 종속 항목에서 추적하지 않습니다.

CMake 튜토리얼의 빠른 검색은 include_directories내가 원하는 것을하지 않는 것으로 나타났습니다 ...

CMake에 특정 디렉토리에 포함 할 헤더가 포함되어 있고 생성 된 Makefile에서 해당 헤더를 추적해야한다는 신호를 보내는 올바른 방법은 무엇입니까?


이 질문을 수정하면 혼란스러워집니다. 원래 질문과 답변은 IDE에서 헤더 파일을 추적하는 방법이었습니다. 이는 생성 된 Makefile에 누락 된 헤더 파일 종속성 및 해당 문제를 해결하는 방법과는 매우 다릅니다.
fdk1342

@Fred : 당신이 무슨 말을하는지 모르겠습니다. 수정본 개정판이 명확하게 보여 주듯이, 마지막 문장이 항상 존재합니다. 이 질문에 대한 부분적인 수정 만 있었으며 어떤 단어도 소개되지 않았습니다.
Matthieu M.

그렇다면 그것은 나의 오해입니다. 전체 단락이 추가 된 것을 좋아했습니다. stackoverflow.com/questions/13703647/… 는 IDE에서 헤더 파일을 나열하는 방법에 대한 일반적인 이해가 있다고 말합니다. 이것은 .cbp프로젝트 파일을 참조했을 것 입니다. 이제 cmake 의존성 스캐너가 헤더 파일을 Makefile의 의존성으로 올바르게 식별하지 못하면 문제를 해결할 수있는 방법이 있지만 경우에 따라 전체 전처리 기가 포함되어 있지 않아 잘못 될 수 있습니다.
fdk1342

답변:


267

두 가지를 수행해야합니다.

먼저 포함 할 디렉토리를 추가하십시오.

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

을 지원하지 않고 매우 오래된 CMake 버전 (2.8.10 이상)이 붙어있는 경우 target_include_directories레거시를 include_directories대신 사용할 수도 있습니다 .

include_directories(${YOUR_DIRECTORY})

그런 다음 헤더 파일을 현재 대상의 소스 파일 목록에 추가해야합니다 (예 :

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

이런 식으로 헤더 파일은 Makefile에 종속 항목으로 표시되며 생성 된 Visual Studio 프로젝트 (예 : 생성 된 Visual Studio 프로젝트)에도 표시됩니다.

여러 대상에 해당 헤더 파일을 사용하는 방법 :

set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)

add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

아! 나는 그것이 어리석은 일이어야한다는 것을 알고 있었다. 실제로 헤더를 나열하지 않았습니다 ...이 라이브러리의 헤더 또는 라이브러리에 의존 할 수있는 모든 헤더를 나열해야합니까 (라이브러리에 대한 종속성 선언 위에)? 점점 커지는 프로젝트이며 루트 라이브러리에 헤더를 추가 할 때 모든 종속성에 헤더를 추가한다는 아이디어가 무섭습니다 .
Matthieu M.

더 나은 종속성 추적을 허용하려면 (예를 들어 헤더 파일을 수정하면 영향을받는 모든 대상에 대한 컴파일이 트리거되는지 확인) 예입니다. 그러나 cmake 변수를 사용하여 헤더 파일을 한 번만 나열하고 여러 곳에서 사용할 수 있습니다. 내 편집을 참조하십시오.
SirDarius

1
내 질문은 서로 의존하는 여러 라이브러리가 있다는 의미에서 더 그렇습니다. libroot, liba는 libroot에 의존하고 libb는 libroot에 의존합니다. 내가 사용할 수 LIBROOT_HEADER_FILES의 변수를 liba/CMakefile하고 libb/CMakefile다음?
Matthieu M.

2
이것은 잘못된 것입니다, 당신이해야 결코 사용하지 않는 include_directories이상 target_include_directories. 전자는 해당 디렉토리의 모든 대상에 대해 재귀 적으로 설정합니다. 후자는 대상으로 설정합니다. 전자를 수행하면 CMake에서 대상 그래프의 개념이 깨지고 대신 파일 계층 구조의 부작용에 의존합니다.
Andy

1
target_include_directories현대 CMake 코드 를 선호하는 현재 개념을 반영하도록 답변을 편집했습니다 . 변경 사항에 동의하지 않으면 언제든지 채팅에 초대하십시오.
ComicSansMS

74

먼저 include_directories()CMake에게 디렉토리를 -I컴파일 명령 줄 에 추가 하도록 지시 하는 데 사용 합니다 . 둘째, 당신 add_executable()이나 add_library()전화에 헤더를 나열합니다 .

예를 들어 프로젝트 소스가에 있고에서 src헤더가 필요한 include경우 다음과 같이 할 수 있습니다.

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)

19
정말로 헤더를 추가해야 add_executable합니까? CMake가 포함 파일 종속성을 자동으로 파악했다고 생각했습니다.
콜린 D 베넷

57
@ColinDBennett 의존성 이유로 그것들을 나열 할 필요는 없습니다. CMake는 빌드 의존성을 나타내지 않으면 빌드 종속성을 알아냅니다. 그러나 그것들을 나열하면 프로젝트의 일부로 간주되며 IDE (질문의 주제)에 나열됩니다.
Angew는 더 이상

적어도 QtCreator의 경우 class.cpp가있는 경우 class.h를 추가 할 필요가 없습니다. lonely.h 만 소스에 추가해야합니다. www.th-thielemann.de/cmake
Th의

19

CMake는 Makefile을 만드는 다른 방법 (예 : make 또는 qmake)과 비교하면 스크립트 언어와 비슷합니다. 파이썬처럼 시원하지는 않지만 여전히 그렇습니다.

사람들이 디렉토리를 포함하는 방법을 다양한 오픈 소스 프로젝트에서 살펴보면 " 올바른 방법 " 과 같은 것은 없습니다 . 그러나 두 가지 방법이 있습니다.

  1. Crude include_directories 는 현재 프로젝트 및 일련의 add_subdirectory 명령을 통해 추가 할 다른 모든 하위 프로젝트에 디렉토리를 추가 합니다. 때때로 사람들은 그러한 접근법이 레거시라고 말합니다.

  2. 보다 우아한 방법은 target_include_directories 입니다. 다양한 포함 디렉토리의 불필요한 상속이나 충돌없이 특정 프로젝트 / 대상에 대한 디렉토리를 추가 할 수 있습니다. 또한 미묘한 구성을 수행하고이 명령에 대해 다음 마커 중 하나를 추가 할 수 있습니다.

PRIVATE- 이 지정된 빌드 대상에만 사용

공개 -지정된 대상 및이 프로젝트와 연결된 대상에 사용하십시오.

인터페이스 -현재 프로젝트와 연결되는 대상에만 사용

추신:

  1. 두 명령 모두 디렉토리를 SYSTEM으로 표시하여 지정된 디렉토리에 경고가 포함 된 것은 사용자의 비즈니스가 아님을 암시합니다.

  2. 비슷한 대답은 target_compile_definitions / add_definitions , target_compile_options / CMAKE_C_FLAGS 명령의 다른 쌍입니다.


13

추가하십시오 include_directories("/your/path/here").

옵션 으로 호출 gcc하는 것과 비슷합니다 -I/your/path/here/.

경로를 큰 따옴표로 묶어야합니다. 다른 사람들은 그것을 언급하지 않았고 2 일 동안 나를 고착시켰다. 따라서이 답변은 CMake를 처음 접하고 혼란스러워하는 사람들을위한 것입니다.


7

나는 같은 문제가 있었다.

내 프로젝트 디렉토리는 다음과 같습니다.

    --project
    ---Classes
    ----Application
    -----.h and .c files
    ----OtherFolders
    --main.cpp

그리고 내가 그 모든 폴더에 파일을 포함시키는 데 사용한 것 :

    file(GLOB source_files
            "*.h"
            "*.cpp"
            "Classes/*/*.cpp"
            "Classes/*/*.h"
    )

    add_executable(Server ${source_files})

그리고 그것은 완전히 작동했습니다.


cglo는 파일 빌드를 사용하는 '빌드 시스템'이 아니라 '빌드 시스템 생성기'라는 것을 기억하는 것은 파일 글로브가 '빌드'가 아닌 '빌드'시간에 평가되기 때문에 현대 cmake (버전 3.0 이상의 CMake)에서는 좋은 생각이 아닙니다. 시스템 생성 시간. 링크 참조 : gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1
ggulgulia
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.