使用 clang++ 在 Mac OSX 上创建动态库
Creating dynamic library on Mac OSX using clang++
我想学习如何用 C++ 创建共享库。所以我找到了一些生成Mandelbrot PPM图像的逻辑,并将其封装在src/mandelbrot.cpp
中(附带头文件include/mandelbrot.cpp
)。目录树如下所示:
$ tree
.
├── Makefile
├── include
│ └── mandelbrot.h
├── lib
│ └── mandelbrot.dylib
└── src
├── client.cpp
├── main
├── main.cpp
├── mandelbrot.cpp
└── mandelbrot.o
目标是 src/client.cpp
使用 lib/mandelbrot.dylib
绘制分形而无需访问 src/mandelbrot.cpp
或 src/mandelbrot.o
。
生成文件:
.PHONY=clean
main: src/mandelbrot.o
clang++ src/main.cpp -o src/main src/mandelbrot.o -I ./include
src/mandelbrot.o:
clang++ -c src/mandelbrot.cpp -o src/mandelbrot.o -I ./include
clean:
rm src/*.o
rm lib/*.dylib
lib/mandelbrot.dylib:
clang++ -dynamiclib -o lib/mandelbrot.dylib src/mandelbrot.cpp -I ./include
src/client: lib/mandelbrot.dylib
clang++ src/client.cpp -o src/client -L ./lib -I ./include
运行 没有 dylib 的可执行文件工作:
$ make main
clang++ src/main.cpp -o src/main src/mandelbrot.o -I ./include
$ ./src/main # runs fine!
但是编译时我无法将我的共享库获取到 link src/client.cpp
:
$ make src/client
clang++ src/client.cpp -o src/client -L ./lib -I ./include
Undefined symbols for architecture x86_64:
"fractal::Mandelbrot::writeToFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_main in client-e344c7.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [src/client] Error 1
即使该符号似乎在 dylib 中:
$ file lib/mandelbrot.dylib
lib/mandelbrot.dylib: Mach-O 64-bit dynamically linked shared library x86_64
$ nm -C lib/mandelbrot.dylib | grep writeToFile
0000000000001460 T fractal::Mandelbrot::writeToFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
我正在尝试深入挖掘并理解 linking/compilation 过程。我如何进行设置以演示我想做什么?
尝试将您的库命名为 libmandelbrot.dylib 以匹配 -lmandelbrot 标志
归功于@Daniel 找到了答案,但有点原因。
我可以通过重命名 mandelbrot.dylib
-> libmandelbrot.dylib
来完成编译工作,正如@daniel 的回答所建议的那样。
我深入研究了 man ld
(链接器)并找到了以下定义:
-lx This option tells the linker to search for libx.dylib or libx.a in the library search path. If string x is of the form y.o, then that file is searched for in the same places, but without prepending
`lib' or appending `.a' or `.dylib' to the filename.
因此,如果您想任意命名动态加载的库(并且出于某种原因不喜欢在名称前加上 libxxxx 的魔力,您必须这样做(我已经确认这有效):
lib/whatever.o:
clang++ -dynamiclib -o lib/whatever.o src/mandelbrot.cpp -I ./include
src/client: lib/whatever.o
clang++ src/client.cpp -o src/client -L ./lib -I ./include -l whatever.o
TL;DR = 通过将 -l
选项作为以 .o
结尾的文件名,链接器直接在 [= 指定的目录中查找17=] 用于在 -l
中指定的确切文件名。否则 -l foo -L /path/
搜索 /path/libfoo.[dylib|a]
我想学习如何用 C++ 创建共享库。所以我找到了一些生成Mandelbrot PPM图像的逻辑,并将其封装在src/mandelbrot.cpp
中(附带头文件include/mandelbrot.cpp
)。目录树如下所示:
$ tree
.
├── Makefile
├── include
│ └── mandelbrot.h
├── lib
│ └── mandelbrot.dylib
└── src
├── client.cpp
├── main
├── main.cpp
├── mandelbrot.cpp
└── mandelbrot.o
目标是 src/client.cpp
使用 lib/mandelbrot.dylib
绘制分形而无需访问 src/mandelbrot.cpp
或 src/mandelbrot.o
。
生成文件:
.PHONY=clean
main: src/mandelbrot.o
clang++ src/main.cpp -o src/main src/mandelbrot.o -I ./include
src/mandelbrot.o:
clang++ -c src/mandelbrot.cpp -o src/mandelbrot.o -I ./include
clean:
rm src/*.o
rm lib/*.dylib
lib/mandelbrot.dylib:
clang++ -dynamiclib -o lib/mandelbrot.dylib src/mandelbrot.cpp -I ./include
src/client: lib/mandelbrot.dylib
clang++ src/client.cpp -o src/client -L ./lib -I ./include
运行 没有 dylib 的可执行文件工作:
$ make main
clang++ src/main.cpp -o src/main src/mandelbrot.o -I ./include
$ ./src/main # runs fine!
但是编译时我无法将我的共享库获取到 link src/client.cpp
:
$ make src/client
clang++ src/client.cpp -o src/client -L ./lib -I ./include
Undefined symbols for architecture x86_64:
"fractal::Mandelbrot::writeToFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_main in client-e344c7.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [src/client] Error 1
即使该符号似乎在 dylib 中:
$ file lib/mandelbrot.dylib
lib/mandelbrot.dylib: Mach-O 64-bit dynamically linked shared library x86_64
$ nm -C lib/mandelbrot.dylib | grep writeToFile
0000000000001460 T fractal::Mandelbrot::writeToFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
我正在尝试深入挖掘并理解 linking/compilation 过程。我如何进行设置以演示我想做什么?
尝试将您的库命名为 libmandelbrot.dylib 以匹配 -lmandelbrot 标志
归功于@Daniel 找到了答案,但有点原因。
我可以通过重命名 mandelbrot.dylib
-> libmandelbrot.dylib
来完成编译工作,正如@daniel 的回答所建议的那样。
我深入研究了 man ld
(链接器)并找到了以下定义:
-lx This option tells the linker to search for libx.dylib or libx.a in the library search path. If string x is of the form y.o, then that file is searched for in the same places, but without prepending
`lib' or appending `.a' or `.dylib' to the filename.
因此,如果您想任意命名动态加载的库(并且出于某种原因不喜欢在名称前加上 libxxxx 的魔力,您必须这样做(我已经确认这有效):
lib/whatever.o:
clang++ -dynamiclib -o lib/whatever.o src/mandelbrot.cpp -I ./include
src/client: lib/whatever.o
clang++ src/client.cpp -o src/client -L ./lib -I ./include -l whatever.o
TL;DR = 通过将 -l
选项作为以 .o
结尾的文件名,链接器直接在 [= 指定的目录中查找17=] 用于在 -l
中指定的确切文件名。否则 -l foo -L /path/
搜索 /path/libfoo.[dylib|a]