Как использовать модули С++ в Clang?
Модули являются альтернативой #includes. Clang имеет полную реализацию для С++. Как бы я пошел, если бы захотел использовать модули с помощью Clang сейчас?
Использование
import std.io;
в исходном файле С++ не работает (компилируется), так как спецификация модулей (включая синтаксис) не является окончательной.
Документация Clang утверждает, что при передаче флага -fmodules
#includes будут переписаны на соответствующий импорт. Однако проверка препроцессора предполагает иное (test.cpp содержит только #include <stdio.h>
и пустую главную):
$ clang++-3.5 -fmodules -E test.cpp -o test
$ grep " printf " test
extern int printf (const char *__restrict __format, ...);
Кроме того, компиляция этого тестового файла с помощью -fmodules
vs no flags вообще создает один и тот же файл объекта.
Что я делаю неправильно?
Ответы
Ответ 1
Как вы уже упоминали, clang еще не имеет синтаксиса С++ для импорта,
поэтому я сомневаюсь, что директивы #include
будут буквально переписаны как импорт при предварительной обработке файла, поэтому это может быть не лучший способ проверить, работают ли модули по назначению.
Однако, если вы явно задали -fmodules-cache-path=<path>
, вы можете наблюдать, как clang заполняет его предварительно скомпилированными файлами модулей (*.pcm) во время сборки - если есть какие-либо модули.
Вам нужно будет использовать libС++ (который, кажется, поставляется с модулем .modulemap с версии 3.7.0), если вы хотите использовать стандартную библиотеку с включенными модулями прямо сейчас, хотя по моему опыту это не работает полностью только пока.
(Visual Studio 2015 С++ компилятор также должен получить некоторую форму поддержки модуля с обновлением 1 в ноябре)
Независимо от stdlib, вы все равно можете использовать модули в своем собственном коде. В документах clang содержится подробное описание Module Map Language, но
Я также создал небольшой пример проекта здесь (используя cmake), который должен сгенерировать каталог cache
с некоторыми модулями при построении.
Ответ 2
От этот коммит, Clang имеет экспериментальную поддержку Модули TS.
Возьмем те же файлы примеров (с небольшим изменением), что и в сообщение в блоге VS об экспериментальной поддержке модуля.
Сначала определите файл интерфейса модуля. По умолчанию Clang распознает файлы с расширением cppm
(и некоторыми другими) в качестве файлов интерфейса модуля С++.
// file: foo.cppm
export module M;
export int f(int x)
{
return 2 + x;
}
export double g(double y, int z)
{
return y * z;
}
Обратите внимание, что декларация интерфейса модуля должна быть export module M;
, а не только module M;
, как в сообщении в блоге VS.
Затем используйте модуль следующим образом:
// file: bar.cpp
import M;
int main()
{
f(5);
g(0.0, 1);
return 0;
}
Теперь предварительно скомпилируйте модуль foo.cppm
с помощью
clang++ -fmodules-ts --precompile foo.cppm -o M.pcm
или, если расширение интерфейса модуля отличается от cppm
(скажем, ixx
, как и у VS), вы можете использовать:
clang++ -fmodules-ts --precompile -x c++-module foo.ixx -o M.pcm
Затем создайте программу с помощью
clang++ -fmodules-ts -fprebuilt-module-path=. bar.cpp
или, если имя файла pcm не совпадает с именем модуля, вам нужно будет использовать:
clang++ -fmodules-ts -fmodule-file=M.pcm bar.cpp
Я тестировал эти команды в Windows, используя r303050 build (15 мая 2017 г.).
Примечание. При использовании параметра -fprebuilt-module-path=.
я получаю предупреждение:
clang++. exe: warning: аргумент, не использованный во время компиляции: '-fprebuilt-module-path =.' [-Wunused-командной строки-аргумента]
который кажется неправильным, потому что без этой опции модуль M
не найден.