Эквивалент CMake листам свойств Visual Studio (.vsprops)

Я пытаюсь перейти с Visual Studio на (отличную) CLion IDE от Jetbrains, которая использует CMake для организации проектов.

До сих пор переход был гладким: создавать проекты CMake и импортировать их в CLion легко, и я могу начать кодирование на одной платформе, а затем без проблем продолжить на другой.

Однако есть один аспект Visual Studio, аналога которому я не смог найти в CMake, — это таблицы свойств: я использую их в основном для хранения путей к включаемым каталогам и связывания библиотек для библиотек (т.е. один .vsprops файл для каждой библиотеки, например OpenCV.vsprops, Boost.vsprops и т. д.).

Таким образом, в VS я мог совместно использовать файл .vsprops библиотеки между разными проектами без необходимости каждый раз настраивать пути/библиотеки.

Есть ли в CMake механизм, аналогичный листам свойств Visual Studio? Как возможно сохранить библиотечные включения/библиотеки в файле CMake-parsable, а затем «импортировать» его в CMakeLists.txt, чтобы связать с библиотекой?

В принципе, я хочу сделать следующее:

  1. Создайте «лист свойств cmake» (из-за отсутствия лучшего имени) для данной библиотеки.
  2. Затем в CMakeLists.txt напишите что-то вроде link_target_to_libs(myTarget "path/to/propertySheet1" "path/to/propertySheet2" ...) .

person maddouri    schedule 02.02.2015    source источник
comment
Как я могу эмулировать листы свойств Visual Studio (для библиотек) в CMake? Вы должны создать их самостоятельно, используя команды cmake для создания файлов.   -  person drescherjm    schedule 02.02.2015
comment
Я использую их в основном для хранения путей к включаемым каталогам и связывания библиотек с библиотеками Я бы просто использовал обработку CMake, если библиотеки и включаемые файлы. Или вы не хотите создавать свои проекты Visual Studio с помощью CMake.   -  person drescherjm    schedule 02.02.2015
comment
Я отредактировал последнюю часть своего сообщения, чтобы уточнить свои намерения :) И вы правы, я больше не хочу использовать VS. Я просто хочу иметь проекты CMake, исходный код которых я собираюсь редактировать с помощью CLion.   -  person maddouri    schedule 02.02.2015


Ответы (3)


В CMake библиотеки могут экспортировать пакет с ИМПОРТИРОВАННЫМИ целями, которые другие системы сборки импортируют с помощью find_package:

http://www.cmake.org/cmake/help/v3.1/manual/cmake-packages.7.html

http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html

http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#imported-targets

Вместо «ссылки на листы свойств» вы ссылаетесь на ИМПОРТИРОВАННЫЕ цели.

target_link_libraries(myTarget Dep1::Dep1 Dep2::Dep2)

Не все библиотеки создают IMPORTED target, и не все предоставляют пакеты файлов конфигурации cmake. В этих случаях (включая OpenCV и Boost) CMake предоставляет модули поиска:

http://www.cmake.org/cmake/help/v3.0/manual/cmake-developer.7.html#find-modules

который вы используете с find_package и ссылаетесь на содержимое переменных.

person steveire    schedule 02.02.2015

Поскольку я действительно хочу, чтобы включение/связывание библиотек выполнялось в однострочную команду, и, насколько мне известно (базовые) знания CMake, я думаю, что должен быть сделан некоторый компромисс - в основном совместное использование целевого имени переменная между CMakeLists.txt и "листами свойств". Итак, это мое решение... пока кто-нибудь не предложит более простой/чистый вариант:

  1. Список свойств CMake представляет собой .cmake текстовый файл,
  2. Известное имя переменной --TARGET-- обозначает цель (т. е. первый аргумент add_executable()),
  3. Помимо команд, специфичных для библиотеки, файл .cmake содержит вызовы target_include_directories(${TARGET} PRIVATE ${PATH_TO_INCLUDE_DIR}) и target_link_libraries(${TARGET} ${LIST_OF_LIBS}),
  4. Чтобы использовать/связать библиотеку, вызовите include("path/to/.cmake") в CMakeLists.txt.

Я успешно создал и выполнил простую программу, использующую X11 и OpenCV, со следующими файлами:

x11.cmake

target_include_directories(${TARGET} PRIVATE "/usr/include/X11")
target_link_libraries(${TARGET} "/usr/lib/x86_64-linux-gnu/libX11.so")

opencv.cmake

# OpenCV-specific stuff
set(OpenCV_DIR "/PATH/TO/OPENCV/INSTALL/DIR/share/OpenCV") # path to OpenCVConfig.cmake
find_package(OpenCV REQUIRED)
# include path
target_include_directories(${TARGET} PRIVATE ${OpenCV_INCLUDE_DIRS})
# linking libs
target_link_libraries(${TARGET} opencv_world opencv_ts)

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.4)
project(hello_clion)

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

## hello-clion ##############################
# make a new target name
set(TARGET hello-clion)

# find sources
file(GLOB_RECURSE SOURCE_FILES "src/*.cpp" "src/*.hpp")

# declare a target
add_executable(${TARGET} ${SOURCE_FILES})

# link the libraries (to the last-declared ${TARGET}, which should be the last-added executable)
include("x11.cmake")
include("opencv.cmake")
#############################################

main.cpp

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <thread>

#include <opencv2/opencv.hpp>

#include <Xlib.h>

int main_x11()
{
    // adapted from: http://rosettacode.org/wiki/Window_creation/X11#Xlib
}

int main_ocv()
{
    // adapted from: http://docs.opencv.org/doc/tutorials/introduction/display_image/display_image.html#source-code
}

int main()
{
    using namespace std;

    thread tocv(main_ocv);
    thread tx11(main_x11);

    tocv.join();
    tx11.join();

    return 0;
}

Теперь каждый раз, когда я хочу использовать OpenCV в проекте/программе, мне просто нужно поставить include("opencv.cmake") в соответствующий CMakeLists.txt.

person maddouri    schedule 07.02.2015
comment
Это не будет хорошим решением, когда вы определяете несколько целей в одном каталоге. Я предлагаю вам посмотреть ссылки на документы, которые я предоставил. - person steveire; 07.02.2015
comment
Не могли бы вы уточнить, почему это решение может быть проблематичным, пожалуйста? Я вижу, что путь include может быть загрязнен (т.е. содержать ненужные каталоги), но я думаю, что это не проблема... не так ли? - person maddouri; 07.02.2015
comment
Я отредактировал свое решение, чтобы использовать target_include_directories(), чтобы включить каталоги для каждой цели. - person maddouri; 22.02.2015

Кажется, это отлично работает, но, безусловно, могут быть проблемы, которые я не обнаружил. (Я беспокоился, что несколько макросов, добавляющих одни и те же target_link_libraries, вызовут «уже определенные» ошибки связывания, но, по крайней мере, g++ 5.1.0 обрабатывает одно и то же имя библиотеки несколько раз без ошибок.)

В корневом файле CMakeLists.txt ДО вызовов add_subdirectory() или подстановок включают:

macro(USES_WX)
    include_directories(SYSTEM /usr/local/include/wx-3.0)
    include_directories(SYSTEM /usr/local/lib/wx/include/gtk3-unicode-3.0)
    link_directories(/usr/local/lib)
    add_definitions(-D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread)
    target_link_libraries(${TARGET} pthread wx_gtk3u_xrc-3.0 wx_gtk3u_html-3.0 wx_gtk3u_qa-3.0 wx_gtk3u_adv-3.0 wx_gtk3u_core-3.0 wx_baseu_xml-3.0 wx_baseu_net-3.0 wx_baseu-3.0)
endmacro()

(Вы можете сделать макрос более причудливым, например, проверить, является ли CMAKE_BUILD_TYPE «Отладкой» или «Выпуском», чтобы связать с соответствующими библиотеками, изменить определения препроцессора и т. д. См. http://www.cmake.org/cmake/help/v3.0/command/if.html)

И пусть ваш проект CMakeLists.txt будет таким:

set(TARGET myProgramName)
add_executable(${TARGET} myProgramName.cpp)
USES_WX()

^^ Вызов макроса ДОЛЖЕН быть после add_executable()


И, если вам нужна поддержка нескольких целей, измените строку в корневом разделе CMakeLists.txt, показанную выше, на:

    ...
    target_link_libraries(${ARGV0} pthread wx_gtk3u_xrc-3.0 ...)
    ...

И пусть ваш проект CMakeLists.txt будет таким (меньше строк, но больше шансов на ошибку):

add_executable(myProgramName myProgramName.cpp)
USES_WX(myProgramName)
person user1902689    schedule 04.05.2015
comment
Спасибо за ответ. Я должен сказать, что я улучшил свое решение, инкапсулировав содержимое листов свойств .cmake внутри функций, которые принимают на вход имя цели (мне больше не нужно полагаться на глобальную переменную TARGET). Кроме того, я сделал add_executable()-подобную функцию, которая занимается управлением включением листов свойств и т. Д. На самом деле она имеет некоторое сходство с тем, что вы предложили :) - person maddouri; 04.05.2015
comment
Если у меня будет время, я размещу свое окончательное решение в своем публичном репозитории или где-нибудь еще. их проекты на основе cmake... - person maddouri; 04.05.2015
comment
Было бы здорово, если бы вы могли его куда-нибудь выложить. Я был бы рад увидеть лучшее/другое решение. - person user1902689; 04.05.2015