我使用的是 Marc Gregoire 所著的《Professional C++,第五版》第 1 章中的示例,并添加了一些修改,以便 VSCode 中的 Intellisense 不会出现错误:
员工模块.cppm:
export module employee;
export struct Employee {
char firstInitial;
char lastInitial;
int employeeNumber;
int salary;
};
员工.cpp:
#ifdef __INTELLISENSE__
#include <iostream>
#include <format>
#include "employee-module.cppm"
#else
import <iostream>;
import <format>;
import employee;
#endif
using namespace std;
int main() {
Employee anEmployee;
anEmployee.firstInitial = 'J';
anEmployee.lastInitial = 'D';
anEmployee.employeeNumber = 42;
anEmployee.salary = 80'000;
cout << format("Employee: {}{}", anEmployee.firstInitial,
anEmployee.lastInitial)
<< endl;
cout << format("Number: {}", anEmployee.employeeNumber) << endl;
cout << format("Salary: ${}", anEmployee.salary) << endl;
}
这是我的 Makefile,以防我遗漏了什么:
CXX_VERSION = 23
CXX = g++
CXXFLAGS = -std=c++$(CXX_VERSION) -fmodules-ts
EXE = employee hello
SYSTEM_MODULES = fstream filesystem thread algorithm any array atomic barrier bit bitset charconv chrono compare complex concepts condition_variable coroutine deque \
exception expected format forward_list functional future initializer_list istream iomanip ios iosfwd iostream iterator latch limits list locale map \
memory memory_resource mutex new numbers numeric optional ostream queue ranges ratio regex scoped_allocator semaphore set shared_mutex \
source_location span sstream stack stacktrace stdexcept stdfloat stop_token streambuf string string_view syncstream system_error tuple type_traits \
typeindex typeinfo unordered_map unordered_set utility valarray variant vector version execution random spanstream
.PHONY = all clean system-modules
default: all
all: $(EXE)
employee: employee-module.o employee.o
$(CXX) $(CXXFLAGS) -o $@ $^
hello: hello.o
$(CXX) $(CXXFLAGS) -o $@ $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $^
%.o: %.cppm
$(CXX) $(CXXFLAGS) -c -x c++ $^
clean:
rm -f $(EXE) *.o
deepclean: clean
rm -rf gcm.cache/
$(SYSTEM_MODULES):
$(CXX) $(CXXFLAGS) -x c++-system-header $@
system-modules: $(SYSTEM_MODULES) | gcm.cache/
构建它会给出以下输出,当它尝试链接最终的可执行文件时,会因链接器错误而终止:
$ make
g++ -std=c++23 -fmodules-ts -c -x c++ employee-module.cppm
g++ -std=c++23 -fmodules-ts -c employee.cpp
g++ -std=c++23 -fmodules-ts -o employee employee-module.o employee.o
/usr/bin/ld: employee.o: in function `unsigned char std::__detail::__from_chars_alnum_to_val<false>(unsigned char)':
employee.cpp:(.text._ZNSt8__detail25__from_chars_alnum_to_valILb0EEEhh[_ZNSt8__detail25__from_chars_alnum_to_valILb0EEEhh]+0x12): undefined reference to `std::__detail::__from_chars_alnum_to_val_table<false>::value'
collect2: error: ld returned 1 exit status
make: *** [Makefile:18: employee] Error 1
系统模块均按预期构建并处于
gcm.cache/
状态(如果不是,我会收到编译器错误)。
我的第一个想法是 libstdc++ 没有被链接进来,所以凭直觉我在构建和链接步骤的命令行中添加了
-lstdc++
,但我得到了相同的结果。
此外,我重写了程序,只使用
cout
并将变量直接放入流中,完全避免使用format()
。它完全按照预期构建、链接和运行,没有错误,即使我将 -lstdc++
排除在命令行之外也是如此。
郑重声明,Makefile 中的
"hello"
目标可以正常构建、链接和运行,这是一个使用 "Hello, World!"
的简单的 <iostream>
程序。
所以,然后我用谷歌搜索了(未损坏的)符号名称,希望这能提供一些见解。据我所知,
std::detail::from_chars_alnum_to_val
是charconv
模块的一部分,所以我构建了它,将import <charconv>;
添加到employee.cpp
,然后再次尝试。编译得很好,但同样的链接器错误。
接下来,我决定疯狂地构建每个标准库模块(因此是长得可笑的
SYSTEM_HEADERS
变量)。没有骰子,同样的链接器错误。
我缺少一些基本的东西吗?
我使用的是 Slackware Linux 当前版本、64 位 Intel、g++ 13.2.0、binutils 2.41
您可以尝试升级
gcc
来解决此问题。
我尝试了
gcc 13.3.0
,但错误仍然存在。
但是当您将
gcc
升级到 14.1.0
时,一切正常。
sudo update-alternatives --config gcc
0 /usr/bin/gcc-12 220 auto mode
1 /opt/gcc-13.3.0/bin/gcc 133 manual mode
* 2 /opt/gcc-14.1.0/bin/gcc 141 manual mode
3 /usr/bin/gcc-12 220 manual mode
g++ -std=c++20 -fmodules-ts -o employee employee-module.o employee.o
我想
gcc
对C++20
模块的支持仍在进行中。