The header files in C are mostly redundant to the corresponding source files. For example, for the following example source file:
// This is hello.c
#include <stdio.h>
void greet(const char *name)
{
printf("Hello, %s!!\n", name);
}
the corresponding header file can be generated mechanically:
// This is hello.h
void greet(const char *);
And indeed, there are tools for that, in particular makeheaders(1), which is sophisticated to also support struct declaration, static functions and more.
https://compiler-dept.github.io/makeheaders/
https://invisible-island.net/cproto
At first I was very excited about saved typing and avoided redundancy, but then I noticed that my build system became slower. Much slower than can be attributed to the execution time of makeheaders(1) alone. After a little investigation, the reason became clear -- auto-generating headers changes the build dependency graph.
Let's consider a trivial project with three files: "main.c", "hello.h" and "hello.c". The dependency graph, written in Makefile syntax would be the following:
main.o: main.c hello.h
hello.o: hello.c hello.h
main: main.o hello.o
If hello.h is now generated from hello.c, the graph looks like below. Just one more edge, but now "main.o" indirectly depends on "hello.c", so changes to "hello.c" cause re-compilation of "main.c".
hello.h: hello.c
hello.o: hello.c hello.h
main.o: main.c hello.h
main: main.o hello.o
It is possible for the build system to recognize that "hello.h" didn't actually change, and skip re-compiling of "main.c", but most build system don't for performance reasons. Check for file modification time is one stat(2) syscall, check for file content requires open(2), read(2), close(2) and also some kind of hash calculation. It is inherently slower.
I don't know if header generation is good idea for your project or not, I am just sharing my experience. I thought I've found a free lunch; there is none.