mesonbuild / mesonbuild/meson

Linking C++ executable with Objective-C dynamic library fails

Open
#3,183 2 comments 0 reactions 0 assignees View on GitHub
bug compilers
Dominant language
Python
Stars
6.6k
Forks
1.9k
Avg merge
2d 6h
Merged PRs (30d)
33

Description

When linking a C++ application using C++11 threads to a library built from Objective-C sources, it seems like Meson incorrectly selects the Objective-C linker which leaves standard library symbols unresolved since no C++ standard library is linked. Linking a similar application with a library built from Objective-C++ sources works fine, because the Objective-C++ linker is selected (I believe this would be the correct behavior even in the first case).

Example:
```
project('test', ['cpp', 'objc', 'objcpp'], default_options: ['cpp_std=c++11'])

t = dependency('threads')

l1 = library('lib_1', 'lib.m')
d1 = declare_dependency(link_with: l1, include_directories: include_directories('.'))
e1 = executable('app_1', 'test.cpp', dependencies: [t, d1])

l2 = library('lib_2', 'lib.mm')
d2 = declare_dependency(link_with: l2, include_directories: include_directories('.'))
e2 = executable('app_2', 'test.cpp', dependencies: [t, d2])
```

The implementation of `lib.m` and `lib.mm` is irrelevant, but `test.cpp` must use C++11 threads or atomics. When building `app_2`, everything is fine, but building `app_1` yields the following:
```
[1/1] Linking target app_1.
FAILED: app_1
cc -o app_1 'app_1@exe/test.cpp.o' liblib_1.dylib -pthread -Wl,-rpath,/private/tmp/test/build/
clang: warning: argument unused during compilation: '-pthread' [-Wunused-command-line-argument]
Undefined symbols for architecture x86_64:
"std::__1::__thread_struct::__thread_struct()", referenced from:
std::__1::thread::thread(void (&&&)()) in test.cpp.o
"std::__1::__thread_struct::~__thread_struct()", referenced from:
std::__1::thread::thread(void (&&&)()) in test.cpp.o
void* std::__1::__thread_proxy >, void (*)()> >(void*) in test.cpp.o
"std::__1::__thread_local_data()", referenced from:
void* std::__1::__thread_proxy >, void (*)()> >(void*) in test.cpp.o
"std::__1::__throw_system_error(int, char const*)", referenced from:
std::__1::thread::thread(void (&&&)()) in test.cpp.o
"std::__1::thread::~thread()", referenced from:
_main in test.cpp.o
"operator delete(void*)", referenced from:
std::__1::thread::thread(void (&&&)()) in test.cpp.o
void* std::__1::__thread_proxy >, void (*)()> >(void*) in test.cpp.o
"operator new(unsigned long)", referenced from:
std::__1::thread::thread(void (&&&)()) in test.cpp.o
"___gxx_personality_v0", referenced from:
std::__1::thread::thread(void (&&&)()) in test.cpp.o
void* std::__1::__thread_proxy >, void (*)()> >(void*) in test.cpp.o
Dwarf Exception Unwind Info (__eh_frame) in test.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
```

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the shown Meson project with the two library targets, app_1 and app_2, and compare their generated link commands. Trace how the source language of linked libraries affects executable linker selection. Done means the app_1 C++11 threads example links successfully with the required C++ standard library, like app_2.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, objective-c
Domain
build-system, compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.