3 ms·
Compiling with `-Werror=missing-declarations -Werror=redundant-decls`, and having a test rule that verifies that every .h file is included on exactly the first
by o11c 3y ago
Compiling with `-Werror=missing-declarations -Werror=redundant-decls`, and having a test rule that verifies that every .h file is included on exactly the first line of the corresponding .c file, is very useful at enforcing proper headers. Non-`static` declarations should be forbidden outside of headers. Violating this rule is often the only thing needed to make a project hard to understand. Easy-to-understand projects usually only have to add a few `static`s on unintentionally-exported symbols.
For libraries, it is critical that a distinction be made between "header files that will be installed" (which should use the project name as a directory prefix!) and "header files used internally". I put the latter in src/ but practice varies widely.
I argue that the flat layout is somewhat harmful (though at least using src/ beats shoving everything in ./), because even small projects eventually grow a distinction between "source files that are part of the main installed project" and "source files used solely for maintenance tooling".
Making a distinction between "code that needs to be cross-compiled" and "code that needs to be native" is useful even if you're not planning to do cross-compilation.
- JonChesterfield 3y agoAn alternative to the ritual include foo.h as the first line of foo.c strategy is to compile each header individually, `clang -x c -Wall foo.h -c -o /dev/null` or similar. That catches roughly the same developer intent. Similar to the cross compiled / native distinction, it's probably a good idea to put platform specific things behind an interface up front. Link time is a good point to swap out win32 for linux or similar and implementing the second target is much easier if you drew the line up front. The platform layer might also be one worth writing a mock for as part of testing.
- o11c 3y agoThe problem with `-x c foo.h` is that `#pragma once` isn't legal in the top-level source file. There might be other problems too. Using manual header guards is a bug-prone waste. Nobody has ever demonstrated me a case where `#pragma once` fails to work with compilers from the last decade or two.
- JonChesterfield 3y agoI've heard that `#pragma once` fails to work in the top-level source file, such as when compiling a header using -xc to see whether it is independently well formed...