2015-03-27 3 views
1

Я пытаюсь изучить CMake, но я не могу справиться с имеющимися учебниками.Создание и использование библиотеки с CMake

Предположим, у моего проекта есть структура ниже, и я хочу сделать my_lib доступным через его файл CMakeLists и использовать его в моем main.cpp, как будут выглядеть мои файлы CMakeLists?

├── CMakeLists.txt 
├── externals 
│ └── my_lib 
│  └── src 
│   ├── CMakeLists.txt 
│   ├── MyClass.h 
│   └── MyClass.cpp 
└── main.cpp 

Должен ли я использовать include_directories или add_subdirectory?

ответ

2

Чтобы соответствовать структуре каталога Вы указали, файлы CMakeLists.txt может выглядеть следующим образом:

/CMakeLists.txt:

cmake_minimum_required(VERSION 3.0) 
project(Main) 
add_subdirectory(externals/my_lib/src) 
add_executable(my_main main.cpp) 
target_link_libraries(my_main my_lib) 

/externals/my_lib/src/CMakeLists.txt:

cmake_minimum_required(VERSION 3.0) 
project(MyLib) 
add_library(my_lib MyClass.cpp MyClass.h) 
target_include_directories(my_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 

Использование PUBLIC в target_include_directories вызова означает, что не только ваша библиотека имеет это как «включать путь», но так же любая цель связывания к нему.

Недостатком этой настройки является то, что вы также собираетесь подвергать любые внутренние заголовки my_lib также потребляющим целям. Скажем, у вас также есть «Internal.h» как часть my_lib, которую вы не хотите раскрывать. Вы можете сделать это, перемещая преднамеренно-публичные заголовки в отдельную папку, например. "Включают":

├── CMakeLists.txt 
├── externals 
│ └── my_lib 
│  ├── CMakeLists.txt 
│  ├── include 
│  │ └── MyClass.h 
│  └── src 
│   ├── Internal.h 
│   └── MyClass.cpp 
└── main.cpp 

Ваш верхнего уровня CMakeLists.txt не изменится, но /externals/my_lib/CMakeLists.txt (который перешел на уровень выше) теперь гласит:

cmake_minimum_required(VERSION 3.0) 
project(MyLib) 
add_library(my_lib src/MyClass.cpp src/Internal.h include/MyClass.h) 
target_include_directories(my_lib 
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include 
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src 
    ) 

Теперь, поскольку папка «src» вашей библиотеки - PRIVATE - my_lib, main.cpp не сможет #include "Internal.h".

+0

Благодарим вас, это сделало вещь намного яснее, и это действительно сработало! Правильно ли я предполагаю, что любые файлы в каталоге include могут теперь использовать Internal.h? –

+0

«include» dir обычно содержит только заголовки. Эти заголовки должны содержать только '# include' другие заголовки в директории include. Скажем, «MyClass.h» cointained '#include" Internal.h "'. Это будет проблемой для чего угодно, в зависимости от 'my_lib', например. «main.cpp» имеет «#include» MyClass.h ». Компилятор знает, где найти «MyClass.h» - мы рассказывали об «externals/my_lib/include», но он не может найти «Internal.h», который нужен «MyClass.h». Таким образом, ни один из заголовков в «include» не должен ссылаться на файлы в «src». – Fraser

+0

Если нет возможности избежать раскрытия «Internal.h» (часто в случае с кодом шаблона), это нормально разместить в подкаталоге «include» с именем «detail», чтобы указать потребителям библиотеки, что это своего рода частный код которые могут измениться без предупреждения и не должны быть действительно '# include'ed непосредственно ими. – Fraser

Смежные вопросы