0

I have a CMake custom target that depends on an input file and a program, like this:

add_custom_command(
    OUTPUT generate
    COMMAND install generate
)
add_custom_command(
    OUTPUT header.h
    DEPENDS generate header.txt
    COMMAND generate -i header.txt -o header.h
)

Because of how the build system works, the 'generate' application is not available when compiling and needs to be installed everytime with the first custom command.

The issue I have is that, since the application always needs to be installed, the custom command is always running, obviously. So what I want is for the output 'header.h' to only be generated when 'header.txt' changes. Basically, 'header.txt' changes would be the only trigger to this custom command. However, if this is triggered, then I also want to run the first custom command so that we can install the application.

If 'header.txt' did not change, then there is no need to install the application with the first custom command since it is not going to be used.

How can this be done in CMake?

sycc90
  • 83
  • 6
  • You could move `COMMAND install generate` from the first custom command to the second one, and remove the first `add_custom_command` call. That way `generate` will be built only in case of *building* `header.h`. But if you have several "headers" which are needed to be generated with the same `generate` executable and you don't want to build the executable several times, then you would need to **manually** implement that "singleton", e.g. by using scripting. Like many other build tools, CMake doesn't support a "dependency-needed-only-for-build". – Tsyvarev Apr 11 '22 at 12:13
  • @Tsyvarev What exactly do you mean by using scripting? Does CMake support custom scripts? Or do you mean to just write a script in whatever language and call that from the custom command? My case is the 2nd you mention, multiple headers need to be generated. I guess I can move the first command into the second and create a function for this so I don't have to move it everywhere. It's a shame this can't be done with CMake, seems like a pretty common usecase I think. – sycc90 Apr 12 '22 at 21:39
  • I actually didn't understand your case. Assume someone needs `header.h`. The only way to generate it the **first time** is using `generate` utility. So if `header.h` exists, then `generate` utility exists(installed) too. There: "If 'header.txt' did not change, then there is no need to install the application with the first custom command since it is not going to be used." you describe the situation when `header.txt` has not been changed **since the last creation** of `header.h`. But as deduced before, in that case `generate` is **already installed**,so it is not clear what do you want to avoid – Tsyvarev Apr 12 '22 at 21:58
  • Like I mentioned in the question, because of how the build system works, the `generate` utility is never already installed, so whenever you try to build it will be missing and will run the custom command to install it. The input and output files will be there, but the `generate` application gets deleted after every build (this is how the build system works and not in control of the cmake file). – sycc90 Apr 12 '22 at 22:47
  • What this means is that `generate` will always be missing, regardless of this being the first time or not. However, if this is not the first time, `header.h` will already exist and if there were no changes to `header.txt` then there is no need to regenerate that file. The problem is that since `generate` is always missing, the custom command will always get triggered, even when `header.txt` didn't change after the first time. – sycc90 Apr 12 '22 at 22:50
  • "It's a shame this can't be done with CMake, seems like a pretty common usecase I think." - Unlike to what you think, the situation with removed intermediate dependency is not common. I know no build system which can process this removed dependency in a way which you want. Note, that CMake by itself is not a build system: it just configures the project and generates "build" files for the real build system. E.g. if you configure the project for Make utility, then CMake simply cannot process build dependencies which are not supported by Make. – Tsyvarev Apr 12 '22 at 23:52
  • I know CMake is not a build system, that's why I explicitely mentioned that the problem is because of the build system. But I can see many situations in which I want a generated file only triggering for _some_ dependencies but building all of them in those cases. For example when an intermediate temporary file needs to be generated, sometimes you can't keep those files around for security reasons. In any case, I think the answer is that it cannot be done with CMake. So unless someone else says otherwise, I'd be happy to select yours if you type it as an actual answer. – sycc90 Apr 16 '22 at 18:10

0 Answers0