I can't use the Clion 2023.3 to compile cpp20 modules code successfully. Here is the code:
//Hello.cppm
#include <iostream>
export module Hello;
export void hello() {
std::cout << "Hello World!\n";
}
//main.cpp
import Hello;
int main() {
hello();
return 0;
}
when I build these code, some errors come out:
error: module interface compilation requires '-std=c++20' or '-fmodules-ts'
error: unknown type name 'import'
error: use of undeclared identifier 'hello'
I searched on some site and decide to build it in Clion's terminal First build the module:
clang++ -std=c++20 -fmodules-ts Hello.cppm --precompile -o Hello.pcm
Hello.pcm was generated with no error, then build the main.cpp:
clang++ -std=c++20 main.cpp -fmodule-file=Hello=Hello.pcm Hello.pcm -o Hello.out
errors comes again:
error: unknown type name 'import'
error: use of undeclared identifier 'hello'
my os version is macOS Sonoma 14.2.1, clang version 15 clion toolchains used Bundled(cmake 3.27.8)
Anybody can help? Thx!
As far as compiler switches go, use either -std=c++20
or -fmodules-ts
, but do not use both. The modules TS has been superseded by C++20, so I recommend the former.
The only mistake I saw in the program itself was to omit the global module fragment. That comes first in a module unit, and begins with the module;
declaration.
Old-school include directives belong in the global module fragment.
// hello.cppm
// Clang uses the file extension `.cppm` for "module interface units."
module; // "global module fragment" begins here
// Include directives belong in the global module fragment.
#include <iostream>
// The global module fragment ends when a module declaration is encountered.
export module Hello;
export void hello() {
std::cout << "Hello World!\n";
}
// end file: hello.cppm
According to the Clang documentation for modules:
The file name of an importable module unit should end with .cppm (or .ccm, .cxxm, .c++m). The file name of a module implementation unit should end with .cpp (or .cc, .cxx, .c++).
If the file names use different extensions, Clang may fail to build the module.
So, make sure the file name of your module interface unit ends with .cppm
.
Non-module files, such as main.cpp
are regular C++ translation units. So, they should use the file name extension .cpp
.
Your file main.cpp
looks fine.
// main.cpp
import Hello;
int main() {
hello();
return 0;
}
// end file: main.cpp
I am not a Clang user, so I ran your program under MSVC. Might be irrelevant as far as Clang is concerned, but the program above ran correctly in Visual Studio (although I did use Microsoft's ixx
file name extension for the module interface unit).
Note: the program above is very similar to one given in the Clang documentation. For that program, the docs recommend the following compilation commands:
$ clang++ -std=c++20 Hello.cppm --precompile -o Hello.pcm
$ clang++ -std=c++20 main.cpp -fmodule-file=Hello=Hello.pcm Hello.pcm -o Hello.out
$ ./Hello.out
Hello World!
These are identical to what you are using, except -fmodules-ts
has been omitted.
You might also try a "modules-only" approach. This places function main
into a module, and also uses header units, rather than include files, for access to the Standard Library. Downstream, you may be able to switch to C++23's import std;
(which I have been using in Microsoft projects for six months now).
// Hello.cppm
export module Hello;
import <iostream>; // "header unit"
export void hello() {
std::cout << "Hello World!\n";
}
// end file: Hello.cppm
// main.cppm
export module main;
import Hello;
export int main()
{
hello();
return 0;
}
// end file: main.cppm
Check the Clang documentation for more information about how to compile header units.