To paint the picture let's imagine we have a header called headertest.h
and where going to use it in a file called test.c
It's context look like this
#include <stddef.h>
extern size_t string_lenght(const char *);
size_t string_lenght(const char *str)
{
size_t n = 0;
while (str[n] != '\0')
n ;
return (n);
}
It's purpose is to count the lenght of a given string and give output as size_t
if we include it in our test.c
file like this and compile with gcc -o test test.c
#include "<location to header>/headertest.h"
int main ()
{
}
it compiles successfully and by running the command du -b test | awk '{print $1}'
it outputs 16504, telling us it's size is 16504 bytes. However if we comment #include
and just leave int main ()
and recompile test and run the same command again, we get 16464.
so in conclusion, how do you tell C to specifically only include a function when compiling only if it's present in the main C program, from a self made header file.
CodePudding user response:
Solutions from article mentioned in comments are pretty good, but they have their own quirks:
static
works great for private stuff, but makes little sense for things that may be directly called from more than one.c
file- smarter things like
lto
, or linker garbage collection require compiler/linker support and each impose their own quirks/cons
Libraries often use macros to explicitly disable/enable certain features. The advantages are:
- simplicity and portability
- unused code isn't even compiled, so you can also reduce build time
- less dependencies if feature requires extra lib
- it also allows for switching functionality that isn't separate function (e.g. param validation)
Example:
// file mylib.h
#ifndef MYLIB_FOO_OFF // ifndef - "if macro not defined"
void mylib_foo();
#endif
#ifndef MYLIB_BAR_OFF
#include <otherlib.h>
void mylib_foo(otherlib_struct s);
#endif
// file mylib.c
#include "mylib.h"
#ifndef MYLIB_FOO_OFF
void mylib_foo() { /* implementation */ };
#endif
#ifndef MYLIB_BAR_OFF
void mylib_foo(otherlib_struct s) { /* implementation */ }
#endif
Then if you don't need mylib_bar()
you can just instruct your's compiler/build system to define MYLIB_BAR_OFF
, e.g gcc -DMYLIB_BAR_OFF main.c mylib.c
.
Preprocessor will then remove code within #ifndef
directives scope, as if it wasn't typed in the first place
Example from real world library: https://www.sqlite.org/compile.html#overview
CodePudding user response:
It is not uncommon to use pre-compiler defines in a header file to exclude code for one OS or another...
#ifdef __linux__
void Do_one_thing(void);
#elif _WIN32
void Do_another_thing(void);
#else __APPLE__
void Do_yet_another_thing(void);
#endif