From 5f2bf6ecc6b6fadca63da57188097a5f4f3d8854 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Dec 2022 18:38:10 -0500 Subject: Help: Drop misleading add_custom_command "makefile terms" explanation The "In makefile terms" explanation is left from very early days of CMake to help developers migrating from hand-written makefiles. These days it is often misinterpreted, particularly in the context of multiple `add_custom_command` calls, to mean that we generate a single Makefile containing rules for all custom commands. This leads to an incorrect mental model of the expressed build system. The actual generated build system may spread the rules across multiple targets that do not see the each other's file-level rules, which makes target-level dependencies important too. --- Help/command/add_custom_command.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 5878997..4978075 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -35,10 +35,6 @@ Do not list the output in more than one independent target that may build in parallel or the two instances of the rule may conflict (instead use the :command:`add_custom_target` command to drive the command and make the other targets depend on that one). -In makefile terms this creates a new target in the following form:: - - OUTPUT: MAIN_DEPENDENCY DEPENDS - COMMAND The options are: -- cgit v0.12 From 303c48fbd41745fe967ca6988a845678f44c67a6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Dec 2022 19:21:42 -0500 Subject: Help: Add add_custom_command example with output consumed by multiple targets This is a common use case, so add an example demonstrating it. --- Help/command/add_custom_command.rst | 51 ++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 4978075..9dd8b95 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -31,10 +31,12 @@ This defines a command to generate specified ``OUTPUT`` file(s). A target created in the same directory (``CMakeLists.txt`` file) that specifies any output of the custom command as a source file is given a rule to generate the file using the command at build time. + Do not list the output in more than one independent target that -may build in parallel or the two instances of the rule may conflict -(instead use the :command:`add_custom_target` command to drive the -command and make the other targets depend on that one). +may build in parallel or the instances of the rule may conflict. +Instead, use the :command:`add_custom_target` command to drive the +command and make the other targets depend on that one. See the +`Example: Generating Files for Multiple Targets`_ below. The options are: @@ -385,6 +387,49 @@ will re-run whenever ``in.txt`` changes. where ```` is the build configuration, and then compile the generated source as part of a library. +Example: Generating Files for Multiple Targets +"""""""""""""""""""""""""""""""""""""""""""""" + +If multiple independent targets need the same custom command output, +it must be attached to a single custom target on which they all depend. +Consider the following example: + +.. code-block:: cmake + + add_custom_command( + OUTPUT table.csv + COMMAND makeTable -i ${CMAKE_CURRENT_SOURCE_DIR}/input.dat + -o table.csv + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/input.dat + VERBATIM) + add_custom_target(generate_table_csv DEPENDS table.csv) + + add_custom_command( + OUTPUT foo.cxx + COMMAND genFromTable -i table.csv -case foo -o foo.cxx + DEPENDS table.csv # file-level dependency + generate_table_csv # target-level dependency + VERBATIM) + add_library(foo foo.cxx) + + add_custom_command( + OUTPUT bar.cxx + COMMAND genFromTable -i table.csv -case bar -o bar.cxx + DEPENDS table.csv # file-level dependency + generate_table_csv # target-level dependency + VERBATIM) + add_library(bar bar.cxx) + +Output ``foo.cxx`` is needed only by target ``foo`` and output ``bar.cxx`` +is needed only by target ``bar``, but *both* targets need ``table.csv``, +transitively. Since ``foo`` and ``bar`` are independent targets that may +build concurrently, we prevent them from racing to generate ``table.csv`` +by placing its custom command in a separate target, ``generate_table_csv``. +The custom commands generating ``foo.cxx`` and ``bar.cxx`` each specify a +target-level dependency on ``generate_table_csv``, so the targets using them, +``foo`` and ``bar``, will not build until after target ``generate_table_csv`` +is built. + .. _`add_custom_command(TARGET)`: Build Events -- cgit v0.12