Reputation: 2334
I'm trying to learn a little bit about c++ modules. I wrote simple source code which I'm trying to compile without luck. For some reason I'm experiencing linker issues with multiple definitions but I don't understand the reason. My g++ version is 11.2 from cygwin. Do I have a bug in my code? Is it something else?
$ g++ -std=c++20 -fmodules-ts module_a.cpp module_b.cpp main.cpp
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0xc): multiple definition of `std::string::_Alloc_hider::~_Alloc_hider()'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0xc): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0xc): multiple definition of `std::string::_Alloc_hider::~_Alloc_hider()'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0xc): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0x28): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0x28): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0x28): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0x28): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0x82): multiple definition of `std::string::_Alloc_hider::_Alloc_hider(char*, std::allocator<char> const&)'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0x82): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0x82): multiple definition of `std::string::_Alloc_hider::_Alloc_hider(char*, std::allocator<char> const&)'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0x82): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0xb8): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&)'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0xb8): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0xb8): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&)'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0xb8): first defined here
collect2: error: ld returned 1 exit status
main.cpp:
import module_a;
import module_b;
int main()
{
test_a();
test_b();
}
module_a.cpp:
module;
import <iostream>;
export module module_a;
export void test_a()
{
std::cout << std::string("test module a\n");
}
module_b.cpp:
module;
import <iostream>;
export module module_b;
export void test_b()
{
// std::cout << "test module b\n"; // <- this works
std::cout << std::string("test module b\n"); // <- this cause the issue
}
Upvotes: 2
Views: 1022
Reputation: 1578
I'm not exactly sure what went wrong in your example, likely several things (check my comment to the question). In any case, this code should work fine:
// module_a.cpp
export module module_a;
import <iostream>;
import <string>;
export void test_a()
{
std::cout << std::string("test module a\n");
}
// module_b.cpp
export module module_b;
import <iostream>;
import <string>;
export void test_b()
{
std::cout << std::string("test module b\n");
}
// main.cpp
import module_a;
import module_b;
int main()
{
test_a();
test_b();
return 0;
}
# Makefile
GCC=g++-11 -std=c++20 -fmodules-ts
all: std_headers module_a.o module_b.o main
std_headers:
$(GCC) -xc++-system-header iostream
$(GCC) -xc++-system-header string
module_a.o: module_a.cpp
$(GCC) -c $< -o $@
module_b.o: module_b.cpp
$(GCC) -c $< -o $@
main: main.cpp module_a.o module_b.o
$(GCC) $^ -o $@
clean:
rm -f *.o
rm -rf gcm.cache/
rm -f main
If I should take a guess, it could be that you import iostream
in the global module fragment instead of inside the module declaration, in which case the definitions of iostream, e.g. "std::cout", are not exported as well.
$ make
g++-11 -std=c++20 -fmodules-ts -xc++-system-header iostream
g++-11 -std=c++20 -fmodules-ts -xc++-system-header string
g++-11 -std=c++20 -fmodules-ts -c module_a.cpp -o module_a.o
g++-11 -std=c++20 -fmodules-ts -c module_b.cpp -o module_b.o
g++-11 -std=c++20 -fmodules-ts main.cpp module_a.o module_b.o -o main
$ ./main
test module a
test module b
$ g++-11 --version | head -n 1
g++-11 (Ubuntu 11.1.0-1ubuntu1~20.04) 11.1.0
Upvotes: 1