1

I am currently using the CMake for a project. I would like to check the git tag when making the project, if the git tag does not satisfy a certain format, the making process shall fail.

Here is what I am doing in the CMakeList.txt

execute_process(
    COMMAND git describe --always --tags
    OUTPUT_VARIABLE git_tag
    OUTPUT_STRIP_TRAILING_WHITESPACE
    WORKING_DIRECTORY ${PX4_SOURCE_DIR}
    )

string(REPLACE "-" ";" git_tag_list ${git_tag})
list(GET git_tag_list 0 git_tag_short)
string(REPLACE "." ";" ver_list ${git_tag_short})
set(ver_check_fail_msg "The git tag must be in the format of X.X.XX (6 characters), where X are digits. The current is ${git_tag_short}.") 
list(LENGTH ver_list ver_len)
if (NOT "${ver_len}" STREQUAL "3")
    message(FATAL_ERROR "${ver_check_fail_msg}")
endif()

The problem is that the check is only executed every time I call cmake, but I would like the check to be executed every time I call make.

Any suggestions?

torek
  • 448,244
  • 59
  • 642
  • 775
Nyaruko
  • 4,329
  • 9
  • 54
  • 105
  • If you want to run some command every build (make), then use `add_custom_target`. See e.g. that question: https://stackoverflow.com/questions/13920072/how-to-always-run-command-when-building-regardless-of-any-dependency. Note, that at building stage "normal" CMake is not accessible, so you normally should write a script in some other language for implement your check logic. (Or you may use CMake scripting mode, `cmake -P`). – Tsyvarev May 18 '22 at 13:17
  • @Tsyvarev, Ok, but even if I used the add_custom_target and say created a python script to return a value, how could I force the build process to fail and stop with some custom warning message? – Nyaruko May 18 '22 at 13:24
  • You could print any message in your script and return **non-zero** from it. This tells `make` (or any other build tool) that building fails. – Tsyvarev May 18 '22 at 13:26
  • @Tsyvarev, I have followed your example, the python script did get executed every time, but I cannot see its output, also how to make the python script to return non-zero? – Nyaruko May 18 '22 at 14:49
  • "how to make the python script to return non-zero" - You could use `sys.exit()` for that purpose, see e.g. [that question](https://stackoverflow.com/q/285289/3440745). – Tsyvarev May 18 '22 at 15:02
  • This is a bad idea! Cuz this way u limiting your builds to work only from Git clone. Means, that building from a tarball or `git export` gonna be broken. There is absolutely no point to make it so. At least consider any fallback code... – zaufi May 18 '22 at 20:43
  • @zaufi, could you suggest any idea on the fallback? – Nyaruko May 19 '22 at 05:32
  • Apparently, this feature (check) must be optional cuz there is no fallback. Information about a tag just missed in a tarball. What I suggest is to use e.g. Github actions (or the similar for GitLab or whatever Git hosting u have) and not do this at the build time of the project. It just unrelated things! Whatever tag has set shouldn't break the build! – zaufi May 20 '22 at 06:51

1 Answers1

0

The answer is originally from: How to always run command when building regardless of any dependency?

One can use the following code:

add_custom_target(
    my_custom_target_that_always_runs ALL
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/__header.h
)

add_custom_command(
    OUTPUT
        ${CMAKE_CURRENT_BINARY_DIR}/__header.h  # fake! ensure we run!
        ${CMAKE_CURRENT_BINARY_DIR}/header.h    # real header, we write.
    # this command must generate: ${CMAKE_CURRENT_BINARY_DIR}/header.h
    COMMAND some_script
)

For some explanation, the key here is the file ${CMAKE_CURRENT_BINARY_DIR}/__header.h which should never exist.

Since it does not exist and the custom target depends on it, it will trigger the some_script in the add_custom_command to try generate the missing file.

Makesure that some_script never really generate the ${CMAKE_CURRENT_BINARY_DIR}/__header.h. As long as the file does not exist, the add_custom_target will always trigger the some_script.

Nyaruko
  • 4,329
  • 9
  • 54
  • 105
  • Not sure why people like to introduce "fake header", when `add_custom_target` itself is a perfect place for "run every time" commands, as described in [that answer](https://stackoverflow.com/a/43206544/3440745). As for your answer and the question it refers to, their code is the very similar to [another answer](https://stackoverflow.com/a/31518137/3440745). – Tsyvarev May 19 '22 at 09:36
  • @Tsyvarev, after testing on my own system, what I found is that `add_custom_target` do get executed every time, if the command/script is directly inside the `add_custom_target` then it will be executed every time. However, it the command/script is in the `add_custom_command `, it wont be executed if `add_custom_target` finds all its dependency is already satisfied. – Nyaruko May 19 '22 at 09:58
  • Yes, this is exactly how `add_custom_target`/`add_custom_command` works. If you want a script to be executed **unconditionally**, then you place it in COMMAND clause for `add_custom_target`. If you want a script to be executed only for **update** some **files**, then you create `add_custom_command`, place the script into its COMMAND clause and list the files in the OUTPUT clause. Then you create `add_custom_target` which DEPENDS on given files. – Tsyvarev May 19 '22 at 10:34