我有一个用Fortran和C ++混合编写的库。它还在Fortran层使用MPI。让我们说用户想要将新的c ++程序链接到我的库。根据我在互联网上找到的内容,最好的方法是让他们用C ++编译器编译代码,并使用mpif90 fortran包装器链接到我的库。这是为了确保您链接到正确版本的MPI。但是为了使这一切都能正常工作,你还必须明确地链接libc ++,否则你的c ++程序将无法正常工作。所以,例如:
mpic++ their_code.cc -c
mpif90 their_code.o -o program.exe -lmylib -lstdc++
在许多平台和编译器(gnu,intel等)中,这种方法对我来说很好。它也适用于clang,直到Xcode 9.0发布,这打破了这个过程。编译器错误似乎与c ++标准库中的不兼容性有关,因为它只在我调用传递std :: string的函数时才会中断。在Xcode release notes中它说:
使用此Xcode版本创建的项目使用标准C ++库的新libc ++实现。 libc ++库仅在iOS 5.0及更高版本和OS X 10.7及更高版本上可用。 12221787
要在项目的早期版本的iOS和OS X上启用部署,请将C ++标准库构建设置设置为libstdc ++(Gnu C ++标准库)。
这让我相信我需要修改我与libc ++的链接方式。您可以使用以下代码重现此问题(假设您已将Xcode升级到版本9)。
main.cc:
#include<string>
using namespace std;
void fun_str(string s);
void fun_num(int n);
int main() {
string my_str = "test";
int my_num = 1;
fun_str(my_str);
fun_num(my_num);
return 0;
}
fun.cc:
#include <string>
using namespace std;
void fun_str(string s) {}
void fun_num(int n) {}
生成文件:
test: main.o fun.o
mpif90 main.o fun.o -o program.exe -lstdc++
main.o: main.cc
mpic++ main.cc -c
fun.o: fun.cc
mpic++ fun.cc -c
注意如果删除对字符串的所有引用,它确实可以正确编译。但如果没有,则会出现以下错误:
mpic++ main.cc -c
mpic++ fun.cc -c
mpif90 main.o fun.o -o program.exe -lstdc++
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)", referenced from:
_main in main.o
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
_main in main.o
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [test] Error 1
此外,如果您通过将环境变量OMPI_CXX设置为g ++ - 7来切换到GNU,它也可以毫不费力地编译。所以这绝对只是一个Clang问题,只出现在新版本中。任何帮助将不胜感激:)!