Daniel Jour
Daniel Jour

Reputation: 16156

Custom command / target run only for default build not install

I want to build my documentation (doxygen) alongside my project with CMake by default. I let CMake generate Makefiles. I know of these approaches so far:

1)

add_custom_target(doc ALL
  COMMAND ${DOXYGEN_COMMAND})

2)

add_custom_command(
  TARGET my-executable
  POST_BUILD
  COMMAND ${DOXYGEN_COMMAND})

The issue I have with the first approach is that the target is build both during build and install (i.e. when running make and when running make install). This is a no-go.

The issue with the second approach is that it is not actually correct: the documentation doesn't have to be built after the executable (in fact, it can be done in parallel even). Moreover I cannot build only the executable now.

Is there a way to create this custom command / target such that it is run only during make (building) and not during make install (installing) but independently from other targets such as executables?

Basically I'd need a "default target". Also I really want to avoid having to execute CMake recursively or make directly.

Upvotes: 1

Views: 1822

Answers (2)

Daniel Jour
Daniel Jour

Reputation: 16156

The solution given by @Tsyvarev works perfectly except for one issue:

Running make docs manually doesn't cause a re-build of the documentation because the "output file" ${documentation_file} is always considered up to date (there are no dependencies specified that could be newer).

Three workarounds I found:

  • Run make -B docs. The -B flags causes GNU Make to consider all targets out of date, and thus causes the documentation to be build.

  • Add a "manual docs" target which depends on first a docs-clean target which removes ${documentation_file} and then on docs itself (to build the documentation and the file), and run make docs-manual:

    add_custom_target(docs-clean
      COMMAND ${CMAKE_COMMAND} -E remove ${documentation_file})
    add_custom_target(docs-manual)
    add_dependencies(docs-manual docs-clean docs)
    

    Note that I fear that this is just a dirty hack: AFAIK the order in which the dependencies (docs-clean and docs) are build isn't specified, and as they don't have a dependency between them, they could even be built in parallel.

    Using add_custom_command with a TARGET docs-manual and PRE_BUILD (which runs the command before building dependencies) instead of the docs-clean target would've been perfect, but this only works for Visual Studio 7 or later.

  • Add a custom target that depends on docs but removes the generated ${documentation_file}:

    add_custom_target(docs-manual
      COMMAND ${CMAKE_COMMAND} -E remove ${documentation_file})
    add_dependencies(docs-manual docs)
    

    This works except for when running it the first time after a make docs, because then the generated file will still be there when docs is built.

edit: Use add_dependencies instead of DEPENDS of add_custom_target because the later is only intended for files, not for dependencies on targets.

Upvotes: 1

Tsyvarev
Tsyvarev

Reputation: 65928

Just create a file, which existence means that documentation file have been built:

set(documentation_file ${CMAKE__BINARY_DIR}/docs_ready)

# Documentation target
add_custom_target(docs ALL DEPENDS ${documentation_file})
# Documentation command
add_custom_command(OUTPUT ${documentation_file}
    COMMAND ${DOXYGEN_COMMAND}
    # And mark that documentation is created
    COMMAND ${CMAKE_COMMAND} -E touch ${documentation_file}
)

Upvotes: 1

Related Questions