GCC's shared library constructor technique has ceased working with the tool chain provided with XCode 16.4 and XCode 26. This is the GCC attribute:
__attribute__((constructor))
Example use:
void aConstructor(void) __attribute__((constructor));
void aConstructor(void)
{
printf("Called aConstructor\n");
}
In our case aConstructor() was not called.
I clicked 'Accepted Answer' by mistake and can't undo it?
Indeed )-: See tip 12 in Quinn’s Top Ten DevForums Tips for more about that.
Note that the comment facility here is failing to post comments
Well, they post but there’s a bug causing them to not show up immediately (i. 98940414)-: In general, I recommend that you reply as a reply. See tip 5 for more on that.
Coming back to your technical issue, this seems to be working for me in Xcode 26.1. Here’s what I did:
-
Using Xcode 26.1 on macOS 15.7.1, I created a new project from the macOS > Command Line Tool template, selecting C as the language.
-
I changed
main.cto this:#include <stdlib.h> #include <stdio.h> __attribute__((constructor(200))) void foo(void); __attribute__((constructor(101))) void bar(void); void foo(void) { printf("foo\n"); } void bar(void) { printf("bar\n"); } int main(int argc, char **argv) { #pragma unused(argc) #pragma unused(argv) printf("main\n"); return EXIT_SUCCESS; }This is based on the example in the latest Clang docs [1].
-
I ran my program. It printed:
bar foo mainwhich is what I expected: The constructors ran before main and in the order specified by the attribute.
-
I created a new target based on the macOS > Library template, selecting Plain C/C++ Library in the Framework popup and Dynamic in the Type popup. I called this Waffle, resulting in
libWaffle.dylib. -
I created the following C source file and added it to that target:
#include <stdio.h> __attribute__((constructor(200))) void fooWaffle(void); __attribute__((constructor(101))) void barWaffle(void); void fooWaffle(void) { printf("fooWaffle\n"); } void barWaffle(void) { printf("barWaffle\n"); } extern void varnishWafflesNow(void); extern void varnishWafflesNow(void) { printf("varnishWafflesNow\n"); } -
I added the
libWaffle.dyliblibrary to the command-line tool target. -
I changed the bottom of
main.clike so:… as above … extern void varnishWafflesNow(void); int main(int argc, char **argv) { #pragma unused(argc) #pragma unused(argv) printf("main\n"); varnishWafflesNow(); return EXIT_SUCCESS; }Note that I copy’n’pasted the prototype to avoid faffing around with headers (-:
-
I ran the tool. It printed:
barWaffle fooWaffle bar foo main varnishWafflesNow
This seems right to me. The library constructors ran first, then the main executable constructors, and then main.
Please repeat these steps in your environment to make sure you get the same results. If so, you have a working and a non-working example, and you can explore the differences.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] https://clang.llvm.org/docs/AttributeReference.html#constructor-destructor