Создание библиотеки Dynami c на Ma c OSX с использованием clang ++ - PullRequest
0 голосов
/ 01 апреля 2020

Я хотел узнать, как создать общую библиотеку на C ++. Поэтому я нашел несколько логик 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.

Makefile:

.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!

Но я не могу получить ссылку на мою общую библиотеку при компиляции 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> >)

Я пытаюсь углубиться и понять процесс компоновки / компиляции. Как мне выполнить настройку, которая у меня есть, чтобы продемонстрировать, что я хочу сделать?

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

Попробуйте назвать вашу библиотеку как libmandelbrot.dylib в соответствии с флагом -lmandelbrot

0 голосов
/ 01 апреля 2020

Благодарность идет к @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.

Таким образом, если вы хотите произвольно назвать ваши динамически загруженные библиотеки (и по какой-то причине не ' Как волхвы c добавления имени 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, компоновщик ищет непосредственно в каталоге, указанном -L, для точного имени файла, указанного в -l. В противном случае -l foo -L /path/ ищет /path/libfoo.[dylib|a]

...