Hi! For example i have library with structure like ModuleA/test.cpp, ModuleB/test.cpp, then i build it like:
#Building library
clang++ -c ModuleA/test.cpp -o ModuleA/test.o
clang++ -c ModuleB/test.cpp -o ModuleB/test.o
libtool -o module.a ModuleA/test.o ModuleB/test.o
#Now reproducing build steps from Xcode
#Compiling...
clang++ -c main.cpp -o main.o
#Linking...
clang++ -Xlinker -reproducible -o main main.o module.a
Now if we launch lldb main,
we cant set breakpoint in file ModuleB/test.cpp, only in ModuleA/test.cpp, if link without -Xlinker -reproducible
, both breakpoints working as expected.
Also dsymutil completely delete symbols for "duplicate" library if link with reproducible
flag.
It's just example, in real static library i can't change behavior of building process, and can't change names of producing object files.
Xcode always set -Xlinker -reproducible
flag, and i don't know how to disable it, and my debugging process partially broken.
ENV: macos: 15.4.1 Xcode: 16.2
Thanks for that.
I reproduced the problem and then, after tweaking your setup a little, did some digging. Consider this:
(lldb) image lookup -r -n ModuleA
1 match found in /Users/quinn/Test/cppmodule-ok/main:
Address: main[0x00000001000010e4] (main.__TEXT.__text + 3068)
Summary: main`ModuleA::test() at test.cpp:6
(lldb) image lookup -r -n ModuleB
1 match found in /Users/quinn/Test/cppmodule-ok/main:
Address: main[0x0000000100001114] (main.__TEXT.__text + 3116)
Summary: main`ModuleB::test() at test.cpp:9
In this context:
-
cppmodule-ok
is a directory containing a copy of your test with the-Xlinker -reproducible
removed. -
Similarly,
cppmodule-ng
is your test with-Xlinker -reproducible
still in place. -
I added three blank lines to the front of
ModuleB/test.cpp
so that we can tell the two files apart.
Contrast this to:
(lldb) image lookup -r -n ModuleA
2 matches found in /Users/quinn/Test/cppmodule-ng/main:
Address: main[0x00000001000010e4] (main.__TEXT.__text + 3068)
Summary: main`ModuleA::test() at test.cpp:6
Address: main[0x00000001000010e4] (main.__TEXT.__text + 3068)
Summary: main`ModuleA::test() at test.cpp:6
(lldb) image lookup -r -n ModuleB
1 match found in /Users/quinn/Test/cppmodule-ng/main:
Address: main[0x0000000100001114] (main.__TEXT.__text + 3116)
Summary: main`ModuleB::test()
Note how the debug symbol for ModuleB has somehow disappeared and the one for ModuleA has somehow been duplicated.
The next thing I wanted to check was whether your use of a static library was a factor here. To do that, I tweaked the cppmodule-ng
case to not use module.a
but instead link directly with $BUILD_DIR/ModuleA/test.o
and $BUILD_DIR/ModuleB/test.o
. That got things working, confirming that, yep, the static library is a factor.
When I compare the debugger symbols in the static library vs no-static library case I see this:
% diff main-ok.txt main-ng.txt
249c249
< 0000000000000000 - 00 0001 OSO /Users/quinn/Test/cppmodule-ng/build/ModuleA/test.o
---
> 0000000000000000 - 00 0001 OSO /Users/quinn/Test/cppmodule-ng/build/module.a(test.o)
257c257
< 0000000000000000 - 00 0001 OSO /Users/quinn/Test/cppmodule-ng/build/ModuleB/test.o
---
> 0000000000000000 - 00 0001 OSO /Users/quinn/Test/cppmodule-ng/build/module.a(test.o)
Note how in the main-ng.txt
file both OSO
symbols reference the same item within the archive, that is, module.a(test.o)
. This seems like it’d be bad |-:
The weird part here is that this is triggered by -reproducible
. I see similar results in the cppmodule-ok
, so it’s not the sole factor in play. I suspect that -reproducible
is causing the linker to do more work which is then getting confused by this setup.
At this point I think I’m gonna have to draw a line under this investigation. Something weird is going on here, and the linker team should look at that. I recommend that you file a bug about this, making sure to attach your test case and include a link to this thread.
Please post your bug number, just for the record.
As to a workaround, I think that’s pretty straightforward. If you give both test.o
files a unique name, things work. For example, in your test I changed the file names to ModuleA-test.o
and ModuleB-test.o
, and that fixed the problem you’re seeing in the cppmodule-ng
case.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"