вторник, 24 февраля 2015 г.

Кто использует точку монтирования?

Иногда при попытке отмонтировать каталог, будь то точка монтирования устройства или tmpfs, мы получаем ошибку devise is busy. Причиной этому могут служить различные факторы, рассмотрим несколько способов узнать кто же захватил нашу точку монтирования:
  1. fuser -v <полный путь> - если точку монтирования блокирует обычный процесс, эта команда покажет какой;
  2. lsof +D <полный путь> - аналогично;
  3. cat <полный путь>/etc/exports - проверяем экспортируются ли для NFS какие-либо каталоги. Запущенный NFS сервер внутри chroot может не определится в шагах 1 и 2;
  4. mount | grep <полный путь> - если внутри этого каталога есть bind mounts или другие mounts (procfs, tmpfs и т.д.), которые не определятся в шагах 1 и 2;

четверг, 6 марта 2014 г.

Миф о переходе Qt с C++ на QML

В сети уже давно циркулируют слухи, а точнее миф о том, что Qt перейдёт с С++ на QML, и весь код, написанный на С++ якобы будет объявлен deprecated. Эти слухи появились из статьи Ларса Нолла опубликованной здесь. Из этой статьи следует следующее:
  • Qt5 поддерживает и будет поддерживать C++ widgets, они не будут объявлены derprecated;
  • C++ виджеты объявлены как законченный модуль, новые возможности на данный момент никто не добавляет, но это не значит, что он заброшен и deprecated;
  • QML - дополнительный способ создания приложений;
  • QML - технология, ориентированная на будущее;
То есть C++ остаётся основным методом написания приложений, а QML просто даёт дополнительный метод создания приложений, часто - для мобильных платформ.

От себя добавлю несколько гадостей о QML (если быть точным, то о Quick), которые могут предотвратить ваш переход на него:
  • QML - довольно простая и ограниченная технология, сложные проекты будут представлять собой спагетти из QML и C++;
  • QML зависит от 2d-ускорения и качества видеодрайверов. Не удивляйтесь, что ваше окошко при быстром перемещении по рабочему столу начнёт чудовищно искажаться - это вина драйверов, то есть то, что вы не сможете починить. При отсутствии 2d-ускорения QML начинает серьёзно тормозить;
  • В QML до сих пор нет некоторых виджетов, которые вы использовали в C++, например дерева или диалогов. Вам придётся искать сторонние варианты реализации таких компонентов, либо писать их самим;
  • В QML компонентах, которые отображают данные, вроде TableView, нет поддержки сортировки, вам придётся в С++ коде создавать объект QSortFilterProxyModel с нужными переопределёнными виртуальными методами, и экспортировать его в QML;
  • В QML нет простого способа импортировать сложные С++ объекты, вам придётся писать дополнительный С++ код-обёртку чтобы передать сложный объект в QML;
  • периодически вы будете сталкиваться с разными недочётами и пользоваться костылями для их обхода (например, массивы в ListElement);
  • в QML нельзя передать любой enumerator из C++. Для этой операции вам потребуется выполнить несколько условий, а именно: 1) enum должен быть объявлен внутри QObject класса 2) внутри этого же класса должны быть объявления Q_OBJECT и Q_ENUMS(). Если вы используете чужие заголовочные файлы с enum-ами, то как вы сами понимаете, сделать их доступными в QML не получится. Самый прямой способ - дублирование объявления значений из enum-a в QML. Самый кривой - различные хаки с moc, работоспособность которых мне, к сожалению, неизвестна;

четверг, 2 января 2014 г.

Несколько слов о локализации ПО

Решил написать несколько слов о локализации ПО, а именно о тех вещах, с которыми столкнулся я сам. В тексте используется Qt-специфичные слова и методы перевода, хотя это не особо важно. Без лишних вступлений перейдём сразу к сути:
  • не расставляйте знаки препинания, да и вообще не воздействуйте на структуру предложения программно. Например, у вас в одном месте используется текст "Prefix", в другом - "Prefix:".  Чтобы сэкономить на спичках вы можете написать в первом месте tr("Prefix"), во втором - tr("Prefix") + ':', таким образом в файле перевода строка "Prefix" встретится только один раз. Это неверно, потому что в некоторых языках, например, во французском, перед двоеточием принято ставить пробел. Написав tr("Prefix") + ':' вы сделаете неприятный сюрприз для французских пользователей;
  • переводческие бюро, которые заявляют об услуге локализации ПО, часто даже не знают что такое XLIFF или .po;
  • ни одна переводческая фирма не даст отличный результат для текста со специфичными для какой-то области словами. Особенно для текста со сленговыми словами, которые понимают только работники данной области. Например, попробуйте перевести с английского глагол "untar" (UNIX-специфичный сленг) - вы даже не найдете его в словаре;
  • гарантированный результат качества перевода даст только индивидуальная работа с переводчиком, но и стоит это соответственно;
  • вы можете использовать онлайн сервисы для перевода вашего проекта добровольцами, например Transifex. Но если ваш проект не слишком популярен, то маловероятно, что добровольцы его переведут хотя бы на три языка;
  • на том же сервисе Transifex вы можете за деньги заказать перевод своего проекта в коммерческих сервисах Gengo и Texmaster. Gengo имеет больше языков и переводит довольно быстро (обычно в течение часа-двух), но Textmaster по моим субъективным ощущениям переводит качественнее, хоть стоит дешевле, но и переводит в течение суток-двух;
  • заказанный за деньги перевод на Transifex всё равно нужно вычитывать;
  • чтобы перевести небольшой текст на платной основе можно воспользоваться коммерческими онлайн переводчиками типа Gengo, Textmaster или Alconst Nitro, и его всё равно нужно будет вычитывать.

понедельник, 11 ноября 2013 г.

Сокращение размера собственного инсталлятора Qt4 (компилятор MinGW)

Если вы собрали свой инсталлятор Qt4 для каких-то своих целей, то вероятно обратили внимание на то, что в каталоге сборки Qt в подкаталогах bin и lib лежат дублирующие друг друга наборы Qt библиотек - bin\QtCore4.dll, lib\QtCore4.dll и т.д. Если вы собирали Qt с флагом -debug-and-release, то один такой набор занимает порядка 500 Mb, то есть ваш инсталлятор установит лишние 500 Mb файлов, и сам будет больше на 50-60 "лишних" мегабайт. При использовании MinGW мы можем решить эту проблему никак не трогая проекта, который будет собираться напротив этой сборки Qt.

Сперва удаляем все Qt-шные dll из подкаталога lib. Библиотеки Qt теперь останутся только в подкаталоге bin.

При линковке вашего проекта, основанного на Qt, линкер будет искать библиотеки Qt именно в почищенном нами lib. Данную проблему можно решить заданием флагов QMAKE_LFLAGS в вашем проекте (QMAKE_LFLAGS += -L <ПУТЬ УСТАНОВКИ Qt>/bin), но решение с обёртками мне кажется более логичным. К тому же не забывайте, что разработчик не ожидает такого поведения от вашей сборки Qt. Для компилятора отличного от MinGW решение с QMAKE_LFLAGS может быть единственным. Чтобы решить эту проблему для сборки на основе MinGW мы можем создать файлы-обёртки для линкера.

Итак, чтобы создать обёртку для библиотеки QtCore4.dll нужно:
  1. Создать пустой файл libQtCore4.a в подкаталоге lib;
  2. Добавить в него текст GROUP(../bin/QtCore4.dll). Этой строкой вы укажете линкеру, что ему нужно добавить в список линковки библиотеку QtCore4.dll из каталога bin.
Теперь когда ваш проект будет линковаться с QtCore4, линкер откроет файл lib\libQtCore4.a, прочтёт скрипт, и подлинкует библиотеку bin\QtCore4.dll. Повторите эти действия для всех библиотек из вашей сборки Qt (QtCore4.dll, QtGui4.dll, QtSql4.dll и т.д.). Теперь ваш инсталлятор cможет похудеть на 50-60 Mb, а установленная Qt - приблизительно на 500.

воскресенье, 27 октября 2013 г.

Перемещение собранного Qt4

Как известно, во время сборки Qt4 в библиотеке QtCore и qmake сохраняется путь к каталогу сборки, например F:\qt4. Если вы переместите этот каталог в другое место, например, F:\toolchains\qt4, и попытаетесь использовать его как новый профиль в Qt Creator, то некоторые вещи откажутся работать - например, не будет грузиться sqlite плагин, т.к. программа будет искать его по старому пути в F:\qt4. Для этих целей существуют специальные программы-патчеры, которые изменяют пути внутри QtCore или qmake. Рассмотрим следующие варианты:
  • QtBinPatcher. Источник: 1. Позволяет патчить все необходимые файлы без указания каких-либо параметров командной строки. Наилучший вариант из виденных мной;
  • QtPathCorrector. Источник: 1 2. Позволяет патчить файл без указания старого пути. Требует задать новый путь через параметры командной строки. Например, зайдите в перемещённый каталог F:\toolchains\qt4 и выполните: qtpathcorrector patch -n "%cd%" -f bin\qmake.exe bin\QtCore4.dll lib\QtCore4.dll . Пути в qmake и QtCore установятся в "F:\toolchains\qt4". Недостатки: если возникли ошибки, то файл, который должен был быть исправлен, становится размером 0;
  • QPatch. Источник: 1. Требует задать как старый, так и новый путь через параметры командной строки. Недостатки: нужно указывать старый каталог, новый путь должен быть короче старого (что скорее всего неприемлимо для вас);
Теперь qmake будет знать, что prefix поменялся, и будет использовать новое значение. Чтобы проверить установился ли новый prefix, выполните команду qmake -query.

Встречаются заметки, что нужно также патчить пути в .prl файлах в каталоге lib (т.е. F:\toolchains\qt4\lib), но я не обнаружил ошибок или неправильного поведения или компиляции своих программ, если эти пути оставить как есть при использовании патчера, которому нужно в явном виде указывать какие файлы патчить.