qmlls: add option to disable cmake-calls
Add option to disable cmake calls via commandline arguments, environment
variable and settings file.
Also fix the qmlls.ini generation script to include a line with
no-cmake-calls=false.
Picking back to 6.7 because the cmake call feature introduced in 6.7
might break stuff, so it should be easily disableable.
Fixes: QTBUG-119953
Fixes: QTBUG-119565
Change-Id: Ic3f2e369172aef430c52a98c1713e46b598a4f21
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit d976ddc5b1
)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
7ef31a5763
commit
2f4b7e8f8a
|
@ -763,7 +763,7 @@ function(_qt_internal_write_deferred_qmlls_ini_file)
|
||||||
# cmake list separator and windows path separator are both ';', so no replacement needed
|
# cmake list separator and windows path separator are both ';', so no replacement needed
|
||||||
set(concatenated_build_dirs "${_qmlls_ini_build_folders}")
|
set(concatenated_build_dirs "${_qmlls_ini_build_folders}")
|
||||||
endif()
|
endif()
|
||||||
set(file_content "[General]\nbuildDir=${concatenated_build_dirs}\n")
|
set(file_content "[General]\nbuildDir=${concatenated_build_dirs}\nno-cmake-calls=false\n")
|
||||||
file(CONFIGURE OUTPUT "${qmlls_ini_file}" CONTENT "${file_content}")
|
file(CONFIGURE OUTPUT "${qmlls_ini_file}" CONTENT "${file_content}")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|
|
@ -90,8 +90,17 @@ QQmlCodeModel::QQmlCodeModel(QObject *parent, QQmlToolingSettings *settings)
|
||||||
DomEnvironment::Option::SingleThreaded)),
|
DomEnvironment::Option::SingleThreaded)),
|
||||||
m_settings(settings)
|
m_settings(settings)
|
||||||
{
|
{
|
||||||
QObject::connect(&m_cppFileWatcher, &QFileSystemWatcher::fileChanged, this,
|
}
|
||||||
&QQmlCodeModel::onCppFileChanged);
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Disable the functionality that uses CMake, and remove the already watched paths if there are some.
|
||||||
|
*/
|
||||||
|
void QQmlCodeModel::disableCMakeCalls()
|
||||||
|
{
|
||||||
|
m_cmakeStatus = DoesNotHaveCMake;
|
||||||
|
m_cppFileWatcher.removePaths(m_cppFileWatcher.files());
|
||||||
|
QObject::disconnect(&m_cppFileWatcher, &QFileSystemWatcher::fileChanged, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlCodeModel::~QQmlCodeModel()
|
QQmlCodeModel::~QQmlCodeModel()
|
||||||
|
@ -419,17 +428,34 @@ void QQmlCodeModel::openUpdateEnd()
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
Test for CMake on the current system, and save result in m_cmakeStatus.
|
Performs initialization for m_cmakeStatus, including testing for CMake on the current system.
|
||||||
*/
|
*/
|
||||||
QQmlCodeModel::CMakeStatus QQmlCodeModel::testCMakeStatus()
|
void QQmlCodeModel::initializeCMakeStatus(const QString &pathForSettings)
|
||||||
{
|
{
|
||||||
|
if (m_settings) {
|
||||||
|
const QString cmakeCalls = u"no-cmake-calls"_s;
|
||||||
|
m_settings->search(pathForSettings);
|
||||||
|
if (m_settings->isSet(cmakeCalls) && m_settings->value(cmakeCalls).toBool()) {
|
||||||
|
qWarning() << "Disabling CMake calls via .qmlls.ini setting.";
|
||||||
|
m_cmakeStatus = DoesNotHaveCMake;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.setProgram(u"cmake"_s);
|
process.setProgram(u"cmake"_s);
|
||||||
process.setArguments({ u"--version"_s });
|
process.setArguments({ u"--version"_s });
|
||||||
process.start();
|
process.start();
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
m_cmakeStatus = process.exitCode() == 0 ? HasCMake : DoesNotHaveCMake;
|
m_cmakeStatus = process.exitCode() == 0 ? HasCMake : DoesNotHaveCMake;
|
||||||
return m_cmakeStatus;
|
|
||||||
|
if (m_cmakeStatus == DoesNotHaveCMake) {
|
||||||
|
qWarning() << "Disabling CMake calls because CMake was not found.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject::connect(&m_cppFileWatcher, &QFileSystemWatcher::fileChanged, this,
|
||||||
|
&QQmlCodeModel::onCppFileChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -547,13 +573,14 @@ void QQmlCodeModel::newDocForOpenFile(const QByteArray &url, int version, const
|
||||||
{
|
{
|
||||||
qCDebug(codeModelLog) << "updating doc" << url << "to version" << version << "("
|
qCDebug(codeModelLog) << "updating doc" << url << "to version" << version << "("
|
||||||
<< docText.size() << "chars)";
|
<< docText.size() << "chars)";
|
||||||
|
|
||||||
|
const QString fPath = url2Path(url, UrlLookup::ForceLookup);
|
||||||
|
if (m_cmakeStatus == RequiresInitialization)
|
||||||
|
initializeCMakeStatus(fPath);
|
||||||
|
|
||||||
DomItem newCurrent = m_currentEnv.makeCopy(DomItem::CopyOption::EnvConnected).item();
|
DomItem newCurrent = m_currentEnv.makeCopy(DomItem::CopyOption::EnvConnected).item();
|
||||||
QStringList loadPaths = buildPathsForFileUrl(url);
|
QStringList loadPaths = buildPathsForFileUrl(url);
|
||||||
|
|
||||||
if (m_cmakeStatus == ToTest) {
|
|
||||||
m_cmakeStatus = testCMakeStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_cmakeStatus == HasCMake && !loadPaths.isEmpty() && m_rebuildRequired) {
|
if (m_cmakeStatus == HasCMake && !loadPaths.isEmpty() && m_rebuildRequired) {
|
||||||
callCMakeBuild(loadPaths);
|
callCMakeBuild(loadPaths);
|
||||||
m_rebuildRequired = false;
|
m_rebuildRequired = false;
|
||||||
|
@ -563,7 +590,6 @@ void QQmlCodeModel::newDocForOpenFile(const QByteArray &url, int version, const
|
||||||
if (std::shared_ptr<DomEnvironment> newCurrentPtr = newCurrent.ownerAs<DomEnvironment>()) {
|
if (std::shared_ptr<DomEnvironment> newCurrentPtr = newCurrent.ownerAs<DomEnvironment>()) {
|
||||||
newCurrentPtr->setLoadPaths(loadPaths);
|
newCurrentPtr->setLoadPaths(loadPaths);
|
||||||
}
|
}
|
||||||
QString fPath = url2Path(url, UrlLookup::ForceLookup);
|
|
||||||
Path p;
|
Path p;
|
||||||
DomCreationOptions options;
|
DomCreationOptions options;
|
||||||
options.setFlag(DomCreationOption::WithScriptExpressions);
|
options.setFlag(DomCreationOption::WithScriptExpressions);
|
||||||
|
|
|
@ -104,6 +104,7 @@ public:
|
||||||
QQmlToolingSettings *settings();
|
QQmlToolingSettings *settings();
|
||||||
QStringList findFilePathsFromFileNames(const QStringList &fileNames) const;
|
QStringList findFilePathsFromFileNames(const QStringList &fileNames) const;
|
||||||
static QStringList fileNamesToWatch(const QQmlJS::Dom::DomItem &qmlFile);
|
static QStringList fileNamesToWatch(const QQmlJS::Dom::DomItem &qmlFile);
|
||||||
|
void disableCMakeCalls();
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void updatedSnapshot(const QByteArray &url);
|
void updatedSnapshot(const QByteArray &url);
|
||||||
private:
|
private:
|
||||||
|
@ -122,8 +123,8 @@ private:
|
||||||
|
|
||||||
static bool callCMakeBuild(const QStringList &buildPaths);
|
static bool callCMakeBuild(const QStringList &buildPaths);
|
||||||
void addFileWatches(const QQmlJS::Dom::DomItem &qmlFile);
|
void addFileWatches(const QQmlJS::Dom::DomItem &qmlFile);
|
||||||
enum CMakeStatus { ToTest, HasCMake, DoesNotHaveCMake };
|
enum CMakeStatus { RequiresInitialization, HasCMake, DoesNotHaveCMake };
|
||||||
CMakeStatus testCMakeStatus();
|
void initializeCMakeStatus(const QString &);
|
||||||
|
|
||||||
mutable QMutex m_mutex;
|
mutable QMutex m_mutex;
|
||||||
State m_state = State::Running;
|
State m_state = State::Running;
|
||||||
|
@ -145,7 +146,7 @@ private:
|
||||||
QQmlToolingSettings *m_settings;
|
QQmlToolingSettings *m_settings;
|
||||||
QFileSystemWatcher m_cppFileWatcher;
|
QFileSystemWatcher m_cppFileWatcher;
|
||||||
bool m_rebuildRequired = true; // always trigger a rebuild on start
|
bool m_rebuildRequired = true; // always trigger a rebuild on start
|
||||||
CMakeStatus m_cmakeStatus = ToTest;
|
CMakeStatus m_cmakeStatus = RequiresInitialization;
|
||||||
private slots:
|
private slots:
|
||||||
void onCppFileChanged(const QString &);
|
void onCppFileChanged(const QString &);
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,7 @@ void tst_generate_qmlls_ini::qmllsIniAreCorrect()
|
||||||
auto secondFolder = QDir(build.absolutePath().append(u"/qml/hello/subfolders"_s));
|
auto secondFolder = QDir(build.absolutePath().append(u"/qml/hello/subfolders"_s));
|
||||||
QVERIFY(secondFolder.exists());
|
QVERIFY(secondFolder.exists());
|
||||||
QCOMPARE(fileContent,
|
QCOMPARE(fileContent,
|
||||||
u"[General]\nbuildDir=%1%2%3\n"_s.arg(build.absolutePath(), QDir::listSeparator(),
|
u"[General]\nbuildDir=%1%2%3\nno-cmake-calls=false\n"_s.arg(build.absolutePath(), QDir::listSeparator(),
|
||||||
secondFolder.absolutePath()));
|
secondFolder.absolutePath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ void tst_generate_qmlls_ini::qmllsIniAreCorrect()
|
||||||
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
|
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
|
||||||
const auto fileContent = QString::fromUtf8(file.readAll());
|
const auto fileContent = QString::fromUtf8(file.readAll());
|
||||||
QCOMPARE(fileContent,
|
QCOMPARE(fileContent,
|
||||||
u"[General]\nbuildDir=%1\n"_s.arg(buildSubfolder.absolutePath()));
|
u"[General]\nbuildDir=%1\nno-cmake-calls=false\n"_s.arg(buildSubfolder.absolutePath()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,12 @@ int main(int argv, char *argc[])
|
||||||
"command line options into consideration"));
|
"command line options into consideration"));
|
||||||
parser.addOption(ignoreSettings);
|
parser.addOption(ignoreSettings);
|
||||||
|
|
||||||
|
QCommandLineOption noCMakeCallsOption(
|
||||||
|
QStringList() << "no-cmake-calls",
|
||||||
|
QLatin1String("Disables automatic CMake rebuilds and C++ file watching."));
|
||||||
|
parser.addOption(noCMakeCallsOption);
|
||||||
|
settings.addOption("no-cmake-calls", "false");
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
|
|
||||||
if (parser.isSet(writeDefaultsOption)) {
|
if (parser.isSet(writeDefaultsOption)) {
|
||||||
|
@ -213,6 +219,19 @@ int main(int argv, char *argc[])
|
||||||
},
|
},
|
||||||
(parser.isSet(ignoreSettings) ? nullptr : &settings));
|
(parser.isSet(ignoreSettings) ? nullptr : &settings));
|
||||||
|
|
||||||
|
const bool disableCMakeCallsViaEnvironment =
|
||||||
|
qmlGetConfigOption<bool, qmlConvertBoolConfigOption>("QMLLS_NO_CMAKE_CALLS");
|
||||||
|
|
||||||
|
if (disableCMakeCallsViaEnvironment || parser.isSet(noCMakeCallsOption)) {
|
||||||
|
if (disableCMakeCallsViaEnvironment) {
|
||||||
|
qWarning() << "Disabling CMake calls via QMLLS_NO_CMAKE_CALLS environment variable.";
|
||||||
|
} else {
|
||||||
|
qWarning() << "Disabling CMake calls via command line switch.";
|
||||||
|
}
|
||||||
|
|
||||||
|
qmlServer.codeModel()->disableCMakeCalls();
|
||||||
|
}
|
||||||
|
|
||||||
const QStringList envPaths =
|
const QStringList envPaths =
|
||||||
qEnvironmentVariable("QMLLS_BUILD_DIRS").split(u',', Qt::SkipEmptyParts);
|
qEnvironmentVariable("QMLLS_BUILD_DIRS").split(u',', Qt::SkipEmptyParts);
|
||||||
for (const QString &envPath : envPaths) {
|
for (const QString &envPath : envPaths) {
|
||||||
|
|
Loading…
Reference in New Issue