LINUX.ORG.RU

А знаете как деплоить C++20 modules с библиотекой?

 , ,


0

4

А никак.

В доках GCC (ссылку не дам, уже потерял) прямым текстом сказано, что CMI (Compiled Module Interface) – формат не портабельный и может использоваться только для кеширования в процессе сборки. Он может меняться даже в зависимости от версии компилятора и целевой архитектуры, его смысл и scope примерно тот же что у precompiler headers. Что в общем естественно: компилятор сериализует туда свои внутренние структуры.

Следовательно, деплоить интерфейс модуля можно исключительно исходником. Т.е. если раньше было .h + .cpp, то теперь вместо .h у нас будет какой-нибудь .cppm – интерфейс модуля, который тоже надо деплоить вместе с либой, а в сорцах опять два исходника на модуль: .cppm + .cpp. Что поменялось? Расширение интерфейсного файла. Который теперь ещё и замусорен новыми кейвордами export и import.

Никаких намёков на попытки разработчиков компиляторов договориться о портабельном формате CMI и о расположении CMI-файлов внутри .a-архивов – не нагуглилось. Есть разве что вот такой пропозал в т.ч. про стандартный маппинг имён модулей на имена файлов, но читать его печально. Ну, может моим правнукам, работающим в поле пока светло, голубиная почта принесёт добрые вести.

Тьфу. Ни одну фичу не могут сразу нормально и ДО КОНЦА проработать.

★★★★

Ответ на: комментарий от dimgel

По-прежнему не вижу, каким образом.

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

сам код инетрфейса модуля не зависит от предыдущих инклудов и определений.

интерфейс замкнут и раздельно компилируется… хидер вообще не обязан раздельно компилироваться. это будущая тестовая вставка.

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

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

alysnix ★★ ()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

Ок, принято. Выше ты это уже акцентировал, и я даже мысленно согласился, но показалось как-то жиденько это на фоне удобства жавы. Поэтому, согласившись, пропустил мимо и продолжил давить на портабельные CMI.

Ну шо ж, дождёмся значит, когда стандартизируют расширение и пути для исходников интерфейсов, как давным-давно стандартизировали /usr/include. Щетаю, тему можно закрывать. :)

dimgel ★★★★ ()
Ответ на: комментарий от James_Holden

@James_Holden, в догонку моему последнему ответу (при редактировании уведомления упомянутым никам не рассылаются): но обфускации с .cppm один хрен не будет – как нет её в .h и тем более в .class (который вообще целиком дизассемблируется во вполне понятный java-код). Так что её можно сократить из уравнения.

dimgel ★★★★ ()
Ответ на: комментарий от dimgel

И чем это отличается от PCH, нафига надо было модули городить?

PCH это дамп памяти компилятора. Размер PCH в разы больше чем у модулей, и PCH может быть только один, а модулей много.

fsb4000 ★★★★★ ()

непопулярное мнение, в C++ в принципе нафиг не нужны никакие модули. Лучше бы pragma once стандартизировали

Lrrr ★★★ ()
Ответ на: комментарий от dimgel

С точки зрения перфекциониста-байтодрочера и одновременно любителя комфорта, альтернатив плюсам на самом деле не существует.

А ты стандартную библиотеку используешь или свой велосипед? Просто, если первое, то ты даже на уровне языка не владеешь байтиками, потому что контейнеры с алгоритмами — чёрные ящики, к тому же всякие интересные детали реализации вроде small-string-optimization, до недавнего времени повсеместно были copy-on-write и т.д. Что компилятор вытворяет с твоим кодом — я вообще молчу.

Я сердцем понимаю твою боль и тоже люблю плюсы «за это», но по факту эта байтодроческая низкоуровневость — скорее миф.

filosofia ()

Модули в С++ — это что-то с чем-то. В других языках они просто есть, в плюсах же — это СОБЫТИЕ. Событие, длящееся уже годами, и конца которому не видно.

filosofia ()
Ответ на: комментарий от filosofia

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

Usruser ()
Ответ на: комментарий от filosofia

А ты стандартную библиотеку используешь или свой велосипед?

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

если первое, то ты даже на уровне языка не владеешь байтиками, потому что контейнеры с алгоритмами — чёрные ящики

Я достаточно неплохо себе представляю реализацию довольно многих плюсовых вещей – и в языке, и в либе, и юзаю многие из них даже в сишном стиле без зазрения совести – где понимаю, что мой собственный велосипед будет ничем не лучше (e.g. наследование, RAII – их вообще нет смысла велосипедить), или овчинка не стоит усилий (e.g. vector, unordered_map).

к тому же всякие интересные детали реализации вроде small-string-optimization, до недавнего времени повсеместно были copy-on-write и т.д.

А вот со строками в байтодрочерском коде работаю обычно по сишному (а аллоцирую в арене). Хотя вот string_view люблю.

Что компилятор вытворяет с твоим кодом — я вообще молчу.

Компилятор молодец. :) Кстати когда-то была забавная инфа, что сишный код GCC оптимизирует лучше, если его обозвать .cpp.

В общем, как обычно: depends.

dimgel ★★★★ ()
Последнее исправление: dimgel (всего исправлений: 4)
Ответ на: комментарий от dimgel

Потому, что мне крайне не нравится принятый в Java/C# подход, когда интерфейсная часть класса в исходниках файла отсутствует. Это удобно для быстрого говнокодинга, но крайне неудобно для сопровождения. Да, там МОЖНО отдельно сделать интерфейс и породить от него класс, на деле же этим занимаются только когда в проекте это принято сверху, волевым решением.

Я вот ковырялся в исходниках сишарпного NBU Explorer, чтобы понять, как там этот NBU разбирается — занятие в программе с кучей классов и методов было на любителя. К автору программы претензий, разумеется, нет, он не обязан поощрять написание программ-аналогов (хотя если кто-то захочет написать и прислать автору патч для развития самого NBU Explorer, ему тоже будет несладко). Претензии к языку, который такой стиль исходников поощряет в качестве основного.

Как в жаве: .jar-архив содержит скомпилятые .class-файлы, из которых javac эффективно выковыривает интерфейс.

Вот только я хочу возможность читать интерфейс, имея только исходники. Иначе это уже метапрог какой-то.

Основная же проблема, которую должны решать модули (на мой взгляд) — это замена кошмарных препроцессорных костылей на синтаксические единицы языка, которые контролируются компилятором. Это позволит 1) радикально ускорить сборку; 2) исключить глупые, труднообнаруживаемые и зависящие от применяемых библиотек ошибки, связанные с разруливанием зависимостей; 3) для проектов низкой и средней сложности вообще отказаться от сборочной системы как отдельной по отношению к ЯП сущности (в Delphi/fpc это работает, например, там все зависимости разматываются непосредственно компилятором из главного модуля).

Решит ли эти проблемы реализация в C++20 — пока не знаю. Это для плюсов вообще новая концепция и можно ожидать, что она будет эволюционировать. Поэтому,

не могут сразу нормально и ДО КОНЦА проработать.

ИМХО, это предсказуемо.

hobbit ★★★★★ ()
Последнее исправление: hobbit (всего исправлений: 3)
Ответ на: комментарий от dimgel

Например в жаве, которая с GC, файлы приходится закрывать явно внутри finally{}, т.к. из-за GC он не закрывается сам при выходе из scope, а оставлять его открытым на неопределённый срок, пока GC до него доберётся

Нет. Подобные объекты расширяют интерфейс AutoCloseable. Это интерфейс подхватывает оператор try-with-resources и автоматически закрывает открытые файлы/коннекшены и т.п. при выходе из области видимости try. Получается практически тот же RAII.

static_lab ★★★★★ ()
Ответ на: комментарий от hobbit

мне крайне не нравится принятый в Java/C# подход, когда интерфейсная часть класса в исходниках файла отсутствует.

Лютая вкусовщина. В жавовских IDE, даже самых убогих (aka Eclipse), есть очень удобные outline view: с цветовым кодированием, навигацией туда-сюда и т.п. Тут можно предвидеть возражение «я в vim сижу» – ну так и платишь за не-использование нормальных тулзов разработчика необходимостью дублирования объявлений методов.

В моём личном случае неиспользование outline view в плюсах – это следствие существования .h-файлов, а не причина (впрочем, изредка использую qtcreator-овый combobox для навигации). Хотя и в .h многие методы инлайнятся (особенно в шаблонах), да и в примерах C++20 модулей, что мне попадались – дык там почти всегда инлайнились (к вопросу о том, чего люди таки-ждали от модулей).

dimgel ★★★★ ()
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от dimgel

Тут можно предвидеть возражение «я в vim сижу»

Чё сразу в vim? Практически в любом редакторе кода, не прибитом к C# или Java.

Именно для чтения чужого кода на C# я в своё время пытался поставить MonoDevelop. Проблему так и не решил (говоря по совести, не сильно пытался), и тема собрала все положенные в этих случаях ненужно. Обошёлся в итоге текстовым редактором с подсветкой, хоть и не совсем комфортно было по классам шастать… Код на C++ с инклудами в аналогичных случаях читался бы намного удобнее.

hobbit ★★★★★ ()
Ответ на: комментарий от hobbit

Чё сразу в vim?

:)) Это собирательное для:

Практически в любом редакторе кода, не прибитом к C# или Java.

:)

И таки да, действительно ненужно. Классная IDE (а теперь aka JetBrains) может дать языку (в смысле удобства и производительности программиста) гораздо больше, чем многие собственно языковые фичи.

С ходу пример – JetBrains неприведигосподь PHPStorm: он умел контролировать типы параметров и прочих переменных, в то время когда сам PHP – нет. Разумеется, это не работало там где была вообще лютая динамика (типа $obj->$propertyName или eval()).

dimgel ★★★★ ()
Последнее исправление: dimgel (всего исправлений: 2)
Ответ на: комментарий от dimgel

С модулями я трахался достаточно долго (в рамках одного проекта, т.к. см. сабж), и никакой разницы в workflow не заметил: только сущностей в makefile побольше стало. И секса (с module map и корявой генерацией gcc-шных .d-файлов), так что в итоге откатил.

А как делил проект на модули? Каждый хидер превращал в модуль? Т.е. хидеров в итоге вообще не осталось (планировал)?

kvpfs ()
Последнее исправление: kvpfs (всего исправлений: 1)
Ответ на: комментарий от dimgel

Ясно. Никто хидеры выкидывать не собирается, ими и дальше нужно пользоваться упаковывать в модуль следует какие-то логически самостоятельные единицы (возможно это вообще целый проект). Иначе да, лишь бессмысленный секс на ровном месте.

kvpfs ()
Последнее исправление: kvpfs (всего исправлений: 1)
Ответ на: комментарий от kvpfs

Я таки не поленился и нашёл: см. первые полтора предложения здесь от Страуструпа. Я даже процитирую: «Header files are a major source of complexity, errors caused by dependencies, and slow compilation. Modules address all three problems» Всё, что вы мне тут дружно доказываете, противоречит этой цитате.

dimgel ★★★★ ()
Последнее исправление: dimgel (всего исправлений: 2)
Ответ на: комментарий от dimgel

Ни разу не противоречит. Я могу подтянуть в свой проект 100500 зависимостей-модулей и получу все плюшки не смотря на то, что сами эти зависимости используют тупые инклуды. Чего говорить, если даже в новой модульной std, останутся include’ы для некоторый сущностей. И вообще, инклуд - гораздо более мощное (по возможностям) средство.

kvpfs ()
Ответ на: комментарий от kvpfs

И вообще, инклуд - гораздо более мощное (по возможностям) средство.

А динамическая типизация мощнее статической, потому что с ней можно чудить вообще любую дичь. Только вот потом всё это рассыпается от любого простейшего рефакторинга. Примерно в этом же ключе вещал о пользе модулей @alysnix.

dimgel ★★★★ ()
Последнее исправление: dimgel (всего исправлений: 2)
Ответ на: комментарий от dimgel

Долгий трах ничему не научил, ну дело хозяйское. А дичь вполне допустима в каких-то пределах (всяикие X Macro и тп), главное не вываливать это пользователям наружу, вот здесь модуль в самый раз.

kvpfs ()
Ответ на: комментарий от kvpfs

«Even Bjarne Stroustrup has called header files a kludge. But without a standard binary format which includes the necessary metadata (like Java class files, or .Net PE files) I don’t see any way to implement the feature.» (отсюда)

Так что не я один такой с идеей портабельного CMI.

Или вот из его интервью:

«This gives far better code hygiene than #including headers that leak implementation details and macros. Modules can also be dramatically faster to compile.»

dimgel ★★★★ ()
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от dimgel

Попробуй посмотреть на это под другим углом, и тогда скорее всего цитаты Страуструпа перестанут противоречить тому, что тебе пишут.

Модуль по-моему очень близок по смыслу package в Го. Он предоставляет какой-то API, но может быть реализован в нескольких файлах для разбиения внутренних сущностей. Таким образом, ты можешь использовать удобные гибкие инклуды внутри модуля, но ограничить их скоуп до модуля. То есть, что у тебя внутри модуля — это деталь реализации, которая не торчит наружу. Поменял широко используемый заголовочный файл? Перекомпилируй что-то в пределах модуля, но это не потянет за собой перекомпиляцию всей программы.

Да, пожалуй аналогия с Го мне очень нравится. Концептуально очень близко плюсовым модулям.

filosofia ()
Ответ на: комментарий от filosofia

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

Про такой подход выше уже писали, но как по мне это дичь. Вместо одной фичи – корявой по Страуструпу, и я в упор не вижу, как прямым текстом сказанное может перестать противоречить – теперь две, одна другой корявей.

dimgel ★★★★ ()
Ответ на: комментарий от dimgel

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

alysnix ★★ ()
Ответ на: комментарий от dimgel

модули(как концепт) это реально эстетически красиво, но только в виде когда есть файл интерфейса модуля(definition), и файл (файлы) реализации его(implementation). в куцем же ввиде - когда есть только реализация, где стоят пометки типа «export» - это полумера, портящая всю идею.

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

хидеры в каком-то виде тоже реализуют эту идею, но они искусственно подгоняются под «интерфейс» модуля. то есть у правильных погромистов модульность давно поддерживается некими соглашениями об оформлении хидеров и кода.

но модули это делают в чистом и проверяемом компилятором виде.

alysnix ★★ ()
Ответ на: комментарий от alysnix

но только в виде когда есть файл интерфейса модуля(definition), и файл (файлы) реализации его(implementation)

Для твоих целей – написать интерфейс и раздать людям реализации – наверное да. Но что-то не припомню я с ходу языков кроме сей-плюсей, где модуль != файл. Не то чтобы я их много знаю, но… Прям начиная от turbo-pascal-евого «unit».

dimgel ★★★★ ()
Ответ на: комментарий от dimgel

Но что-то не припомню я с ходу языков кроме сей-плюсей, где модуль != файл.

потому что модульная идея давняя и применяется повсеместно. в той или иной форме. о вреде половинчатости(файл модуля без файла дефиниций) я уже говорил. вот такая половинчатость слишком широко распространена и только идею портит.

alysnix ★★ ()
Ответ на: комментарий от dimgel

Отсюда вывод: RAII и GC – взаимно-исключающие концепции.

Конечно нет. Никто тебе не мешает в деструкторе закрыть файл и положить свой буфер в (глобальную) очередь на освобождение.

Stil ★★★★★ ()
Ответ на: комментарий от Stil

Накостылить руками можно всё что угодно. Весь пойнт и GC, и RAII в том, что «оно само». Тут даже ранее упоминавшийся try-with-resources – тоже костыль (синтаксический сахар поверх try-finally), про который нужно знать, помнить и явно использовать.

dimgel ★★★★ ()
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от alysnix

(в сторону) …впрочем, у меня у самого многие либы - один .h плюс куча .cpp.

dimgel ★★★★ ()
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от dimgel

Ресурсы это вообще не только про память. К слову, RAII тоже далеко не про память. И это её прелесть и киллер фича над всякими GC.

hatred ★★ ()
Ответ на: комментарий от hatred

К слову, RAII тоже далеко не про память. И это её прелесть и киллер фича над всякими GC.

Кстати да, хорошо сформулировал.

dimgel ★★★★ ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.