Executing a custom command on modified files.

From what I understand compilation works something like:

  1. If the first time compile all files
  2. else only compile modified files

I’d like to do something similar but instead of compile I’d like to run our companies style checker. I’d like the logic to be similar

  1. If the first time check all files
  2. else only check modified files

Is this possible?

I remember doing something like this long ago with classic makefile patterns, like:

%.stvn : %.cpp
	myExe $< -o $@

In the beginning there are no .stvn files so it will run myExe one by one for each .cpp file creating a subsequent .stvn file.

Later if a .cpp is updated it’s found to be newer and so myExe is executed on just the newer file.

So I get and understand and use this in makefiles.

How can I do something similar in Cmake?

Here’s the basic skeleton to get you started:

add_custom_command(
  OUTPUT myfile1.stvn
  COMMAND myExe myfile1.cpp -o myfile1.stvn
  DEPENDS myfile1.cpp
  VERBATIM
)
add_custom_command(
  OUTPUT myfile2.stvn
  COMMAND myExe myfile2.cpp -o myfile2.stvn
  DEPENDS myfile2.cpp
  VERBATIM
)
add_custom_target(
  RunChecker ALL
  COMMENT "Running Checker where necessary"
  DEPENDS
    ${CMAKE_CURRENT_BINARY_DIR}/myfile1.stvn
    ${CMAKE_CURRENT_BINARY_DIR}/myfile2.stvn
)

See docs of add_custom_command() and add_custom_target() for deeper explanation and for other potential options.

You can also use option DEPFILE of add_custom_command for more fine-grain dependency management.

Be aware that DEPFILE is only supported by Ninja until 3.19. Makefiles generators were added in 3.20. And Xcode will be available in next release (3.21).

Thank you for sharing the skeleton Peter.

It appears that this requires that we need to explicitly add a custom command for each and every file in the product? That CMake doesn’t have an equivalent to the pattern paradigm in make? Am I correct?

No, there’s no pattern support (because that would still only support the Makefiles generators). I recommend wrapping it up in a CMake function then calling it in a loop.