Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • CMake CMake
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 3,823
    • Issues 3,823
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 9
    • Merge requests 9
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Releases
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • External wiki
    • External wiki
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • CMake
  • CMakeCMake
  • Issues
  • #19767
Closed
Open
Created Sep 29, 2019 by melak47@melak47

Ninja: Compilation of generated Windows Resource .rc file has incorrect dependencies

I'm using add_custom_command with the Ninja generator on Windows to invoke mc.exe on an .mc file, to generate an .rc file, to create a resource DLL.

When making changes to the example.mc file, rebuilding only invokes mc.exe, but dependencies that use the generated example.rc file are not rebuilt until I invoke ninja a second time:

> ninja
[0.014s 1/1] Generating example.rc, example.hpp, example_MSG00001.bin
MC: Compiling D:/repro/example.mc
> ninja
[0.027s 1/2] Building RC object CMakeFiles\example.dir\example.rc.res
Microsoft (R) Windows (R) Resource Compiler Version 10.0.10011.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

[0.084s 2/2] Linking CXX shared module example.dll

I tried the latest releases of CMake 3.11 through 3.15, and this behavior occurred with all of them. Here are my example CMakeLists.txt and example.mc.

The resulting build.ninja contains this dependency chain:

build example.dll: CXX_MODULE_LIBRARY_LINKER__example CMakeFiles\example.dir\example.rc.res

build CMakeFiles\example.dir\example.rc.res: RC_COMPILER__example D$:\repro\build\example.rc || cmake_object_order_depends_target_example

build D$:\repro\build\example.rc: CUSTOM_COMMAND cmake_object_order_depends_target_example
  COMMAND = cmd.exe /c
  restat = 1

build cmake_object_order_depends_target_example: phony || example.hpp example.rc example_MSG00001.bin

build example.rc example.hpp example_MSG00001.bin: CUSTOM_COMMAND ..\example.mc
  COMMAND = cmd.exe /C "cd /D D:\repro\build && "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64\mc.exe" -b -e hpp -h D:/repro/build -r D:/repro/build D:/repro/example.mc"
  DESC = Generating example.rc, example.hpp, example_MSG00001.bin
  restat = 1

I think that D$:\repro\build\example.rc depending on the actual example.rc file in order-only is the problem, since that tells ninja not to rebuild D$:\repro\build\example.rc if example.rc changes. IIRC ninja does not try to figure out that two distinct paths refer to the same file (otherwise, this would produce an error about multiple build statements producing the same file), so ninja does not discover that D$:\repro\build\example.rc has changed until the next run. The restat = 1 also doesn't help in this case, since it only causes a restat if the command runs.

If CMake instead emitted a phony like this:

build D$:\repro\build\example.rc: phony example.rc

Then targets depending on D$:\repro\build\example.rc would have a real dependency on example.rc, and would be rebuilt when it changes. Also, phony build statements don't appear in the build log, unlike the empty CUSTOM_COMMAND which shows up as cmd /c.

Edited Sep 30, 2019 by Brad King
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking