>>> 2- once again, why not use the linker support for initialization? >>> If behavior has to depend on whether ECL was initialized yet, >>> the initialization could consider in calling ecl_register_init_function, >>> which depending on whether ECL was booted, would either call the function >>> and/or add it to a hook. >>> See once again attached files on how to use linker support for >>> initialization. >> >> Fact that we might bundle many objects in one archive doesn't mean that >> they don't have dependencies on one another. *I think* that we have to >> strictly control initialization order. It's possible that I'm wrong here >> though. >> It *is* possible to strictly control initialization order while using linker functions: either ensure that you link objects in the correct order (duh), and/or have your ensure_foo_initialized functions explicitly call each other.
>> Also do we want to *always* initialize *everything* what is linked? We >> may have compiled-in support for number of lisp libraries in one module >> just for conveniance and require them on demand depending on the >> application using our code. >> There again, the linker-called code could "just" register the initialization function to be called later, if that's what you want. >> I'm guessing here since it's a design decision made by someone >> else. Your proposition is surely worth investigating - it is like it is >> because it was that way when I approached the codebase. >> Some decisions that might have made sense 30 years ago when C++ was a new thing and linkers didn't specially support constructors don't make sense 30 years later when linkers do. I'll attach my proof-of-concept code, that didn't make it to the list. —♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org I'd rather write programs that write programs than write programs — Dick Sites
/* gcc -W -Wall -Os -fPIC -Wl,-init,constructor1_init -shared -o constructor1.so constructor1.c && gcc -W -Wall -Os -o constructor0 constructor0.c -ldl && ./constructor0 */ #include <stdio.h> #include <dlfcn.h> #define SECTION( S ) __attribute__ ((section ( S ))) #pragma GCC diagnostic ignored "-Wunused-variable" __asm__(".section .init \n call init0extern \n .section .text\n"); extern void init0extern(void) { printf ("init0extern\n"); } static void ctor0static(void) { printf("ctor0static -- SHOULDN'T BE CALLED!\n"); } static void (*ctor0static_ptr)(void) SECTION(".ctors") =ctor0static; // won't be called. static void ctor0extern(void) { printf("ctor0extern\n"); } /*extern*/ void (*ctor0extern_ptr)(void) SECTION(".ctors") =ctor0extern; __attribute__((constructor (110))) static void constructor0static110() { printf("constructor0static110\n"); } __attribute__((constructor (130))) static void constructor0static130() { printf("constructor0static130\n"); } __attribute__((constructor (120))) extern void constructor0extern120() { printf("constructor0extern120\n"); } typedef void thunk(void); static void constructor0static(void) { printf("constructor0static\n"); } thunk* constructor0static_ptr = constructor0static; extern int main (int argc, char** argv) { (void)argc; (void)argv; printf("Hello, World!\n"); (*constructor0static_ptr)(); void* dl = dlopen("./constructor1.so", RTLD_LOCAL|RTLD_NOW); // RTLD_GLOBAL|RTLD_NOW printf("dl = %p\n", dl); if (!dl) { printf("dlerror(): %s\n", dlerror()); } thunk* c1 = (thunk*) dlsym(dl, "constructor1"); printf("constructor1 = %p\n", c1); if (c1) { (*c1)(); } else { printf("dlerror(): %s\n", dlerror()); } return 0; }
#include <stdio.h> #define SECTION( S ) __attribute__ ((section ( S ))) #pragma GCC diagnostic ignored "-Wunused-variable" static void init1static(void) { printf ("init1static\n"); } static void init1static_caller(void) { __asm__(".section .init"); init1static(); __asm__(".section .text\n"); } static void ctor1static(void) { printf("ctor1static -- SHOULDN'T BE CALLED!\n"); } static void (*ctor1static_ptr)(void) SECTION(".ctors") =ctor1static; // won't be called. static void ctor1extern(void) { printf("ctor1extern\n"); } /*extern*/ void (*ctor1extern_ptr)(void) SECTION(".ctors") =ctor1extern; __attribute__((constructor (111))) static void constructor1static111(void) { printf("constructor1static111\n"); } __attribute__((constructor (131))) static void constructor1static131(void) { printf("constructor1static131\n"); } __attribute__((constructor (121))) extern void constructor1extern121(void) { printf("constructor1extern121\n"); } extern void constructor1(void) { printf("constructor1\n"); } extern void constructor1_init(void) { printf("constructor1_init\n"); }