Merge pull request #5817 from aws-lumberyard-dev/Prism/CMakePATH

Fix Project Manager not finding CMake on Windows
This commit is contained in:
AMZN-Phil
2021-11-22 11:04:27 -08:00
committed by GitHub
8 changed files with 53 additions and 54 deletions
@@ -19,7 +19,7 @@ namespace O3DE::ProjectManager
{ {
// Attempt to use the Ninja build system if it is installed (described in the o3de documentation) if possible, // Attempt to use the Ninja build system if it is installed (described in the o3de documentation) if possible,
// otherwise default to the the default for Linux (Unix Makefiles) // otherwise default to the the default for Linux (Unix Makefiles)
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"}, QProcessEnvironment::systemEnvironment()); auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"});
QString cmakeGenerator = (whichNinjaResult.IsSuccess()) ? "Ninja Multi-Config" : "Unix Makefiles"; QString cmakeGenerator = (whichNinjaResult.IsSuccess()) ? "Ninja Multi-Config" : "Unix Makefiles";
bool compileProfileOnBuild = (whichNinjaResult.IsSuccess()); bool compileProfileOnBuild = (whichNinjaResult.IsSuccess());
@@ -38,7 +38,7 @@ namespace O3DE::ProjectManager
AZ::Outcome<QStringList, QString> ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const AZ::Outcome<QStringList, QString> ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const
{ {
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"}, QProcessEnvironment::systemEnvironment()); auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"});
bool compileProfileOnBuild = (whichNinjaResult.IsSuccess()); bool compileProfileOnBuild = (whichNinjaResult.IsSuccess());
QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix); QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix);
QString launcherTargetName = m_projectInfo.m_projectName + ".GameLauncher"; QString launcherTargetName = m_projectInfo.m_projectName + ".GameLauncher";
@@ -19,16 +19,15 @@ namespace O3DE::ProjectManager
// The list of clang C/C++ compiler command lines to validate on the host Linux system // The list of clang C/C++ compiler command lines to validate on the host Linux system
const QStringList SupportedClangVersions = {"13", "12", "11", "10", "9", "8", "7", "6.0"}; const QStringList SupportedClangVersions = {"13", "12", "11", "10", "9", "8", "7", "6.0"};
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment() AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
{ {
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); return AZ::Success();
return AZ::Success(currentEnvironment);
} }
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform() AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
{ {
// Validate that cmake is installed and is in the command line // Validate that cmake is installed and is in the command line
auto whichCMakeResult = ProjectUtils::ExecuteCommandResult("which", QStringList{ProjectCMakeCommand}, QProcessEnvironment::systemEnvironment()); auto whichCMakeResult = ProjectUtils::ExecuteCommandResult("which", QStringList{ProjectCMakeCommand});
if (!whichCMakeResult.IsSuccess()) if (!whichCMakeResult.IsSuccess())
{ {
return AZ::Failure(QObject::tr("CMake not found. <br><br>" return AZ::Failure(QObject::tr("CMake not found. <br><br>"
@@ -39,8 +38,8 @@ namespace O3DE::ProjectManager
// Look for the first compatible version of clang. The list below will contain the known clang compilers that have been tested for O3DE. // Look for the first compatible version of clang. The list below will contain the known clang compilers that have been tested for O3DE.
for (const QString& supportClangVersion : SupportedClangVersions) for (const QString& supportClangVersion : SupportedClangVersions)
{ {
auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang-%1").arg(supportClangVersion)}, QProcessEnvironment::systemEnvironment()); auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang-%1").arg(supportClangVersion)});
auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang++-%1").arg(supportClangVersion)}, QProcessEnvironment::systemEnvironment()); auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang++-%1").arg(supportClangVersion)});
if (whichClangResult.IsSuccess() && whichClangPPResult.IsSuccess()) if (whichClangResult.IsSuccess() && whichClangPPResult.IsSuccess())
{ {
return AZ::Success(QString("clang-%1").arg(supportClangVersion)); return AZ::Success(QString("clang-%1").arg(supportClangVersion));
@@ -54,7 +53,7 @@ namespace O3DE::ProjectManager
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath) AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath)
{ {
AZ::Outcome processEnvResult = GetCommandLineProcessEnvironment(); AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
if (!processEnvResult.IsSuccess()) if (!processEnvResult.IsSuccess())
{ {
return AZ::Failure(processEnvResult.GetError()); return AZ::Failure(processEnvResult.GetError());
@@ -68,7 +67,6 @@ namespace O3DE::ProjectManager
} }
QProcess process; QProcess process;
process.setProcessEnvironment(processEnvResult.GetValue());
// if the project build path is relative, it should be relative to the project path // if the project build path is relative, it should be relative to the project path
process.setWorkingDirectory(projectPath); process.setWorkingDirectory(projectPath);
@@ -88,7 +86,6 @@ namespace O3DE::ProjectManager
return ExecuteCommandResultModalDialog( return ExecuteCommandResultModalDialog(
QString("%1/python/get_python.sh").arg(engineRoot), QString("%1/python/get_python.sh").arg(engineRoot),
{}, {},
QProcessEnvironment::systemEnvironment(),
QObject::tr("Running get_python script...")); QObject::tr("Running get_python script..."));
} }
@@ -19,16 +19,14 @@ namespace O3DE::ProjectManager
{ {
AZ::Outcome<QString, QString> QueryInstalledCmakeFullPath() AZ::Outcome<QString, QString> QueryInstalledCmakeFullPath()
{ {
auto environmentRequest = ProjectUtils::GetCommandLineProcessEnvironment(); auto environmentRequest = ProjectUtils::SetupCommandLineProcessEnvironment();
if (!environmentRequest.IsSuccess()) if (!environmentRequest.IsSuccess())
{ {
return AZ::Failure(environmentRequest.GetError()); return AZ::Failure(environmentRequest.GetError());
} }
auto currentEnvironment = environmentRequest.GetValue();
auto queryCmakeInstalled = ProjectUtils::ExecuteCommandResult("which", auto queryCmakeInstalled = ProjectUtils::ExecuteCommandResult("which",
QStringList{ProjectCMakeCommand}, QStringList{ProjectCMakeCommand});
currentEnvironment);
if (!queryCmakeInstalled.IsSuccess()) if (!queryCmakeInstalled.IsSuccess())
{ {
return AZ::Failure(QObject::tr("Unable to detect CMake on this host.")); return AZ::Failure(QObject::tr("Unable to detect CMake on this host."));
@@ -18,28 +18,36 @@ namespace O3DE::ProjectManager
{ {
namespace ProjectUtils namespace ProjectUtils
{ {
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment() AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
{ {
// For CMake on Mac, if its installed through home-brew, then it will be installed // For CMake on Mac, if its installed through home-brew, then it will be installed
// under /usr/local/bin, which may not be in the system PATH environment. // under /usr/local/bin, which may not be in the system PATH environment.
// Add that path for the command line process so that it will be able to locate // Add that path for the command line process so that it will be able to locate
// a home-brew installed version of CMake // a home-brew installed version of CMake
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); QString pathEnv = qEnvironmentVariable("PATH");
QString pathValue = currentEnvironment.value("PATH"); QStringList pathEnvList = pathEnv.split(":");
pathValue += ":/usr/local/bin"; if (!pathEnvList.contains("/usr/local/bin"))
currentEnvironment.insert("PATH", pathValue); {
return AZ::Success(currentEnvironment); pathEnv += ":/usr/local/bin";
if (!qputenv("PATH", pathEnv.toStdString().c_str()))
{
return AZ::Failure(QObject::tr("Failed to set PATH environment variable"));
}
}
return AZ::Success();
} }
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform() AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
{ {
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
QString pathValue = currentEnvironment.value("PATH"); if (!processEnvResult.IsSuccess())
pathValue += ":/usr/local/bin"; {
currentEnvironment.insert("PATH", pathValue); return AZ::Failure(processEnvResult.GetError());
}
// Validate that we have cmake installed first // Validate that we have cmake installed first
auto queryCmakeInstalled = ExecuteCommandResult("which", QStringList{ProjectCMakeCommand}, currentEnvironment); auto queryCmakeInstalled = ExecuteCommandResult("which", QStringList{ProjectCMakeCommand});
if (!queryCmakeInstalled.IsSuccess()) if (!queryCmakeInstalled.IsSuccess())
{ {
return AZ::Failure(QObject::tr("Unable to detect CMake on this host.")); return AZ::Failure(QObject::tr("Unable to detect CMake on this host."));
@@ -47,7 +55,7 @@ namespace O3DE::ProjectManager
QString cmakeInstalledPath = queryCmakeInstalled.GetValue().split("\n")[0]; QString cmakeInstalledPath = queryCmakeInstalled.GetValue().split("\n")[0];
// Query the version of the installed cmake // Query the version of the installed cmake
auto queryCmakeVersionQuery = ExecuteCommandResult(cmakeInstalledPath, QStringList{"-version"}, currentEnvironment); auto queryCmakeVersionQuery = ExecuteCommandResult(cmakeInstalledPath, QStringList{"-version"});
if (!queryCmakeVersionQuery.IsSuccess()) if (!queryCmakeVersionQuery.IsSuccess())
{ {
return AZ::Failure(QObject::tr("Unable to determine the version of CMake on this host.")); return AZ::Failure(QObject::tr("Unable to determine the version of CMake on this host."));
@@ -55,7 +63,7 @@ namespace O3DE::ProjectManager
AZ_TracePrintf("Project Manager", "Cmake version %s detected.", queryCmakeVersionQuery.GetValue().split("\n")[0].toUtf8().constData()); AZ_TracePrintf("Project Manager", "Cmake version %s detected.", queryCmakeVersionQuery.GetValue().split("\n")[0].toUtf8().constData());
// Query for the version of xcodebuild (if installed) // Query for the version of xcodebuild (if installed)
auto queryXcodeBuildVersion = ExecuteCommandResult("xcodebuild", QStringList{"-version"}, currentEnvironment); auto queryXcodeBuildVersion = ExecuteCommandResult("xcodebuild", QStringList{"-version"});
if (!queryCmakeInstalled.IsSuccess()) if (!queryCmakeInstalled.IsSuccess())
{ {
return AZ::Failure(QObject::tr("Unable to detect XCodeBuilder on this host.")); return AZ::Failure(QObject::tr("Unable to detect XCodeBuilder on this host."));
@@ -104,7 +112,6 @@ namespace O3DE::ProjectManager
return ExecuteCommandResultModalDialog( return ExecuteCommandResultModalDialog(
QString("%1/python/get_python.sh").arg(engineRoot), QString("%1/python/get_python.sh").arg(engineRoot),
{}, {},
QProcessEnvironment::systemEnvironment(),
QObject::tr("Running get_python script...")); QObject::tr("Running get_python script..."));
} }
@@ -21,7 +21,7 @@ namespace O3DE::ProjectManager
{ {
namespace ProjectUtils namespace ProjectUtils
{ {
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment() AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
{ {
// Use the engine path to insert a path for cmake // Use the engine path to insert a path for cmake
auto engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo(); auto engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
@@ -31,26 +31,34 @@ namespace O3DE::ProjectManager
} }
auto engineInfo = engineInfoResult.GetValue(); auto engineInfo = engineInfoResult.GetValue();
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); // Append cmake path to the current environment PATH incase it is missing, since if
// we are starting CMake itself the current application needs to find it using Path
// Append cmake path to PATH incase it is missing // This also takes affect for all child processes.
QDir cmakePath(engineInfo.m_path); QDir cmakePath(engineInfo.m_path);
cmakePath.cd("cmake/runtime/bin"); cmakePath.cd("cmake/runtime/bin");
QString pathValue = currentEnvironment.value("PATH"); QString pathEnv = qEnvironmentVariable("Path");
pathValue += ";" + cmakePath.path(); QStringList pathEnvList = pathEnv.split(";");
currentEnvironment.insert("PATH", pathValue); if (!pathEnvList.contains(cmakePath.path()))
return AZ::Success(currentEnvironment); {
pathEnv += ";" + cmakePath.path();
if (!qputenv("Path", pathEnv.toStdString().c_str()))
{
return AZ::Failure(QObject::tr("Failed to set Path environment variable"));
}
}
return AZ::Success();
} }
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform() AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
{ {
// Validate that cmake is installed // Validate that cmake is installed
auto cmakeProcessEnvResult = GetCommandLineProcessEnvironment(); auto cmakeProcessEnvResult = SetupCommandLineProcessEnvironment();
if (!cmakeProcessEnvResult.IsSuccess()) if (!cmakeProcessEnvResult.IsSuccess())
{ {
return AZ::Failure(cmakeProcessEnvResult.GetError()); return AZ::Failure(cmakeProcessEnvResult.GetError());
} }
auto cmakeVersionQueryResult = ExecuteCommandResult("cmake", QStringList{"--version"}, cmakeProcessEnvResult.GetValue()); auto cmakeVersionQueryResult = ExecuteCommandResult("cmake", QStringList{"--version"});
if (!cmakeVersionQueryResult.IsSuccess()) if (!cmakeVersionQueryResult.IsSuccess())
{ {
return AZ::Failure(QObject::tr("CMake not found. \n\n" return AZ::Failure(QObject::tr("CMake not found. \n\n"
@@ -104,7 +112,7 @@ namespace O3DE::ProjectManager
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath) AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath)
{ {
AZ::Outcome processEnvResult = GetCommandLineProcessEnvironment(); AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
if (!processEnvResult.IsSuccess()) if (!processEnvResult.IsSuccess())
{ {
return AZ::Failure(processEnvResult.GetError()); return AZ::Failure(processEnvResult.GetError());
@@ -118,7 +126,6 @@ namespace O3DE::ProjectManager
} }
QProcess process; QProcess process;
process.setProcessEnvironment(processEnvResult.GetValue());
// if the project build path is relative, it should be relative to the project path // if the project build path is relative, it should be relative to the project path
process.setWorkingDirectory(projectPath); process.setWorkingDirectory(projectPath);
@@ -139,7 +146,6 @@ namespace O3DE::ProjectManager
return ExecuteCommandResultModalDialog( return ExecuteCommandResultModalDialog(
"cmd.exe", "cmd.exe",
QStringList{"/c", batPath}, QStringList{"/c", batPath},
QProcessEnvironment::systemEnvironment(),
QObject::tr("Running get_python script...")); QObject::tr("Running get_python script..."));
} }
@@ -157,7 +163,7 @@ namespace O3DE::ProjectManager
.arg(shortcutPath) .arg(shortcutPath)
.arg(targetPath) .arg(targetPath)
.arg(arguments.join(' ')); .arg(arguments.join(' '));
auto createShortcutResult = ExecuteCommandResult(cmd, QStringList{"-Command", arg}, QProcessEnvironment::systemEnvironment()); auto createShortcutResult = ExecuteCommandResult(cmd, QStringList{"-Command", arg});
if (!createShortcutResult.IsSuccess()) if (!createShortcutResult.IsSuccess())
{ {
return AZ::Failure(QObject::tr("Failed to create desktop shortcut %1 <br><br>" return AZ::Failure(QObject::tr("Failed to create desktop shortcut %1 <br><br>"
@@ -117,18 +117,16 @@ namespace O3DE::ProjectManager
// Show some kind of progress with very approximate estimates // Show some kind of progress with very approximate estimates
UpdateProgress(++m_progressEstimate); UpdateProgress(++m_progressEstimate);
auto currentEnvironmentRequest = ProjectUtils::GetCommandLineProcessEnvironment(); auto currentEnvironmentRequest = ProjectUtils::SetupCommandLineProcessEnvironment();
if (!currentEnvironmentRequest.IsSuccess()) if (!currentEnvironmentRequest.IsSuccess())
{ {
QStringToAZTracePrint(currentEnvironmentRequest.GetError()); QStringToAZTracePrint(currentEnvironmentRequest.GetError());
return AZ::Failure(currentEnvironmentRequest.GetError()); return AZ::Failure(currentEnvironmentRequest.GetError());
} }
QProcessEnvironment currentEnvironment = currentEnvironmentRequest.GetValue();
m_configProjectProcess = new QProcess(this); m_configProjectProcess = new QProcess(this);
m_configProjectProcess->setProcessChannelMode(QProcess::MergedChannels); m_configProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
m_configProjectProcess->setWorkingDirectory(m_projectInfo.m_path); m_configProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
m_configProjectProcess->setProcessEnvironment(currentEnvironment);
auto cmakeGenerateArgumentsResult = ConstructCmakeGenerateProjectArguments(engineInfo.m_thirdPartyPath); auto cmakeGenerateArgumentsResult = ConstructCmakeGenerateProjectArguments(engineInfo.m_thirdPartyPath);
if (!cmakeGenerateArgumentsResult.IsSuccess()) if (!cmakeGenerateArgumentsResult.IsSuccess())
@@ -181,7 +179,6 @@ namespace O3DE::ProjectManager
m_buildProjectProcess = new QProcess(this); m_buildProjectProcess = new QProcess(this);
m_buildProjectProcess->setProcessChannelMode(QProcess::MergedChannels); m_buildProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
m_buildProjectProcess->setWorkingDirectory(m_projectInfo.m_path); m_buildProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
m_buildProjectProcess->setProcessEnvironment(currentEnvironment);
auto cmakeBuildArgumentsResult = ConstructCmakeBuildCommandArguments(); auto cmakeBuildArgumentsResult = ConstructCmakeBuildCommandArguments();
if (!cmakeBuildArgumentsResult.IsSuccess()) if (!cmakeBuildArgumentsResult.IsSuccess())
@@ -520,12 +520,10 @@ namespace O3DE::ProjectManager
AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog( AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog(
const QString& cmd, const QString& cmd,
const QStringList& arguments, const QStringList& arguments,
const QProcessEnvironment& processEnv,
const QString& title) const QString& title)
{ {
QString resultOutput; QString resultOutput;
QProcess execProcess; QProcess execProcess;
execProcess.setProcessEnvironment(processEnv);
execProcess.setProcessChannelMode(QProcess::MergedChannels); execProcess.setProcessChannelMode(QProcess::MergedChannels);
QProgressDialog dialog(title, QObject::tr("Cancel"), /*minimum=*/0, /*maximum=*/0); QProgressDialog dialog(title, QObject::tr("Cancel"), /*minimum=*/0, /*maximum=*/0);
@@ -611,11 +609,9 @@ namespace O3DE::ProjectManager
AZ::Outcome<QString, QString> ExecuteCommandResult( AZ::Outcome<QString, QString> ExecuteCommandResult(
const QString& cmd, const QString& cmd,
const QStringList& arguments, const QStringList& arguments,
const QProcessEnvironment& processEnv,
int commandTimeoutSeconds /*= ProjectCommandLineTimeoutSeconds*/) int commandTimeoutSeconds /*= ProjectCommandLineTimeoutSeconds*/)
{ {
QProcess execProcess; QProcess execProcess;
execProcess.setProcessEnvironment(processEnv);
execProcess.setProcessChannelMode(QProcess::MergedChannels); execProcess.setProcessChannelMode(QProcess::MergedChannels);
execProcess.start(cmd, arguments); execProcess.start(cmd, arguments);
if (!execProcess.waitForStarted()) if (!execProcess.waitForStarted())
@@ -47,7 +47,6 @@ namespace O3DE::ProjectManager
AZ::Outcome<QString, QString> ExecuteCommandResult( AZ::Outcome<QString, QString> ExecuteCommandResult(
const QString& cmd, const QString& cmd,
const QStringList& arguments, const QStringList& arguments,
const QProcessEnvironment& processEnv,
int commandTimeoutSeconds = ProjectCommandLineTimeoutSeconds); int commandTimeoutSeconds = ProjectCommandLineTimeoutSeconds);
/** /**
@@ -61,10 +60,9 @@ namespace O3DE::ProjectManager
AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog( AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog(
const QString& cmd, const QString& cmd,
const QStringList& arguments, const QStringList& arguments,
const QProcessEnvironment& processEnv,
const QString& title); const QString& title);
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment(); AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment();
AZ::Outcome<QString, QString> GetProjectBuildPath(const QString& projectPath); AZ::Outcome<QString, QString> GetProjectBuildPath(const QString& projectPath);
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath); AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath);
AZ::Outcome<QString, QString> RunGetPythonScript(const QString& enginePath); AZ::Outcome<QString, QString> RunGetPythonScript(const QString& enginePath);