вторник, 29 марта 2016 г.

[prog] По следам опыта с Mxx_ru-1.6.8 и перед релизом Mxx_ru-1.6.9

Накопился некоторый, пусть и небольшой, опыт работы с 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 с этими двумя нововведениями выйдет в свет.

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

Во-первых, вероятно, нужно фиксировать правила, по которым происходила установка зависимостей. И при выполнении команд remove и reget использовать эти правила при очистке установленных зависимостей. Нужно это для ситуации, когда при командной разработке кто-то из коллег правит externals.rb. Например, в старой версии externals.rb было:

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

затем я подгружаю обновления из репозитория, а там уже оказывается:

MxxRu::arch_externals :libmosquitto do |e|
  e.url 'http://mosquitto.org/files/source/mosquitto-1.4.8.tar.gz'

  e.map_dir 'lib/*' => 'dev/src/mosquitto_wrapper/mosquitto'
  e.map_file 'config.h' => 'dev/include/mosquitto_wrapper/*'
end

И все! Просто так сделать libmosquitto:reget уже не получится, т.к. в виде мусора останутся старые каталоги с зависимостями для libmosquitto. А вот если бы при установке где-то сохранялось все, что было установлено, то при выполнении remove/reget мусор за собой можно было бы подобрать.

Во-вторых, сейчас, если я нуждаюсь в трех подпроектах, каждый из которых нуждается еще в трех подпроектах, то в своем externals.rb я должен прописать все девять зависимостей. С одной стороны, это решает проблему конфликтов зависимостей. Т.е. если подпроект A нуждается в подпроекте C версии 1.4.8, а подпроект B -- в подпроекте C, но версии 1.3.4, то здесь это сразу же вылазит на поверхность и я это все сразу разруливаю.

Но, с другой стороны, если конфликтов нет, то приходится делать работу, которую можно было бы и не делать. Т.е. хотелось бы просто описать три моих непосредственные зависимости. А уже при их обработке рекурсивно вытащить и всех их зависимости.

Тут есть о чем подумать. Так что не факт, что эта фича быстро появится.

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

Более интересно было бы, если бы можно было подобное правило один раз описать, где-то его опубликовать, а далее просто использовать ссылку на это опубликованное правило.

MxxRu::externals_rule 'https://svn.code.sf.net/p/sobjectizer/repo/tags/so_5/5.5.16/extspec.rb'

MxxRu::externals_rule 'https://bitbucket.org/another_mosquitto_wrapper/raw/commit-id/extspec.rb'

В общем, есть куда двигаться. И, надеюсь, по мере накопления дальнейшего опыта, будем двигаться дальше.

PS. По ходу работы над MxxRu::externals неоднократно ловил себя на мысли о том, что здесь от Ruby используется только возможность задешево получить embedded DSL. А так эта же задача вполне может успешно решаться на любом более-менее развитом нативном языке, будь то C++, Go или Rust. Причем, чем более новый язык, чем моднее и молодежнее у него стандартная библиотека, тем проще это будет сделать. Основная загвоздка разве что в выборе вменяемого языка описания зависимостей. Хотя и здесь ничего сложного, какой-нибудь TOML вполне может подойти.

Комментариев нет: