1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-06-10 16:21:40 +08:00
CMake/Source/QtDialog/FirstConfigure.cxx
Robert Maynard 9d13674337
cmake-gui: Hint that the preset compilers will be used
Instead of stating that the default is the native compilers,
say we will use the compilers from the preset. This makes it
more clear that the preset is working as expected.
2024-01-05 12:04:12 -05:00

752 lines
21 KiB
C++

#include "FirstConfigure.h"
#include "QCMakeSizeType.h"
#include <QComboBox>
#include <QRadioButton>
#include <QSettings>
#include <QVBoxLayout>
#include "cmStringAlgorithms.h"
#include "Compilers.h"
StartCompilerSetup::StartCompilerSetup(QString defaultGeneratorPlatform,
QString defaultGeneratorToolset,
QWidget* p)
: QWizardPage(p)
, DefaultGeneratorPlatform(std::move(defaultGeneratorPlatform))
, DefaultGeneratorToolset(std::move(defaultGeneratorToolset))
{
QVBoxLayout* l = new QVBoxLayout(this);
l->addWidget(new QLabel(tr("Specify the generator for this project")));
this->GeneratorOptions = new QComboBox(this);
l->addWidget(this->GeneratorOptions);
// Add the generator platform
this->PlatformFrame = CreatePlatformWidgets();
l->addWidget(PlatformFrame);
// Add the ability to specify toolset (-T parameter)
this->ToolsetFrame = CreateToolsetWidgets();
l->addWidget(ToolsetFrame);
l->addSpacing(6);
this->CompilerSetupOptions[0] =
new QRadioButton(tr("Use default native compilers"), this);
this->CompilerSetupOptions[1] =
new QRadioButton(tr("Specify native compilers"), this);
this->CompilerSetupOptions[2] =
new QRadioButton(tr("Specify toolchain file for cross-compiling"), this);
this->CompilerSetupOptions[3] =
new QRadioButton(tr("Specify options for cross-compiling"), this);
l->addWidget(this->CompilerSetupOptions[0]);
l->addWidget(this->CompilerSetupOptions[1]);
l->addWidget(this->CompilerSetupOptions[2]);
l->addWidget(this->CompilerSetupOptions[3]);
this->CompilerSetupOptions[0]->setChecked(true);
QObject::connect(this->CompilerSetupOptions[0], &QRadioButton::toggled, this,
&StartCompilerSetup::onSelectionChanged);
QObject::connect(this->CompilerSetupOptions[1], &QRadioButton::toggled, this,
&StartCompilerSetup::onSelectionChanged);
QObject::connect(this->CompilerSetupOptions[2], &QRadioButton::toggled, this,
&StartCompilerSetup::onSelectionChanged);
QObject::connect(this->CompilerSetupOptions[3], &QRadioButton::toggled, this,
&StartCompilerSetup::onSelectionChanged);
QObject::connect(
this->GeneratorOptions,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &StartCompilerSetup::onGeneratorChanged);
}
QFrame* StartCompilerSetup::CreateToolsetWidgets()
{
QFrame* frame = new QFrame(this);
QVBoxLayout* l = new QVBoxLayout(frame);
l->setContentsMargins(0, 0, 0, 0);
ToolsetLabel = new QLabel(tr("Optional toolset to use (argument to -T)"));
l->addWidget(ToolsetLabel);
Toolset = new QLineEdit(frame);
l->addWidget(Toolset);
// Default to CMAKE_GENERATOR_TOOLSET env var if set
if (!DefaultGeneratorToolset.isEmpty()) {
this->Toolset->setText(DefaultGeneratorToolset);
}
return frame;
}
QFrame* StartCompilerSetup::CreatePlatformWidgets()
{
QFrame* frame = new QFrame(this);
QVBoxLayout* l = new QVBoxLayout(frame);
l->setContentsMargins(0, 0, 0, 0);
this->PlatformLabel = new QLabel(tr("Optional platform for generator"));
l->addWidget(this->PlatformLabel);
this->PlatformOptions = new QComboBox(frame);
this->PlatformOptions->setEditable(true);
l->addWidget(this->PlatformOptions);
return frame;
}
StartCompilerSetup::~StartCompilerSetup() = default;
void StartCompilerSetup::setGenerators(
std::vector<cmake::GeneratorInfo> const& gens)
{
this->GeneratorOptions->clear();
QStringList generator_list;
for (cmake::GeneratorInfo const& gen : gens) {
generator_list.append(QString::fromStdString(gen.name));
if (gen.supportsPlatform) {
this->GeneratorsSupportingPlatform.append(
QString::fromStdString(gen.name));
this->GeneratorDefaultPlatform[QString::fromStdString(gen.name)] =
QString::fromStdString(gen.defaultPlatform);
auto platformIt = gen.supportedPlatforms.cbegin();
while (platformIt != gen.supportedPlatforms.cend()) {
this->GeneratorSupportedPlatforms.insert(
QString::fromStdString(gen.name),
QString::fromStdString((*platformIt)));
platformIt++;
}
}
if (gen.supportsToolset) {
this->GeneratorsSupportingToolset.append(
QString::fromStdString(gen.name));
}
}
this->GeneratorOptions->addItems(generator_list);
}
void StartCompilerSetup::setCurrentGenerator(const QString& gen)
{
int idx = this->GeneratorOptions->findText(gen);
if (idx != -1) {
this->GeneratorOptions->setCurrentIndex(idx);
}
}
void StartCompilerSetup::setPlatform(const QString& platform)
{
this->PlatformOptions->setCurrentText(platform);
}
void StartCompilerSetup::setToolset(const QString& toolset)
{
this->Toolset->setText(toolset);
}
void StartCompilerSetup::setCompilerOption(CompilerOption option)
{
std::size_t index = 0;
switch (option) {
case CompilerOption::DefaultPreset:
this->CompilerSetupOptions[0]->setText(
tr("Use default preset compilers"));
CM_FALLTHROUGH;
case CompilerOption::DefaultNative:
index = 0;
break;
case CompilerOption::SpecifyNative:
index = 1;
break;
case CompilerOption::ToolchainFile:
index = 2;
break;
case CompilerOption::Options:
index = 3;
break;
}
this->CompilerSetupOptions[index]->setChecked(true);
}
QString StartCompilerSetup::getGenerator() const
{
return this->GeneratorOptions->currentText();
};
QString StartCompilerSetup::getPlatform() const
{
return this->PlatformOptions->currentText();
};
QString StartCompilerSetup::getToolset() const
{
return this->Toolset->text();
};
bool StartCompilerSetup::defaultSetup() const
{
return this->CompilerSetupOptions[0]->isChecked();
}
bool StartCompilerSetup::compilerSetup() const
{
return this->CompilerSetupOptions[1]->isChecked();
}
bool StartCompilerSetup::crossCompilerToolChainFile() const
{
return this->CompilerSetupOptions[2]->isChecked();
}
bool StartCompilerSetup::crossCompilerSetup() const
{
return this->CompilerSetupOptions[3]->isChecked();
}
void StartCompilerSetup::onSelectionChanged(bool on)
{
if (on) {
emit selectionChanged();
}
}
void StartCompilerSetup::onGeneratorChanged(int index)
{
QString name = this->GeneratorOptions->itemText(index);
// Display the generator platform for the generators supporting it
if (GeneratorsSupportingPlatform.contains(name)) {
// Change the label title to include the default platform
std::string label =
cmStrCat("Optional platform for generator(if empty, generator uses: ",
this->GeneratorDefaultPlatform[name].toStdString(), ')');
this->PlatformLabel->setText(tr(label.c_str()));
// Regenerate the list of supported platform
this->PlatformOptions->clear();
QStringList platform_list;
platform_list.append("");
QList<QString> platforms = this->GeneratorSupportedPlatforms.values(name);
platform_list.append(platforms);
this->PlatformOptions->addItems(platform_list);
PlatformFrame->show();
// Default to generator platform from environment
if (!DefaultGeneratorPlatform.isEmpty()) {
cm_qsizetype platform_index =
platforms.indexOf(DefaultGeneratorPlatform);
if (platform_index != -1) {
// The index is off-by-one due to the first empty item added above.
this->PlatformOptions->setCurrentIndex(
static_cast<int>(platform_index + 1));
}
}
} else {
PlatformFrame->hide();
}
// Display the toolset box for the generators supporting it
if (GeneratorsSupportingToolset.contains(name)) {
ToolsetFrame->show();
} else {
ToolsetFrame->hide();
}
}
int StartCompilerSetup::nextId() const
{
if (compilerSetup()) {
return NativeSetup;
}
if (crossCompilerSetup()) {
return CrossSetup;
}
if (crossCompilerToolChainFile()) {
return ToolchainSetup;
}
return -1;
}
NativeCompilerSetup::NativeCompilerSetup(QWidget* p)
: QWizardPage(p)
{
QVBoxLayout* l = new QVBoxLayout(this);
QWidget* c = new QWidget(this);
l->addWidget(c);
this->setupUi(c);
}
NativeCompilerSetup::~NativeCompilerSetup() = default;
QString NativeCompilerSetup::getCCompiler() const
{
return this->CCompiler->text();
}
void NativeCompilerSetup::setCCompiler(const QString& s)
{
this->CCompiler->setText(s);
}
QString NativeCompilerSetup::getCXXCompiler() const
{
return this->CXXCompiler->text();
}
void NativeCompilerSetup::setCXXCompiler(const QString& s)
{
this->CXXCompiler->setText(s);
}
QString NativeCompilerSetup::getFortranCompiler() const
{
return this->FortranCompiler->text();
}
void NativeCompilerSetup::setFortranCompiler(const QString& s)
{
this->FortranCompiler->setText(s);
}
CrossCompilerSetup::CrossCompilerSetup(QWidget* p)
: QWizardPage(p)
{
this->setupUi(this);
QWidget::setTabOrder(systemName, systemVersion);
QWidget::setTabOrder(systemVersion, systemProcessor);
QWidget::setTabOrder(systemProcessor, CrossCompilers->CCompiler);
QWidget::setTabOrder(CrossCompilers->CCompiler, CrossCompilers->CXXCompiler);
QWidget::setTabOrder(CrossCompilers->CXXCompiler,
CrossCompilers->FortranCompiler);
QWidget::setTabOrder(CrossCompilers->FortranCompiler, crossFindRoot);
QWidget::setTabOrder(crossFindRoot, crossProgramMode);
QWidget::setTabOrder(crossProgramMode, crossLibraryMode);
QWidget::setTabOrder(crossLibraryMode, crossIncludeMode);
// fill in combo boxes
QStringList modes;
modes << tr("Search in Target Root, then native system");
modes << tr("Search only in Target Root");
modes << tr("Search only in native system");
crossProgramMode->addItems(modes);
crossLibraryMode->addItems(modes);
crossIncludeMode->addItems(modes);
crossProgramMode->setCurrentIndex(2);
crossLibraryMode->setCurrentIndex(1);
crossIncludeMode->setCurrentIndex(1);
this->registerField("systemName*", this->systemName);
}
CrossCompilerSetup::~CrossCompilerSetup() = default;
QString CrossCompilerSetup::getCCompiler() const
{
return this->CrossCompilers->CCompiler->text();
}
void CrossCompilerSetup::setCCompiler(const QString& s)
{
this->CrossCompilers->CCompiler->setText(s);
}
QString CrossCompilerSetup::getCXXCompiler() const
{
return this->CrossCompilers->CXXCompiler->text();
}
void CrossCompilerSetup::setCXXCompiler(const QString& s)
{
this->CrossCompilers->CXXCompiler->setText(s);
}
QString CrossCompilerSetup::getFortranCompiler() const
{
return this->CrossCompilers->FortranCompiler->text();
}
void CrossCompilerSetup::setFortranCompiler(const QString& s)
{
this->CrossCompilers->FortranCompiler->setText(s);
}
QString CrossCompilerSetup::getSystem() const
{
return this->systemName->text();
}
void CrossCompilerSetup::setSystem(const QString& t)
{
this->systemName->setText(t);
}
QString CrossCompilerSetup::getVersion() const
{
return this->systemVersion->text();
}
void CrossCompilerSetup::setVersion(const QString& t)
{
this->systemVersion->setText(t);
}
QString CrossCompilerSetup::getProcessor() const
{
return this->systemProcessor->text();
}
void CrossCompilerSetup::setProcessor(const QString& t)
{
this->systemProcessor->setText(t);
}
QString CrossCompilerSetup::getFindRoot() const
{
return this->crossFindRoot->text();
}
void CrossCompilerSetup::setFindRoot(const QString& t)
{
this->crossFindRoot->setText(t);
}
int CrossCompilerSetup::getProgramMode() const
{
return this->crossProgramMode->currentIndex();
}
int CrossCompilerSetup::getLibraryMode() const
{
return this->crossLibraryMode->currentIndex();
}
int CrossCompilerSetup::getIncludeMode() const
{
return this->crossIncludeMode->currentIndex();
}
void CrossCompilerSetup::setProgramMode(int m)
{
this->crossProgramMode->setCurrentIndex(m);
}
void CrossCompilerSetup::setLibraryMode(int m)
{
this->crossLibraryMode->setCurrentIndex(m);
}
void CrossCompilerSetup::setIncludeMode(int m)
{
this->crossIncludeMode->setCurrentIndex(m);
}
ToolchainCompilerSetup::ToolchainCompilerSetup(QWidget* p)
: QWizardPage(p)
{
QVBoxLayout* l = new QVBoxLayout(this);
l->addWidget(new QLabel(tr("Specify the Toolchain file")));
this->ToolchainFile = new QCMakeFilePathEditor(this);
l->addWidget(this->ToolchainFile);
}
ToolchainCompilerSetup::~ToolchainCompilerSetup() = default;
QString ToolchainCompilerSetup::toolchainFile() const
{
return this->ToolchainFile->text();
}
void ToolchainCompilerSetup::setToolchainFile(const QString& t)
{
this->ToolchainFile->setText(t);
}
FirstConfigure::FirstConfigure()
{
const char* env_generator = std::getenv("CMAKE_GENERATOR");
const char* env_generator_platform = nullptr;
const char* env_generator_toolset = nullptr;
if (env_generator && std::strlen(env_generator)) {
mDefaultGenerator = env_generator;
env_generator_platform = std::getenv("CMAKE_GENERATOR_PLATFORM");
env_generator_toolset = std::getenv("CMAKE_GENERATOR_TOOLSET");
}
if (!env_generator_platform) {
env_generator_platform = "";
}
if (!env_generator_toolset) {
env_generator_toolset = "";
}
// this->setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
this->mStartCompilerSetupPage = new StartCompilerSetup(
env_generator_platform, env_generator_toolset, this);
this->setPage(Start, this->mStartCompilerSetupPage);
QObject::connect(this->mStartCompilerSetupPage,
&StartCompilerSetup::selectionChanged, this,
&FirstConfigure::restart);
this->mNativeCompilerSetupPage = new NativeCompilerSetup(this);
this->setPage(NativeSetup, this->mNativeCompilerSetupPage);
this->mCrossCompilerSetupPage = new CrossCompilerSetup(this);
this->setPage(CrossSetup, this->mCrossCompilerSetupPage);
this->mToolchainCompilerSetupPage = new ToolchainCompilerSetup(this);
this->setPage(ToolchainSetup, this->mToolchainCompilerSetupPage);
}
FirstConfigure::~FirstConfigure() = default;
void FirstConfigure::setGenerators(
std::vector<cmake::GeneratorInfo> const& gens)
{
this->mStartCompilerSetupPage->setGenerators(gens);
}
void FirstConfigure::setCurrentGenerator(const QString& gen)
{
this->mStartCompilerSetupPage->setCurrentGenerator(gen);
}
void FirstConfigure::setPlatform(const QString& platform)
{
this->mStartCompilerSetupPage->setPlatform(platform);
}
void FirstConfigure::setToolset(const QString& toolset)
{
this->mStartCompilerSetupPage->setToolset(toolset);
}
void FirstConfigure::setCompilerOption(CompilerOption option)
{
this->mStartCompilerSetupPage->setCompilerOption(option);
}
QString FirstConfigure::getGenerator() const
{
return this->mStartCompilerSetupPage->getGenerator();
}
QString FirstConfigure::getPlatform() const
{
return this->mStartCompilerSetupPage->getPlatform();
}
QString FirstConfigure::getToolset() const
{
return this->mStartCompilerSetupPage->getToolset();
}
void FirstConfigure::loadFromSettings()
{
QSettings settings;
// restore generator
settings.beginGroup("Settings/StartPath");
QString lastGen = settings.value("LastGenerator").toString();
this->setCurrentGenerator(lastGen);
settings.endGroup();
// restore compiler setup
settings.beginGroup("Settings/Compiler");
this->mNativeCompilerSetupPage->setCCompiler(
settings.value("CCompiler").toString());
this->mNativeCompilerSetupPage->setCXXCompiler(
settings.value("CXXCompiler").toString());
this->mNativeCompilerSetupPage->setFortranCompiler(
settings.value("FortranCompiler").toString());
settings.endGroup();
// restore cross compiler setup
settings.beginGroup("Settings/CrossCompiler");
this->mCrossCompilerSetupPage->setCCompiler(
settings.value("CCompiler").toString());
this->mCrossCompilerSetupPage->setCXXCompiler(
settings.value("CXXCompiler").toString());
this->mCrossCompilerSetupPage->setFortranCompiler(
settings.value("FortranCompiler").toString());
this->mToolchainCompilerSetupPage->setToolchainFile(
settings.value("ToolChainFile").toString());
this->mCrossCompilerSetupPage->setSystem(
settings.value("SystemName").toString());
this->mCrossCompilerSetupPage->setVersion(
settings.value("SystemVersion").toString());
this->mCrossCompilerSetupPage->setProcessor(
settings.value("SystemProcessor").toString());
this->mCrossCompilerSetupPage->setFindRoot(
settings.value("FindRoot").toString());
this->mCrossCompilerSetupPage->setProgramMode(
settings.value("ProgramMode", 0).toInt());
this->mCrossCompilerSetupPage->setLibraryMode(
settings.value("LibraryMode", 0).toInt());
this->mCrossCompilerSetupPage->setIncludeMode(
settings.value("IncludeMode", 0).toInt());
settings.endGroup();
// environment variables take precedence over application settings because...
// - they're harder to set
// - settings always exist after the program is run once, so the environment
// variables would never be used otherwise
// - platform and toolset are populated only from environment variables, so
// this prevents them from being taken from environment, while the
// generator is taken from application settings
if (!mDefaultGenerator.isEmpty()) {
this->setCurrentGenerator(mDefaultGenerator);
}
}
void FirstConfigure::saveToSettings()
{
QSettings settings;
// save generator
settings.beginGroup("Settings/StartPath");
QString lastGen = this->mStartCompilerSetupPage->getGenerator();
settings.setValue("LastGenerator", lastGen);
settings.endGroup();
// save compiler setup
settings.beginGroup("Settings/Compiler");
settings.setValue("CCompiler",
this->mNativeCompilerSetupPage->getCCompiler());
settings.setValue("CXXCompiler",
this->mNativeCompilerSetupPage->getCXXCompiler());
settings.setValue("FortranCompiler",
this->mNativeCompilerSetupPage->getFortranCompiler());
settings.endGroup();
// save cross compiler setup
settings.beginGroup("Settings/CrossCompiler");
settings.setValue("CCompiler",
this->mCrossCompilerSetupPage->getCCompiler());
settings.setValue("CXXCompiler",
this->mCrossCompilerSetupPage->getCXXCompiler());
settings.setValue("FortranCompiler",
this->mCrossCompilerSetupPage->getFortranCompiler());
settings.setValue("ToolChainFile", this->getCrossCompilerToolChainFile());
settings.setValue("SystemName", this->mCrossCompilerSetupPage->getSystem());
settings.setValue("SystemVersion",
this->mCrossCompilerSetupPage->getVersion());
settings.setValue("SystemProcessor",
this->mCrossCompilerSetupPage->getProcessor());
settings.setValue("FindRoot", this->mCrossCompilerSetupPage->getFindRoot());
settings.setValue("ProgramMode",
this->mCrossCompilerSetupPage->getProgramMode());
settings.setValue("LibraryMode",
this->mCrossCompilerSetupPage->getLibraryMode());
settings.setValue("IncludeMode",
this->mCrossCompilerSetupPage->getIncludeMode());
settings.endGroup();
}
bool FirstConfigure::defaultSetup() const
{
return this->mStartCompilerSetupPage->defaultSetup();
}
bool FirstConfigure::compilerSetup() const
{
return this->mStartCompilerSetupPage->compilerSetup();
}
bool FirstConfigure::crossCompilerSetup() const
{
return this->mStartCompilerSetupPage->crossCompilerSetup();
}
bool FirstConfigure::crossCompilerToolChainFile() const
{
return this->mStartCompilerSetupPage->crossCompilerToolChainFile();
}
QString FirstConfigure::getCrossCompilerToolChainFile() const
{
return this->mToolchainCompilerSetupPage->toolchainFile();
}
QString FirstConfigure::getSystemName() const
{
return this->mCrossCompilerSetupPage->getSystem();
}
QString FirstConfigure::getCCompiler() const
{
if (this->compilerSetup()) {
return this->mNativeCompilerSetupPage->getCCompiler();
}
if (this->crossCompilerSetup()) {
return this->mCrossCompilerSetupPage->getCCompiler();
}
return QString();
}
QString FirstConfigure::getCXXCompiler() const
{
if (this->compilerSetup()) {
return this->mNativeCompilerSetupPage->getCXXCompiler();
}
if (this->crossCompilerSetup()) {
return this->mCrossCompilerSetupPage->getCXXCompiler();
}
return QString();
}
QString FirstConfigure::getFortranCompiler() const
{
if (this->compilerSetup()) {
return this->mNativeCompilerSetupPage->getFortranCompiler();
}
if (this->crossCompilerSetup()) {
return this->mCrossCompilerSetupPage->getFortranCompiler();
}
return QString();
}
QString FirstConfigure::getSystemVersion() const
{
return this->mCrossCompilerSetupPage->getVersion();
}
QString FirstConfigure::getSystemProcessor() const
{
return this->mCrossCompilerSetupPage->getProcessor();
}
QString FirstConfigure::getCrossRoot() const
{
return this->mCrossCompilerSetupPage->getFindRoot();
}
const QString CrossModes[] = { "BOTH", "ONLY", "NEVER" };
QString FirstConfigure::getCrossProgramMode() const
{
return CrossModes[this->mCrossCompilerSetupPage->getProgramMode()];
}
QString FirstConfigure::getCrossLibraryMode() const
{
return CrossModes[this->mCrossCompilerSetupPage->getLibraryMode()];
}
QString FirstConfigure::getCrossIncludeMode() const
{
return CrossModes[this->mCrossCompilerSetupPage->getIncludeMode()];
}