Связывание библиотеки Dynami c, которая связывает символы из библиотеки stati c: macOS против Linux - PullRequest
1 голос
/ 10 января 2020

Я портирую приложение Linux на macOS, и есть разница в поведении линковки, на раскрытие которой у меня ушло некоторое время. В проекте используется двухэтапный процесс сборки на основе CMake: одно дерево CMake создает динамическую библиотеку c, которая связывается с библиотекой stati c, которая создается во втором дереве, которое создается позже. Библиотека stati c еще не существует при создании библиотеки Dynami c. Это работает на Linux: библиотека Dynami c создается с символами из библиотеки stati c, и они объявлены заранее. Когда создается второе дерево, библиотека Dynami c связывается с исполняемым файлом, который также связывает библиотеку Stati c, и таким образом все работает нормально. Это не работает в macOS, потому что в первом дереве CMake происходит сбой компилятора на этапе связывания библиотеки Dynami c, поскольку библиотека stati c из второго дерева еще не существует.

Я уменьшил мое приложение к минимальному примеру (код можно найти в конце моего вопроса).

Настройка выглядит следующим образом:

  • Минимальная C программа с функцией main ()
  • Dynami c библиотека с одной функцией
  • Stati c библиотека с одной функцией
  • Программа вызывает функцию из библиотеки Dynami c. Библиотека Dynami c, конечно, динамически связана с программой.
  • Библиотека Dynami c вызывает функцию из библиотеки Stati c. Библиотека stati c статически связана с динамической библиотекой c.

Если мы прекратим связывать библиотеку stati c с библиотекой Dynami c:

# This target_link_libraries is intentionally commented out.
#target_link_libraries(dynamic_lib static_lib)

мы, конечно, получаем ошибки при сборке программы. Но ошибки в macOS различны, и Linux:

macOS / clang завершается с ошибкой раньше на этапе, когда библиотека Dynami c становится связанной с Linux / g cc терпит неудачу позже на этапе, когда программа связывается

Я признаю, что разница может заключаться в том, что я использую clang в macOS и g cc в Linux, но это делает не объясните мне проблему.

Я хотел бы знать:

  1. Почему существует эта разница?
  2. Могу ли я получить поведение Linux в macOS путем настройки флагов компилятора / компоновщика?

Пример был опубликован на Github: Связывание библиотеки Dynami c, которая связывает символы из библиотеки stati c ( macOS против Linux) .

Это ключевые файлы из моего примера на Github:

CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(untitled1 C)

add_compile_options("-fPIC")

set(CMAKE_C_STANDARD 99)

add_library(static_lib static_lib.c)
add_library(dynamic_lib SHARED dynamic_lib.c)

# THE ISSUE IS HERE:
# This target_link_libraries is intentionally commented out.
# on macOS the build process fails when linking dynamic_lib
# on Linux the build process fails when linking the
# 'untitled1' program.
#target_link_libraries(dynamic_lib static_lib)

add_executable(untitled1 main.c)
target_link_libraries(untitled1 dynamic_lib)

dynamic_lib. c

#include "dynamic_lib.h"

#include "static_lib.h"

void dynamic_lib_func() {
  static_lib_func();
}

static_lib. c

#include "static_lib.h"
void static_lib_func() {}

выход macOS * 10 64 *

[ 25%] Building C object CMakeFiles/dynamic_lib.dir/dynamic_lib.c.o
/Library/Developer/CommandLineTools/usr/bin/cc -Ddynamic_lib_EXPORTS  -g -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -fPIC   -fPIC -std=gnu99 -o CMakeFiles/dynamic_lib.dir/dynamic_lib.c.o   -c /Users/stanislaw/workspace/code/Examples/untitled1/dynamic_lib.c
[ 50%] Linking C shared library libdynamic_lib.dylib
/Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake -E cmake_link_script CMakeFiles/dynamic_lib.dir/link.txt --verbose=1
/Library/Developer/CommandLineTools/usr/bin/cc -g -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -dynamiclib -Wl,-headerpad_max_install_names  -o libdynamic_lib.dylib -install_name @rpath/libdynamic_lib.dylib CMakeFiles/dynamic_lib.dir/dynamic_lib.c.o 
Undefined symbols for architecture x86_64:
  "_static_lib_func", referenced from:
      _dynamic_lib_func in dynamic_lib.c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Linux выход

[ 16%] Linking C shared library libdynamic_lib.so
[ 33%] Built target dynamic_lib
Scanning dependencies of target untitled1
[ 50%] Linking C executable untitled1
libdynamic_lib.so: undefined reference to `static_lib_func'
collect2: error: ld returned 1 exit status

1 Ответ

0 голосов
/ 28 января 2020

Мне удалось найти решение связанной проблемы, с которой я также столкнулся при переносе того же проекта с Linux на macOS: Как разделить глобальную переменную между основным процессом и динамической c библиотекой через библиотеку stati c (macOS)? .

Оказывается, что такое «прямое объявление» символов библиотеки возможно в macOS:

Добавление * Флаг 1007 * заставляет macOS передавать исходную ошибку.

Добавление этого в файл CMakeLists.txt моего примера решает проблему:

target_link_options(dynamic_lib PRIVATE -undefined dynamic_lookup)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...