Статическая сборка — удобное и практичное решение. Особенно в Linux, где бинарная совместимость между разными дистрибутивами и даже между разными версиями одного дистрибутива регулярно нарушается.
Для проектов среды разработки QtCreator, использующих систему сборки qmake (у таких проектов имя файла имеет формат "*.pro"), есть ряд простых рецептов по части статической сборки.
Вы собираете библиотеку как часть проекта, и она тоже собирается через QMake? Есть два варианта:
В чём разница? По умолчанию, QtCreator кладёт файлы сборки отдельно от папки с исходниками, причём имя целевой папки зависит от имени выбранного комплекта (Kit). Это явление называется теневой сборкой.
Процесс перенаправления сборки сложнее, так что о нём читайте ниже. Для линковки библиотеки libsuper.so, собираемой в теневой папке как часть проекта QtCreator, есть следующий способ:
Библиотеки, необходимые для программы, можно поместить рядом с ней и затем при сборке программы заставить Linux всё-таки искать библиотеки рядом с исполняемым файлом. Это делается с помощью флагов компоновщика ld; в проекте QtCreator, достаточно добавить три строчки:
Хотите, чтобы библиотеки находились в подпапке libs рядом с исполняемым файлом? Нет проблем:
Подробнее о том, как создавать распространяемые архивы с программами для Linux без DEB/RPM пакетов, читайте здесь: sergey-shambir.blogspot.ru/2015/06/ubuntu-root.html
В предложенном ниже решении функция поможет разложить собираемые библиотеки и бинарники в подпапки ~build/release-x64, ~build/debug-x64, ~build/release-x32, ~build/debug-x32 внутри папки с исходным кодом проекта в зависимости от конфигурации сборки.
Затем в своей статической библиотеке сделайте так:
А в каждом использующем её подпроекте - так:
Последняя строчка обеспечит вам ещё и пересборку бинарника в случае, когда библиотека libminijava.a изменяется. Да-да, сам по себе qmake не будет следить за модификацией данной библиотеки — пока вы не заставите его это делать.
Для проектов среды разработки QtCreator, использующих систему сборки qmake (у таких проектов имя файла имеет формат "*.pro"), есть ряд простых рецептов по части статической сборки.
Выборочная линковка: 1-2 в статике, остальное в динамике
Если надо статически прилинковать лишь парочку библиотек, а всё остальное подключать как .so, для QMake можно сделать так:# Подключаем библиотеку libminijava.so !msvc:LIBS += -Wl,-Bstatic -lminijava -Wl,-BdynamicУсловие "!msvc" заставляет qmake применять эти настройки только для компиляторов G++ и Clang++, но не для Visual C++. Тем самым мы защищаем Visual C++ от непонятных для него флагов.
Линковка библиотеки из /usr/local
Вы установили библиотеку в usr local? Её можно подключить так:LIBS += /usr/local/lib
Линковка библиотеки в составе проекта
Речь, разумеется, идёт о проектах типа TEMPLATE = subdir, которые содержат внутри себя другие проекты (аналогично файлу .sln в Visual Studio).Вы собираете библиотеку как часть проекта, и она тоже собирается через QMake? Есть два варианта:
- подключить либу из теневой папки сбоки
- перенаправить сборку либы в папку с исходным кодом.
В чём разница? По умолчанию, QtCreator кладёт файлы сборки отдельно от папки с исходниками, причём имя целевой папки зависит от имени выбранного комплекта (Kit). Это явление называется теневой сборкой.
Процесс перенаправления сборки сложнее, так что о нём читайте ниже. Для линковки библиотеки libsuper.so, собираемой в теневой папке как часть проекта QtCreator, есть следующий способ:
LIBS += -L"$$OUT_PWD/../libsuper.so" LIBS += -lsuperСтрока "$$OUT_PWD" раскроет переменную OUT_PWD.
Я слинковал, а программа не запускается!
Не запускается потому, что Linux, в отличие от Windows, не будет искать .so файлы в той же директории, где лежит исполняемый файл. Такое ограничение действует уже десятки лет ради безопасности.Библиотеки, необходимые для программы, можно поместить рядом с ней и затем при сборке программы заставить Linux всё-таки искать библиотеки рядом с исполняемым файлом. Это делается с помощью флагов компоновщика ld; в проекте QtCreator, достаточно добавить три строчки:
unix:!macx { QMAKE_LFLAGS += '-Wl,-rpath,\'\$$ORIGIN\',-z,origin' }
Хотите, чтобы библиотеки находились в подпапке libs рядом с исполняемым файлом? Нет проблем:
unix:!macx { QMAKE_LFLAGS += '-Wl,-rpath,\'\$$ORIGIN/libs\',-z,origin' }
Подробнее о том, как создавать распространяемые архивы с программами для Linux без DEB/RPM пакетов, читайте здесь: sergey-shambir.blogspot.ru/2015/06/ubuntu-root.html
Перенаправление пути сборки исполняемых файлов
Здесь потребуется объявить в qmake новую функцию через defineReplace, и использовать её везде, где требуется получить перенаправленный путь к файлу.В предложенном ниже решении функция поможет разложить собираемые библиотеки и бинарники в подпапки ~build/release-x64, ~build/debug-x64, ~build/release-x32, ~build/debug-x32 внутри папки с исходным кодом проекта в зависимости от конфигурации сборки.
defineReplace(inferTargetDir) { buildSubdir = release-x64 debug { equals(QT_ARCH, x86_64) { buildSubdir = debug-x64 } else { buildSubdir = debug-x32 } } else { !contains($$QT_ARCH, x86_64) { buildSubdir = release-x32 } } buildDir=$$PWD/../~build/$$buildSubdir return($$buildDir) } defineReplace(inferTarget) { buildTargetPath=$$inferTargetDir()/$$1 return($$buildTargetPath) }
Затем в своей статической библиотеке сделайте так:
TARGET = "$$inferTarget(minijava)"
А в каждом использующем её подпроекте - так:
LIBS += -L"$$inferTargetDir()" -Wl,-Bstatic -lminijava -Wl,-Bdynamic PRE_TARGETDEPS += $$inferTargetDir()/libminijava.a
Последняя строчка обеспечит вам ещё и пересборку бинарника в случае, когда библиотека libminijava.a изменяется. Да-да, сам по себе qmake не будет следить за модификацией данной библиотеки — пока вы не заставите его это делать.
Комментариев нет:
Отправить комментарий