Proposal: Running linter tasks independent of compilation
At the moment, we run linters like iwyu, cppcheck, cpplint and clang-tidy as co-compile jobs. That means you always have to run both the linter and compiler together, you can't run them independently. This is rather inflexible. Projects often want to run linter jobs in CI without actually building things (CMake itself does this). They can't currently make use of CMake's linter support for that because it is coupled with compilation.
I propose a new variable CMAKE_LINTERS_INDEPENDENT
(open to better naming suggestions) which determines whether linters run separately or as co-compiled like now. When true, it would define the linter tasks as separate steps from compilation. I would recommend also providing a global target for each linter type which depends on each individual linter task of that type so that one could easily do things like cmake --build ... --target lint-iwyu
, cmake --build ... --target lint-clang-tidy
, etc. We probably could also define a top level lint-everything target so you could do cmake --build ... --target lint-all
.
One could argue that this is a global behavior, so rather than a variable, we might want to use a global property instead. I'm open to either choice. I don't know if it makes sense for the behavior to be user-configurable. If it does, then a variable would seem more appropriate. If we went with a variable, we would need to decide at what point the value is used. While it is tempting to make that its value at the end of the top level CMakeLists.txt
file that would control the behavior, that would preclude the project from adding its own linters to the global targets. It might be better to make the decision point be the first project()
call. Then the project will have access to the lint-all
target and other similar targets. The project should be able to add dependencies to these top level targets so that their own linter tasks can be incorporated.
I would go so far as to make independent linters the default behavior. That gives the build tool a greater ability to schedule tasks more efficiently. In some projects, the linting tasks will be quick, but in others they might take much longer than compilation (that is especially true for clang-tidy). Such a behavior change would require a policy. That policy could set CMAKE_LINTERS_INDEPENDENT
to true for NEW
behavior, and leave it unset otherwise. Making the first project()
call the decision point would also make the policy setting easier to reason about than, say, the end of the top level CMakeLists.txt
scope.