After several hours studying the QtMSBuild scripts, I was able to find where the problem occurs, but not why. So I kludged a workaround.
The qt_vars.targets file (in the QtMSBuild directory) is loaded by the MSVC .vcxproj project file. In the targets file, this command is issued to create a temporary file named "props.txt". I guess this dumps the contents of the project's .pro file:
qmake -query >props.txt
qmake -query >props.txt
To copy to clipboard, switch view to plain text mode
props.txt starts with this and contains all sorts of Qt-related path names and parameters in a "Key:Value" format:
QMAKE_TARGET:x86_64
QMAKE_TARGET.arch:x86_64
QT_SYSROOT:
QT_INSTALL_PREFIX:
...
QMAKE_TARGET:x86_64
QMAKE_TARGET.arch:x86_64
QT_SYSROOT:
QT_INSTALL_PREFIX:
...
To copy to clipboard, switch view to plain text mode
This file then is parsed and its contents converted into the MSBuild XML that is then executed during the build. Except it doesn't, because the "QMAKE_TARGET.arch" string gets converted into an invalid XML element tag (containing a ".").
So my workaround / kludge was to add some commands in this qt_vars.targets file to edit the props.txt file (using sed) and replace the "QMAKE_TARGET.arch" string with "QMAKE_TARGET_arch". This modified props.txt gets parsed and executed without problems by MSBuild with no apparent effect on the result - the project compiles, links, and runs just fine.
If you run into this same problem, here are the relevant lines from qt_vars.targets, starting around line 100. My changes are between the Begin and End bug fix comments:
<!--// Run qmake: query properties -->
<PropertyGroup>
<Cmd><![CDATA[("$(QtToolsPath)\qmake.exe" -query) 1> props.txt 2> NUL]]></Cmd>
</PropertyGroup>
<Exec WorkingDirectory="$(QtVarsWorkDir)" Command="$(Cmd)"/>
<!-- Begin bug fix: Replace QMAKE_TARGET.arch in props.txt with QMAKE_TARGET_arch to avoid parsing error in MSBuild -->
<!-- Use sed to edit the line, then copy the temp file back into props.txt -->
<PropertyGroup>
<Sed><![CDATA[("$(QtMsBuild)\sed.exe" -f "$(QtMsBuild)\script.sed" props.txt >foo.txt) ]]></Sed>
</PropertyGroup>
<Exec WorkingDirectory="$(QtVarsWorkDir)" Command="$(Sed)"/>
<PropertyGroup>
<CopyFoo><![CDATA[(copy /Y foo.txt props.txt 1> NUL) ]]></CopyFoo>
</PropertyGroup>
<Exec WorkingDirectory="$(QtVarsWorkDir)" Command="$(CopyFoo)"/>
<!-- End bug fix -->
<ReadLinesFromFile
File="$(QtVarsWorkDir)\props.txt">
<Output TaskParameter="Lines" ItemName="QMakeQueryResult"/>
</ReadLinesFromFile>
<!--// Run qmake: query properties -->
<PropertyGroup>
<Cmd><![CDATA[("$(QtToolsPath)\qmake.exe" -query) 1> props.txt 2> NUL]]></Cmd>
</PropertyGroup>
<Exec WorkingDirectory="$(QtVarsWorkDir)" Command="$(Cmd)"/>
<!-- Begin bug fix: Replace QMAKE_TARGET.arch in props.txt with QMAKE_TARGET_arch to avoid parsing error in MSBuild -->
<!-- Use sed to edit the line, then copy the temp file back into props.txt -->
<PropertyGroup>
<Sed><![CDATA[("$(QtMsBuild)\sed.exe" -f "$(QtMsBuild)\script.sed" props.txt >foo.txt) ]]></Sed>
</PropertyGroup>
<Exec WorkingDirectory="$(QtVarsWorkDir)" Command="$(Sed)"/>
<PropertyGroup>
<CopyFoo><![CDATA[(copy /Y foo.txt props.txt 1> NUL) ]]></CopyFoo>
</PropertyGroup>
<Exec WorkingDirectory="$(QtVarsWorkDir)" Command="$(CopyFoo)"/>
<!-- End bug fix -->
<ReadLinesFromFile
File="$(QtVarsWorkDir)\props.txt">
<Output TaskParameter="Lines" ItemName="QMakeQueryResult"/>
</ReadLinesFromFile>
To copy to clipboard, switch view to plain text mode
The sed script (in script.sed) is very simple. I put the script file and a copy of sed.exe into the QtMSBuild directory for convenience:
s/QMAKE_TARGET.arch/QMAKE_TARGET_arch/
s/QMAKE_TARGET.arch/QMAKE_TARGET_arch/
To copy to clipboard, switch view to plain text mode
----------------------------------------
Edit: *&!#**& Each time Visual Studio starts, it replaces the files in the QtMSBuild directory with the original versions, thereby wiping out my changes to the qt_vars.targets file. I am determined that I will be the one who wins this battle.
Bookmarks