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

Пользователь

Отправить сообщение

в XM5 есть разочаровывающая особенность для наушников с 8 микрофонами и за 400 баксов. Аудиошнур не является шнуром гарнитуры, т.е. если вдруг нет Bluetooth, то как гарнитурой воспользоваться нельзя. Они натурально сэкономили на одном контакте в аудиоразъеме будто. Интересно, что будет в новых. Упоминания этой особенности не встречал ни в одном обзоре ни на одни наушники.

А что именно подразумевается под 'выберут стратегию обучения'? Если тема изучения новая, откуда берется отправная точка и первоначальный план действий?

Именно вручную и рекомендуется. Не так часто в проектах добавлять и удалять файлы десятками требуется.

Хидера вообще не надо включать в сборку. Пути поиска должны быть настроены, чтобы компилятор все нашел. А CMake прекрасно разберется. (Оговорка для MSVC - для красивого дерева проекта можно напильником доточить https://cmake.org/cmake/help/latest/command/source_group.html#source-group)

Менять глобальные переменные внутри своего проекта - плохая практика, ломающая source-only включения разных проектов. Target-oriented опции, настройки и параметры - лучше и более точны.

Указывать тип библиотеки - нежелательно. Сборщик имеет право выбирать (https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html#build-shared-libs)

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

CMake предоставляет https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html#gnuinstalldirs чтобы вручную пути назначения для разных артефактов не указывать.

Если есть библиотека, то было бы неплохо реализовать в ней поддержку CMake, для пользователей библиотеки и предоставить CMake Config файлы.

А зачем сразу делать вторую статью о том же самом? (прошлая https://habr.com/ru/articles/901132/)?

По сути вопроса, мотивация завернуть FFMpeg в Rust понятна. Как учебный проект по изучению Rust, FFI, и FFMpeg, вполне имеет смысл. Но есть фундаментальный изъян в подходе. FFMpeg растет стихийно, и за года развития превратился в монолитный комбайн, чем и решает вообще все возникающие проблемы. При этом наличие libav* библиотек в составе, не предполагает их использование во внешних программах как есть без приличного объема логики, реализованной в самом ffmpeg/ffprobe/ffplay инструменте. Точкой входа для траскодирования всего во все с сотней опций является именно исполняемый файл, который склеивает библиотеки в полезный инструмент. И FFI - будучи лишь пустой абстракцией - не уменьшает сложность использования, а лишь увеличивает. Большая часть требуемых операций при транскодировании сосредоточена в транскодирующем конвейере, который как раз в приложении и реализован. Зачем мне брать вашу библиотеку и городить еще один огород конвейера, если я могу сразу написать 200 опций в командлайн?

При использовании FFMpeg функционала в своем приложении не хватает немного другой функции - точки интеграции своего компонента(на любом удобном языке) в транскодирующий конвейер. Другими словами, мой проект может обладать уникальным функционалом по работе с сжатым или несжатым медиаконтентом. Я не хочу заморачиваться с поддержкой отдельных форматов и протоколов и хотел бы взять FFMpeg и расширить его конвейер. Интеграция напрямую - это C, легаси, и 15 лет стихийной разработки. В то же время, FFMpeg позволяет подключить внешние источники такие как Unix-сокеты, пайпы, сырые байтовые массивы и прочее. Было бы неплохо иметь нативные для конкретного языка абстракции, которые будут до и после моего компонента поднимать например инстансы FFMpeg, сматывать их не на уровне конвейера, а на уровне медиапотока, и предлагать вменяемую абстракцию в мой компонент.

Конкретный пример на злобу дня: Yolo детектор объектов в видео. FFMpeg в пайп-> Python из пайпа с метаданными в пайп -> FFMpeg из пайпа. По типу https://github.com/PyAV-Org/PyAV/blob/main/examples/numpy/generate_video_with_pts.py . Хотя используемые там абстракции мне не нравятся, так как они напрямую унаследованы от низкоуровнего FFMpeg API.

Добавлю из собственного опыта:

  • не стоит ожидать корректной работы корневого логгера по умолчанию. Конфигурация логгеров в пакетах не описана в PEP, потому кто в лес, кто по дрова. И неприятно обнаруживать, что твои логи пропали из-за чужого хэндлера присунутого в корневой логгер с низким уровнем логирования.

  • единственное место где должны конфигурироваться ВООБЩЕ все логгеры - это уровень приложения. Пакеты могут(должны?) предоставить хелперные сущности, но финальная конфигурация всегда на стороне приложения. Только оно в полной мере понимает, какие логи оно хочет, где собирать, и куда отправлять. Пакеты без публичного интерфейса логгирования, или завязанные на корневой логгер - трудноотлаживаемые.

  • инстанс логгера можно создать и сконфигурировать как синглтон уровня пакета, и включать в модули для использования как логгер-потомок уровня модуля, а в приложение для конфигурирования как логгер пакета. Пакет может не владеть конфигурацией логгера единолично.

  • Порядок хэндлеров, уровней логирования и фильтров - повод вырвать пару волос. Сообщение отфильтрованное уровнем дочернего логгера не достигнет хэндлеров в родительском логгере. Получить дебаг логи из одного модуля, предупреждения из всего пакета, и ошибки из другого пакета, направив дебаглоги в стдерр, а ошибки и предупреждения в syslog вообще не тривиальная конфигурация.

Официальная документация не проясняет как правильно писать хорошие CMake Config и CMake Modules. Абстракция опции для сборки протекла под Windows с релизом толи MSVC 2012, то ли MSVC 2015, и архитектура указывается теперь специальным образом. Синтаксис условных конструкций с разрешением переменных и значений переменных - как минное поле. Как выше уже отметили, JSON и не-JSON для одного инструмента, для ручного редактирования - ну такое. А если еще и CMakeCache.txt в расчет брать, то вообще 3 разных синтаксиса, один из которых - вообще для машиночитаемости.

Но что есть, то есть. Мне CMake все равно нравится больше всех остальных систем сборки и генерации.

Печальный опыт показывает, что такие инструменты хорошо работают на примитивных примерах и затыкают пробелы в инженерной культуре. С ростом приложения, невозможность непосредственной отладки хоть бы и в рантайме осложняет поддержку, лишний шаг в сборке на кодогенерацию отдаляет изменения от выполнения, ну и к паре языков общего назначения изучать специфичный DSL перемешанный с SQL, без гарантий стандартизированной поддержки - ну такая себе перспектива. Выстраивание культуры 3-этапных развертываний, определение зон изменений и автоматизация развертывания включая откаты, стоит затрачиваемых усилий, если на продукт долгоиграющие планы.

А GORM уже адаптировался к дженерикам и позволяет мапить шаблонные и шаблонизированные типы в базу данных? Пару лет назад его разрывало в клочья при компиляции при таком подходе.

А в чем ценность обертки?

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

Shell-скрипт на 20 строчек, чтобы принять аргументы выбора платформы, спрятать 100500 параметров под пресет, и сгенерить Shell- или bat-скрипт сборки, можно и в MinGW запускать. (https://pastebin.com/h7RY2UqJ)

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

Environment.yaml умеет не только пакеты Conda перечислять, но и pip, на случай, если какие-то пакеты надо установить оттуда. Сама Conda рекомендует ставить максимум из Conda, и только потом сверху ставить из pip. И тут можно использовать недокументированную особенность. Если pip пакеты записать в штатные requirements.txt и constraints.txt, то можно заставить Conda использовать их во время conda env update -f environment.yaml, указав этом файле блок pip: как

-pip:

-r requirements.txt

Не сказывается ли на качестве шифрования 64 битное переполнение в state[0] = oldstate * 6364136223846793005ULL + (state[1]|1); ?

Насколько безопасен унарный минус для беззнакового целого ((-rot)) без указания целевой платформы, используемого компилятора, и версии стандарта?

Если даже в стандартной библиотеке разночтения, то на что опираться, выбирая сигнатуры для своих функций?

func ParseIP(s string) IP , но func ParseMAC(s string) (hw HardwareAddr, err error) Ну как так-то.

В любой непонятной ситуации просто прибить билд директорию - это так и есть. И хорошо если проект - не LLVM, который только генерится минуты... Черт знает почему ломается, непонятно как чинится. Кэш файл - тоже странная штука.

Однако выступлю в защиту СМаке, и то, что он modern. Он такой же неидеальный, как и остальные системы сборки. Но, во-первых, он повернут к пользователю лицом с большей частью нормально читаемым синтаксисом. (if ${VAR}, я косо смотрю на тебя ). Во-вторых, из всего изобилия систем сборки единственный укладывает в стройную систему вообще все возможные случаи: нативная сборка, кросс-компиляция, разные тулчейны, отладка, релиз, деплой, взаимодействие с бинарными или сорс-онли компонентами, разные операционные системы, архитектуры и вот это вот все в разных сочетаниях поддерживаются через нормально описанные параметры, опции и настройки. Напоследок, активно развивается не сильно ломая концепцию. Ситуацию с переходом с версии 2 на 3 забудем, дела давно минувших дней. Но ни одна система сборки известная мне не может однообразно поддерживать MSVC, mingw, clang и упаковку в DEB. А Смейку надо просто нагородить сотню опций.

Они даже поддержку систем контроля версий расширяют, хотя я не одобряю.

Крайне жаль, что не каждый проект обеспечивает поддержку CMake предоставляя нормальные CMake-config файлы, которые в принципе даже самому можно не писать, можно шаблон использовать.

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

make удобен, если не переусложнять. Он интуитивно описывает и решает зависимости между целями. Очень помогает собирать монорепозиторий из 20 Python пакетов, где и кодогенерация, и Docker образы, и тесты. Каждый таргет описан простыми понятными выражениями, таргеты при сборке сами по очереди выставляются если какой-то артефакт протух или удалили.

Городить CMake для Python, как-то странно, а много пакетов сразу, разрулив порядок, ни один сборщик Python не может.

Кидаю камень в огород Go по поводу сборки Go проектов, использующих внешние библиотеки или реализующие биндинги для бинарных зависимостей. Потому что интеграция ключей компилятора даже не в файл системы сборки, а в специально форматированные комментарии - это, на мой взгляд, плод сумрачного гения.

Собрать confluent-kafka для Go оказалось нетривиальной задачей из-за прибитых гвоздями ключей компилятора и никакого способа это порулить снаружи

Про make стоит упомянуть, что большинство проектов после make команды будут в недособранном состоянии размазаны по дереву исходников, и финальным аккордом ожидают make install DESTDIR=/some-folder чтобы правильно создать всю структуру файлов. Ну и тут тоже бывает кто в лес, кто по дрова. Кому-то надо configure --prefix делать, кому-то не надо и вообще RTFM проекта.

А SCons разве живой еще? Я несколько лет назад выбирал для пет-проекта систему сборки, и подорвался со SCons на том, что он не понимал про компоненты по кастомным путям и всякие левые библиотеки не хотел подключать нормально без ручного закатывания Солнца за горизонт.

CMake можно тыкать в префикс, где лежат отдельно собранные как надо библиотеки.

Практически каждый модуль CMake дополнительно имеет свой аргумент <Package>_ROOT, чтобы ему дополнительно ткнуть пальцем в конкретный модуль.

Конкретно связка Boost+CMake прошла тяжелый путь от CMake-модуля до CMake-конфига, и какие-то сочетания друг с другом плохо стыкуются. Это да. Ничего не мешает в отдельный префикс положить целый CMake нужной версии.

Собственно о статье - начали с нестыковок между системный окружением и требованиями конкретного проекта, а потом перешли на базовые принципы линковки, заметя проблему под ковер Docker-а. А после сборки в Ubuntu 20, как бинарь в хост-Gentoo использовать?

Опишу собственный подход к такой проблеме:

Системное окружение остается системным окружением, согласно завету пакетного менеджера. Проект или навязывает необходимые зависимости и окружение, или мы сами выбираем под что будем собирать и запускать. В отдельный префикс вручную по инструкциям собираем все то, что или недоступно в системе, или нас не устраивает. На этом шаге больше всего проблем, ибо даже одну систему сборки разные проекты используют по разному, а еще есть meson, autotools, make, и прочий зоопарк, и никто не читает инструкции для инструмента. После страданий с указанием префикса для тех зависимостей, которые не могут с префиксом и out-of-source сборку, берем свой проект, тыкаем CMake в нужные префикс и полетели. И это для разработки. Для релиза/деплоя все пройденные этапы упаковываем в скрипты сборки под целевую платформу, и объединяем со сборкой нашего проекта, кладя в тот же префикс. Итого, имеет почти самодостаточную директорию проекта со всеми зависимостями. Отсюда уже варианты - упаковка в контейнеры, в пакеты для целевой платформы, архивы и все такое.

Описанный подход прекрасно работает для Linux семейства, позволяя деволопить в одной системе, а деплоить в другие, где зависимости нужных версий не доступны. Чуть менее комфортно поддерживать или девелопить в Windows, Mingw сглаживает трудности, и если оставаться в пределах Mingw окружения - то все то же самое. А при намерении нативно собираться MSVC и следовать заветам Windows окружения, приходится собирать зависимости 'под Windows', уговаривать CMake дополнительными флагами и опциями, и страдать над GNU библиотеками, которым для MSVC сборки надо через Cygwin присовывать в autotools черте-что, и не косячить с путями и слэшами.

Да. 24/7. Блок питания горячее, чем я бы хотел. Само устройство - не греется.

Acer Aspire One устройство того же класса. Трудится у меня как хаб умного дома. Запилил на него Slackware 15. Штатных 1 GB RAM едва хватало на ОС(360MB) и OpenHAB(Java такая Java). Докупил еще 1 GB RAM(Новой, я не знаю, зачем сейчас продают DDR2 SO-DIMM, но спасибо им) да старенький SSD в него воткнул. Вполне ничего, отзывчиво работает.

Собственно, все вопросы к авторам Pydantic. У них же должна быть веская причина игнорировать официальную документацию.

Все остальные указанные случаи - только указывают на смысл assert - отладка кода.

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

А зачем кому-то запускать тесты с pytest с оптимизациями? Это же скорее всего юнит-тесты, упал-отладил. А для всего прочего со сложного логикой pytest.fail().

1
23 ...

Информация

В рейтинге
6 834-й
Зарегистрирован
Активность