Determine dependencies of Windows resource files
Windows resource files support a subset of C preprocessor directives. Among others they can have #include directives. Use QMake's own scanner to retrieve the files that are included by a Windows resource file and add them to its dependencies. For the test case the TestCompiler class had to be extended: runCommand is now public, and commandOutput is less peculiar. Fixes: QTBUG-3859 Change-Id: I138703352c37c98297c0574a9a440510c1c494b8 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
00076a2695
commit
42d32e468a
@ -342,7 +342,11 @@ void MingwMakefileGenerator::writeRcFilePart(QTextStream &t)
|
||||
if (defines.isEmpty())
|
||||
defines = ProString(" $(DEFINES)");
|
||||
|
||||
t << escapeDependencyPath(var("RES_FILE")) << ": " << escapeDependencyPath(rc_file) << "\n\t"
|
||||
addSourceFile(rc_file, QMakeSourceFileInfo::SEEK_DEPS);
|
||||
const QStringList rcDeps = QStringList(rc_file) << dependencies(rc_file);
|
||||
|
||||
t << escapeDependencyPath(var("RES_FILE")) << ": "
|
||||
<< escapeDependencyPaths(rcDeps).join(' ') << "\n\t"
|
||||
<< var("QMAKE_RC") << " -i " << escapeFilePath(rc_file) << " -o " << fileVar("RES_FILE")
|
||||
<< incPathStr << defines << "\n\n";
|
||||
}
|
||||
|
@ -667,6 +667,9 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t)
|
||||
incPathStr += escapeFilePath(path);
|
||||
}
|
||||
|
||||
addSourceFile(rc_file, QMakeSourceFileInfo::SEEK_DEPS);
|
||||
const QStringList rcDeps = QStringList(rc_file) << dependencies(rc_file);
|
||||
|
||||
// The resource tool may use defines. This might be the same defines passed in as the
|
||||
// compiler, since you may use these defines in the .rc file itself.
|
||||
// As the escape syntax for the command line defines for RC is different from that for CL,
|
||||
@ -678,7 +681,8 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t)
|
||||
// Also, we need to add the _DEBUG define manually since the compiler defines this symbol
|
||||
// by itself, and we use it in the automatically created rc file when VERSION is defined
|
||||
// in the .pro file.
|
||||
t << escapeDependencyPath(res_file) << ": " << escapeDependencyPath(rc_file) << "\n\t"
|
||||
t << escapeDependencyPath(res_file) << ": "
|
||||
<< escapeDependencyPaths(rcDeps).join(' ') << "\n\t"
|
||||
<< var("QMAKE_RC") << (project->isActiveConfig("debug") ? " -D_DEBUG" : "")
|
||||
<< defines << incPathStr << " -fo " << escapeFilePath(res_file)
|
||||
<< ' ' << escapeFilePath(rc_file);
|
||||
|
@ -164,15 +164,17 @@ bool TestCompiler::runCommand(const QString &cmd, const QStringList &args, bool
|
||||
return errorOut();
|
||||
}
|
||||
|
||||
child.setReadChannel(QProcess::StandardError);
|
||||
child.waitForFinished(-1);
|
||||
bool ok = child.exitStatus() == QProcess::NormalExit && (expectFail ^ (child.exitCode() == 0));
|
||||
|
||||
foreach (const QByteArray &output, child.readAllStandardError().split('\n')) {
|
||||
testOutput_.append(QString::fromLocal8Bit(output));
|
||||
|
||||
if (output.startsWith("Project MESSAGE: FAILED"))
|
||||
ok = false;
|
||||
for (auto channel : { QProcess::StandardOutput, QProcess::StandardError }) {
|
||||
child.setReadChannel(channel);
|
||||
while (!child.atEnd()) {
|
||||
const QString output = QString::fromLocal8Bit(child.readLine());
|
||||
if (output.startsWith("Project MESSAGE: FAILED"))
|
||||
ok = false;
|
||||
testOutput_.append(output);
|
||||
}
|
||||
}
|
||||
|
||||
return ok ? true : errorOut();
|
||||
|
@ -71,13 +71,17 @@ public:
|
||||
bool removeProject( const QString &workPath, const QString &project );
|
||||
// removes the file specified by 'fileName' on the 'workPath'
|
||||
bool removeFile( const QString &workPath, const QString &fileName );
|
||||
// returns each line of stdout of the last command append with a "new line" character(s) to suit the platform
|
||||
|
||||
// Returns each line of stdout/stderr of the last commands
|
||||
// separated by platform-specific line endings.
|
||||
QString commandOutput() const;
|
||||
|
||||
// clear the results of storage of stdout for running previous commands
|
||||
void clearCommandOutput();
|
||||
|
||||
private:
|
||||
bool runCommand(const QString &cmd, const QStringList &args, bool expectFail = false);
|
||||
|
||||
private:
|
||||
bool errorOut();
|
||||
|
||||
QString makeCmd_;
|
||||
|
1
tests/auto/tools/qmake/testdata/windows_resources/inter.inc
vendored
Normal file
1
tests/auto/tools/qmake/testdata/windows_resources/inter.inc
vendored
Normal file
@ -0,0 +1 @@
|
||||
#include "version.inc"
|
1
tests/auto/tools/qmake/testdata/windows_resources/main.cpp
vendored
Normal file
1
tests/auto/tools/qmake/testdata/windows_resources/main.cpp
vendored
Normal file
@ -0,0 +1 @@
|
||||
int main() {}
|
28
tests/auto/tools/qmake/testdata/windows_resources/version.inc
vendored
Normal file
28
tests/auto/tools/qmake/testdata/windows_resources/version.inc
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
FILEFLAGS 0x0L
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEOS 0x00040004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "The Qt Company Ltd"
|
||||
VALUE "FileDescription", "A Good File"
|
||||
VALUE "FileVersion", "1.0.0.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2019 The Qt Company Ltd."
|
||||
VALUE "InternalName", "foo"
|
||||
VALUE "OriginalFilename", "foo.exe"
|
||||
VALUE "ProductName", "A Good Product"
|
||||
VALUE "ProductVersion", "1.0.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
4
tests/auto/tools/qmake/testdata/windows_resources/windows_resources.pro
vendored
Normal file
4
tests/auto/tools/qmake/testdata/windows_resources/windows_resources.pro
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
QT = core
|
||||
SOURCES = main.cpp
|
||||
RC_FILE = windows_resources.rc
|
||||
TEMPLATE = app
|
2
tests/auto/tools/qmake/testdata/windows_resources/windows_resources.rc
vendored
Normal file
2
tests/auto/tools/qmake/testdata/windows_resources/windows_resources.rc
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
#include "winver.h"
|
||||
#include "inter.inc"
|
@ -76,8 +76,10 @@ private slots:
|
||||
void findMocs();
|
||||
void findDeps();
|
||||
void rawString();
|
||||
#if defined(Q_OS_MAC)
|
||||
#if defined(Q_OS_DARWIN)
|
||||
void bundle_spaces();
|
||||
#elif defined(Q_OS_WIN)
|
||||
void windowsResources();
|
||||
#endif
|
||||
void substitutes();
|
||||
void project();
|
||||
@ -512,7 +514,8 @@ struct TempFile
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
#if defined(Q_OS_DARWIN)
|
||||
|
||||
void tst_qmake::bundle_spaces()
|
||||
{
|
||||
QString workDir = base_path + "/testdata/bundle-spaces";
|
||||
@ -543,7 +546,34 @@ void tst_qmake::bundle_spaces()
|
||||
QVERIFY( !non_existing_file.exists() );
|
||||
QVERIFY( test_compiler.removeMakefile(workDir) );
|
||||
}
|
||||
#endif // defined(Q_OS_MAC)
|
||||
|
||||
#elif defined(Q_OS_WIN) // defined(Q_OS_DARWIN)
|
||||
|
||||
void tst_qmake::windowsResources()
|
||||
{
|
||||
QString workDir = base_path + "/testdata/windows_resources";
|
||||
QVERIFY(test_compiler.qmake(workDir, "windows_resources"));
|
||||
QVERIFY(test_compiler.make(workDir));
|
||||
|
||||
// Another "make" must not rebuild the .res file
|
||||
test_compiler.clearCommandOutput();
|
||||
QVERIFY(test_compiler.make(workDir));
|
||||
QVERIFY(!test_compiler.commandOutput().contains("windows_resources.rc"));
|
||||
test_compiler.clearCommandOutput();
|
||||
|
||||
// Wait a second to make sure we get a new timestamp in the touch below
|
||||
QTest::qWait(1000);
|
||||
|
||||
// Touch the deepest include of the .rc file
|
||||
QVERIFY(test_compiler.runCommand("cmd", QStringList{"/c",
|
||||
"echo.>>" + QDir::toNativeSeparators(workDir + "/version.inc")}));
|
||||
|
||||
// The next "make" must rebuild the .res file
|
||||
QVERIFY(test_compiler.make(workDir));
|
||||
QVERIFY(test_compiler.commandOutput().contains("windows_resources.rc"));
|
||||
}
|
||||
|
||||
#endif // defined(Q_OS_WIN)
|
||||
|
||||
void tst_qmake::substitutes()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user