1

This is a simplification of another problem. But it boils down to the last add_custom_command (one which appends), which I want to only execute when the target T1 is build.

However currently the problem is that every time I run make, the Appending file.. command is always running.

# Fitst time running make
$ make
[100%] Creating file..
Appending file..
[100%] Built target T1

# Second time on
$ make
Appending file..
[100%] Built target T1

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(proj12 NONE)

# Phony target T1, which depends on t1.txt.
add_custom_target(T1 ALL DEPENDS t1.txt T1)

# Rule to create t1.txt dependency
add_custom_command(
    OUTPUT t1.txt
    COMMAND echo "Created at `date`" > t1.txt
    COMMENT "Creating file.."
    )

# Should only execute if T1 target needs to be built.
add_custom_command(
    POST_BUILD
    TARGET T1
    COMMAND echo "Appended at `date`" >> t1.txt
    COMMENT "Appending file.."
    )

The cmake documentation states the following

add_custom_command: This is useful for performing an operation before or after building the target. The command becomes part of the target and will only execute when the target itself is built. If the target is already built, the command will not execute.

So I was in the impression that the 'Appending' will only occur only when T1 target is build (which only builds when t1.txt is absent).

I am just learning CMake and is confused as to how this can be done. Do I need to create a dummy file for the appending to depend on?

The original problem

With older CMake the UseJava function add_jar places resource files in wrong namespace in the jar file. So my solution is to provide add_jar with only *.java files and later will add the extra resource files using jar command in a CMake custom command.

The solution works and the resource files are placed properly in the jar file, but this custom command is executed every time. I want this to execute only when the jar file actually changes.

Arjob Mukherjee
  • 387
  • 1
  • 10
  • 2
    "So I was in the impression that the 'Appending' will only occur only when T1 target is build (which only builds when t1.txt is absent)" - No, building a **custom** target is not equal to building the files that the target DEPENDS from. Your target is built every time because of ALL keyword. When a custom target is building, its DEPENDS files are evaluated, and it is decided whether to rebuild them or not. But whatever decision will be, the target will be considered to be being built. – Tsyvarev Feb 25 '23 at 14:23
  • 1
    CMake [documentation for build events](https://cmake.org/cmake/help/latest/command/add_custom_command.html#build-events) is somehow confusing: when it tells about building the target, in case of executable/library target it means the building of the target's "main file" (creation of which is requested by `add_executable` or `add_library` call). Custom targets (created by `add_custom_target`) don't have "main file" (at least, I do not know how to define such file), so for a custom target build events are executed when the target itself is being built. – Tsyvarev Feb 25 '23 at 14:29
  • @Tsyvarev Thanks for your comments, but I am still in doubt. I have added the actual problem that I am trying to solve. May be it will provide better context. – Arjob Mukherjee Feb 25 '23 at 16:25
  • "With older CMake the UseJava function `add_jar` places resource files in wrong namespace in the jar file." - You could take `UseJava.cmake` script from new CMake, ship that script with your project and adjust [CMAKE_MODULE_PATH](https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_PATH.html) variable. That way `include(UseJava)` will prefer the script from your project to the one shipped with the (old) CMake. While copying CMake modules usually should be avoided, I find this way nicer than attempting to "hack" existed modules. – Tsyvarev Feb 25 '23 at 16:46
  • Thanks @Tsyvarev. That seems to be a better solution. However wonder what else could be done, in general in situations like this. – Arjob Mukherjee Feb 25 '23 at 17:57
  • @Tsyvarev Well, I tried adding the newer `UseJava.cmake`, but the script uses functions which were added in later versions of CMake. I will have to ship the whole cascade of scripts for this to work. May be I should ditch UseJava and write something of my own. Cannot believe, how CMake can be so incomplete. – Arjob Mukherjee Feb 25 '23 at 19:53

0 Answers0