В версии 1.6.10 MxxRu::externals теперь может самостоятельно обнаруживать, что изменилось в файле описаний внешних зависимостей и предпринимать соответствующие действия. Подробнее под катом.
Управление зависимостями для C++ сейчас, к счастью, горячая тема. На слуху vcpkg, conan, build2, buckaroo и др. Но мы вот уже 2.5 года используем собственный велосипед, MxxRu::externals. И сегодня я попробую на простом примере показать, почему этот подход нам нравится больше всего.
Вышла версия 1.6.7 инструмента Mxx_ru с начальной поддержкой т.н. externals. Теперь в Mxx_ru есть средства для выкачивания внешних зависимостей из Git/Hg/Svn и установки частей этих зависимостей в нужные подкаталоги. Пока внешние зависимости берутся только из репозиториев Git/Hg/Svn. Поддержка закачки тарболлов/архивов будет добавлена в следующей версии. Надеюсь, получится выкатить ее достаточно быстро.
Установить Mxx_ru можно командой gem install Mxx_ru
Обновить Mxx_ru можно командой gem update Mxx_ru
Так же Mxx_ru можно загрузить с SourceForge (gem-файл).
PDF-ку с документацией пока не обновлял. Сделаю это уже после выпуска версии с поддержкой тарболлов. Посему единственная имеющаяся в наличии документация собрана в этом посте под катом.
Итак, что такое MxxRu::externals и как с ними бороться?
Понадобилось добавить в проект еще одну зависимость -- библиотеку procxx. Эта малюсенькая header-only библиотека, которая живет на GitHub-е, имеет только одну ветку master и не имеет на данный момент ни одного релиза. Добавляю всего несколько строк в externals.rb и получаю зависимость от конкретного коммита в репозитории procxx (что позволяет не боятся сюрпризов, если в последующих коммитах появятся какие-нибудь ломающие совместимость изменения):
MxxRu::git_externals :procxx do |e|
e.url 'https://github.com/skystrife/procxx'
e.commit 'dfd9818'
e.map_file 'include/process.h' => 'dev/procxx/*'
end
Начал чесать репу на тему создания такого mchain-а или mbox-а для SObjectizer-а, который бы позволил двум SObjectizer-приложениям на одной ноде взаимодействовать друг с другом через разделяемую память. Беглый поиск по Интернету показал, что выбор инструментов для этой задачи сравнительно небольшой: либо придется делать свой собственный велосипед, либо же нужно брать что-то из Boost, ACE, POCO или чего-то сравнимого по размеру.
Писать свой лисапед не захотелось, тем более, что сперва нужно сделать какой-то прототип нового mchain-а, ибо на данный момент реализация такого mchain-а выглядит как сплошное белое пятно. Хочется без лишних проволочек начать работать над прототипом, а уже потом, когда прототип заработает, решать, что же делать дальше.
Решил попробовать Boost.Interprocess. Но т.к. с "большим" Boost-ом иметь дело не хочется, то попробовал подтащить в небольшой демо-проектик Boost.Interprocess и все его зависимости из "модульного" Boost-а, который нынче доступен на github-е.
Методом проб и ошибок это удалось сделать (в очередной раз скажу, что Boost в виде большой говнопомойки не нужен и должен быть разрушен). Результат можно увидеть в этом репозитории. Ниже чуть-чуть прокомментирую то, что получилось.
Вышла версия 1.6.8 инструмента Mxx_ru с первой полной реализацией т.н. externals. Теперь внешние проекты можно забирать из репозиториев Git, Hg, Subversion, а так же в виде tar, zip и 7z архивов.
Установить Mxx_ru можно командой gem install Mxx_ru
Обновить Mxx_ru можно командой gem update Mxx_ru
Так же Mxx_ru можно загрузить с SourceForge (gem-файл).
PDF-ку с документацией буду обновлять. Если все пойдет нормально, то надеюсь выложить ее в начале следующей недели. Пока же информацию о возможностях версии 1.6.8 можно найти в блоге и G+ (запись номер раз, запись номер два, запись номер три, плюс дополнительная информация под катом).
Под катом пример MxxRu::externals-скрипта, посредством которого подтягиваются почти все зависимости для одного из текущих проектов. Почти все потому, что Boost таким образом не подцепишь (пока по крайней мере не пробовали).
В дополнение к тем соображениям по поводу будущих доработок в MxxRu::externals, которые были изложены здесь, добавилась еще одна идея: нужно иметь разные списки externals-ов для разных кусков проекта. Например, делаю библиотеку libX. Для нее нужны spdlog и tinyformat. Посему желательно, чтобы эти зависимости подхватывались автоматически всеми, кто берет libX к себе. Для тестов библиотеки libX нужен Catch. Поэтому Catch должен относиться к зависимостями libX-tests. И нужен Catch будет только тем, кто хочет гонять тесты для libX. Для примеров библиотеки libX может быть нужен rapidjson. Посему rapidjson должен быть в externals-ах libX-samples, но его не должно быть в externals-ах самой библиотеки libX.
В общем, есть над чем покурить.
Ну а пока пример того, что сейчас используется в повседневной работе:
Накопился некоторый, пусть и небольшой, опыт работы с MxxRu::externals из Mxx_ru-1.6.8. Хорошая новость: externals-ы таки работают. А вот плохих новостей нет :)
Однако, уже очевидно, что некоторые доработки нужны.
Прежде всего, оказалось желательно разрешит переименования исходного каталога в команде map_dir. Например, был каталог some-prj/src/lib, захотели, чтобы он скопировался просто в some-prj/src. Версия 1.6.8 это не позволяла делать.
Так же несколько утомляет необходимость писать имя копируемого файла и в источнике, и в приемнике для map_file. Т.е., когда несколько раз напишешь что-то вроде e.map_file 'prj/src/h/config.h' => 'h/config.h', то это надоедает.
В связи с этим сделаны наметки версии 1.6.9, в которой реализованы решения для двух вышеуказанных случаев:
MxxRu::arch_externals :libmosquitto do |e|
e.url 'http://mosquitto.org/files/source/mosquitto-1.4.8.tar.gz'
e.map_dir 'lib/*' => 'dev/libmosquitto/src'
e.map_file 'config.h' => 'dev/libmosquitto/*'
end
Т.е. если в параметре src для map_dir последним элементом является звездочка, то считается, что в dst задано новое имя для исходного каталога. В данном примере каталог lib копируется в каталог dev/libmosquitto под именем src.
Если в параметре dst для map_file последним элементом является звездочка, то считается, что имя файла при копировании должно сохраниться. Т.е. в примере выше файл config.h будет скопирован в файл dev/libmosquitto/config.h.
Лично мне пока оба решения нравятся. Вроде бы просто и понятно, плюс совместимость не нарушается. Но это мое мнение. Интересно и другие мнения послушать. Если есть противопоказания, то проще сейчас все переделать, а не после того, как версия 1.6.9 будет зафиксирована.
В общем, если не будет никаких возражений, то через два-три дня версия 1.6.9 с этими двумя нововведениями выйдет в свет.
Но есть так же еще несколько соображений, которые имеет смысл обдумать и, может быть, реализовать в последующих версиях...
Из мелочей: в данной версии появились новые шаблоны externals и ext-cmake-prj для mxxrugen. А так же новый тип obj_placement-а под именем ToolsetRuntimeSubdirObjPlacement, который создает имена подкаталогов с результатами компиляции вида vc14_0_19_00_23918_x64 и gccmingw_5_3_0__x86_64_w64_mingw32.
А из главного в этой версии реализована возможность использования проектов с CMake-вскими проектными файлами в рамках контролируемой Mxx_ru сборки. Как это может выглядеть покажу на примере подключения исходников библиотеки soci в Mxx_ru-шный проект.
Попробовал представить, как сделать адаптацию SO-5 под новую волшебную пилюлю от Microsoft под названием Vcpkg. Проблевался. Какую только херню, пардон май френч, народ готов жрать только потому, что эта херня от MS или от Google. Поразительно.
Суть Vcpkg в том, что под каждый проект, который хочется затянуть в этот самый Vcpkg, нужно создать файлик portfile.cmake, в котором будут находится инструкции по доставанию исходников этого проекта и по его сборке (если проект нуждается в сборке). Для примера покажу, как выглядит portfile.cmake для библиотеки Range-V3. И как это же самое выглядит в виде рецепта для MxxRu::externals.
e.map_dir 'include/*' => 'dev/range-v3'
e.map_file 'LICENSE.txt' => 'dev/range-v3/*'
end
Резюмируя. Если кому-то действительно нужно, чтобы SO-5 был доступен из портов Vcpkg, то дайте знать. Мы сделаем. Но только если это кому-то действительно нужно. Ибо Vcpkg выглядит как говно и пахнет как говно. А посему вмазываться в говно и сопровождать потом это говно просто так не хочется, только если на то будут причины.
Где-то с год назад попробовали сделать эксперимент: написали на SObjectizer небольшую обертку над mosquitto. Написали, попробовали каково это, поиспользовали для прототипирования. И забыли :)
Теперь вот вспомнили. Чуток причесали и открыли исходники на BitBucket-е: mosquitto_transport-0.6.
Обертка самая простая. SSL не поддерживаем. Сообщения с QoS выше 0 -- не поддерживаем. За счет того, что libmosquitto, как мне показалось, с Windows не дружит, то работает это все только под Unix-ами (мы проверяли только под Linux-ами).
Цель эксперимента была в том, чтобы посмотреть, насколько просто будет подружить разработку на SObjectizer с использованием MQTT в качестве транспорта. А т.к. MQTT -- это всего лишь протокол передачи данных, который не определяет, как именно будут упакованы сами пользовательские данные, то мы еще хотели сделать так, чтобы mosquitto_transport не был привязан к конкретному типу encoding-а. В общем, все цели были достигнуты. Использовать MQTT можно, получается довольно удобно (по крайней мере на мой взгляд). Разные типы encoding-а подключаются посредством несложной шаблонной магии (подробнее я писал об этом в прошлом году). У себя мы использовали JSON-encoding (посредством rapidjson и json_dto, о json_dto Коля Гродзицкий рассказывал на Corehard C++ Autumn 2016).
Разве что быстро стало понятно, что libmosquitto не есть хорошо. Во-первых, libmosquitto заточен под однопоточную синхронную обработку MQ-шных сообщений. Т.е. когда приходит сообщение, вызывается соответствующий callback и при возврате из него libmosquitto сразу же начинает обработку QoS. Т.е., если сообщение пришло с QoS выше 0, то факт успешного возврата из callback-а воспринимается libmosquitto как факт успешной доставки и подтверждение получения. Что делает невозможным длительную асинхронную обработку сообщений. Во-вторых, исходники libmosquitto оставляют печальное впечатление, да и нам их пришлось патчить, чтобы можно было использовать libmosquitto-овский event-loop в многопоточном окружении (поэтому, кстати, mosquitto_transport использует пропатченную мной версию libmosquitto, а не оригинальную). В-третьих, хотелось бы больше кроссплатформенности.
В общем, mosquitto_transport сделали на libmosqitto, в самом libmosquitto разочаровались, начали делать свою реализацию MQTT. Но пришлось пока это дело заморозить. Может быть к весне получится разморозить.
Еще нужно добавить, что mosquitto_transport для управления зависимостями использует MxxRu::externals. Так что для того, чтобы собрать, нужно воспользоваться MxxRu. Приносим свои извинения, но нам так было удобнее, да и сам mosquitto_transport вряд ли кому-то потребуется. Поэтому адаптацию под какие-то другие менеджеры зависимостей для C++ (коих, по сути-то и нет), мы не делали. Да, еще нужен Boost, но Boost через MxxRu::externals мы не подключали (еще раз лучи поноса Boost-оводам, которым, блин, нравятся ну очень большие архивы и которые, блин, не знают, что такое нормальная модульность). Так что Boost нужно ставить либо вручную, либо через систему пакетов конкретного дистрибутива Linux-а.
Ну вот как-то так. Сам mosquitto_transport работает стабильно, но развивать мы его вряд ли будем. Скорее это станет основой для нашего собственного MQTT-шного транспорта для SObjectizer. Но если есть какие-то вопросы или замечания, или предложения, то всегда пожалуйста: выслушаем, ответим, прислушаемся... :)
Надеюсь, что тем, кто интересуется проблемой управления зависимостями в С++ проектах, могут быть интересны эти два доклада. Первый хорош тем, что показывает спектр проблем, с которыми приходится иметь дело в больших и кроссплатформенных C++ проектах.
Второй доклад хорош тем, что он дает небольшой, но веселый и бодрый обзор некоторых из существующих пакетных менеджеров для C++:
Мне же, однако, подходы на базе централизованых хранилищ пакетов, будь то conan.io (в ближайшем будущем conan-central), hunter или cppan.org не очень нравятся. Точнее говоря, я не верю, что это окажется достаточно жизнеспособным из-за разных причин. Во-первых, в C++ все очень разобщено, поэтому слабо верится в то, что народ массово начнет концентироваться вокруг какого-то одного центрального репозитория C++ных проектов. Во-вторых, кто и с какой радости должен будет оплачивать сей банкет? Хостинг 100500 непонятных проектов и кучи версий для них -- это накладные расходы, которые кто-то должен оплачивать. Что-то в мире C++ мне не видится организации, которая взяла бы на себя бремя этих накладных расходов. Тем более, что почти что все уже живет на ресурсах типа GitHub, BitBucket или SourceForge.
Кроме того, те же Conan и Hunter работают по принципу организации центрального хранилища загруженных пакетов на машине разработчика. Т.е., если разработчик однажды скачал себе Boost-1.64 для проекта A, а затем захотел использовать Boost-1.64 для проекта B, то пакетный менеджер будет переиспользовать уже загруженный ранее Boost.
Как по мне, то этот подход хорош для быстрой разработки какой-нибудь мелкой программулины. Ну, например, прочитал я на Хабре какую-то статью и захотелось мне проверить один из ее тезисов. Или задали на LOR-е вопрос, для поиска ответа на который нужно написать программку на 50 строк. В этих случаях хочется приложить минимум усилий: где-то просто перечислить список нужных мне внешних зависимостей (например, таких, как Boost, ICU, zlib) и потратить минимум времени на подгрузку и сборку этих зависимостей. Поскольку, если я пишу программу на 50 строк "на выброс", то мне вряд ли захочется ждать, пока Boost еще раз скачается и скомпилируется. Поэтому переиспользование того, что было загружено ранее, в таких условиях -- это вполне себе разумный подход.
С другой стороны, когда я делаю какой-то внутренний проект (или же работаю с какой-то приватной веткой), то у меня могут возникать ситуации, когда мне нужно взять не просто библиотеку X, а конкретный ее слепок. Скажем, библиотека X разрабатывается моим коллегой и он добавил в X новый нужный мне функционал, но еще не зафиксировал ее стабильную версию. Поэтому я на свой страх и риск хочу взять X от ревизии (коммита) R1. С большой долей вероятности я могу наткнуться в X@R1 на какую-то проблему. Из-за чего мне потребуется перейти на X от ревизии R2 (может быть даже эту ревизию я создам сам для того, чтобы исправить проблему, а потом вернуть правки в основную ветку
разработки X).
В этих случаях, как мне кажется, плохо работают обе составляющие централизованного подхода (положенного в основу canon/hunter/cppan):
Центральное хранилище опубликованных пакетов. Поскольку для работы с X@R1 кто-то должен быть создать соответствующий пакет и опубликовать его в этом хранилище.
Потом это же нужно будет проделать с X@R2 и т.д. При том, что вряд ли хорошо засирать центральное хранилище промежуточными пакетами. Как и делать собственное зекало этого центрального хранилища для того, чтобы засирать его локально.
Централизованное хранилище загруженных на локальную машину пакетов. Поскольку если X@R1 и X@R2 мне нужны только для проекта Y, да и то в какой-то временной ветке Y, то не есть хорошо сохранять X@R1 и X@R2 там же, где хранятся нормальные стабильные версии чего-то вроде Boost-а или ICU.
во-первых, MxxRu::externals сам забирает исходники стороннего компонента оттуда, где эти исходники лежат. Например, лежит Boost в tar.bz2 на SourceForge -- оттуда его и заберем. А исходники spdlog от конкретного коммита есть в git-е на GitHub-е -- ну значит вытянем их через git с GitHub-а. Таким образом для того, чтобы сделать свой пакет доступным для пользователей, не нужно предпринимать каких-то серьезных усилий. Можно даже свой тарбол не делать, если кроме GitHub-а ни на что мозгов не хватает, то достаточно просто теги в своем репозитории создавать, GitHub сам для них тарбол доступным для загрузки сделает. Ну а если нужно забирать какие-то промежуточные версии собственных компонентов из закрытых репозиториев внутри своей организации, то тут вообще никаких проблем нет, ничего дополнительно поднимать не нужно (речь про локальный инстанс того же Conan-а);
во-вторых, загруженные зависимости кладутся только в локальный рабочий каталог. Поэтому, если моему проекту Y потребовался сперва X@R1, а затем X@R2, то исходники X@R1 и X@R2 никуда за пределы рабочего каталога Y не уйдут. И, соответственно, когда я удалю этот рабочий каталог, то автоматически исчезнет и весь "мусор"
, который был с этим связан.
Однако, поскольку мир сходит с ума и куча народа с удовольствием жрут тот же самый CMake, то есть серьезные подозрения, что CMake в качестве системы сборки и пакетные менеджеры на его основе (вроде Conan-а и Hunter-а) таки станут де-факто стандартом в мире C++. Ну что тут поделать, количество разума -- величина постоянная,
а население-то растет.
ЗЫ. Отдельно хочется помянуть незлым тихим словом красноглазых Linux-оидов, которые всерьез считают, что для управления C++зависимостями нужно пользоваться штатным пакетным менеджером вашего любимого дистрибутива Linux-а. Этих сторойными рядами прямо направляю в жопу. Ибо ваше мнение не интересно. Ну вот от слова совсем. По крайней мере пока не поймете, что "кроссплатформенность" -- это "переносимость между разными платформами", а не "переносимость между разными дистрибутивами Linux-а".
Мы выпустили первую версию своего нового проекта поверх SObjectizer -- so_5_extra версии 1.0.0.
В этой версии в so_5_extra доступны:
so_5::extra::env_infrastructures::asio::simple_not_mtsafe -- реализация однопоточной инфраструктуры SObjectizer-а на базе Asio. Т.е. с использованием этой инфраструктуры и Asio, и SObjectizer смогут работать на одной и той же рабочей нити;
so_5::extra::mboxes::round_robin -- специальный mbox, который доставляет сообщения поочередно каждому из N агентов, подписанных на это сообщение;
so_5::extra::shutdowner -- небольшой инструмент для упрощения операции завершения работы в больших приложениях.
Исходники можно взять либо из репозитория, либо загрузить из соответствующего раздела.
Документацию по проекту можно найти в Wiki. Если из документации чего-то не понятно или что-то в ней не описано, то не сочтите за труд, дайте нам знать. Улучшим, расширим и углубим :)
Проект header-only. Если захочется собрать тесты и примеры самостоятельно, то придется воспользоваться Ruby и Mxx_ru. Зависимости так же подтягиваются через MxxRu::externals. Но в секции Files есть архивы с именами вида so_5_extra-1.0.0-full.tar.xz, в которых уже все зависимости присутствуют. Поэтому можно брать *-full.tar.xz архив, распаковывать, прописывать в INCLUDE путь к so_5_extra-1.0.0/dev и пробовать.
Работоспособность проверялась под Linux-ом (gcc 5.4 и 7.1, clang 3.7 и 4.8) и Windows (gcc 5.2-7.1, VC++ 14.0 и 15.0). На всякий случай выставлять -Werror при работе с so_5_extra не советуем, т.к. и gcc, и clang очень сильно ругаются на потроха Asio.
В планах у нас добавление еще нескольких фич в so_5_extra. Следующие версии будут выходить по мере добавления новых фич. В том числе в планах и simple_mtsafe-инфраструктура для Asio, но приоритет у этой задачи не самый высокий. Если кому-то нужна thread-safe реализация Asio-инфраструктуры для SO-5, то дайте знать. Постараемся повысить приоритет.
Обращаем внимание, что so_5_extra распространяется под двойной лицензией: GNU Affero GPL для OpenSource применения, и коммерческая лицензия для использования в закрытых проектах. Если кому-то интересна коммерческая лицензия, то пишите на info at stiffstream dot com, там цена вопроса порядка $40 за одного разработчика в год.
Попутно мы сделали SObjectizer-5.5.19.2, в который вошло несколько фич, необходимых для реализации so_5_extra. Дистрибутивы SObjectizer лежат там же, где и обычно.
На Хабре обнаружилась статья, в которой рассматриваются реализации на Go и D одних и тех же простеньких примеров из области многопоточности.
Меня лично статья удивила. Мне почему-то казалось, что на D такие игрушечные примеры должны получаться короче и проще. Но, надеюсь, автор статьи лучше понимал, что и как он делает. Мой же интерес в том, чтобы проверить возможности SO-5 на этом же поле.
Для чего на SO-5 было реализована два примера. Краткий их разбор под катом. Взять поиграться их можно из github-овского репозитория (для сборки нужны Ruby+rake+Mxx_ru, заодно там возможности MxxRu::externals можно увидеть).
PS. К сожалению, работает только под Linux-ом, т.к. под FreeBSD и procxx обнаружились какие-то проблемы, а разбираться с ними совершенно нет времени. Утилита же ping была выбрана в качестве удобного подопытного кролика: очень просто ограничивать ее время работы, плюс легко читать ее stdout.
Последние пару месяцев плотно работаю с C++14 (на том уровне, который поддерживается в GCC-5.2 и 5.3). Конечно же C++14 -- это небольшое улучшение над C++11, но в общем и целом, если сравнивать с C++03, современный C++ является совершенно другим языком. Уж не знаю, как C++14 ощущается в задачах, где нужно выжимать такты из битов и наоборот. Но вот у меня сейчас C++ что-то вроде клеевого языка, основная задача которого экономить ресурсы, коих на целевых машинах не то, чтобы уж много. И ощущается C++14 в таком контексте практически так же, как какой-нибудь Ruby или Python. С приблизительно такими отличиями:
для C++ не так уж много хороших и живых библиотек, а те, что есть, нужно подключать в свой проект сильно по разному (впрочем, здесь MxxRu::externals ну очень сильно упрощает жизнь);
проходит гораздо больше времени между внесениями изменений в код и первым запуском измененного кода. В Ruby, например, не нужно ждать, пока проект с туевой хучей шаблонов из header-only библиотек скомпилируется и слинкуется;
но уж если C++ный код скомпилировался, то не приходится ожидать вылета ошибки из-за несовпадения типов переменных или еще какой-нибудь мелочевки, которая в языках со статической компиляцией вылавливается на стадии компиляции, а в динамических языка -- в run-time;
если уж твой C++ный код тормозит, то только из-за тебя :)
В общем, если затащить в свой проект качественные библиотеки и есть возможность пользоваться нормальным компилятором, то жить с C++11/14 легко и весело. Особенно если увлечься шаблонами и auto, то C++ный код по читабельности для меня оказывается ну очень похожим на Ruby-новый код: точно так же сначала все просто и очевидно, а через пару недель чешешь голову стараясь понять, какой же тип у этого выражения ;) В качестве демонстрации покажу ниже небольшой фрагментик (что называется, "из недавнего").
Но к чему я это все? А к тому, что оглядываясь по сторона возникает некоторое недоумение. Иногда задумываешься: куда же катится этот мир? Взять, например, русскоязычные профильные форумы. Мало того, что активность вокруг C++ там не такая уж и активная. Так еще и вопросы такие всплывают, что невольно задаешься вопросом: а вменяемые C++ники вообще остались? Глядя на вот такое (или такое, или такое) напрашивается вывод о том, что нас практически-то и не осталось. Если же задуматься еще и о том, что за такие художества кому-то еще и деньги платят, то как-то совсем грустно...
Recent and recurrent boost-dev discussions have
raised the lack of cmake based tooling; lack of ABI management and
the consequent ODR violation when mixing Boost versions in the same
process; the anti-social behaviour of Boost towards library end
users, new ideas, new blood and the wider C++ community; and the
chronic lack of maintenance of up to half the Boost libraries.
One question which needs to be answered is whether a clean reboot of
Boost from the first principles of proving high quality C++ libraries
well suited for use with the latest C++ standard is viable. This new
collection of C++ libraries would be started completely from scratch
(even if some existing libraries were ported into the new
organisation), so ANYTHING is possible.
Т.е. у Boost-а куча проблем, поэтому давайте-ка подумаем, как начать все заново.
Стало еще грустнее. На мой взгляд, Boost-оводы сделали много хорошего, но за это придется платить слишком большую цену. Подход, при котором из Boost-а пытаются сделать централизованную коллекцию высококлассных библиотек, был спорным с самого начала. Но раньше он хотя бы был оправдан тем, C++ развивался крайне медленно и в Boost-е обкатывались многие базовые вещи, которые следовало бы иметь в языке гораздо раньше.
Теперь же этот подход с единым сборищем библиотек только вредит. И если Boost-овы решив начать с начала пойдут по тому же самому пути, то они еще раз наступят на те же самые грабли.
Уже неоднократно говорил о том, что C++у нужно брать на вооружение идеи из других языков. RubyGems из Ruby или Cargo и Rust-а. Вот что нужно C++ сейчас, а не монстроузный Boost. Но, к сожалению, только у Boost-а достаточный авторитет, чтобы сделать какую-то систему управления зависимостями для C++ де-факто стандартом.
В общем, несколько досадно, что в кои-то веки C++ стал действительно хорошим и удобным языком. А вот инфраструктура вокруг него как была болотом, так и осталась.
Профессионально программирую более 28 лет. Несколько раз создавал с нуля новый софт в безнадежных проектах, какие-то из этих разработок затем сопровождал в течении многих лет, что-то из этого работает до сих пор.
И постоянно строил велосипеды, которые тут же шли в работу. За счет чего приобрел специфический опыт и навыки.
Не претендую на роль терпеливо разгребающего таски из JIRA разработчика. Как и на роль архитектора, рисующего UML-диаграммы больших систем. Наверняка есть более подходящие кандидаты, которые любят, умеют и стремятся делать именно это.
А вот если вам нужен программист-камикадзе с нестандартными идеями чтобы соорудить велосипед на котором можно ехать быстрее/безопаснее/комфортнее... Таковым могу быть я.
Открыт для предложений в виде контракта между заказчиком и СтифСтрим. Варианты войти наемным сотрудником в штат клиента на данный момент не рассматриваются.
С получением денег из-за рубежа у нас в РБ сейчас все не очень гладко, поэтому наиболее интересны заказчики из РБ/РФ.
Монстрам ИТ-шного рынка, вроде Яндекса, ВКонтакта, Лаборатории Касперского, Тинькова и пр., мои услуги вряд ли понадобятся. А вот небольшим компаниям, которые не могут конкурировать на рынке труда с подобными монстрами, вполне. И обойдется это значительно дешевле 700k в месяц ;)
Связаться со мной можно через eao197 на gmail тчк com. Если кому-то интересен профиль на LinkedIn, то вот.
Дабы не быть голословным по поводу опыта создания велосипедов вот несколько примеров "из недавнего":
timertt. С++ библиотека для поддержки таймеров. Реализует механизмы timer_wheel, timer_list и timer_heap. Позволяет поддерживать большое количество (миллионы и десятки миллионов) активных таймеров. С 2014-го года используется в SObjectizer.
so5extra. Набор прибамбасов для SObjectizer-а, вроде дополнительных типов диспетчеров, mbox-ов и пр.
easy_parser в составе RESTinio, который представляет из себя реализацию PEG-парсера на С++ных шаблонах и constexpr-функциях (в рамках C++14) Подробнее в основной документации или вот этих статьях: раз и два.
MxxRu::externals. Велосипед, который мы с 2016-го года используем для управления зависимостями в собственных C++-проектах. В отличии от conan, vcpkg и пр., он не требует предварительного опакечивания зависимостей. Ознакомиться можно здесь или здесь. Кстати говоря, MxxRu -- это также мой старый собственный велосипед (документация здесь).
Упомяну также arataga. Хоть это и не инструмент для разработчика, но лисапед, сделанный практически в одиночку под специфические условия.
Кому-то я известен по проектам SObjectizer и RESTinio. Эти все создано с моим непосредственным участием и под моим руководством.
Опыт велосипедостроения в наличии.
Кроме собственно построения велосипедов могу еще и связно описывать построенное нормальным и понятным языком. Свидельством чему могут быть как публикации в этом блоге, так и статьи на Хабре.
Теперь дело за тем, кому мой опыт и навыки понадобится.
Буду признателен, если вы сможете поделиться ссылкой на этот пост в своих соцсетях и/или распространить среди своих профессиональных контактов.
Есть такая система сборки для C++ проектов: Buck.
И к ней система управления зависимостями Buckaroo.
Кажется, от чуваков из Facebook.
Так вот, раньше эта система управлениями зависимостями была написана на Java. Соответственно, хочешь использовать для своих C++ проектов Buckaroo -- ставь себе JRE.
А теперь это все добро взяли и переписали на чем?
На .NET.
Инсталлятор этой прелести для Windows весит 35Mb, для Linux-а и Mac-а чуть больше 65Mb. Для FreeBSD готового инсталлятора нет.
Что в этом всем печальнее всего?
А то, что по своей задумке и Buck, и особенно Buckaroo, наиболее интересные и вменяемые из всего, что сейчас развивается в мире C++ инструментария, включая CMake, build2, meson, vcpkg, Conan, Hunter и пр. А уж Bockaroo, так это чуть ли не доведенный до своего логического завершения MxxRu::externals. Все ИМХО, конечно же.
SObjectizer-4 был написан в 2002-ом году. Затем более-менее активно развивался года до 2004-го. Потом менее активно, но все-таки куда-то двигался до 2006-го года, когда была сделана версия 4.4. После чего развитие линейки SObjectizer-4 остановилось окончательно. Были баг фиксы, последний из которых, если не ошибаюсь, был сделан где-то в середине 2010-го года. Но развития уже не было. Вот уже 10 лет как.
В общем, поскольку для меня лично SO-4 -- это дела давно минувших дней, то полагал, что SO-4 уже не используется и написанный на его базе софт либо уже давно выведен из эксплуатации, либо же не менее давно переведен на SO-5.
Тем удивительнее было обнаружить, что софт на SO-4 не только есть, но он еще и работает. И, время от времени, нуждается в доработках. Правда, используются для этого какие-то древние компиляторы, да и собираются приложения в 32-х битовом режиме, т.к. были в свое время какие-то заморочки с какими-то библиотеками из-за чего портировать SO-4 в 64-бита не стали.
Ну а т.к. негоже по нынешним временам сидеть на древних C++03 компиляторах, то на выходных портировал SObjectizer-4 и сопутствующие ему библиотеки под C++11/14. Или, другими словами, после многолетнего перерыва появилась версия SObjectizer 4.5. Чему я сам несказанно удивлен, т.к. не мог себе представить такого развития событий и в кошмарном сне :)
Тем не менее, если вдруг кому-то надо, то можно взять SO-4.5 из SVN-а. Проверял работоспособность под Windows и VC++ 14.0, под Linux и GCC-6.1 (но, думаю, и под 4.9-5.3 так же будет работать). Вроде как работает и в 32-х, и в 64-х битах. При компиляции с высокими уровнями предупреждений, конечно же, довольно много ворнингов от компилятора идет, особенно в тестах и примерах. Но вычищать все это ну совсем уже не хочется, да и незачем, думаю.
В общем, мораль сей басни: программа - не воробей, выпустишь - не поймаешь будешь фиксить потом, даже когда захочешь забыть, что же это такое :)
PS. В репозитории SObjectizer-а -- это первый проект, в котором зависимости подтягиваются через MxxRu::externals. Вот здесь можно глянуть, как это выглядит. В том числе подтягивается и такая "тяжелая" зависимость, как ACE.