Я портирую приложение 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, но это делает не объясните мне проблему.
Я хотел бы знать:
- Почему существует эта разница?
- Могу ли я получить поведение 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