Splint can still expose useful C mistakes through annotations and strict checking, but its last upstream release is from 2007. Use it for legacy compatibility or learning—not as the only security control—and pair it with current compilers, path-sensitive analyzers, sanitizers, tests, and human review.
Build one C executable from multiple translation units without turning the project into a library first. The example separates declarations from definitions, compiles object files independently, links them with GCC, inspects symbols, diagnoses common failures, and automates correct incremental rebuilds.
This modern JNI example replaces removed `javah` instructions with `javac -h`, derives the active JDK include path, compiles position-independent C into a shared library, and verifies both the exported symbol and Java-to-native call.
A single GCC command hides several distinct transformations, followed later by Linux process startup. Saving each intermediate file makes macros, assembly, ELF objects, linking, and dynamic loading much easier to reason about.