How to act as a C alias library?

I have a static C library that I can create with different compile time options (e.g. _BUILD_SMALL, _BUILD_FAST). It has a function

void Foo(void); 

I would like to use one instance of the comparison tool to compare the "small" and "fast" versions of the library. I do not want to use a DLL.

How can I refer to the “small” and “fast” libraries and the function name alias so that I can name the small version and the fast version. Ideally, it would look like this:

 void benchmark(void) { FAST_Foo(); SMALL_Foo(); } 

Additional Information:

A library can be built with various -Os optimization options compared to -O3. In addition, the algorithms vary slightly (i.e., cached vs values ​​always look for values). I want to compare the size and tradeoff between versions of different versions. I would like to make unit tests and benchmarking as simple as possible in both versions of the library.

+6
source share
6 answers

This is just a variation of the method given by @ Michał Górny (I end up with a comment space there) ...

You can create an include file of the following form:

 /* Automatically created file - do not edit or ugly dinosaur will eat you */ #ifndef PREFIX # define RENAME(f) #else # define RENAME(f) PREFIX ## f #endif /* list all the function and variables you want to rename here in one place */ #define func_foo RENAME(func_foo) #define func_bar RENAME(func_bar) /* ... many more ... */ #undef RENAME 

At least gcc allows you to specify the inclusion of a header file from the command line with the -include rename.h option (provided that this file is called rename.h ). Since you are using gcc alternatives ( -O3 and Os ), I assume that you are using gcc for the rest of this answer. Otherwise, if your C compiler is reasonable, you should do it the same way.

You can easily create two or even three versions of your library that can be linked at the same time if you want by providing various parameters for your C compiler (here via the CFLAGS parameter):

 CFLAGS += -include rename.h -DPREFIX=fast_ -D_BUILD_FAST -O3 -DBENCHMARKING CFLAGS += -include rename.h -DPREFIX=small_ -D_BUILD_SMALL -Os -DBENCHMARKING CFLAGS += -D_BUILD_FAST -O2 

If your library's header files look very regular, and if you declare static private library functions, it's easy to extract functions from these header files with some dummy script, using very simple regular expressions to automatically generate rename.h for you. This is a natural build goal if you use make or something like that. All global variables must also be renamed using the same method for simultaneous use.

There are three main points in this decision:

  • The ugly business of renaming can be hidden in one file, you do not need to edit the actual source files, especially you do not need to clutter up the source files, but they can keep them clean and easy to read.
  • Renaming can be easily automated if you follow a few simple principles (coding conventions for header files and header files will declare all global variables and functions).
  • There is no reason to make the comparative analysis more cumbersome if you need to run the test program several times (this is true if you are as lazy as I am and I don’t like repetitive tasks as much as I do - I know that many people don’t care, this is somewhat a matter of preference).
+3
source

One way would be to keep the same name for both and call accordingly, depending on the set compilation time parameter.

 ifdef SMALL_FOO void foo() { /* Small foo code */ } #endif ifdef BIG_FOO void foo() { /* Big foo code */ } #endif 

Set SMALL_FOO/BIG_FOO at compile time with -d .

+2
source

As a quick fix, you can use a macro to change the name of a function, for example:

 #ifdef FAST # define FUNC(x) FAST_##x #else # define FUNC(x) SLOW_##x #endif void FUNC(Foo)(); 

And now with -DFAST a library with FAST_Foo will be built; and without it, one with SLOW_Foo . Just note that you need to use the FUNC() macro in the implementation part (and whenever you access this function from within the library) and #ifdef FAST to switch between fast / slow code.

Just don't use this in production code.

+2
source

If you try to establish a link in both static libraries to the same executable file, the second library indicated in your link line will have no effect, because all the symbols provided to it are satisfied by the first library. If you provided simple unique wrapper functions to invoke Foo , that would still fail, now due to several definitions. Here is an example:

 /* xc */ extern void Y_Bar (); extern void Z_Bar (); int main () { Y_Bar(); Z_Bar(); } 

This call invokes the unique wrapper functions that are provided in liby.a and libz.a

 /* yc in liby.a */ #include <stdio.h> void Y_Bar () { extern void Foo (); Foo(); } void Foo () { printf("%s\n", "that Foo"); } /* zc in libz.a */ #include <stdio.h> void Z_Bar () { extern void Foo (); Foo(); } void Foo () { puts("this foo"); } 

Attempting to link the executable to -ly -lz will fail.

The simplest job for you is to create two separate executables. Then your test driver could execute both executables to compare their relative performance.

+2
source

You say that you can create a library by changing the compilation time settings, so why not change the code to change the names of the functions in each. (You would make two different versions of your library.)

0
source

Maybe you can use the -D option when call gcc, like -D_FAST_, -D_SMALL_, or yours can get the input parameter when using make, for example use make CFG=FAST, make CFG=SMALL, in your makefile , you can define when you get the FAST, link to FAST library parameter FAST, link to FAST library .

0
source

Source: https://habr.com/ru/post/922985/


All Articles