Mar 10, 2016 - Введение в OpenGL (2)

Продолжаю готовить материалы по OpenGL: шейдеры и преобразование координат.

Feb 26, 2016 - Введение в OpenGL

Начал оформлять в текстовом виде материал семинаров. Пока выложил первую часть.

Feb 18, 2016 - CMake и работа с зависимостями

CMake позволяет быстро и удобно писать сборочные скрипты для кроссплатформенной сборки программных проектов. Под Windows генерируются проекты для Visual Studio, под Linux - Makefiles. Поддерживаются и другие среды разработки.

Но CMake позволяет также удобно подключать зависимости (сторонние библиотеки) к проекту. И здесь CMake предоставляет ряд возможностей, которые я хочу кратко рассмотреть.

Поиск библиотек

Для подключения внешней библиотеки нужно как минимум указать компилятору путь к заголовочным файлам и линкеру - к самой библиотеке (.lib, .so). CMake может попробовать найти эти пути с помощью команд find_path и find_library, которые в простейшей форме выглядят так:

find_path(ПЕРЕМЕННАЯ1 имя_заголовочного_файла)
find_library(ПЕРЕМЕННАЯ2 имя_библиотеки)    

Если файл с именем имя_заголовочного_файла будет найден, то в переменную ПЕРЕМЕННАЯ1 будет записан полный путь к директории, где этот файл лежит. Если файл с именем имя_библиотеки будет найден, то в переменную ПЕРЕМЕННАЯ2 будет записан полный путь к этому файлу.

После этого эти переменные можно будет подключить к цели сборки:

target_include_directories(цель_сборки ${ПЕРЕМЕННАЯ1})
target_link_libraries(цель_сборки ${ПЕРЕМЕННАЯ2})

Но вот только где CMake будет производить поиск? Можно указать несколько стандартных путей, например так:

find_library(ПЕРЕМЕННАЯ2 имя_библиотеки
    PATHS
    /usr/lib
    /usr/local/lib)

Это хорошо работает под Линуксом, где все библиотеки обычно лежат по нескольким стандартным путям. Под Windows хуже: нужная библиотека может располагаться, где угодно.

Можно договориться, что при установке библиотеки на компьютер путь к ней будет прописываться в переменную окружения ПЕРЕМЕННАЯ_ОКРУЖЕНИЯ, тогда CMake сможет это использовать:

find_library(ПЕРЕМЕННАЯ2 имя_библиотеки
    PATHS
    /usr/lib
    /usr/local/lib
    $ENV{ПЕРЕМЕННАЯ_ОКРУЖЕНИЯ})

Если ничего не помогло, то пользователю придется вручную вводить в интерфейсе CMake нужные пути.

Упрощение поиска

Для сложных сторонних библиотек с кучей модулей и версий может понадобиться большое нагромождение команд find_path и find_library. Для удобства эти команды можно выделить в отдельный скрипт с именем FindБИБЛИОТЕКА.cmake.

После этого можно вызывать скрипт командой find_package:

find_package(БИБЛИОТЕКА)

(и не забыть прописать в переменной CMAKE_MODULE_PATH путь к папке со скриптами).

Это серьезно упрощает структуру корневого файла CMakeLists.txt. Также для популярных библиотек уже существуют скрипты для поиска, которые устанавливаются вместе с CMake. Под Линуксом такие скрипты лежат в папке /usr/share/cmake/Modules, а под Windows в папке C:\Program Files (x86)\CMake\share\cmake-3.2\Modules.

Также некоторые библиотеки предоставляют такие скрипты для поиска самих себя. В этом случае его нужно скопировать себе в проект из репозитория сторонней библиотеки.

Импорт целей сборки

Помимо путей к заголовочным файлам и библиотекам бывает необходима информация об опциях компилятора, об определениях препроцессора, о зависимостях зависимостей и т.д. Было бы удобно работать со сторонними библиотеками как с обычными целями сборки.

CMake позволяет это. Для этого необходимо создать «виртуальную» цель сборки и описать её свойства. В терминологии CMake такая цель сборки называется импортированная.

Создать и описать импортированную цель сборки можно с помощью ключевого слова IMPORTED. Пример:

add_library(внешняя_цель_сборки STATIC IMPORTED)
set_property(TARGET внешняя_цель_сборки PROPERTY IMPORTED_LOCATION полный_путь_к_библиотеке)
target_compile_definitions(внешняя_цель_сборки INTERFACE "ОПРЕДЕЛЕНИЕ_ПРЕПРОЦЕССОРА")
target_include_directories(внешняя_цель_сборки PUBLIC $<INSTALL_INTERFACE:include>)

После этого можно подключить эту внешюю цель сборки к нашей цели:

add_executable(цель_сборки src1.cpp src2.cpp)
target_link_libraries(цель_сборки внешняя_цель_сборки)

При сборки нашего проекта автоматически будут прописаны пути к заголовочным файлам и библиотеке, определение препроцессора. Этот способ является альтернативным использованию функций find_library и find_path.

Описание импортированной цели сборки удобно вынести в отдельный скрипт. Но лучше, если сама внешняя библиотека сгенерирует этот скрипт за нас. Здесь описано как генерировать такой скрипт автоматически.

Тогда нашему проекту достаточно будет подключить готовый скрипт:

include(${PREFIX}/lib/cmake/библиотека/библиотека-targets.cmake)

Сборка зависимостей

Но что, если в системе не установлена нужная зависимость? Можно попросить пользователя установить её, либо поручить это CMake-скрипту.

Есть 2 основные стратегии в зависимости от размера внешней библиотеки.

Исходный код маленькой библиотеки можно просто добавить в дерево исходников нашего проекта, например, в подпапку 3rdParty. Далее библиотеку можно подключить в из корневого файла CMakeLists.txt с помощью команды add_subdirectory:

add_subdirectory(путь_к_внешней_библиотеке)

Тогда эта библиотека будет скомпилирована вместе с нашим проектом, и будут доступны её цели сборки.

Если внешняя библиотека слишком большая, то можно использовать команду ExternalProject_Add. Например:

ExternalProject_Add(ИМЯ_БИБЛИОТЕКИ		
    GIT_REPOSITORY путь_к_гит_репозиторию
    GIT_TAG        номер_коммита_или_ветка_или_тег
    CMAKE_ARGS "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
        "-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}"			
)

Команда имеет множество параметров. Она позволяет скачать архив из интернета и распаковать его, либо клонировать репозиторий, вызвать отдельный экземпляр CMake для создания проектов Visual Studio или Makefiles. Такой многофункциональный комбайн.

Однако, команда имеет и недостатки. Дело в том, что конфигурирование и сборка внешней библиотеки происходят не во время ExternalProject_Add. Они происходят одновременно со сборкой нашего проекта, а значит до начала сборки ни самих библиотек, ни заголовочных файлов, ни скриптов не существует. А это значит, что команды find_library, find_path будут выдавать ошибки при конфигурировании в CMake. Цели сборки внешней библиотеки будут недоступны…

Поэтому команда ExternalProject_Add не является панацеей и её нужно использовать осторожно.

Суперсборка

В обсуждениях в интернете встретил подход к сборке проекта, основанный на ExternalProject_Add, который назвали «суперсборкой».

Идея в том, что и сторонние библиотеки, и наш проект собирать с помощью ExternalProject_Add. Корневой CMakeLists.txt просто содержит вызовы этой команды и всё.

В этом случае скачивание и конфигурирование происходит во время сборки. Когда мы вызываем команду make под Линуксом или запускаем сборку в Visual Studio под Windows, то происходит следующее:

  1. Скачивается внешняя библиотека, конфигурируется, собирается, устанавливается.
  2. Конфигурируется наш проект (теперь find_library, find_path срабатывают без ошибок, т.к. внешняя библиотека уже физически существует) и собирается.

Пример реализации суперсборки.

Комментировать

Feb 17, 2016 - Vulkan

Вчера официально вышел новый графический интерфейс Vulkan, который приходит на смену OpenGL. Новый интерфейс не ускоряет вычисления на видеокарте, но уменьшает накладные расходы в драйвере, что в определенных ситуациях может в целом ускорить работу графического приложения. При этом новый GAPI значительно более низкоуровневый.

NVidia и AMD выложили драйвера (раз, два) для своих видеокарт, которые были выпущены в 2012м году и позднее.

Моя Quadro 600 на стационарном компе, увы, в пролете. На ноутбуке AMD Radeon HD 7800M должна поддерживаться, но Вулкан пока на ней не заработал. Думаю, придется покупать новую видеокарту для стационарного компа. Пока склоняюсь к GeForce GTX 960.

Полезные ресурсы на будущее:

Комментировать

Feb 7, 2016 - Шуховская башня на Шаболовке на WebGL

Уже несколько лет участвую в долгоиграющем проекте ИИЕТ РАН по созданию виртуальной Шуховской башни на Шаболовке, которая была построена знаменитым инженером Шуховым в 1920-1922 годах.

Собственно сама 3д-модель Башни давно готова - создана коллегами из компании Триметари по данным лазерного сканирования. А дальше и до сих пор продолжается шлифовка интерактивного приложения для работы с 3д-моделью.

Изначально было разработано нативное приложение на OpenSceneGraph, которое содержит полный набор данных: облако точек и неcколько 3д-моделей. Позже добавлено приложение на движке Unity с упрощенной моделью Башни для просмотра прямо в браузере. Недавно поддержка Unity Web Player была прекращена, и сейчас приложение работает на WebGL.

Ссылка для просмотра

Комментировать