37

I have a custom command

add_custom_command(
    OUTPUT config.h
    PRE_BUILD
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/mk_config_h.py ${CMAKE_CURRENT_BINARY_DIR}/config.h
)

I'm trying to run it before everything else and I generate unix Makefiles.

However PRE_BUILD is only supported for VS2010 which means that config.h is build before linking.

how do I make a custom command before cmake starts compiling sources.

Alexander Oh
  • 24,223
  • 14
  • 73
  • 76
  • 1
    Is the output file from your custom command (i.e. config.h) used as a source file in another CMake target (i.e. in the list of sources passed via `add_executable` or `add_library`)? If so, you shouldn't need to worry about the execution order - CMake will invoke the custom command as and when required. – Fraser Apr 13 '13 at 00:14

2 Answers2

55

You should use add_custom_target instead and add_dependencies to make your normal target depend on it:

add_custom_target(
    myCustomTarget
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/mk_config_h.py ${CMAKE_CURRENT_BINARY_DIR}/config.h
)
add_dependencies(myTarget myCustomTarget)

This should ensure that the command is run before compiling the sources of myTarget.

Simon
  • 31,675
  • 9
  • 80
  • 92
  • 1
    It took me a while that add_custom_target is much better for running an executable than add_custom_command. Thank you for that solution! – Anonymous Nov 10 '15 at 08:47
  • 2
    @Anonymous - No, its not better. It has significant drawback, it ALWAYS runs as described in documentation (The target has no output file and is *always considered out of date* even if the commands try to create a file with the name of the target), even if dependency does not change. – Andry Apr 11 '18 at 12:46
  • Using `add_custom_target` and `add_dependencies` as suggested by @Simon worked for me, to force some header and library files from another build to be copied before my normal target builds. I had previously tried to use `add_custom_command( ... PRE_BUILD ... )`, but it would not execute in the correct order. – Mike Finch Jun 19 '19 at 21:41
  • 3
    I'm finding that this fails in parallel builds, if the custom target takes a long time to finish. Later build stages will run in the right order, but will use the incompletely-written output files. I have not yet figured out how to force run-to-completion. – Linas Dec 18 '19 at 20:34
  • 1
    @Linas, same issue with Ninja, unable to figure out. But, I have no problems with Makefile since I added the trick explained here : https://stackoverflow.com/a/31518137/1729117 – Joël Esponde Nov 29 '22 at 15:53
3

Usualy build systems which are based on makefiles do not need to mention headers as part of a target. Further more, adding headers to target is considered to be an antipattern. But generating a header is an exception from this rule.

http://voices.canonical.com/jussi.pakkanen/2013/03/26/a-list-of-common-cmake-antipatterns/

You should set your ${CMAKE_CURRENT_BINARY_DIR}/config.h as part of some other compilled target. For example:

set(PROGRAM1_SOURCES main_program1.cpp)
set(PROGRAM1_HEADERS main_program1.h ${CMAKE_CURRENT_BINARY_DIR}/config.h)
add_executable(program1 ${PROGRAM1_SOURCES} ${PROGRAM1_HEADERS})

So that, CMake will know which target actually needs the generated config.h and will be able to insert the generation commands into a right build steps.

Also, see an example at https://cmake.org/cmake-tutorial/#s5

Piroxiljin
  • 621
  • 6
  • 14
  • 2
    You need headers if you want code analysis from the various IDEs to work. – ZeroPhase May 04 '17 at 09:38
  • @zerophase, I agree. Project-files for IDE often need reference to all files of the project. But cmake is able to build the project without header files. – Piroxiljin May 05 '17 at 03:24
  • 2
    Oh for sure. Just usually headers end up having to be added in to support different end users. – ZeroPhase May 05 '17 at 03:26