Pull to refresh
0
0
Иванов Никита @RamzesXI

Разработчик C++

Send message
С++17 полностью (по крайней мере на словах) 3 популярных компилятора поддерживают.

Как там поживает <memory_resource>? А < execution >?

Никто в C++20 не добавлял expected, не вводите людей в заблуждение. Это все еще proposal.
У меня коллеги ускорили сборку своего проекта с 15 до 5 минут с помощью unity билдов. И думаю, что скорость инкреметного билда их не сильно разражает, т.к. большую часть этого времени все равно занимает линковка пачки статических зависимостей.

Распределенную сборку они тоже пробовали — не взлетело, слишком медленно. Полагаю, что уперлись в wifi сетку.

Но мой поинт в другом. Модули по своей сути могут отчасти напоминать идею unity билдов. Предобработать исходники, объединить их в удобном виде и закешировать — и последующая компиляция будет быстрой.
Видимо, мы друг друга не убедим до тех пор, пока не увидим, как implementation defined детали работы с модулями будут реализованы в компиляторах.
У меня такое чувство, что вы мало знакомы с темой, очень мало.

Может, не стоит скатываться в обвинения о непрофессионализме? Это оскорбительно и лишь провоцирует на взаимные обвинения.


Давайте лучше почитаем proposals по модулям и предположим, как эти предложения смогут реализовать компиляторы. А для начала договоримся об одном понимании header-only библиотек, какие "гарантии" они дают, а какие — нет.


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

Предположим, я пишу проект на последнем C++17 и подключаю к нему header-only библиотеку, которая:


  • Использует в своей реализации старенький std::bind1st. Эта вещь была удалена в 17 плюсах. Gcc спокойно скомпилирует заинклюженную в мои cpp файлы эту header-only библиотеку. Clang тоже. Но только если будет использоваться std либа от gcc. Если я подключу std от clang, то получу ошибку — там эта вещь была удалена в соответствии со стандартом. Флаг std не совместим сверху вниз, в нашем примере он навязывается проекту от header-only либы, иначе проект не соберется только из-за несборки кода header-only библиотеки.
  • Использует чуть более современный std::thread. Чтобы мой проект собрался с этой header-only либой на линуксе, я должен слинковаться с pthread.
  • Использует std::filesystem. Тогда на компиляторе gcc я должен слинковаться с stdc++fs.
    Вывод: header-only библиотека может зависеть от бинарей даже в случае, если используется только стандартный c++.

А теперь о том, какие же "гарантии" дает header-only либа. А она гарантирует лишь:


  • что все необходимые файлы с реализацией будут автоматически подключены в конечный cpp файл;
  • если какая-то часть библиотеки не используется в конечных cpp файлах, она туда не подключается и соответственно не собирается, ускоряя сборку;

А так же гарантирует минусы:


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

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


И почему вообще header-only библиотеки вы называете "современным" подходом? Что в этом современного? Его разве изобрели пару лет назад?


Неужели эти "гарантии" не смогут предоставить модули?
Способ поиска модуля при импорте — implementation defined. Компилятор точно так же может сделать директиву, где будет принимать директорию для поиска подключаемых модулей.
В случае, если будет принято предложение ATOM об объявлении модуля только на верху файла, тогда компилятору будет достаточно прочесть заголовки всех файлов в этой директории, чтобы понять, что потребует сборки. Это не так быстро, как чтение хедера по прямому пути из инклюда, но выполняется однократно, в отличии от многократного чтения хедера при каждом включении. Если предложении от ATOM не будет принято, компилятору придется прочесть/распарсить каждый файл целиком, чтобы найти там объявления модуля. Это соответственно дольше.
Всё! Гарантии header-only либы могут быть соблюдены и модулями! При этом они лишены недостатоков header-only либы — вся внутренняя реализация библиотеки не будет видна конечному коду и будет компилироваться только один раз.


И это все для случая дистрибуции только исходников модуля. В случае дистрибуции их бинарного представления будет больше работы по учету платформы сборки, но этой работы будет априори меньше, чем при дистрибуции финальных бинарей библиотек.

Создавать файлы, которые будут эмулировать хедеры, перекладывать это на шею ide?

Почему бы и нет? Либо просто показывать интерфейс в менюшке автокомплита, как это делается во многих ide сейчас?

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

Далее, дистрибуция. Это опять приключения. Нужна статическая линковка, либо приключения с контейнерами.

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

Если и о компиляторах думать не хочется, можно распространять только исходники и собирать их самостоятельно в модули, в любом случае соберутся быстрее старого подхода. header-only библиотека ортогональна простоте сборки: у неё точно так же могут быть зависимости, которые потребуется собрать, у неё могут особые требования на флаги компиляции, которые желательно носить рядом, в том же cmake. Хорошие header-only либы этими проблемами не страдают, ну так и модули можно писать точно так же, избегая сложных зависимостей и сложной сборки.
Мы потеряем то самое преимущество, особенно в контексте header-only, когда мы всегда можем увидеть как минимум сигнатуры функций.

Не совсем понял. Под «увидеть» понимается посмотреть на код в human-readable формате? Если да, то вопрос тулчейна, он должен научиться показывать интерфейс модуля в читаемом виде, все необходимое для этого в модуле есть.

Опять же, один из тех же профитов, который даёт header-only — простую кросскомпиляцию и между платформами и между компиляторами. Дадут ли тоже самое модули? Сомневаюсь.

Какая связь между кроссплатформенностью и header-only? Как в header-only спокойно можно писать непереносимый код, так и не в header-only можно писать кроссплатформенно. Это ортогональные понятия.
Все еще не понятно, действительно ли модули смогут значительно ускорить сборку по сравнению с unity билдами. Не очень похоже, что препроцессниг макросов занимает значительное время.

И сразу открытый вопрос: а почему нельзя совместить оба подхода, с экспортом макросов и без? Даже если модуль с макросами будет собираться дольше, пусть это будет опцией при сборке модуля. Если опция не включена, то и хранить модуль можно в более оптимальном виде, и знать можно, что он не повляет на последующие текстовые инклюды. Дескать, если разработчик настолько сильно желает экспортировать макросы в своем апи, что готов пожертвовать временем компиляции у конечных потребителей — пусть. Пользователям решать, использовать такую библиотеку или нет.
Детали эксперимента можно тут посмотерть: reddit. Это всего лишь локальный эксперимент какого-то разработчика, но все же лучше, чем ничего.

Если рассуждать о скорости компиляции, то модули подступаются к этому вопросу с нескольких сторон.

Например в случае, если не экспортим макросы, то единицей модуля может быть единица трансляции после фаз трансляции 1-7(8), представленная в оптимальном бинарном виде. Согласитесь, если вам вместо файла с исходниками дадут вот такую единицу модуля — компилироваться все в итоговый файл будет быстрее.

Или, например, объявление модуля. Не знаю, как там после последней встречи объединили Modules TS и ATOM, но конкретно от ATOM ранее было предложение разрешать объявление модуля только на верху единицы трансляции. Это позволит компилятору прочесть только заголовки файлов и построить граф зависимостей между файлами, чтобы потом оптимальнее подгружать их при компиляции.

Другой момент касается шаринга явных и неявных инстанцирований шаблонов: в модулях их стараются расшаривать по-максимому, чтобы не делать повторно одни и те же инстанцирования. Я правда не знаю, как современные компиляторы работают с инстанцированиями — пытаются ли запоминать, что какой-то шаблон уже обрабатывали и инстанцировали в другой единице трансляции? Если нет, то здесь модули так же дадут ускорение, т.к. это одно из главных вкладов во время компиляции.
Вот поэтому и хочется узнать о результатах экспериментов от разрабов Modules TS. Что-то вроде: «Вот мы сделали модули без макросов и компиляция ускорилась в 10 раз, а сделали с макросами — получили прирост в 0,1».
Может подход в духе precompiled headers и достигает теоретического предела в приросте?

Я ни в коем случае не защищаю макросы и не пишу своих в кодовой базе. Я заинтересован в том, чтобы разработчики библиотек активно переходили на модули, но как бы не получилось так, что будем еще 10 лет разрабатывать модули, а потом 10 лет переходить на них.
Modules TS предлагает по-максимому расшаривать explicit и implict инстанцирования, идущие с модулем.
А вот тут хочется подробностей, полагаю, что авторы Modules TS и ATOM должны были проводить какие-то эксперименты на своих кодовых базах.

Я читал про эксперимент на модулях от clang (а авторы proposal наверняка вдохновлялись и такими модулями), они давали прирост 60% (или 10% по сравнению с использованием precompiled headers).

Хочется еще узнать, а как реализованы Modules TS и ATOM в gcc. Используют ли они предложенное Страуструпом бинарное представление пропарсенного C++ кода? Или у них какое-то свое представление? И таскают ли в реализации ATOM текстовую копию кода для поддержки экспорта макросов?
Вот и получается, что либо ждем лет 10-15 всех необходимых фич, либо поддерживаем макросы в модулях и делаем быстрый и безболезненный переход.
Тогда просто не будут переходить на модули те, у кого макросы в апи. Тот же gtest/gmock, например.

Information

Rating
Does not participate
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity