# Is there a builtin method to create a target that's only run if dependent files are changed/touched?

**URL:** https://discourse.cmake.org/t/is-there-a-builtin-method-to-create-a-target-thats-only-run-if-dependent-files-are-changed-touched/5927
**Category:** Code
**Created:** [June 24, 2022, 4:41pm UTC](https://discourse.cmake.org/t/is-there-a-builtin-method-to-create-a-target-thats-only-run-if-dependent-files-are-changed-touched/5927 "2022-06-24T16:41:59Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![dundargoc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dundargoc/32/1923_2.png) [@dundargoc](https://discourse.cmake.org/u/dundargoc)
#### Post date: [June 24, 2022, 4:41pm UTC](https://discourse.cmake.org/t/is-there-a-builtin-method-to-create-a-target-thats-only-run-if-dependent-files-are-changed-touched/5927/1 "2022-06-24T16:41:59Z")

</div>

Hey. I looked everywhere for this and couldn’t find anything. So basically I’m looking for a way to create a target that is dependent on existing files. For example, let’s say I have a bunch of python files in my repo and I want to create a target named `lint_python_files` that runs `pylint` on them. If I run the target once it should lint all python files. If I run it again right after, it should know that none of the python files have changed and just skip linting entirely. If I then touch/change a single python file and then run the target, then I’d like only that file to be linted. I have created a custom function that does this, but was wondering if there’s a smarter way to do this or if there’s a builtin function for this?

```auto
function(add_glob_targets)
  cmake_parse_arguments(SMART
    ""
    "TARGET;COMMAND"
    "FLAGS;FILES"
    ${ARGN}
  )

  set(touch_dir ${TOUCHES_DIR}/${SMART_TARGET})
  file(MAKE_DIRECTORY ${touch_dir})

  foreach(f ${SMART_FILES})
    string(REPLACE "/" "_" filename ${f})
    set(touch_file ${touch_dir}/${filename})
    add_custom_command(
      OUTPUT ${touch_file}
      COMMAND ${CMAKE_COMMAND} -E touch ${touch_file}
      COMMAND ${PRG} ${SMART_FLAGS} ${f}
      WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
      DEPENDS ${f})

    list(APPEND touch_list ${touch_file})
  endforeach()

  add_custom_target(${SMART_TARGET} DEPENDS ${touch_list})
endfunction()

```

---

<div class="post-metadata">

### Author: ![kyle.edwards](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/65b543/32.png) [@kyle.edwards](https://discourse.cmake.org/u/kyle.edwards)
#### Post date: [June 24, 2022, 4:50pm UTC](https://discourse.cmake.org/t/is-there-a-builtin-method-to-create-a-target-thats-only-run-if-dependent-files-are-changed-touched/5927/2 "2022-06-24T16:50:56Z")

</div>

You want a combination of `add_custom_command` and `add_custom_target`:

```cmake
add_custom_command(
  OUTPUT lint_python_files.stamp
  COMMAND pylint ${python_files}
  COMMAND ${CMAKE_COMMAND} -E touch lint_python_files.stamp
  DEPENDS ${python_files}
  )
add_custom_target(lint_python_files ALL
  DEPENDS lint_python_files.stamp
  )

```

The lint custom command will create a stamp file to indicate that it’s been run, and will be re-run any time the input files change.

---

<div class="post-metadata">

### Author: ![dundargoc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dundargoc/32/1923_2.png) [@dundargoc](https://discourse.cmake.org/u/dundargoc)
#### Post date: [June 24, 2022, 4:57pm UTC](https://discourse.cmake.org/t/is-there-a-builtin-method-to-create-a-target-thats-only-run-if-dependent-files-are-changed-touched/5927/3 "2022-06-24T16:57:57Z")

</div>

Hmm, wouldn’t this lint all python files even if only one file was changed? Haven’t tested it yet, will give it a try.

---

<div class="post-metadata">

### Author: ![kyle.edwards](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/65b543/32.png) [@kyle.edwards](https://discourse.cmake.org/u/kyle.edwards)
#### Post date: [June 24, 2022, 5:11pm UTC](https://discourse.cmake.org/t/is-there-a-builtin-method-to-create-a-target-thats-only-run-if-dependent-files-are-changed-touched/5927/4 "2022-06-24T17:11:46Z")

</div>

In that case you want something like this:

```cmake
set(pylint_stamp_files)
foreach(file IN LISTS python_files)
  set(stamp_file ${file}.pylint_stamp)
  list(APPEND pylint_stamp_files ${stamp_file})
  add_custom_command(
    OUTPUT ${stamp_file}
    COMMAND pylint ${file}
    COMMAND ${CMAKE_COMMAND} -E touch ${stamp_file}
    DEPENDS ${file}
    )
endforeach()

add_custom_target(lint_python_files ALL
  DEPENDS ${pylint_stamp_files}
  )

```

This will create a stamp file for each Python file.

---

<div class="post-metadata">

### Author: ![dundargoc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dundargoc/32/1923_2.png) [@dundargoc](https://discourse.cmake.org/u/dundargoc)
#### Post date: [June 24, 2022, 5:36pm UTC](https://discourse.cmake.org/t/is-there-a-builtin-method-to-create-a-target-thats-only-run-if-dependent-files-are-changed-touched/5927/5 "2022-06-24T17:36:33Z")

</div>

Sure, but that’s basically what I wrote as the function I use right now in my post.

---

<div class="post-metadata">

### Author: ![kyle.edwards](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/65b543/32.png) [@kyle.edwards](https://discourse.cmake.org/u/kyle.edwards)
#### Post date: [June 24, 2022, 5:39pm UTC](https://discourse.cmake.org/t/is-there-a-builtin-method-to-create-a-target-thats-only-run-if-dependent-files-are-changed-touched/5927/6 "2022-06-24T17:39:33Z")

</div>

Indeed it is… sorry about that. Yeah, you’re already doing it right.
