Какова идеальная структура каталогов установки cmake для перемещаемой установки на несколько платформ? - PullRequest
0 голосов
/ 30 июня 2018

Установка CMake принимает каталоги назначения, часто используя GNUInstallDirs для загрузки стандартных значений для имен назначения. Например:

include(GNUInstallDirs)
install(TARGETS Foo
    EXPORT Foo
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

Однако он не предоставляет разные пути, созданные для разных платформ или архитектур. Я устанавливал в папку для конкретной платформы в моем проекте через CMAKE_INSTALL_PREFIX, например:

CMAKE_INSTALL_PREFIX=dist/${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}

Хотя есть некоторые проблемы:

  • Он дублирует включения, которые одинаковы для разных платформ.
  • Если я установлю разные платформы в один и тот же корень, но изменю директорию lib, cmake не найдет цели конфигурации cmake в lib / non / standard / path / cmake / FooConfig.cmake
  • Поиск в модульном режиме также не позволяет найти библиотеки должным образом, что проблематично, когда выполняется поиск в режиме MODULE. Это может произойти, если в библиотеке также есть модуль cmake, который требует, чтобы каждый find_package указывал «CONFIG», что начинает становиться странным, особенно когда сторонним библиотекам предлагается рассмотреть этот установочный каталог для общей зависимости, а don ' нельзя указать CONFIG в find_package, потому что зачем они?

Я ищу структуру, которая работает с режимом модуля find_package и режимом конфигурации; как то так:

<install_prefix>/
  include/
    foo/
      foo.h
  lib/
    <PLAT x ARCH x CONFIG>/
      cmake/
        foo/
          FooConfig.cmake
      libFoo.a

Цель:

  • libs могут быть установлены совместно для разных платформ, архитектур и конфигураций
  • включает в себя можно поделиться
  • поиск включений должен работать в типичном режиме поиска модуля
  • должен работать только с vanilla find_package (Foo REQUIRED), но для соответствующей платформы и арки.

Учитывая, что я буду устанавливать здесь в основном сторонние библиотеки, если это можно сделать путем переопределения переменных из GNUInstallDirs, это, вероятно, будет работать для многих библиотек. Остальное, я думаю, придется либо отредактировать, либо я просто сдамся и использую отдельные установочные каталоги, которые включают платформу и арку.

Ответы [ 2 ]

0 голосов
/ 20 июля 2018

Я выложу так далеко, как только смог, и, возможно, это будет полезно. Если у кого-то есть недостающие части, я обновлю это.

Документация, описывающая порядок поиска, находится здесь: https://cmake.org/cmake/help/v3.12/command/find_package.html?highlight=%3Cprefix%3E

Существует довольно много поддерживаемых перестановок, поэтому я начну с исключения некоторых:

  • Игнорируйте варианты Apple, потому что это для фреймворков.
  • Игнорировать только пути Windows, потому что это не совсем идиоматично для любой другой платформы.
  • Наконец, у каждого есть варианты, связанные с тем, где находится скрипт cmake. Я просто выберу стиль .../cmake/<name>*/.

То есть (** добавлено дополнительное пространство, чтобы показать сходство):

<prefix>/        (lib/<arch>|lib*|share)/cmake/<name>*/         (U)
<prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/         (W/U)

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

Как вы можете видеть выше, единственное различие для дружественного к Windows формата Unix - это дополнительный префикс имени. Либо это правильный выбор, так что сейчас я буду ссылаться только на стиль Unix, так как он соответствует моим предпочтениям. Наконец, меня не волнует папка «share», потому что мы говорим о библиотеках C / C ++.

Итак, наконец мы подошли к этим двум вариантам:

<prefix>/lib/<arch>/cmake/<name>*/
<prefix>/lib*/cmake/<name>*/

Вариант 1: многоарочный

Пути с lib/<arch> разрешены, если установлена ​​переменная CMAKE_LIBRARY_ARCHITECTURE. CMAKE_<LANG>_LIBRARY_ARCHITECTURE говорится:

Если компилятор <LANG> передает компоновщику специфическую архитектуру каталог поиска системной библиотеки, такой как <prefix>/lib/<arch> this переменная содержит имя <arch>, если / как обнаружено CMake.

Я знаю, что это более конкретно для определенных дистрибутивов, которые поддерживают multiarch, и предназначено для автоматической установки. Тем не менее, я не могу понять, может ли это быть легко использовано с помощью cmake для достижения цели; что бы вы установили, чтобы контролировать это в cmake? В многоархивной системе библиотеки Foo и Bar могут выглядеть так:

<prefix>/lib/x86_64-linux-gnu/
    foo-1.1/
        cmake/FooConfig.cmake
    bar/
        cmake/BarConfig.cmake
    foo-1.1.so
    foo-1.1.lib
    foo-1.1.dll
    foo-1.1.dylib
    bar.so
    bar.lib
    bar.dll
    bar.dylib

Если мы сможем контролировать значение multiarch, этот параметр можно легко использовать для других платформ, таких как: Darwin_x86_64, Windows_x86_64 и т. Д. И он, вероятно, будет совместим с режимом модуля find_package, где все включения будут найдены, без необходимости режим конфигурации для перенаправления на какой-то нестандартный каталог.

Вариант 2: вариации lib

Частичное решение состоит в том, чтобы в префиксе были полностью разделены платформы, но по крайней мере 64-битную и 32-битную архитектуры можно объединить, просто разделив библиотеки.

lib* включает одно или несколько значений lib64, lib32, libx32 или lib (поиск в таком порядке).

  • Пути с lib64 ищутся на 64-битных платформах, если FIND_LIBRARY_USE_LIB64_PATHS свойство установлено в TRUE.
  • Пути с lib32 ищутся на 32-битных платформах, если FIND_LIBRARY_USE_LIB32_PATHS свойство установлено в TRUE.
  • Пути с libx32 ищутся на платформах с использованием x32 ABI, если Для свойства FIND_LIBRARY_USE_LIBX32_PATHS установлено значение TRUE.
  • Путь к lib всегда ищется.

Это хотя бы частично помогает. Я бы продолжал использовать lib как 64-битную версию, а затем просто использовал lib32 для 32-битных нужд.

0 голосов
/ 08 июля 2018

Если вы ожидаете, что пользователь установит какой-то стандартный каталог как CMAKE_PREFIX_PATH , например

/usr/local # installation prefix

но ваш проект устанавливает вещи в нестандартные, специфичные для платформы подкаталоги, такие как

/usr/local/linux/x86/ # actual root directory where things are installed

Вы можете поместить FooConfig.cmake в стандартный подкаталог:

/usr/local/lib/FooConfig.cmake

но запишите его так, чтобы он искал соответствующий .cmake из каталога для конкретной платформы:

# File: FooConfig.cmake
# Location: lib/
#
# This is platform-independent script.
#
# Redirect configuration to the platform-specific script <system>/<cpu>/lib/FooConfig.cmake.
include(${CMAKE_CURRENT_LIST_DIR}/../${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}/lib/FooConfig.cmake)

Сценарий *Config.cmake для конкретной платформы можно написать обычным способом.

Итак, если пользователь напишет

find_package(Foo)

в среде, установленной для Linux/x86, будут установлены импортированные цели для этой платформы.

...