diff options
author | Ola Røer Thorsen <ola@silentwings.no> | 2019-01-03 14:44:15 +0100 |
---|---|---|
committer | Ola Røer Thorsen <ola@silentwings.no> | 2019-01-18 09:39:15 +0000 |
commit | 0be365894406cbca8ed54253419ea2ad6f961bdf (patch) | |
tree | 45a6286600bc61fc56769835d0ee2bb4a93790f0 /tests | |
parent | 9e55ddfa97619f7983ea66213ce6764ee0aed2d9 (diff) |
Add recursive dependency scanning of GNU ld linkerscripts
Linkerscripts may contain INCLUDE and SEARCH_DIR commands that allows
it to include other linkerscripts in a similary way as headers are
included in C++. This commit adds a scanner that adds these additional
dependencies.
[ChangeLog] Added recursive dependency scanning of GNU ld
linkerscripts that contain INCLUDE and SEARCH_DIR commands.
Change-Id: I7549e27aad4fe7ade2a6a26eba14f66880261077
Reviewed-by: Ola Røer Thorsen <ola@silentwings.no>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'tests')
5 files changed, 116 insertions, 12 deletions
diff --git a/tests/auto/blackbox/testdata/linkerscripts/linkerscript_recursive b/tests/auto/blackbox/testdata/linkerscripts/linkerscript_recursive new file mode 100644 index 000000000..11bc411a5 --- /dev/null +++ b/tests/auto/blackbox/testdata/linkerscripts/linkerscript_recursive @@ -0,0 +1 @@ +TEST_SYMBOL_FROM_RECURSIVE = 1; diff --git a/tests/auto/blackbox/testdata/linkerscripts/linkerscript_to_include b/tests/auto/blackbox/testdata/linkerscripts/linkerscript_to_include new file mode 100644 index 000000000..68c67eb60 --- /dev/null +++ b/tests/auto/blackbox/testdata/linkerscripts/linkerscript_to_include @@ -0,0 +1,2 @@ +TEST_SYMBOL_FROM_INCLUDE = 1; +INCLUDE linkerscript_recursive diff --git a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs index b30a498bb..9dd7bf5b2 100644 --- a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs +++ b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs @@ -1,13 +1,22 @@ +import qbs.TextFile + DynamicLibrary { type: base.concat("custom") Depends { name: "cpp" } files: ["testlib.c"] Group { name: "linker scripts" - files: ["linkerscript1", "linkerscript2"] + files: [ + "linkerscript1", + "linkerscript2", + ] fileTags: ["linkerscript"] } + cpp.libraryPaths: [ + product.sourceDirectory, // location of linkerscripts that are included + ] + Rule { multiplex: true outputFileTags: "custom" @@ -21,6 +30,31 @@ DynamicLibrary { } } + Rule { + multiplex: true + requiresInputs: false + Artifact { + filePath: product.buildDirectory + "/linkerscript_with_includes" + fileTags: ["linkerscript"] + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.sourcePath = product.sourceDirectory; + cmd.buildPath = product.buildDirectory; + cmd.sourceCode = function() { + var file = new TextFile(buildPath + "/linkerscript_with_includes", + TextFile.WriteOnly); + file.write("SEARCH_DIR(" + sourcePath + "/scripts)\n" + + "INCLUDE linkerscript_to_include\n" + + "INCLUDE linkerscript_in_directory\n"); + file.close(); + } + cmd.highlight = "codegen"; + cmd.description = "generating linkerscript with SEARCH_DIR and INCLUDE"; + return [cmd]; + } + } + qbs.installPrefix: "" install: true installDir: "" diff --git a/tests/auto/blackbox/testdata/linkerscripts/scripts/linkerscript_in_directory b/tests/auto/blackbox/testdata/linkerscripts/scripts/linkerscript_in_directory new file mode 100644 index 000000000..098156292 --- /dev/null +++ b/tests/auto/blackbox/testdata/linkerscripts/scripts/linkerscript_in_directory @@ -0,0 +1 @@ +TEST_SYMBOL_FROM_DIRECTORY = 1; diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index df4a2066f..fbcd16eb8 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -4385,9 +4385,15 @@ void TestBlackbox::linkerScripts() QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) QSKIP("linker script test only applies to Linux "); - QDir::setCurrent(testDataDir + "/linkerscripts"); - QCOMPARE(runQbs(QbsRunParameters(QStringList("-q") - << ("qbs.installRoot:" + QDir::currentPath()))), 0); + + QbsRunParameters runParams(QStringList() +// << "--log-level" << "debug" + << ("qbs.installRoot:" + QDir::currentPath())); + const QString sourceDir = QDir::cleanPath(testDataDir + "/linkerscripts"); + runParams.buildDirectory = sourceDir + "/build"; + runParams.workingDir = sourceDir; + + QCOMPARE(runQbs(runParams), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); QRegExp pattern(".*---(.*)---.*"); QVERIFY2(pattern.exactMatch(output), qPrintable(output)); @@ -4395,14 +4401,74 @@ void TestBlackbox::linkerScripts() const QString nmPath = pattern.capturedTexts().at(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); - QProcess nm; - nm.start(nmPath, QStringList(QDir::currentPath() + "/liblinkerscripts.so")); - QVERIFY(nm.waitForStarted()); - QVERIFY(nm.waitForFinished()); - const QByteArray nmOutput = nm.readAllStandardOutput(); - QCOMPARE(nm.exitCode(), 0); - QVERIFY2(nmOutput.contains("TEST_SYMBOL1"), nmOutput.constData()); - QVERIFY2(nmOutput.contains("TEST_SYMBOL2"), nmOutput.constData()); + + const auto verifySymbols = [nmPath](const QByteArrayList& symbols) -> bool { + QProcess nm; + nm.start(nmPath, QStringList(QDir::currentPath() + "/liblinkerscripts.so")); + if (!nm.waitForStarted()) { + qDebug() << "Wait for process started failed."; + return false; + } + if (!nm.waitForFinished()) { + qDebug() << "Wait for process finished failed."; + return false; + } + if (nm.exitCode() != 0) { + qDebug() << "nm returned exit code " << nm.exitCode(); + return false; + } + const QByteArray nmOutput = nm.readAllStandardOutput(); + for (const QByteArray& symbol : symbols) { + if (!nmOutput.contains(symbol)) { + qDebug() << "Expected symbol" << symbol + << "not found in" << nmOutput.constData(); + return false; + } + } + return true; + }; + + QVERIFY(verifySymbols({"TEST_SYMBOL1", + "TEST_SYMBOL2", + "TEST_SYMBOL_FROM_INCLUDE", + "TEST_SYMBOL_FROM_DIRECTORY", + "TEST_SYMBOL_FROM_RECURSIVE"})); + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE(sourceDir + "/linkerscript_to_include", + "TEST_SYMBOL_FROM_INCLUDE = 1;", + "TEST_SYMBOL_FROM_INCLUDE_MODIFIED = 1;\n"); + QCOMPARE(runQbs(runParams), 0); + QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), + "No linking after modifying included file"); + QVERIFY(verifySymbols({"TEST_SYMBOL1", + "TEST_SYMBOL2", + "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", + "TEST_SYMBOL_FROM_DIRECTORY", + "TEST_SYMBOL_FROM_RECURSIVE"})); + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE(sourceDir + "/scripts/linkerscript_in_directory", + "TEST_SYMBOL_FROM_DIRECTORY = 1;\n", + "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED = 1;\n"); + QCOMPARE(runQbs(runParams), 0); + QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), + "No linking after modifying file in directory"); + QVERIFY(verifySymbols({"TEST_SYMBOL1", + "TEST_SYMBOL2", + "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", + "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED", + "TEST_SYMBOL_FROM_RECURSIVE"})); + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE(sourceDir + "/linkerscript_recursive", + "TEST_SYMBOL_FROM_RECURSIVE = 1;\n", + "TEST_SYMBOL_FROM_RECURSIVE_MODIFIED = 1;\n"); + QCOMPARE(runQbs(runParams), 0); + QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), + "No linking after modifying recursive file"); + QVERIFY(verifySymbols({"TEST_SYMBOL1", + "TEST_SYMBOL2", + "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", + "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED", + "TEST_SYMBOL_FROM_RECURSIVE_MODIFIED"})); } void TestBlackbox::listProducts() |