1

Short version of question

Is it possible to gather specific symbols in C into a single list/array into the executable statically at compile time, without relying on crt initialization (I frequently support embedded targets, and have limited support on dynamic memory).

EDIT: I'm 100% ok with this happening at link time and also ok with not having symbols cross library boundaries.

EDIT 2: I'm also OK with compiler specific answers if it's gcc or clang but would prefer cross platform if possible.

Longer version with more background

This has been a pain in my side for a while.

Right now I have a number of built-in self tests that I like to run in order.

I enforce the same calling convention on all functions and am manually gathering all the tests into an array statically.

// ThisLibrary_testlist.h
#define DECLARE_TEST(TESTNAME) void TESTNAME##_test(void * test_args)
DECLARE_TEST(test1);
DECLARE_TEST(test2);
DECLARE_TEST(test3);
// ThisLibrary_some_module.c
#include "ThisLibrary_testlist.h"
DECLARE_TEST(test1)
{
   // ... do hood stuff here
}
// ThisLibrary_testarray.c


#include "ThisLibrary_testlist.h"
typedef void (*testfunc_t) (void*);
#define LIST_TEST(TESTNAME)

testfunc_t tests[] =
{
    &LIST_TEST(test1),
    &LIST_TEST(test2)
}; 
// now it's an array... you know what to do.

So far this has kept me alive but it's getting kind of ridiculous that I have to basically modify the code in 3 separate locations if I want to update a test.

Not to mention the absolute #ifdef nightmare that comes with conditionally compiled tests.

Is there a better way?

  • 1
    Just in case you wonder why you do not get any feedback, many C experts here ignore questions which are also tagged C++ and vice versa. So your chances would improve if you do not annoy both groups by giving the impression that C and C++ are basically one language for you. – Yunnosch Mar 16 '20 at 06:58
  • 2
    Are you aware of the concept of X-macros, or the more elegant version "undef-free-X-macros"? – Yunnosch Mar 16 '20 at 07:02
  • Maybe something along the lines of this: https://stackoverflow.com/questions/60453659/is-it-possible-to-define-generics-association-list-dynamically – Lundin Mar 16 '20 at 07:13
  • Yunnosch that's hilarious I've removed the c++ tag. but whatever answer we get should result in something that would benefit c++ users with a similar use case. – user2601592 Mar 16 '20 at 08:58
  • I Should clarify that I could've done the testlist declaration with x-macros and that would make it so i only have to edit two places instead of one ( the testlist and the function implementation) but for the purposes of the question I wanted to keep it simple. I was looking more along the lines of automatic registration to a structure that I could iterate over. – user2601592 Mar 16 '20 at 08:59
  • See: https://stackoverflow.com/q/3633896/1216776 – stark Mar 17 '20 at 21:22

1 Answers1

0

With a bit of scripting magic you could do the following: After compiling your source files (but before linking) you search the object files for symbols that match your test name pattern. See man nm how to obtain symbol names from object files (well, on Unix, that is - no idea about windows, sorry). Based on the list of object names found, you auto-create the file ThisLibrary_testarray.c, putting in all the extern declarations and then the function pointer table. After generation of this file, you compile it and finally link everything.

This way you only have to add new test functions to the source files. No need to maintain the header file ThisLibrary_testlist.h, but you have to make sure the test functions have external linkage, follow the naming pattern - and be sure no other symbol uses the naming pattern :-)

Dirk Herrmann
  • 5,550
  • 1
  • 21
  • 47