2

I have a relatively big CMake project with a lot of subfolders and files. I want to run a custom command after any binary is created when building this project. I've been testing with Hello World and I know I'll need something like this:

EDIT: I've updated the question to reflect my current progress.

# Get list of all files and folders in current dir recursively
set(SUBFDIRS)
file(GLOB_RECURSE ALLFILES LIST_DIRECTORIES true "*" "*")
foreach(SUBFILE ${ALLFILES})
  IF(IS_DIRECTORY ${SUBFILE} AND NOT ${SUBFILE} MATCHES ".*CMakeFiles.*")
    message("Adding directory: ${SUBFILE}")
    LIST(APPEND SUBDIRS ${SUBFILE})
  ENDIF()
endforeach()

# Also add current directory to directory list
LIST(APPEND SUBDIRS .)
LIST(REMOVE_DUPLICATES SUBDIRS)

message("-- Detected subdirectories: ${SUBDIRS}")

# Loop over all subdirectories
foreach(subdir ${SUBDIRS})
  # Get a list of all targets
  get_property(BUILDSYSTEM_TARGETS DIRECTORY ${subdir} PROPERTY BUILDSYSTEM_TARGETS)

  # For each target, add a custom target that will run a custom command
  foreach(TARGET_DEFINED ${BUILDSYSTEM_TARGETS})
    get_target_property(target_type ${TARGET_DEFINED} TYPE)
    if (target_type STREQUAL "EXECUTABLE")
      message("-- Adding custom target for executable ${TARGET_DEFINED}...")
      add_custom_target(custom_${TARGET_DEFINED} ALL)
      add_custom_command(TARGET custom_${TARGET_DEFINED}
        POST_BUILD
        COMMAND my_custom_command $<TARGET_FILE:${TARGET_DEFINED}> $<TARGET_FILE:${TARGET_DEFINED}>
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        DEPENDS $<TARGET_FILE:${TARGET_DEFINED}>
      )
    else()
      message("-- Target ${TARGET_DEFINED} is not an executable. Ignoring!")
    endif()
  endforeach()

endforeach()

This seems to work the way I want it to, except for the fact that it generates CMake errors like this one when trying to get a list of targets for a directory:

CMake Error at CMakeLists.txt:34 (get_property):
  get_property DIRECTORY scope provided but requested directory was not
  found.  This could be because the directory argument was invalid or, it is
  valid but has not been processed yet.
woutwoot
  • 152
  • 1
  • 12
  • 1
    You might be interested in `BUILDSYSTEM_TARGETS`, which yields all targets defined in a subdirectory. You can then iterate over the targets and define the custom commands. But first, you would need to get the list of all subdirectories. I don't think there are built-in commands for that so it would inevitably need to be some sort of hack. Perhaps this post could get you started: https://stackoverflow.com/questions/7787823/cmake-how-to-get-the-name-of-all-subdirectories-of-a-directory. – Raul Laasner Jun 12 '18 at 15:03
  • @RaulLaasner Thanks! This already helped me a lot. Just figuring out how to do it for all subfolders now, but I'm close :) – woutwoot Jun 13 '18 at 06:17
  • @RaulLaasner I've updated the question to reflect my current progress, but now I'm stuck on a CMake error. (while the code seems to do what I want it to do) – woutwoot Jun 13 '18 at 09:06
  • It seems to me that you are getting a list of build directories, but it should be the source directories. According to the `BUILDSYSTEM_TARGETS` documentation, it provides `targets added in the directory`. – Raul Laasner Jun 13 '18 at 15:50
  • My first thought would be to redefine `add_subdirectory` using a macro, so that in addition to doing what it normally does, it also append the present directory to a list. – Raul Laasner Jun 13 '18 at 15:52

0 Answers0