通过命令行编译和链接Swift/Objective-C++应用程序

5
在我的 Swift 应用程序中添加了一个 C++ 组件,通过命令行编译和运行。现在需要编译 C++ 和 Objective-C++ (*.mm) 文件,并将它们与 Swift 应用程序链接。
Makefile:
all: foo-renderer

clean:
  rm -f foo-renderer cpp.o objc.o

cpp.o: FooRenderer/FooRenderer/FooLibrary.cpp
  clang++ -c -o $@ $^

objc.o: cpp.o FooRenderer/FooRenderer/FooLibraryWrapper.mm
  clang++ -c -framework Foundation -o $@ $^

foo-renderer: objc.o FooRenderer/FooRenderer/*.swift
  xcrun -sdk macosx swiftc -import-objc-header FooRenderer/FooRenderer/FooRenderer-Bridging-Header.h -o $@ $^

编译器出现以下错误:
ld: warning: object file (objc.o) was built for newer OSX version (10.12) than being linked (10.9)
Undefined symbols for architecture x86_64:
  "__ZN11FooLibrary23printifyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE", referenced from:
      -[FooLibraryWrapper printify:] in objc.o
  "__ZN11FooLibrary8optimizeERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE", referenced from:
      -[FooLibraryWrapper optimize:] in objc.o
  "__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm", referenced from:
      -[FooLibraryWrapper printify:] in objc.o
      -[FooLibraryWrapper optimize:] in objc.o
  "__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev", referenced from:
      -[FooLibraryWrapper printify:] in objc.o
      -[FooLibraryWrapper optimize:] in objc.o
  "__ZSt9terminatev", referenced from:
      ___clang_call_terminate in objc.o
  "___cxa_begin_catch", referenced from:
      ___clang_call_terminate in objc.o
  "___gxx_personality_v0", referenced from:
      -[FooLibraryWrapper printify:] in objc.o
      -[FooLibraryWrapper optimize:] in objc.o
      Dwarf Exception Unwind Info (__eh_frame) in objc.o
ld: symbol(s) not found for architecture x86_64

我的第一反应是标准的C++库没有被包含进来。我尝试将以下lib标记添加到命令中,但是没有成功:

cpp.o: FooRenderer/FooRenderer/FooLibrary.cpp
  clang++ -c --std=c++14 -lstdc++ -lc++ -stdlib=libstdc++ -o $@ $^

我错过了什么?

你尝试过明确指定要使用的SDK,以及最小和最大的操作系统版本吗?Xcode可以做到这一点。你可能想使用Xcode进行构建,并查看在报告导航器中展开条目时它传递了什么(每行右侧有一个不可见的图标显示)。 - uliwitness
(对于链接器警告,我的意思是) - uliwitness
2个回答

3

问题在于最后一个命令行缺少cpp.o。将其添加到依赖列表中应该可以解决问题:

foo-renderer: objc.o FooRenderer/FooRenderer/*.swift cpp.o
      xcrun -sdk macosx swiftc -import-objc-header FooRenderer/FooRenderer/FooRenderer-Bridging-Header.h -o $@ $^

那是因为连接器需要C++代码中所找到的符号定义。在cpp.o目标命令中添加-l...标志是不必要的,因为那些都是链接器标志,在这个时候你只是在编译。另外,你很可能不需要objc.o目标的cpp.o依赖性,因为你仍然在编译,而编译不依赖其他目标文件。你也可能没有必要用-framework Foundation,但这并不会有任何影响。

非常感谢 @OmniProg!回答得真好,这对我真的很有帮助。 - Beau Hankins

1

虽然我对objc/clang/swift不是很熟悉,但我有一些指导意见,希望能帮到你。

> "__ZN11FooLibrary23printifyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
> referenced from:
>       -[FooLibraryWrapper printify:] in objc.o
上述内容表示在objc对象文件的printify函数中,存在一个未定义的符号,可能是FooLibrary::printify::basic_string::char_traits,因此很可能您缺少c++库,请尝试在链接命令中添加libc++库。
cpp.o: FooRenderer/FooRenderer/FooLibrary.cpp
  clang++ -c --std=c++14 -lstdc++ -lc++ -stdlib=libstdc++ -o $@ $^

在编译时添加链接器标志/库没有意义。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接