Инструменты пользователя

Инструменты сайта



// CMake Imported Targets

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

Для примера, если вам нужно подключить ZLIB к проекту, при классическом подходе пишется что-то вроде:

cmake_minimum_required (VERSION 3.1)
project(Foo)
 
find_package(ZLIB)
 
add_definitions(${ZLIB_DEFINITIONS})
include_directories(${ZLIB_INCLUDE_DIRS})
 
add_executable(foo_target 
               main.cpp)
target_link_libraries(foo_target ${ZLIB_LIBRARIES})

Какие проблемы в коде выше?

  1. Добавляется новая библиотека, нужно не забыть добавить переменные в три места:
    1. add_definitions()
    2. include_direcrories()
    3. target_link_libraries()
  2. Мы забыли ключевое слово REQUIRED в find_package() и узнаем, что у нас нет ZLIB или на компиляции или на линковке (так как других условий и проверок нет, предполагаю: данная библиотека необходима).
  3. Область действия add_definitions() и include_directories() - глобальная (на самом деле нет: все таргеты в текущем CMakeLists.txt во всех далее включённых, но не суть) и распространяется на все таргеты. Что не есть хорошо.

Возможно что-то ещё, чего я не заметил.

Последний пункт можно обойти уже написав более навороченный код:

cmake_minimum_required (VERSION 3.1)
project(Foo)
 
find_package(ZLIB)
 
add_executable(foo_target 
               main.cpp)
target_include_directories(foo_target ${ZLIB_INCLUDE_DIRS})
target_compile_definitions(foo_target ${ZLIB_DEFINITIONS})
target_link_libraries(foo_target ${ZLIB_LIBRARIES})

От проблемы глобальности ушли, но остальные две остались.

А вот, начиная с CMake 3.1 код выше можно переписать так:

cmake_minimum_required (VERSION 3.1)
project(Foo)
 
find_package(ZLIB)
 
add_executable(foo_target 
               main.cpp)
target_link_libraries(foo_target
                      ZLIB::ZLIB)

И теперь правильно подтянутся и параметры для компиляции, причём только для указанного таргета, и параметры линковки. А кода стало меньше. Более того, если библиотека не найдена, то цели ZLIB::ZLIB существовать не будет и вызов cmake завершится с ошибкой. А чем раньше ошибка вылазит - тем лучше.

Как это делается? А достаточно просто, маинтейнеру модуля поиска нужно в конце добавить строчки вида:

if (ZLIB_FOUND AND NOT TARGET ZLIB::ZLIB)
  add_library(ZLIB::ZLIB UNKNOWN IMPORTED)
  set_target_properties(ZLIB::ZLIB PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}"
        INTERFACE_COMPILE_OPTIONS "${ZLIB_DEFINITIONS}"
        INTERFACE_LINK_LIBRARIES "${ZLIB_LIBRARIES}")
endif()

Код для FindZLIB.cmake на самом деле несколько другой, но общую суть он отражает.

Соглашение для таких тергетов простое:

PkgName::PkgComponent

где PkgName соответствует имения пакета, которое передаётся в find_package() (или имя модуля без префикса Find и суффикса .cmake), а PkgComponent - внутренний компонент внутри модуля. Если такой компонент один, он соответствует PkgName. Примеры:

  • ZLIB::ZLIB
  • Threads::Threads
  • Qt::Widgets (см FindQt.cmake)

Кстати, вместо проверки:

if (ZLIB_FOUND)

Можно использовать:

if (TARGET ZLIB::ZLIB)

да, более многословно, но везде фигурирует только одно имя таргета.

Кроме того, эти таргеты можно использовать и совместно с target_include_directories() и target_compile_definitions().

В общем, я крайне рекомендую в свои модули добавить несколько строчек, которые привнесут несколько большей унификации. От старых добрый переменных вас тоже никто отказываться не заставляет :)

ЗЫ ЕМНИП то такой синтаксис можно было использовать и до 3.1, с 3.1 оно появилось в некоторых модулях, которые поставляются с самим CMake.

// Qt Creator, CMake: отображение всех файлов в стоковом плагине

Немного в сторону от CMakeProjectManager2, в направлении стокового плагина.

Дискуссия на LOR навела на мысль. Ради спортивного интереса попробовал реализовать и… получилось! :)

За подробностями под кат.

// CMakeProjectManager2: теперь и с Server Mode

Вот и прошло почти два месяца с последних изменений.

Время было потрачено:

  1. для ожидания некоторой стабилизации апстрима, так как, по сути, они требовали писать абсолютно новый код для реализации текущего функционала, а в условиях сильных и фатальных изменений, переписывать свой код на каждый чих… у меня столько времени нет.
  2. была предпринята неудачная попытка продвинуть код в апстрим.
  3. ну и изучался новый код, когда выпадало время, плюс раздумья - как применить функциональность и для серверного режима работы CMake.

Так как код отвергли, а это, по сути, написанная с нуля реализация старого функционала, то он был взят за основу новых изменений. Ну как основу - 99%.

Есть и изменения. Малой кровью была создана обёртка поверх Server Mode Reader'а, которая предоставляет всего его внутренние профиты за исключением классического вида дерева файлов.

Соответственно изменения, сделанные для старого ридера (Tealeaf Reader), который используется для версий CMake младше 3.7, в части отображения всех файлов, добавления, удаления и переименования теперь применимы и для Server Mode Reader.

Сразу же был найден и первый баг: неправильно обрабатываются дефайны из CMAke (add_definition()). Патч уже отослан, у себя в коде изменений делать не буду, подожду, пока попадёт в апстрим, потом засинхронизируюсь.

Функциональность же передачи Toolchain файлов выла дропнута. Можно делать настройки через Kit или же вручную создать параметр CMAKE_TOOLCHAIN_FILE и задать нужный. Главное не забудьте сделать Build → Clear CMake Configuration после этого. Ну и будьте готовы, что парсер C++ вас перестанет понимать, как минимум, частично.

Пакеты для Ubuntu 14.04 и 16.04 и производных уже доступны через PPA. Не забываем внимательно читать описание репозитория.

В ближайших планах подготовить ветку для стабильной версии QtC - 4.2. Там окажется только текущая функциональность и нового появляться не будет (если только кто-то не возьмёт её на сопровождение). Есть вероятность, что серверный режим будет выключен, так как он требует много смежных изменений и бекпортирования. Явные косяки тоже будут переноситься. В будущем, планирую саппортить только текущую версию QtC. Для старых не планирую даже исправления ошибок переносить. На всё это нужно время.

Если кто-то предложит варианты, как делать пребилды плагина для официальных версий QtC в автоматическом или полуавтоматическом режиме, буду рад выслушать.

Ну и с ошибками и предложениями: https://github.com/h4tr3d/cmakeprojectmanager2/issues

// CMakeProjectManager2 возвращается

В продолжение Qt Creator, CMake и судьба CMakeProjectManager2.

Ревью https://codereview.qt-project.org/#/c/180827/ расставило точки над i: "Project View == Build System View", билд система не может отображать все файлы проекта? Значит не будем показывать. Билд система не предоставляет возможности добавлять, переименовывать и удалять файлы в проекте? Значит не будем даже пытаться предоставить возможность это делать. Не удобно? Ничего, целостность концепции важнее.

Хотя… мне одному кажется, что абстракции тут текут? Ведь Project View сам по себе подразумевает именно проект?

Да, моё решение тоже не верх совершенства, даже так - костыль. Но он же реально помогает в условиях отсутствия более приличной альтернативы…

Ну и обоснование всего одно: «Я боюсь баг-репортов».

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

В любом случае, сейчас будет перезагрузка кода, потому как для новой кодовой базы, по сути, написан новый код. Сейчас буду думать, как наименьшей кровью в истории перенести новые изменения. Скорее всего придётся заревертить все прошлые мои изменений, привести master в состояние идентичное qtc-master, после чего просто сделать новый комит.

Ну а родной менеджер начнёт поддерживать данную функциональность, только кода CMake Server Mode сподобится на это. Удачи в ожидании :) Особенно при том условии, что конкуренты (KDevelop, Clion) это умеют делать.

// Qt Creator, CMake и судьба CMakeProjectManager2

Проект в стадии прекращения работы над ним…

// CMake и Qt Creator: на пути к CMake server mode

В транке появилась пачка изменений, ориентированные на использование CMake Server Mode, в связи с чем плагин теперь может работать только с CMake версии 3.0 и более новым. Тобиас крепко взялся за плагин и будем надеяться, что, как минимум, скоро не будет требоваться:

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

Пока CMake Server Mode большего не предоставлят: в основном информация, но не изменение её. Так что ожидать автоматическое добавление файла к нужной цели или переименование файла в билд-системе средствами этого нового режима не стоит.

Ну а в самом QtC пока только инфраструктурные изменения, чтобы эту фичу начать поддерживать.

И от себя: в CMakeProjectManager2 добавил возможность использовать трюк от cmake, что бы задать варианты возможных значений для какого-то параметра и выводить их при редактировании в виде выпадающего списка. Фичу портировал в апстрим и завёл ревью, кому нужно, голосуйте: https://codereview.qt-project.org/#/c/173340

Про сам трюк:

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

set_property(CACHE OptionName PROPERTY STRINGS PossibleValue1 PossibleValue2 PossibleValue3 ... PossibleValueN)

Ни на что, кроме как для подсказки GUI этот параметр не влияет: CMake не делает валидацию введённых значений, поэтому возможность задать любое другое - остаётся.

Ссылки по теме:

// Новые интересные фичи в Qt Creator Master

Для начала: создал репозиторий PPA, куда буду с разной периодичностью бубликовать снапшот QtC из master-бранча. Кроме того, туда же поместил свой плагин CMakeProjectManager2:
https://launchpad.net/~adrozdoff/+archive/ubuntu/qtcreator-git

Установка:

sudo add-apt-repository ppa:adrozdoff/qtcreator-git
sudo apt-get update
sudo apt-get install qtcrator-git qtcreator-git-plugin-cmake2

Для разработчиков плагинов будет полезен пакет qtcretor-git-dev который ставит в /usr/src/qtcreator-git заголовочники и .pri файлы. Пример использования можно поглядеть в спеках отстройки qtcreator-git-plugin-cmake2:

sudo apt-get install qtcrator-git-dev

Ну а теперь фичи.

Кодовая модель

Уже давно появились приятные дополнительные инструменты вроде «Reparse Externally Changed Files» (удобно при наличии внешних генераторов, тот же протобуф) и «Inspect C++ Code Model…», позволяющая понять, что не так при парсинге и отослать более вменяемый отчёт.

Сравнительно же недавно появилась возможность задавать индивидуально для каждого файла дополнительные директивы препроцессора: «Additional Preprocessor Directives…». Очень удобная штука, когда парсинг почему-то затыкается (например какая-то опция может подхватываться из переданных CXXFLAGS) - обозначил и вперёд! Или правишь код на одной системы, а нужно исправить блок для другой: определяем «#define WIN32» и пробуем что получилось. Для быстрого доступа служит иконка с «#» в верхнем правом углу рядом с номером строки и колонки.

GUI

Тоже появилось сравнительно давно, многие просили: открытие в новом окне (Window → Open in New Window иди Ctrl+E,4). Удобно при навигации и рефакторинге при наличии нескольких мониторов.

CMake

Про свой плагин не пишу. В мейнстриме появилась возможность задавать не один фиксированный cmake, а разные для разных наборов инструментов (Kits).

External Tools

Данный функционал оооочень давно в QtC, но очень многие его не замечают. А ведь очень много проблем можно решить с его помощью. К примеру: править исходники локально, а потом засабмитить на билд-сервер и выполнить на нём процедуру билда. Если чуть поднапрячься, можно и парсинг ошибок разобрать.

Либо вызвать cppcheck на текущий проект, либо… что в голову взбредёт.

Чего хотелось бы, но нет

- Настройки лицензии (шапки для новых файлов) индивидуально для проекта. - Замена отдельных частей Kit индивидуально для проекта - Более гибкая система настройки устройств для Baremetal: сейчас устройство намертво привязано к Kit со своими настройками доступа к, примеру, OpenOCD и gdb. Вот для Cypress SDK нужно как минимум два: для основной прошивки и для Bootloader.

Засим пока всё.

// CMake для Cypress FX3

Слишком много параметров сборки появилось. Поэтому на досуге да под эгидой нового продукта наваял правила для сборки кода при помощи CMake: https://github.com/h4tr3d/fx3-cmake

Под виндой нужно обязательно указывать генератор: при использовании `cs-make` поставляемого вместе с SDK это «MinGW Makefiles».

// CMakeProjectManager2: улучшения в диалоге конфигурирования (2)

Очередная порция изменений в развитие CMakeProjectManager2: улучшения в диалоге конфигурирования:

  1. Исправлен креш при создании конфигурации, при указании тулчейн файла, когда он лежит в директории исходников. Изредка креш проявлялся при переключении уже готовых конфигураций.
  2. Добавлена кнопка обзора для выбора тулчейн-файла. По умолчанию открывается в дереве исходников проекта, если тулчейн выбран в другом месте (к примеру, у вас коллекция тулчейнов независимых от проекта), то открывается в месте, где лежит тулчейн. В быстрые закладки добавляется ссылка на дерево проекта, что бы было можно быстро туда перейти. Закрыта задача #2.
  3. Добавлена возможность очищать кеш при запуске CMake, что бывает необходимо при изменении некоторых параметров, одним из них, к примеру, является CMAKE_TOOLCHAIN_FILE, другим популярным (особенно при выборе разных версий Qt) является CMAKE_PREFIX_PATH. Изменение этих параметров без удаления кеша ни к чему не приводит, поэтому добавил параметр «Reset cache on CMake run». Стоит отметить, что при изменении тулчейна это действие обязательно, поэтому, если тулчейн поменялся, но этот параметр не включен, то будет выдаваться вопрос: «You change toolchain. This action requires CMake cache reset. Continue?». Закрыл задачу #1
  4. При встроенном редактировании тулчейна теперь открывается не пустое окно, если ничего не было, а пример тулчейна для Mingw. Можно оставлять только опции, задающие компилятор, что бы выбрать нужную версию оно в системе, если их стоит несколько.
  5. Небольшое косметическое изменение: кнопка Edit стала поменьше.

// CMakeProjectManager2: улучшения в диалоге конфигурирования

Для тех, кто не в курсе, что такое CMakeProjectManager2, вот ссылка на статью 2012 года: CMakeProjectManager2 - последние изменения. Собственно тогда и были сделаны последние крупные изменения, которых мне хватало до сегодняшнего дня. В остальном была работа по синхронизации кодовой базы с апстримом, что бы плагин продолжал собираться и радовать глаз. Код располагается на GitHub: https://github.com/h4tr3d/cmakeprojectmanager2. Инструкции по сборке приложены в README.txt

Итак, как бы ни хотелось, но времени заниматься реализацией TODO листа нет и не предвидится (суть списка: сделать парсер и обойтись без генерации файла для CodeBlocks, а всё остальное уже на это опирается). Но есть и другие задачи. В частности, в сегодняшнем обновлении несколько изменён вид окна «Run CMake» мастера, а именно:

  1. Добавлена возможность выбирать тип сборки
  2. Добавлена возможность назначать тулчейн (это файл с настройками среды сборки, особенно актуально для кросс-сборки: http://www.vtk.org/Wiki/CMake_Cross_Compiling#The_toolchain_file).

По сути, эти параметры служат для задания в более дружественной формы параметров для CMake: -DCMAKE_BUILD_TYPE= и -DCMAKE_TOOLCHAIN_FILE= соответственно.

Про тулчейн немного подробнее. Изначально планировалось три способа его задания:

  1. Автоматическое конструирование на основе Qt Creator Kit
  2. Ручное задание файла (пока сделано без возможности открытия диалога поиска, только ручной ввод: issue #2)
  3. «Инлайн» тулчейн: редактирует во встроенном редакторе, при запуске контент сохраняется в директории отстройки под именем QtCreator-toolchain-override.cmake

Пока вариант на основе Qt Creator Kit выключен. Будет время - доделаю.

Плюс есть нюанс: согласно документации CMake, смена тулчейна возможно только на новой конфигурации либо на полной очистке текущей (удаления CMakeFiles и CMakeCache.txt), поэтому, если замечены изменения настроек тулчейна, производится полное переконфигурирование без использования кеша. Планирую добавить диалог с предупреждением (issue #1).

Стоит отметить, что пользовательский ввод параметров сохранён, более того, определяется, если параметр уже задан, то будет использоваться пользовательский.

Ну и картинка:

// CMakeProjectManager2 - последние изменения

Как я уже писал, вяло пилю модифицированную версию плагина CMakeProjectManager для Qt Creator'а. Там же указаны причины, вынудившие меня на это. Но разговор, не про это, а про то, что с момента прошлого поста было сделано.

Итак:

  1. Для каждого профиля сборки сохраняются введённые параметры для CMake, так что, выбрав в следующий раз «Run CMake» не нужно вспоминать, с какими параметрами вы его запускали и легче управлять профилями сборки. Вкупе с последней фичей из апстрима: сохранения глобальной истории параметров для CMake, получается достаточно мощный механизм.
  2. Используя вышеприведённую информацию, появилась возможность при модификации дерева исходников (добавление, удаление, переименование) в фоновом режиме запускать обновление CBP файла и дерева сборки, что особо актуально при использовании глоббинга.
  3. По сравнению с первым вариантом, получилось значительно сократить расходование памяти при использовании плагина, особенно когда в дереве проекта много вспомогательных модулей, временного C/C++ кода.

Кодовая база периодически синхронизируется с GIT версией Qt Creator. Если кто-то будет делать клоны для стабильных релизов, просьба отписываться с информацией об оных.

HINT:
Так как, при добавлении, удалении или переименовывании файла, не осуществляется модификация CMakeLists.txt, то нужно вносить изменения самому, либо использовать globbing:

# UTILS
file(GLOB_RECURSE UTIL_SOURCES "../util/*.cpp")
file(GLOB_RECURSE UTIL_HEADERS "../util/*.h" "../util/*.hpp")

На полноценный парсер пока времени нет (хотя уже адоптирован на чистый C++/Qt оный из KDevelop), к тому же, в списке рассылки Qt Creator проскакивала новость, что одна команда разрабатывает полноценный плагин (тыц). Зная это, не хочется делать бесполезную работу, при том, что текущий функционал уже вполне удовлетворяет.

// Boost, CMake, кросскомпиляция

  • Q: Boost.Asio - что нужно указать в cmake среди компонентов при поиске библиотеки boost?
    A: только библиотеку system:
    find_package(Boost REQUIRED COMPONENTS system)
  • Q: Boost.Thread и кроскомпиляция - что делать, если получаем ошибку вида: undefined reference to `boost::tss_cleanup_implemented()'?
    A: для начала чуток обратно: в случае Linux, в качестве компонента при поиске библиотеки нужно указывать thread, а в случае windows (и кроскомпиляции): thread_win32, т.е. необходимо писать что-то вроде такого кода:
    set(BOOST_COMPONENTS
        program_options
        system
    )
    # Boost thread library is different on Win/Linux
    if(WIN32)
      set(BOOST_COMPONENTS ${BOOST_COMPONENTS} thread_win32)
    else()
      set(BOOST_COMPONENTS ${BOOST_COMPONENTS} thread)
    endif()
     
    ...
     
    find_package(Boost COMPONENTS ${BOOST_COMPONENTS} REQUIRED)

    Подсказку увидел тут: http://lists.gnu.org/archive/html/mingw-cross-env-list/2010-11/msg00063.html. Так же следует добавить следующее (при статической линковке):

    add_definitions(-DBOOST_THREAD_USE_LIB=1)

    . Далее, собственно, относительно самого вопроса, предлагают в случае появления такой ошибки при компиляции, поместить в любой свой исходник следующее:

    namespace boost {
     void tss_cleanup_implemented() { }
    }

    чистой воды хак :) Дополнительно написано тут: http://solarcore.blogspot.com/2010/10/boost-c-threads-mingw-mac-os-x.html

// Qt Creator и CMake - продолжение

Некоторое время я поднимал тему связки Qt Creator и CMake, тогда всё показалось не очень хорошо.

В общем, собрался и сделал несколько лучше: малость допилил плагин CMakeProjectManager, реализовав следующие фичи:

  • Дерево проекта берётся не из .cbp файла, а сканированием дерева проекта. Как вариант может оказаться медленно на больших проектах, с другой стороны, релоадинг дерева происходит не каждый раз, а при смене CMakeLists.txt или при добавлении, удалении, переименовывании файлов (этого, кстати, в базовом плагине нет)
  • Теперь можно создавать новые файлы в дереве проектов непосредственно из Qt Creator'а
  • Появилась возможность переименовывать файлы
  • Появилась возможность удалять файлы с диска

Изменения оформлены в виде отдельного плагина (основано на GIT версии Qt Creator, 2.2.81) - CMakeProjectManager2 доступного на Gitorious: http://gitorious.org/hatred-qt-creator-plugins/cmakeprojectmanager2, как устанавливать - читать README.txt, написано моим дряным английским, но, в общем, должно быть понятно.

Кроме того, в основное дерево Qt Creator я подал мёрж-реквест: http://qt.gitorious.org/qt-creator/qt-creator/merge_requests/280

Кроме того, случайно наткнулся мастера новых проектов на CMake: http://apachelog.wordpress.com/2010/09/27/qt-creator-cmake-wizards/ устанавливаются просто.

// Qt Creator и CMake

Пакость: Qt Creator умеет импортировать CMake проекты, проблема в том, что в дереве далеко не все файлы отображаются.

Причина: делается этот импорт через откровенную задницу: вызывает cmake с генератором «-G'CodeBlocks - Unix Makefiles'», генерируя тем самым XML-файл проекта формата CodeBlocks. Но тут накладывается вторая задница: сам генератор обрабатывает файлы только для таргетов: executable, static_library, shared_library, module_library, всё остальное он забывает запихнуть в результирующий '.cbp'.

Решение

Для начала накладываем патч на CMake и пересобираем его:

cmExtraCodeBlocksGenerator.cxx.diff
--- cmExtraCodeBlocksGenerator.cxx.orig 2011-03-15 14:28:30.692010962 +1000
+++ cmExtraCodeBlocksGenerator.cxx      2011-03-15 15:01:05.612566928 +1000
@@ -410,12 +410,14 @@
     for (cmTargets::iterator ti = targets.begin();
          ti != targets.end(); ti++)
       {
+      //std::cout << "Type: " << ti->second.GetType() << std::endl;
       switch(ti->second.GetType())
         {
         case cmTarget::EXECUTABLE:
         case cmTarget::STATIC_LIBRARY:
         case cmTarget::SHARED_LIBRARY:
         case cmTarget::MODULE_LIBRARY:
+        case cmTarget::UTILITY:
           {
           const std::vector<cmSourceFile*>&sources=ti->second.GetSourceFiles();
           for (std::vector<cmSourceFile*>::const_iterator si=sources.begin();

Потом, для тех файлов, которые хотим видеть в дереве создаём фейковый таргет, примерно так:

set(script-files
    process-filelist.sh
)
# hack for display in Qt Creator (with patch for CMake)
add_custom_target(scripts true SOURCES ${script-files})

Всё, после регенерации файлы появятся в списке.

Решение костыльное, но время переписывать импортёр CMake в Qt Creator просто нет, будем надеяться, что разработчики обратят на это внимание.

// Cmake, Qt4 и кросс-компиляция

Есть у меня проектик, он как тестовый полигон, хоть код и достаточно в большом количестве поддается только одной характеристике: исторически сложилось. Но на нем первом я опробовал кросс-компиляцию для Windows из Linux. Теперь его же перевел в обучающих целях на Cmake. Однако, все новое не должно отменять старых достижений, как следствие встал вопрос - а как теперь делать сборку для Windows?

С учетом того, что система сама по себе пока малознакома, решил понапрягать гугл (точнее: http://google.com/linux)

Почти сразу нашел две статьи мини-цикла:

Сделав по этому методу, немного помучавшись, получил все-таки рабочее окружение для отстройки и собрал в проект. Но не давало покоя много ручной суетливой работы, и, практически, полный отказ от уже реализованных методов поиска Qt библиотек в Cmake.

Именно по вышеуказанной причине я решил продолжить изыскания. Поиском по готовым модулям Cmake нашел упоминание некой директивы CMAKE_TOOLCHAIN_FILE, которая, по внутреннему ощущению, должна была мне помочь.

Дальнейший поиск привел меня на вики самого Cmake: How to use MinGW to cross compile software for Windows, где было сказано про тот самый toolchain file. С минимальными изменениями поместил его в каталог cmake в корне дерева проекта.

Ниже приведу листинг этого файла, назвал его win32-x-mingw32.cmake, в адоптации для ArchLinux:

win32-x-mingw32.cmake
# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Windows)
 
# which compilers to use for C and C++
SET(CMAKE_C_COMPILER i486-mingw32-gcc)
SET(CMAKE_CXX_COMPILER i486-mingw32-g++)
SET(CMAKE_RC_COMPILER i486-mingw32-windres)
 
# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH  /usr/i486-mingw32)
 
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search 
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 
# next options is needed by some cases
#set(CMAKE_EXE_LINKER_FLAGS
#    ${CMAKE_EXE_LINKER_FLAGS}
#    -Wl,-subsystem,windows
#    -Wl,-enable-auto-import
#    -Wl,-enable-runtime-pseudo-reloc)
 
# Uncomment this if you have problem: unrecognized option '-rdynamic'
#set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
 
set(MINGW32 1)

Это, конечно, не все, остались последние штрихи.

Использование данного тулчайна приведет к установке переменной CMAKE_CROSSCOMPILING, на основании этого, перед вызовом

find_package(Qt4 REQUIRED)

или аналогичного, достаточно вставить (в случае ArchLinux и пакета mingw32-qt из AUR или моей репы mingw32) следующий код:

if(CMAKE_CROSSCOMPILING)
  set(QT_HEADERS_DIR "/usr/i486-mingw32/include")
  set(QT_LIBRARY_DIR "/usr/i486-mingw32/lib")
endif()

После этого сборка осуществляется примерно так:

mkdir win32-build
cd win32-build
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/win32-x-mingw32.cmake ..
make

Все! :)

PS проверено на Cmake 2.8.1 и Qt 4.6.2

Updated: обновлён файл тулчейна