-
-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CMake+Ninja: dependencies of RC files missing #64
Comments
I wrote a bash script This script must be put next to the cmake executable, see Edit: There is a loophole invoking "cmcldeps LANG": cmake doesn't check the emptiness of the path, see CMakePresets.jsonThis
Edit: Set Edit 2: This is actually a regression in CMake 3.26.0 comfirmed by upstream https://gitlab.kitware.com/cmake/cmake/-/issues/24908. It will be fixed in 3.26.4, after that we do not need touch {
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 23,
"patch": 0
},
"configurePresets": [
{
"name": "msvc-wine",
"generator": "Ninja",
"cacheVariables": {
"CMAKE_C_COMPILER": "/opt/msvc/bin/x64/cl.exe",
"CMAKE_CXX_COMPILER": "/opt/msvc/bin/x64/cl.exe",
"CMAKE_RC_COMPILER": "/opt/msvc/bin/x64/rc.exe",
"CMAKE_NINJA_CMCLDEPS_RC": "ON",
"CMAKE_SYSTEM_NAME": "Windows",
"CMAKE_SYSTEM_VERSION": "10",
"CMAKE_CROSSCOMPILING_EMULATOR": "env;WINEDEBUG=-all;wine64",
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
},
"condition": {
"string": "${hostSystemName}",
"type": "notInList",
"list" : [ "Windows" ]
}
}
]
} cmcldeps#!/bin/bash
# This is a bash implementation of https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.1/Source/cmcldeps.cxx
# This script must be put next to the cmake executable, see
# https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.1/Source/cmSystemTools.cxx#L2611-2615.
# There is a loophole invoking "cmcldeps LANG": cmake doesn't check the emptiness of the path, see
# https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.1/Source/cmNinjaTargetGenerator.cxx#L804-821.
# So Ninja actually treats LANG as the executable in the case cmake doesn't find cmcldeps.
# One can rename this script to LANG (or using symlink) and put it in PATH, if putting the script next to
# the cmake executable is not doable.
usage() {
printf \
"ninja: FATAL: $1\n\nusage:\n"\
"cmcldeps "\
"<language C, CXX or RC> "\
"<source file path> "\
"<output path for *.d file> "\
"<output path for *.obj file> "\
"<prefix of /showIncludes> "\
"<path to cl.exe> "\
"<path to tool (cl or rc)> "\
"<rest of command ...>\n"\
>&2
exit 1
}
outputDepFile() {
local dfile=$1 ; shift
local objfile=$1 ; shift
if [[ -z $dfile ]]; then
return
fi
mapfile -t incs < <(printf '%s\n' "$@" | sort -u)
local cwd="$(pwd)/"
printf '%q \\\n' "$objfile:" "${incs[@]#$cwd}" >$dfile
}
process() {
local srcfilename=$1 ; shift
local dfile=$1 ; shift
local objfile=$1 ; shift
local prefix=$1 ; shift
local cmd=$1 ; shift
local dir=$1 ; shift
local quiet=${1:-false} ; shift
exec {fd}< <([[ -n $dir ]] && cd "$dir"; eval $cmd 2>&1)
local pid=$!
mapfile -t -u $fd
wait $pid
local exit_code=$?
exec {fd}<&-
# process the include directives and output everything else
local includes=()
local isFirstLine=true # cl prints always first the source filename
for inc in "${MAPFILE[@]}"; do
if [[ $inc =~ ^$prefix[[:blank:]]*(.*)$ ]]; then
includes+=("${BASH_REMATCH[1]}")
else
if ! $isFirstLine || [[ $inc != ${srcfilename}* ]]; then
if ! $quiet || [[ $exit_code -ne 0 ]]; then
printf '%s\n' "$inc"
fi
else
isFirstLine=false
fi
fi
done
# don't update .d until/unless we succeed compilation
if [[ $exit_code -eq 0 ]]; then
outputDepFile "$dfile" "$objfile" "${includes[@]}"
fi
return $exit_code
}
lang=$(basename "$0")
if [[ $lang == cmcldeps ]]; then
lang=$1; shift
fi
srcfile=$1; shift
dfile=$1; shift
objfile=$1; shift
prefix=$1; shift
cl=$1; shift
binpath=$1; shift
rest=("$@")
if [[ -z $binpath ]]; then
usage "Couldn't parse arguments."
fi
# https://github.com/ninja-build/ninja/blob/v1.11.1/src/clparser.cc#L46
if [[ -z $prefix ]]; then
prefix="Note: including file: "
fi
# needed to suppress filename output of msvc tools
srcfilename=$(basename "$srcfile")
if [[ $lang == C || $lang == CXX ]]; then
process "$srcfilename" "$dfile" "$objfile" "$prefix" "'$binpath' /nologo /showIncludes ${rest[*]@Q}"
elif [[ $lang == RC ]]; then
# "misuse" cl.exe to get headers from .rc files
clrest=()
for a in "${rest[@]}"; do
case $a in
[-/]fo | *$objfile) ;;
*) clrest+=("$a") ;;
esac
done
# call cl in object dir so the .i is generated there
objdir=$(dirname "$objfile")
# extract dependencies with cl.exe
process "$srcfilename" "$dfile" "$objfile" "$prefix" "'$cl' /P /DRC_INVOKED /TC /nologo /showIncludes ${clrest[*]@Q}" "$objdir" true
exit_code=$?
if [[ $exit_code -ne 0 ]]; then
exit $exit_code
fi
# compile rc file with rc.exe
process "$srcfilename" "" "$objfile" "$prefix" "'$binpath' ${rest[*]@Q}" "" true
else
usage "Invalid language specified."
fi |
Nice hacks with reimplementing this in bash! I took a look at the cmcldeps tool itself, and it doesn't seem all too reliant on Windows specific APIs, so I made an attempt at tweaking it so that it can be built and used on all platforms. See https://gitlab.kitware.com/mstorsjo/cmake/-/commits/cmcldeps. Note, these patches are entirely untested (I've only tested that it does compile), but if you're interested in progressing on this issue, you can have a look at this - hopefully it's not too far away from getting it to work. |
Nice! Regarding P.S. It would be better to merge |
Sorry I do not understand how I could use this workaround, I have the same issue, the installation does not provide rc.exe neither mt.exe that should be used by cmake. |
resource.h
: empty fileembed.rc
:#include "resource.h"
main.cpp
:int main() {}
CMakeLists.txt
:On Windows, touching
resource.h
and executeninja -d explain -d keepdepfile -v -j1
, RC file is correctly rebuilt.cmcldeps.exe
generates depfile forembed.rc
:But using msvc-wine on Linux, no depfile for
embed.rc
is generated. It is due toCMAKE_NINJA_CMCLDEPS_RC
is only defined on Windows.https://gitlab.kitware.com/cmake/cmake/-/blob/0b552eb877b887638e8130bb6c982106a76827d8/Modules/Platform/Windows-MSVC.cmake#L511
Also see related #22.
The text was updated successfully, but these errors were encountered: