forked from qt-creator/qt-creator
Restore a clean system environment
... in case we are being run from another instance of Qt Creator. Remember which environment variables were amended to allow Qt Creator to start and reset them to their original values on start-up. This makes it possible to e.g. use Qt versions different from the ones that Qt Creator itself was built with. Change-Id: I6fc30823acb977f6cad4f67ff2e112c58792e30d Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -552,6 +552,33 @@ int main(int argc, char **argv)
|
|||||||
Options options = parseCommandLine(argc, argv);
|
Options options = parseCommandLine(argc, argv);
|
||||||
applicationDirPath(argv[0]);
|
applicationDirPath(argv[0]);
|
||||||
|
|
||||||
|
// Remove entries from environment variables that were set up by Qt Creator to run
|
||||||
|
// the application (in this case, us).
|
||||||
|
// TODO: We should be able to merge at least some of the stuff below with similar intent
|
||||||
|
// into a more generalized version of this.
|
||||||
|
EnvironmentItems specialItems;
|
||||||
|
EnvironmentItems diff;
|
||||||
|
Environment::systemEnvironment().forEachEntry(
|
||||||
|
[&specialItems](const QString &name, const QString &value, bool enabled) {
|
||||||
|
if (enabled && name.startsWith("_QTC_"))
|
||||||
|
specialItems.emplaceBack(name, value, EnvironmentItem::SetEnabled);
|
||||||
|
});
|
||||||
|
for (const EnvironmentItem &item : std::as_const(specialItems)) {
|
||||||
|
const QString varName = item.name.mid(5);
|
||||||
|
const FilePaths addedPaths
|
||||||
|
= Environment::pathListFromValue(item.value, HostOsInfo::hostOs());
|
||||||
|
FilePaths allPaths = Environment::systemEnvironment().pathListValue(varName);
|
||||||
|
Utils::eraseOne(allPaths, [&addedPaths](const FilePath &p) {
|
||||||
|
return addedPaths.contains(p);
|
||||||
|
});
|
||||||
|
diff.emplaceBack(
|
||||||
|
varName,
|
||||||
|
Environment::valueFromPathList(allPaths, HostOsInfo::hostOs()),
|
||||||
|
EnvironmentItem::SetEnabled);
|
||||||
|
diff.emplaceBack(item.name, "", EnvironmentItem::Unset);
|
||||||
|
}
|
||||||
|
Environment::modifySystemEnvironment(diff);
|
||||||
|
|
||||||
if (qEnvironmentVariableIsSet("QTC_DO_NOT_PROPAGATE_LD_PRELOAD"))
|
if (qEnvironmentVariableIsSet("QTC_DO_NOT_PROPAGATE_LD_PRELOAD"))
|
||||||
Environment::modifySystemEnvironment({{"LD_PRELOAD", "", EnvironmentItem::Unset}});
|
Environment::modifySystemEnvironment({{"LD_PRELOAD", "", EnvironmentItem::Unset}});
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@ FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser)
|
|||||||
{
|
{
|
||||||
const QString toolDir = QLatin1String("QTTOOLDIR=\"");
|
const QString toolDir = QLatin1String("QTTOOLDIR=\"");
|
||||||
Process proc;
|
Process proc;
|
||||||
|
proc.setEnvironment(qtChooser.deviceEnvironment());
|
||||||
proc.setCommand({qtChooser, {"-print-env"}});
|
proc.setCommand({qtChooser, {"-print-env"}});
|
||||||
proc.runBlocking(1s);
|
proc.runBlocking(1s);
|
||||||
if (proc.result() != ProcessResult::FinishedWithSuccess)
|
if (proc.result() != ProcessResult::FinishedWithSuccess)
|
||||||
@@ -107,6 +108,7 @@ QString BuildableHelperLibrary::qtVersionForQMake(const FilePath &qmakePath)
|
|||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
Process qmake;
|
Process qmake;
|
||||||
|
qmake.setEnvironment(qmakePath.deviceEnvironment());
|
||||||
qmake.setCommand({qmakePath, {"--version"}});
|
qmake.setCommand({qmakePath, {"--version"}});
|
||||||
qmake.runBlocking(5s);
|
qmake.runBlocking(5s);
|
||||||
if (qmake.result() != ProcessResult::FinishedWithSuccess) {
|
if (qmake.result() != ProcessResult::FinishedWithSuccess) {
|
||||||
|
@@ -208,6 +208,12 @@ Environment Environment::systemEnvironment()
|
|||||||
return *staticSystemEnvironment();
|
return *staticSystemEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Environment &Environment::originalSystemEnvironment()
|
||||||
|
{
|
||||||
|
static const Environment env(QProcessEnvironment::systemEnvironment().toStringList());
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
void Environment::setupEnglishOutput()
|
void Environment::setupEnglishOutput()
|
||||||
{
|
{
|
||||||
addItem(Item{std::in_place_index_t<SetupEnglishOutput>()});
|
addItem(Item{std::in_place_index_t<SetupEnglishOutput>()});
|
||||||
@@ -238,8 +244,24 @@ FilePaths Environment::path() const
|
|||||||
|
|
||||||
FilePaths Environment::pathListValue(const QString &varName) const
|
FilePaths Environment::pathListValue(const QString &varName) const
|
||||||
{
|
{
|
||||||
const QStringList pathComponents = expandedValueForKey(varName).split(
|
return pathListFromValue(expandedValueForKey(varName), osType());
|
||||||
OsSpecificAspects::pathListSeparator(osType()), Qt::SkipEmptyParts);
|
}
|
||||||
|
|
||||||
|
void Environment::setPathListValue(const QString &varName, const FilePaths &paths)
|
||||||
|
{
|
||||||
|
set(varName, valueFromPathList(paths, osType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Environment::valueFromPathList(const FilePaths &paths, OsType osType)
|
||||||
|
{
|
||||||
|
return transform(paths, &FilePath::toUserOutput)
|
||||||
|
.join(OsSpecificAspects::pathListSeparator(osType));
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePaths Environment::pathListFromValue(const QString &value, OsType osType)
|
||||||
|
{
|
||||||
|
const QStringList pathComponents
|
||||||
|
= value.split(OsSpecificAspects::pathListSeparator(osType), Qt::SkipEmptyParts);
|
||||||
return transform(pathComponents, &FilePath::fromUserInput);
|
return transform(pathComponents, &FilePath::fromUserInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -72,6 +72,9 @@ public:
|
|||||||
|
|
||||||
FilePaths path() const;
|
FilePaths path() const;
|
||||||
FilePaths pathListValue(const QString &varName) const;
|
FilePaths pathListValue(const QString &varName) const;
|
||||||
|
void setPathListValue(const QString &varName, const FilePaths &paths);
|
||||||
|
static QString valueFromPathList(const FilePaths &paths, OsType osType);
|
||||||
|
static FilePaths pathListFromValue(const QString &value, OsType osType);
|
||||||
|
|
||||||
QString expandedValueForKey(const QString &key) const;
|
QString expandedValueForKey(const QString &key) const;
|
||||||
QString expandVariables(const QString &input) const;
|
QString expandVariables(const QString &input) const;
|
||||||
@@ -91,6 +94,7 @@ public:
|
|||||||
bool operator==(const Environment &other) const;
|
bool operator==(const Environment &other) const;
|
||||||
|
|
||||||
static Environment systemEnvironment();
|
static Environment systemEnvironment();
|
||||||
|
static const Environment &originalSystemEnvironment();
|
||||||
|
|
||||||
static void modifySystemEnvironment(const EnvironmentItems &list); // use with care!!!
|
static void modifySystemEnvironment(const EnvironmentItems &list); // use with care!!!
|
||||||
static void setSystemEnvironment(const Environment &environment); // don't use at all!!!
|
static void setSystemEnvironment(const Environment &environment); // don't use at all!!!
|
||||||
|
@@ -52,8 +52,22 @@ protected:
|
|||||||
|
|
||||||
environment.addModifier([this](Environment &env) {
|
environment.addModifier([this](Environment &env) {
|
||||||
BuildTargetInfo bti = buildTargetInfo();
|
BuildTargetInfo bti = buildTargetInfo();
|
||||||
if (bti.runEnvModifier)
|
if (bti.runEnvModifier) {
|
||||||
|
Environment old = env;
|
||||||
bti.runEnvModifier(env, useLibraryPaths());
|
bti.runEnvModifier(env, useLibraryPaths());
|
||||||
|
const EnvironmentItems diff = old.diff(env, true);
|
||||||
|
for (const EnvironmentItem &i : diff) {
|
||||||
|
switch (i.operation) {
|
||||||
|
case EnvironmentItem::SetEnabled:
|
||||||
|
case EnvironmentItem::Prepend:
|
||||||
|
case EnvironmentItem::Append:
|
||||||
|
env.addItem(std::make_tuple("_QTC_" + i.name, i.value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setUpdater([this] { updateTargetInformation(); });
|
setUpdater([this] { updateTargetInformation(); });
|
||||||
|
@@ -80,8 +80,11 @@ void SshParameters::setupSshEnvironment(Process *process)
|
|||||||
Environment env = process->controlEnvironment();
|
Environment env = process->controlEnvironment();
|
||||||
if (!env.hasChanges())
|
if (!env.hasChanges())
|
||||||
env = Environment::systemEnvironment();
|
env = Environment::systemEnvironment();
|
||||||
if (SshSettings::askpassFilePath().exists()) {
|
const FilePath askPass = SshSettings::askpassFilePath();
|
||||||
env.set("SSH_ASKPASS", SshSettings::askpassFilePath().toUserOutput());
|
if (askPass.exists()) {
|
||||||
|
if (askPass.fileName().contains("qtc"))
|
||||||
|
env = Environment::originalSystemEnvironment();
|
||||||
|
env.set("SSH_ASKPASS", askPass.toUserOutput());
|
||||||
env.set("SSH_ASKPASS_REQUIRE", "force");
|
env.set("SSH_ASKPASS_REQUIRE", "force");
|
||||||
|
|
||||||
// OpenSSH only uses the askpass program if DISPLAY is set, regardless of the platform.
|
// OpenSSH only uses the askpass program if DISPLAY is set, regardless of the platform.
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include <qmljstools/qmljstoolsconstants.h>
|
#include <qmljstools/qmljstoolsconstants.h>
|
||||||
#include <qtsupport/baseqtversion.h>
|
#include <qtsupport/baseqtversion.h>
|
||||||
#include <qtsupport/qtkitaspect.h>
|
#include <qtsupport/qtkitaspect.h>
|
||||||
|
#include <utils/environment.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -224,6 +225,7 @@ QString QbsProfileManager::runQbsConfig(QbsConfigOp op, const QString &key, cons
|
|||||||
if (qbsConfigExe.isEmpty() || !qbsConfigExe.exists())
|
if (qbsConfigExe.isEmpty() || !qbsConfigExe.exists())
|
||||||
return {};
|
return {};
|
||||||
Utils::Process qbsConfig;
|
Utils::Process qbsConfig;
|
||||||
|
qbsConfig.setEnvironment(QbsSettings::qbsProcessEnvironment());
|
||||||
qbsConfig.setCommand({qbsConfigExe, args});
|
qbsConfig.setCommand({qbsConfigExe, args});
|
||||||
qbsConfig.start();
|
qbsConfig.start();
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
@@ -201,6 +201,7 @@ void QbsSession::initialize()
|
|||||||
QTimer::singleShot(0, this, [this] { setError(Error::InvalidQbsExecutable); });
|
QTimer::singleShot(0, this, [this] { setError(Error::InvalidQbsExecutable); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
d->qbsProcess->setEnvironment(QbsSettings::qbsProcessEnvironment());
|
||||||
d->qbsProcess->setCommand({qbsExe, {"session"}});
|
d->qbsProcess->setCommand({qbsExe, {"session"}});
|
||||||
d->qbsProcess->start();
|
d->qbsProcess->start();
|
||||||
}
|
}
|
||||||
|
@@ -28,12 +28,20 @@ const char QBS_EXE_KEY[] = "QbsProjectManager/QbsExecutable";
|
|||||||
const char QBS_DEFAULT_INSTALL_DIR_KEY[] = "QbsProjectManager/DefaultInstallDir";
|
const char QBS_DEFAULT_INSTALL_DIR_KEY[] = "QbsProjectManager/DefaultInstallDir";
|
||||||
const char USE_CREATOR_SETTINGS_KEY[] = "QbsProjectManager/useCreatorDir";
|
const char USE_CREATOR_SETTINGS_KEY[] = "QbsProjectManager/useCreatorDir";
|
||||||
|
|
||||||
|
static Environment getQbsProcessEnvironment(const FilePath &qbsExe)
|
||||||
|
{
|
||||||
|
if (qbsExe == QbsSettings::defaultQbsExecutableFilePath())
|
||||||
|
return Environment::originalSystemEnvironment();
|
||||||
|
return qbsExe.deviceEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
static QString getQbsVersion(const FilePath &qbsExe)
|
static QString getQbsVersion(const FilePath &qbsExe)
|
||||||
{
|
{
|
||||||
if (qbsExe.isEmpty() || !qbsExe.exists())
|
if (qbsExe.isEmpty() || !qbsExe.exists())
|
||||||
return {};
|
return {};
|
||||||
Process qbsProc;
|
Process qbsProc;
|
||||||
qbsProc.setCommand({qbsExe, {"--version"}});
|
qbsProc.setCommand({qbsExe, {"--version"}});
|
||||||
|
qbsProc.setEnvironment(getQbsProcessEnvironment(qbsExe));
|
||||||
qbsProc.start();
|
qbsProc.start();
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
if (!qbsProc.waitForFinished(5s) || qbsProc.exitCode() != 0)
|
if (!qbsProc.waitForFinished(5s) || qbsProc.exitCode() != 0)
|
||||||
@@ -82,6 +90,11 @@ FilePath QbsSettings::qbsConfigFilePath()
|
|||||||
return qbsConfig;
|
return qbsConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Environment QbsSettings::qbsProcessEnvironment()
|
||||||
|
{
|
||||||
|
return getQbsProcessEnvironment(qbsExecutableFilePath());
|
||||||
|
}
|
||||||
|
|
||||||
QString QbsSettings::defaultInstallDirTemplate()
|
QString QbsSettings::defaultInstallDirTemplate()
|
||||||
{
|
{
|
||||||
return instance().m_settings.defaultInstallDirTemplate;
|
return instance().m_settings.defaultInstallDirTemplate;
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <QVersionNumber>
|
#include <QVersionNumber>
|
||||||
|
|
||||||
|
namespace Utils { class Environment; }
|
||||||
|
|
||||||
namespace QbsProjectManager::Internal {
|
namespace QbsProjectManager::Internal {
|
||||||
|
|
||||||
class QbsSettingsData
|
class QbsSettingsData
|
||||||
@@ -29,6 +31,7 @@ public:
|
|||||||
static Utils::FilePath qbsExecutableFilePath();
|
static Utils::FilePath qbsExecutableFilePath();
|
||||||
static Utils::FilePath defaultQbsExecutableFilePath();
|
static Utils::FilePath defaultQbsExecutableFilePath();
|
||||||
static Utils::FilePath qbsConfigFilePath();
|
static Utils::FilePath qbsConfigFilePath();
|
||||||
|
static Utils::Environment qbsProcessEnvironment();
|
||||||
static bool hasQbsExecutable();
|
static bool hasQbsExecutable();
|
||||||
static QString defaultInstallDirTemplate();
|
static QString defaultInstallDirTemplate();
|
||||||
static bool useCreatorSettingsDirForQbs();
|
static bool useCreatorSettingsDirForQbs();
|
||||||
|
@@ -1337,8 +1337,6 @@ void QtVersionPrivate::updateVersionInfo()
|
|||||||
m_qmakeIsExecutable = false;
|
m_qmakeIsExecutable = false;
|
||||||
qWarning("Cannot update Qt version information from %s: %s.",
|
qWarning("Cannot update Qt version information from %s: %s.",
|
||||||
qPrintable(m_qmakeCommand.displayName()), qPrintable(error));
|
qPrintable(m_qmakeCommand.displayName()), qPrintable(error));
|
||||||
qWarning("If this appears when running Qt Creator in Qt Creator make "
|
|
||||||
"sure to disable \"Add build library search path to LD_LIBRARY_PATH\"");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_qmakeIsExecutable = true;
|
m_qmakeIsExecutable = true;
|
||||||
|
Reference in New Issue
Block a user