Как стать автором
Обновить

Вышел QBS 1.0.0

Время на прочтение1 мин
Количество просмотров14K
Всего голосов 24: ↑22 и ↓2+20
Комментарии35

Комментарии 35

Long live, QBS!

Теперь можно переводить проекты с cmake на qbs более активно)
А с CMake-то зачем? И чем он не устроил, собственно?
НЛО прилетело и опубликовало эту надпись здесь
А Вы CMake и make случаем не путаете? Это совершенно разные вещи.

И если говорить про CMake, то, собственно, что в нем безбожно устарело? Нынче компиляция и линковка проходят как-то по-особенному?
В современном мире сборка проекта — это не только компиляция и линковка исходного кода. Это теперь сборка файлов перевода, установка дополнительных ресурсов — иконки, файлы конфигураци, стили, причем зачастую набор ресурсов, который требуется поставить с приложением — сильно отличается в зависимости от системы. Все это гораздо короче и нагляднее описывается декларативным языком.

В современном мире хочется удобно работать с зависимостями проектов, в QBS достаточно написать:

    Depends {
        name: "boost"
        submodules: [ "threads", "system", "filesystem" ]
    }


И мне в этом месте будет совершенно безразлично — собран ли boost статично, в разделяемую библиотеку, или я его вообще поставляю с собой из исходников. В CMake эти ситуации приходится различать.

В современном мире хочется, чтобы IDE могла полноценно работать со скриптами сборки. QBS был изначально разработан с целью наиболее эффективной интеграции с различными IDE. Для CMake же невозможно, или очень сложно, сделать качественную поддержку в IDE.

В современном мире, так же, могут возникать ситуации, когда во время сборки нужно совершить дополнительные действия, в QBS для этого можно написать свои правила обработки файлов, в CMake нужно либо вызывать внешние утилиты, либо делать что-то до этапа сборки, во время запуска самого cmake'а, что не всегда применимо.

В CMake список доступных для сборки языков жестко определяется самой системой, я не могу при помощи CMake собрать, например, проект на языке R. QBS изначально был сделан так, чтобы бинарному коду индифферентно что именно мы собираем, вся поддержка C++/Qt/whatever находится в *.qbs файлах, единственное исключение — это анализ файлов наличие дополнительных меток и зависимостей. Поэтому существует бинарный плагин для поиска #include/#import директив в файлах для учета зависимостей, а так же плагин для поиска использований Q_OBJECT, чтобы повесить на файл дополнительную метку, которая «натравливает» на файл автоматически moc. Таким образом, чтобы добавить в QBS новый язык — не надо патчить саму систему сборки, достаточно написать пару несложных *.qbs скриптов и, быть может, бинарный плагин для анализа файлов.
Нет, в целом, Вы, конечно, говорите правильные вещи, но есть несколько моментов:
1) Переводы, ресурсы и прочее сейчас также легко цепляются CMake. Для разных систем есть configure_file и #cmakedefine.

2) Если Вы не хотите заморачиваться, как у Вас там собран boost (или что-то еще), то достаточно написать
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})

Либо одной строчкой искать необходимое:
find_package(Boost COMPONENTS threads system filesystem)

И потом просто слинковаться с нужными библиотеками:
${Boost_LIBRARIES}

Неужели это так сложно и непонятно?
Потом, «И мне в этом месте будет совершенно безразлично» — а если нет? Лично у меня чаще небезралично.

3) А как же QtCreator, который отрывает проекты по CMakeLists.txt?
А как же макросы для VS?

4) Неправда.
Вот так вот я генерирую файлы маппинга из моделей:
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/Model)
foreach(_file ${ODB_MODELS})
   string(REPLACE ".h" "-odb.cxx" ODB_GENERATED_FILES ${_file})
   add_custom_command(
     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ODB_GENERATED_FILES}
     COMMAND odb -d sqlite --profile qt --generate-query --generate-schema 
     -o ${CMAKE_CURRENT_BINARY_DIR}/include/Model
     ${CMAKE_CURRENT_SOURCE_DIR}/${_file}
     -I${QT_INCLUDE_DIR}/QtCore
     -I${QT_INCLUDE_DIR}
     DEPENDS ${_file}
     COMMENT "ODB'ing ${_file}..."
     )
   list(APPEND MOC_SOURCES ${ODB_GENERATED_FILES})
endforeach()

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

5) Это правда, в CMake других языков не добавишь (во всяком случае, простыми способами).

Это я все к тому, что инструменты уже давно позволяют решать все эти проблемы. Декларативность — это, конечно, хорошо, но и макроязык CMake — штука простая и удобная. При должном подходе можно все очень точно настроить.
1. Все таки не очень просто

2. Если хочется использовать boost, поставляемый с исходниками, то такой способ уже неприменим, поведение становится неопределенным (boost, конечно не лучший пример, лучше подойдут всякие libgif, libjpeg и прочие). Либо придется городить свои костыли.

3. QtCreator заставляет CMake генерировать CodeBlocks проекты и потом открывает их, при этом возникают различные артефакты: если файлы не прописываются все ручками, а используется glob, то они не подхватываются без перезапуска CMake. Так же QtCreator в таком случае неспособен понять, что используется c++11 или c++03, не всегда понимает какие define'ы определены и какие у них значения.

А что макросы для VS? Не могли бы вы развернуть идею?

4. Здесь происходит запуск внешней утилиты odb, о чем я и говорил. QBS же позволяет писать правила обработки прямо на JavaScript, без запуска внешних утилит.
1) Если говорить о CMake и Qt:
перевод:
set( MYPROJECT_LANG_FILES lang.ts )
qt4_create_translation(MYPROJECT_LANG_SOURCE ${MYPROJECT_LANG_FILES})

ресурсы:
set(MYPROJECT_RESOURCES_FILES resources.qrc)
qt4_add_resources(MYPROJECT_RESOURCES ${MYPROJECT_RESOURCES_FILES})


Конфигурационный файл.
Я, честно говоря, в упор не могу понять, где тут хоть намек на сложность.

2) Не очень Вас понял. Допустим, есть где-то распакованный, но не скомпилированный boost. Ну так достаточно указать в ENV путь к корневой директории boost'а (BOOST_ROOT), чтобы эта конструкция
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})

успешно работала.
Если нужно еще и либы цеплять, просто добавить команду линковщику:
target_link_libraries(projectname ${Boost_LIBRARIES})


Ну и с остальным приблизительно в том же духе. Конечно, тут нужно сказать, что некоторые модули, идущие в поставке, уже давно не обновлялись и ищут вообще что-то не то или не так, так что иногда на их базе приходится писать что-то свое. Но опять же, это 10-20 строк макрокода, как правило.

3) Да, перезапускать нужно. Но это можно сделать прям в QtCreator, без каких-то особых телодвижений.
А в VS даже этого делать ненужно — если что-то в проекте изменилось, VS сама (с помощью CMake'овский макросов) попросить перегенерировать проект.
Т.е., есть взять Ваш пример (файлы добавляются как-то так file(GLOB SOURCES «src/*.cpp»)), то при создании файла в src, а потом при нажатии кнопки компиляции, выскочит окно, которое предложит перегенерировать изменившийся проект. Все это происходит быстро и автоматический.
Ровно тоже самое происходит, если работать в VS с проектом, а потом что-то поправить руками в CMakeLists.txt — автоматически вызовется CMake и перегенирирует проект.

Насчет c++11 или c++03 и define'ов ничего сказать не могу, т.к. просто не знаю.

4) А, понял идею. Обычно все же нужно прогнать файл через moc, odb или еще какую-то софтину, а не самому творить магию с файлом. Но согласен, это может быть очень полезно.
1. В qbs это будет просто
Product {
    files: [ "a.cpp", "b.ts", "c.qrc" ]
}


Дальше как обрабатывать тот или иной файл — определяется автоматически по его типу и подключенным зависимостям модуля. Дело не в том, что в CMake это нельзя сделать, а в том, что для каждого типа файла нужно каждый раз делать что-то свое, нет общего механизма. И если на то пошло, то для Qt5 и Qt4 в CMake работа с moc'ом/qrelease/etc идет по разному, то нисколько не облегчает жизнь. В QBS же ничего не меняется.

2. Что такое BOOST_ROOT, если он не установлен, а только будет собираться вместе с моим проектом?

3. Да, можно, только, как правило, это долгий процесс, на моих проектах это может занимать секунды, а может и десятки, qbs себя ведет гораздо быстрее, отрабатывая за доли секунды.
Вы меня уж простите, но тот фрагмент который Вы привели, сложно описать словами «простая и удобная». По крайней мере слово «простая». Для такой «простой» задачи, как вызов внешней утилиты, как отметили выше.
Честно говоря, под рукой просто нет примера получше.
Простой вызов внешней утилиты выглядит как-то так:
	add_custom_command(
		# Перечисление результирующих файлов (в данном случаи один)
		OUTPUT "${_current_file_name}"
		# Выполняемая команда
		COMMAND icotool
		# Её аргументы
		ARGS -x --icon -i ${_current_index} -o ${_current_outfile} filename.ico
		# Перечисление исходных файлов, от которых зависит результат
		# выполнения команды (в данном случаи тоже один)
		DEPENDS filename.ico
 	)

(взял отсюда).

В моем же примере происходит чуть больше всего:
1) создается директория, куда все будет складываться
2) файлам моделям, вместе посфикса .h, добавляется постфикс -odb.cxx
3) перечисляю выходные файлы
4) вызываю программу с параметрами
При этом, весь код вызываемой программы занимает половину приведенного примера:
     COMMAND odb -d sqlite --profile qt --generate-query --generate-schema 
     -o ${CMAKE_CURRENT_BINARY_DIR}/include/Model
     ${CMAKE_CURRENT_SOURCE_DIR}/${_file}
     -I${QT_INCLUDE_DIR}/QtCore
     -I${QT_INCLUDE_DIR}

Этот код передает необходимые параметры в odb.
5) указываю зависимости
6) пишу коммент
7) добавляю полученные файлы в список

Т.е. тупо вызов программы выглядит ну проще некуда:

add_custom_command(
     OUTPUT ${file}
     COMMAND program)

Другое дело, что просто никогда не бывает.
хорошо, с Вашими пояснениями немного стало легче, спасибо за конструктивные комментарии.
Все же есть некоторая доля субъективности, уж не обессудьте: синтаксис что традиционных makefile-ов, что CMake кажется мне уж больно неинтуитивным. qmake это так вообще тихий ужас. Не то что с поллитрой, но даже в обнимку с доками не разберешься порой. Хоть мне с последним пришлось достаточно повозиться, чтобы создать гибкую систему сборки кучи проектов с настройками в одном месте, с qbs все значительно проще. Я не спорю, что возможно, повозившись с документаций, на CMake это все вышло ничуть не более сложным. Может быть. Но вот какая-то таинственная, личная наверное, «интуитивность» в qbs есть. Для меня. Когда просто пишешь код — и это работает так, как ожидал.

ps. ну например тот же «list(APPEND ..» и уже знакомый яваскриптовый [].concat или [].push_back.
Само собой, каждому свое — спору нет. Я тоже очень ждал полноценного релиза QBS — система смотрится бодро. Речь тредика просто зашла о переходе с CMake на QBS — мне стало не очень понятно, зачем человеку, знающему CMake, переходить на QBS? Что такого необходимого есть в последнем, чего так не хватало в первом?

Вообще, ведь основные проблемы, как кажется мне, появляются не при добавлении файлов, описании зависимостей или вызове сторонней программой. Это все делается просто, уже везде сто раз описано. Интересно — это, например, подключить предкомпилированные заголовки, которые будут работать на всех компиляторах без всяких плясок с бубном. Или unity builds. Как с этим у QBS? Я вижу только пару сообщений на баг-трекере.

В свое время, я несколько дней убил на написание поддержки предкомпилированных заголовков под разные компиляторы (правда, именно тогда я и начала изучать CMake, так что отпечаток неопытности был наложен). Но все равно какие-то косяки вылезали постоянною. Потом нашел проект cotire, реализующий precompiled headers и unity builds для CMake — использую до сих пор. Вот так вроде задача простая, а проект занимает 3000 строк кода. А без них собирать большой проект — постареешь.
А вот, условно говоря, канонический cmake файл для стартового проекта:
cmake_minimum_required (VERSION 2.8)

set(APPLICATION_NAME "Test")
project(${APPLICATION_NAME})

set(CMAKE_USE_RELATIVE_PATHS true)

if(MSVC)
	set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "/W3 /MP")
elseif(CMAKE_COMPILER_IS_GNUCXX)
	set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-Wall -pedantic")
endif()

include_directories(./include)
file(GLOB_RECURSE ${APPLICATION_NAME}_HEADERS "include/*.h")
file(GLOB_RECURSE ${APPLICATION_NAME}_SOURCE  "src/*.cpp")

set(PROJECT_FILES)
list(APPEND PROJECT_FILES ${${APPLICATION_NAME}_HEADERS} ${${APPLICATION_NAME}_SOURCE})

add_executable(${APPLICATION_NAME} ${PROJECT_FILES})
target_link_libraries(${APPLICATION_NAME})
set_target_properties(${APPLICATION_NAME} PROPERTIES DEBUG_POSTFIX "_d")

Прощу прощения, в блоке флагов кавычки неверно стоят. Должно быть так:
if(MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /MP")
elseif(CMAKE_COMPILER_IS_GNUCXX)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic")
endif()
А ведь это логически просто свойство проекта, которое по идее разные тулчейны должны сами разруливать в соответствии со своими тараканами, а тут сам юзер занимается этим бредом из проекта в проект.
Вообще, по умолчанию CMake генерит проект VS с правильными свойствами. Для меня самого загадка, почему те же ворнинги нужно постоянно прописывать так руками. Но это не такая большая проблема, на самом деле.
Кстати, в QBS мне достаточно указать абстрактную «вербозность» компилятора, которое само превратится в нужные флаги :)
Ребят, без шуток, если есть опыт — напишете статью! Я думаю, хабрапользователи будут рады.
Пока, по имеющимся документации и проектам, совершенно непонятно, как это работает на более-менее больших проектах.
Дружище, только первый абзац текста был о CMake, и то в качестве шутливой догадки, а ниже имеется ввиду чисто make.
Это было неочевидно — ведь тредик начался именно с желания перейти с CMake на QBS. Чистые make файлы неинтересны хотя бы потому, что не дают комфортной работы под разными системами.
Это императивные портянки, которые непонятно как парсить, там абсолютно дебильная область видимости, много неочевидной фигни, уродливый язык для скриптования (все эти IF(DEFINED AAAAA) ENDIF() и т.д.
И потом, тот же d или charp в qbs прикручивается за пару суток, а для cmake'а приходится чуть ли не отдельную ветку тащить.

Я уж молчу про ужасы типа получения свойств проекта и их изменения. Cmake чуть красивше autotools' а и наконец-то более менее портабельный, но это ужасы одной эпохи, их пора бы уже закопать и посадить на могилку цветочки. Мне не очень хочется тратить кучу времени на ковыряния скриптов сборки.
Ну, видимо, на вкус и цвет. Мне потребовалось несколько дней, чтобы уверенно работать с CMake. И я говорю не о проектах уровня helloworld, а о сборки проекта с 3d-движком и сопутствующими несколькими десятками библиотек. Ничего сложного или неочевидного я не увидел. По первости можно было встрять на фигне, но, в целом, проблем нет.
А что со свойствами проекта не так? По-моему, они как раз очевиднее всего и правятся.

Что касается прикручивания сторонних языков, то тут я уже писал выше — увы, в CMake это сделать нельзя (во всяком случае, удобным способом).

А вообще, я бы, конечно, с удовольствием посмотрел на QBS в действии на более-менее серьезных проектах. Если у Вас есть опыт и свободное время, может, поделитесь с хабрасообществом? Я бы точно был благодарен. Так пока сложнее helloworld ничего не находится.
Я с cmake тоже очень много работал и с его граблями знаком близко. Из более менее сложных проектов qbs используется в креаторе и еще мы им собирали qutIM.
Qt меня активно радует в последнее время. Теперь еще это =)
Ждем Qt 5.1! Они же обещали до начала лета… Каждый день на сайте жду новостей.
Скоро будет. В списке рассылки объявили Qt 5.1 RC1. А начало лета — понятие растяжимое. :)
Где такие обещания берете, если не секрет? Вроде видел в планах roadmap первоначально на июнь. Но в любом случае, пусть задержат но уж вылижут, качество важнее. Если не терпится, сборка из git всегда была к услугам энтузиастов)
Класс, но всё-таки до полноценного его юзания не хватает.
1. Поиска зависимостей, Probe'ы выглядят крайне недопиленными.
2. Configure, который мог бы протестировать системные особенности и в соответствии с ними настроить проект.
3. Deployment'а. Install это хорошо, но мало, нужно еще уметь для винды подложить все библиотеки и плагины, а для мака собрать портабельную app. Туда же и сборка apk, пакетов для BB или вообще умения делать deb'ки без поллитры.
Про сборку пакетов, как я помню в обсуждениях где-то видел, что решили что это out of scope. Что упаковку должны делать соответствующие специальные тулзы) Ведь и верно, так можно и до systemd докатиться. Поэтому пусть как по мне уж лучше собирает хорошо, и возможно генерирует какие-то спеки для других систем сборки (те же DEBIAN/control файлы например).

P.S. С пробками реально печально, все надеялся что допилят их до 1.0 версии-то. Что-то рановато все же bump сделали. Хотя так вспомнить, Креатор 1.0 тоже не особо функциональный релиз был (первый который я ставил)
Да по сути дела генератор спеков и нужен и плюс штатная утилита для винды и мака. Там примерно одно и тоже нужно делать.
Ребят, расскажите пожалуйста, как осуществляется кросскомпиляция с qbs.
К примеру, у меня есть простейший .qbs файл.
import qbs.base 1.0
CppApplication {
     name: "HelloWorld"
     files: "main.cpp"
}

Как мне собрать проект с разными toolchain'ами?
Допустим, мы только что собрали qbs.
Выполняем следующее в консоли ( doc-snapshot.qt-project.org/qbs/configuring.html ), для которой выполняется одно из условий:
— в PATH доступен mingw32-g++.exe или иначе названный бинарь;
— консоль есть результат использования ярлыка «Developer Command Prompt for VS2012» или иного для других версий;
— действие происходит на машине с Unix-подобной ОС.
Допуская, что qbs тоже в PATH:
qbs detect-toolchains

Для того, чтобы собрать первым попавшимся тулчейном, выбранным qbs-ом как инструментарий по-умолчанию ( doc-snapshot.qt-project.org/qbs/building-applications.html ):
cd в/папку/с/проектом
qbs

Для того, чтобы собрать чем-то другим:
qbs build release profile:<имя профиля, связанного с тулчейном>

Могу ошибаться, ибо с qbs игрался давно, но примерно так всё и должно выглядеть.
К сожалению я так и не нашел нормального способа добавить несколько toolchain'ов.
Команда qbs detect-toolchains может только подменять один на другой.
В результате настроил так:
qbs config preferences.qbsPath /tmp/qbs/share/qbs/
qbs config preferences.pluginsPath /tmp/qbs/plugins/
CROSS_COMPILE=arm-arm926-linux-gnueabi- qbs detect-toolchains
Скопировал настройку кросскомпилятора в буфер обмена. Настройка хранится в ~/.config/QtProject/qbs.conf
Далее настраиваю host gcc и версии Qt:
qbs detect-toolchains # здесь cross gcc подменяется на host gcc
qbs setup-qt /usr/bin/qmake-qt4 qt4
qbs setup-qt /opt/arm-glibc-toolchain-arm926/sys-root/usr/bin/qmake qt5
Вставляю в qbs.conf настройку кросскомпилятора заменяя gcc на gcc-arm.
Теперь могу собирать проекты как с qt4 так и с qt5. По умолчанию использоваться host gcc.
qbs profile:qt4
qbs profile:qt5

Что бы собрать кросскомпилятором, нужно сделать следующее:
qbs config profiles.qt5.baseProfile gcc-arm
qbs profile:qt5
Честно говоря, ничем не могу помочь.

Вот результаты на моей системе:

C:\Dev\git\qbs\bin>qbs detect-toolchains
Detecting MSVC toolchains...
  MSVC detected:
    version 2012
    installed in C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin
Setting up profile 'MSVC2012'.
Platform 'i686-w64-mingw32' detected in 'C:/Dev/mingw/mingw-4.7-x86_32'.

C:\Dev\git\qbs\bin>qbs config --list profiles | grep toolchain
profiles.MSVC2012.cpp.toolchainInstallPath: C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin
profiles.MSVC2012.qbs.toolchain: msvc
profiles.i686-w64-mingw32.cpp.toolchainInstallPath: C:/Dev/mingw/mingw-4.7-x86_32/bin
profiles.i686-w64-mingw32.qbs.toolchain: mingw


Как видите, нашёл msvc2012 и mingw. Чести ради, нашёл он не все имеющиеся версии mingw:

C:\Dev\git\qbs\bin>where g++
C:\Dev\mingw\mingw-4.7-x86_32\bin\g++.exe
C:\Dev\mingw\mingw-4.7-x86_64\bin\g++.exe


Возможно, проблема со взаимоисключающими gcc у нас общая.
Да я уже подсмотрел в исходниках. Если взглянуть на platforms/probe.cpp становится понятно что к чему. Отсюда и родился метод описанный выше, иначе никак не догадаться, как в принципе другой toolchain подцепить. Думаю в следующих версиях команду detect-toolchains расширят. Само ядро qbs умеет работать с множеством toolchain одного типа.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации