From cea9b757abd0ad87a8c834706eb7f5b5621e384e Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Tue, 20 Apr 2021 22:24:33 +0800 Subject: [PATCH] * can compile now --- RedPandaIDE/RedPandaIDE.pro | 6 + RedPandaIDE/compiler/compiler.cpp | 202 ++++++++++++++++++ RedPandaIDE/compiler/compiler.h | 55 +++++ RedPandaIDE/compiler/compilermanager.cpp | 44 ++++ RedPandaIDE/compiler/compilermanager.h | 27 +++ RedPandaIDE/compiler/filecompiler.cpp | 73 +++++++ RedPandaIDE/compiler/filecompiler.h | 22 ++ RedPandaIDE/editor.cpp | 2 +- RedPandaIDE/main.cpp | 8 +- RedPandaIDE/mainwindow.cpp | 24 ++- RedPandaIDE/mainwindow.h | 11 + RedPandaIDE/mainwindow.ui | 80 ++++++- RedPandaIDE/settings.cpp | 121 +++++------ RedPandaIDE/settings.h | 3 - .../compilersetdirectorieswidget.cpp | 2 +- .../compilersetoptionwidget.cpp | 18 +- .../settingsdialog/compilersetoptionwidget.ui | 7 - RedPandaIDE/systemconsts.h | 12 +- RedPandaIDE/utils.cpp | 86 +++++++- RedPandaIDE/utils.h | 13 +- 20 files changed, 707 insertions(+), 109 deletions(-) create mode 100644 RedPandaIDE/compiler/compiler.cpp create mode 100644 RedPandaIDE/compiler/compiler.h create mode 100644 RedPandaIDE/compiler/compilermanager.cpp create mode 100644 RedPandaIDE/compiler/compilermanager.h create mode 100644 RedPandaIDE/compiler/filecompiler.cpp create mode 100644 RedPandaIDE/compiler/filecompiler.h diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index bf2c86ae..43ad7686 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -9,6 +9,9 @@ CONFIG += c++14 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ + compiler/compiler.cpp \ + compiler/compilermanager.cpp \ + compiler/filecompiler.cpp \ editor.cpp \ editorlist.cpp \ main.cpp \ @@ -22,6 +25,9 @@ SOURCES += \ utils.cpp HEADERS += \ + compiler/compiler.h \ + compiler/compilermanager.h \ + compiler/filecompiler.h \ editor.h \ editorlist.h \ mainwindow.h \ diff --git a/RedPandaIDE/compiler/compiler.cpp b/RedPandaIDE/compiler/compiler.cpp new file mode 100644 index 00000000..9ebb9eb8 --- /dev/null +++ b/RedPandaIDE/compiler/compiler.cpp @@ -0,0 +1,202 @@ +#include "compiler.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include + +Compiler::Compiler(bool silent,bool onlyCheckSyntax): + QThread(), + mSilent(silent), + mOnlyCheckSyntax(onlyCheckSyntax) +{ + +} + +void Compiler::run() +{ + emit compileStarted(); + if (prepareForCompile()){ + QElapsedTimer timer; + timer.start(); + runCommand(mCompiler, mArguments, QFileInfo(mCompiler).absolutePath()); + + log(""); + log(tr("Compile Result:")); + log("------------------"); + log(tr("- Errors: %1").arg(0)); + log(tr("- Warnings: %1").arg(0)); + log(tr("- Time Elasped: %1 secs").arg(timer.elapsed() / 1000.0)); + } + this->deleteLater(); + emit compileFinished(); +} + +void Compiler::stopCompile() +{ + mStop = true; +} + +QString Compiler::getCharsetArgument(const QByteArray& encoding) +{ + QString result; + if (compilerSet()->autoAddCharsetParams() && encoding != ENCODING_ASCII) { + QString encodingName; + QString systemEncodingName=QTextCodec::codecForLocale()->name(); + if (encoding == ENCODING_SYSTEM_DEFAULT) { + encodingName = systemEncodingName; + } else if (encoding == ENCODING_UTF8_BOM) { + encodingName = "UTF-8"; + } else { + encodingName = encoding; + } + result += QString(" -finput-charset=%1 -fexec-charset=%2") + .arg(encodingName) + .arg(systemEncodingName); + } + return result; +} + +QString Compiler::getCCompileArguments(bool checkSyntax) +{ + QString result; + if (checkSyntax) { + result += " -fsyntax-only"; + } + + for (PCompilerOption pOption: compilerSet()->options()) { + if (pOption->value > 0 && pOption->isC) { + if (pOption->choices.isEmpty()) { + result += " " + pOption->setting; + } else if (pOption->value < pOption->choices.size()) { + QStringList nameValue=pOption->choices[pOption->value].split('='); + if (nameValue.count()==2) { + result += " " + pOption->setting + nameValue[1]; + } + } + } + } + + if (compilerSet()->useCustomCompileParams() && !compilerSet()->customCompileParams().isEmpty()) { + result += " "+compilerSet()->customCompileParams(); + } + return result; +} + +QString Compiler::getCppCompileArguments(bool checkSyntax) +{ + QString result; + if (checkSyntax) { + result += " -fsyntax-only"; + } + + for (PCompilerOption pOption: compilerSet()->options()) { + if (pOption->value > 0 && pOption->isCpp) { + if (pOption->choices.isEmpty()) { + result += " "+pOption->setting; + } else if (pOption->value < pOption->choices.size()) { + QStringList nameValue=pOption->choices[pOption->value].split('='); + if (nameValue.count()==2) { + result += " "+pOption->setting + nameValue[1]; + } + } + } + } + + if (compilerSet()->useCustomCompileParams() && !compilerSet()->customCompileParams().isEmpty()) { + result += " "+compilerSet()->customCompileParams(); + } + return result; +} + + +QString Compiler::getCIncludeArguments() +{ + QString result; + for (const QString& folder:compilerSet()->CIncludeDirs()) { + result += QString(" -I\"%1\"").arg(folder); + } + return result; +} + +QString Compiler::getCppIncludeArguments() +{ + QString result; + for (const QString& folder:compilerSet()->CppIncludeDirs()) { + result += QString(" -I\"%1\"").arg(folder); + } + return result; +} + +QString Compiler::getLibraryArguments() +{ + QString result; + + for (const QString& folder:compilerSet()->libDirs()) { + result += QString(" -L\"%1\"").arg(folder); + } + + // Add global compiler linker extras + if (compilerSet()->useCustomLinkParams() && !compilerSet()->customLinkParams().isEmpty()) { + result += " "+compilerSet()->customCompileParams(); + } + + //options like "-static" must be added after "-lxxx" + for (PCompilerOption pOption: compilerSet()->options()) { + if (pOption->value > 0 && pOption->isLinker) { + if (pOption->choices.isEmpty()) { + result += " " + pOption->setting; + } else if (pOption->value < pOption->choices.size()) { + QStringList nameValue=pOption->choices[pOption->value].split('='); + if (nameValue.count()==2) { + result += " " + pOption->setting + nameValue[1]; + } + } + } + } + return result; +} + +void Compiler::runCommand(const QString &cmd, const QString &arguments, const QString &workingDir, const QString& inputText) +{ + QProcess process; + mStop = false; + process.setProgram(cmd); + process.setArguments(QProcess::splitCommand(arguments)); + process.setWorkingDirectory(workingDir); + + process.connect(&process, &QProcess::readyReadStandardError,[&process,this](){ + this->log(process.readAllStandardError()); + }); + process.connect(&process, &QProcess::readyReadStandardOutput,[&process,this](){ + this->log(process.readAllStandardOutput()); + }); + process.start(); + if (!inputText.isEmpty()) + process.write(inputText.toUtf8()); + process.closeWriteChannel(); + while (true) { + process.waitForFinished(1000); + if (process.state()!=QProcess::Running) { + break; + } + if (mStop) { + process.kill(); + break; + } + } +} + +void Compiler::log(const QString &msg) +{ + emit compileOutput(msg); +} + +void Compiler::error(const QString &msg) +{ + emit compileError(msg); +} + diff --git a/RedPandaIDE/compiler/compiler.h b/RedPandaIDE/compiler/compiler.h new file mode 100644 index 00000000..c2fd33cf --- /dev/null +++ b/RedPandaIDE/compiler/compiler.h @@ -0,0 +1,55 @@ +#ifndef COMPILER_H +#define COMPILER_H + +#include +#include "settings.h" + +class Compiler : public QThread +{ + Q_OBJECT +public: + enum class TargetType { + Invalid, + cttNone, + File, + Project, + StdIn + }; + Compiler(bool silent,bool onlyCheckSyntax); + +signals: + void compileStarted(); + void compileFinished(); + void compileOutput(const QString& msg); + void compileError(const QString& errorMsg); +public slots: + void stopCompile(); + +protected: + void run() override; + +protected: + virtual Settings::PCompilerSet compilerSet() = 0; + virtual bool prepareForCompile() = 0; + virtual QString getCharsetArgument(const QByteArray& encoding); + virtual QString getCCompileArguments(bool checkSyntax); + virtual QString getCppCompileArguments(bool checkSyntax); + virtual QString getCIncludeArguments(); + virtual QString getCppIncludeArguments(); + virtual QString getLibraryArguments(); + void log(const QString& msg); + void error(const QString& msg); + void runCommand(const QString& cmd, const QString& arguments, const QString& workingDir, const QString& inputText=QString()); + +protected: + bool mSilent; + bool mOnlyCheckSyntax; + QString mCompiler; + QString mArguments; + +private: + bool mStop; + +}; + +#endif // COMPILER_H diff --git a/RedPandaIDE/compiler/compilermanager.cpp b/RedPandaIDE/compiler/compilermanager.cpp new file mode 100644 index 00000000..d09c1998 --- /dev/null +++ b/RedPandaIDE/compiler/compilermanager.cpp @@ -0,0 +1,44 @@ +#include "compilermanager.h" +#include "filecompiler.h" +#include +#include "../mainwindow.h" + +CompilerManager::CompilerManager(QObject *parent) : QObject(parent) +{ + mCompiler = nullptr; + mBackgroundSyntaxChecker = nullptr; +} + +bool CompilerManager::compiling() +{ + return mCompiler!=nullptr; +} + +bool CompilerManager::backgroundSyntaxChecking() +{ + return mBackgroundSyntaxChecker!=nullptr; +} + +void CompilerManager::compile(const QString& filename, const QByteArray& encoding, bool silent, bool onlyCheckSyntax) +{ + { + QMutexLocker locker(&compileMutex); + if (mCompiler!=nullptr) { + return; + } + mCompiler = new FileCompiler(filename,encoding,silent,onlyCheckSyntax); + connect(mCompiler, &Compiler::compileFinished, this ,&CompilerManager::onCompileFinished); + connect(mCompiler, &Compiler::compileOutput, pMainWindow, &MainWindow::onCompileLog); + connect(mCompiler, &Compiler::compileError, pMainWindow, &MainWindow::onCompileError); + mCompiler->start(); + } +} + +void CompilerManager::onCompileFinished() +{ + QMutexLocker locker(&compileMutex); + qDebug() << " Compile Finished"; + + mCompiler=nullptr; +} + diff --git a/RedPandaIDE/compiler/compilermanager.h b/RedPandaIDE/compiler/compilermanager.h new file mode 100644 index 00000000..b0bd7301 --- /dev/null +++ b/RedPandaIDE/compiler/compilermanager.h @@ -0,0 +1,27 @@ +#ifndef COMPILERMANAGER_H +#define COMPILERMANAGER_H + +#include +#include "compiler.h" +#include + +class CompilerManager : public QObject +{ + Q_OBJECT +public: + explicit CompilerManager(QObject *parent = nullptr); + + bool compiling(); + bool backgroundSyntaxChecking(); + + void compile(const QString& filename, const QByteArray& encoding, bool silent=false,bool onlyCheckSyntax=false); +private slots: + void onCompileFinished(); +private: + Compiler* mCompiler; + Compiler* mBackgroundSyntaxChecker; + QMutex compileMutex; + QMutex backgroundSyntaxChekMutex; +}; + +#endif // COMPILERMANAGER_H diff --git a/RedPandaIDE/compiler/filecompiler.cpp b/RedPandaIDE/compiler/filecompiler.cpp new file mode 100644 index 00000000..4f27b1b0 --- /dev/null +++ b/RedPandaIDE/compiler/filecompiler.cpp @@ -0,0 +1,73 @@ +#include "filecompiler.h" +#include "utils.h" +#include "../mainwindow.h" + +#include +#include +#include + + +FileCompiler::FileCompiler(const QString &filename, const QByteArray &encoding,bool silent,bool onlyCheckSyntax): + Compiler(silent,onlyCheckSyntax), + mFileName(filename), + mEncoding(encoding) +{ + +} + +Settings::PCompilerSet FileCompiler::compilerSet() +{ + return pSettings->compilerSets().defaultSet(); +} + +bool FileCompiler::prepareForCompile() +{ + log(tr("Compiling single file...")); + log("------------------"); + log(tr("- Filename: %1").arg(mFileName)); + log(tr("- Compiler Set Name: %1").arg(compilerSet()->name())); + log(""); + FileType fileType = getFileType(mFileName); + mArguments= QString(" \"%1\"").arg(mFileName); + if (!mOnlyCheckSyntax) { + QString outputFilename = getCompiledExecutableName(mFileName); + mArguments+=QString(" -o \"%1\"").arg(outputFilename); + + //remove the old file it exists + QFile outputFile(outputFilename); + if (outputFile.exists()) { + if (!outputFile.remove()) { + error(tr("Can't delete the old executable file \"%1\".\n").arg(outputFilename)); + return false; + } + } + } + + mArguments += getCharsetArgument(mEncoding); + QString strFileType; + switch(fileType) { + case FileType::CSource: + mArguments += getCCompileArguments(mOnlyCheckSyntax); + mArguments += getCIncludeArguments(); + strFileType = "C"; + mCompiler = compilerSet()->CCompiler(); + break; + case FileType::CppSource: + mArguments += getCCompileArguments(mOnlyCheckSyntax); + mArguments += getCIncludeArguments(); + strFileType = "C++"; + mCompiler = compilerSet()->cppCompiler(); + break; + default: + error(tr("Can't the compiler for file %1").arg(mFileName)); + return false; + } + mArguments += getLibraryArguments(); + + + log(tr("Processing %1 source file:").arg(strFileType)); + log("------------------"); + log(tr("%1 Compiler: %2").arg(strFileType).arg(mCompiler)); + log(tr("Command: %1 %2").arg(QFileInfo(mCompiler).fileName()).arg(mArguments)); + return true; +} diff --git a/RedPandaIDE/compiler/filecompiler.h b/RedPandaIDE/compiler/filecompiler.h new file mode 100644 index 00000000..30c47d77 --- /dev/null +++ b/RedPandaIDE/compiler/filecompiler.h @@ -0,0 +1,22 @@ +#ifndef FILECOMPILER_H +#define FILECOMPILER_H + +#include "compiler.h" + +class FileCompiler : public Compiler +{ + Q_OBJECT +public: + FileCompiler(const QString& filename, const QByteArray& encoding,bool silent,bool onlyCheckSyntax); + + // Compiler interface +protected: + Settings::PCompilerSet compilerSet() override; + bool prepareForCompile() override; + +private: + QString mFileName; + QByteArray mEncoding; +}; + +#endif // FILECOMPILER_H diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 56bc2ea3..f532aef1 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -289,7 +289,7 @@ void Editor::onCursorPositionChanged(int line, int index) { } void Editor::onLinesChanged() { - qDebug()<<"lala"< #include -#include +#include "settingsdialog/settingsdialog.h" +#include "compiler/compilermanager.h" +#include MainWindow* pMainWindow; @@ -38,6 +40,8 @@ MainWindow::MainWindow(QWidget *parent) connect(mCompilerSet,QOverload::of(&QComboBox::currentIndexChanged), this, &MainWindow::onCompilerSetChanged); updateCompilerSet(); + + mCompilerManager = new CompilerManager(this); } MainWindow::~MainWindow() @@ -167,3 +171,21 @@ void MainWindow::onCompilerSetChanged(int index) pSettings->compilerSets().setDefaultIndex(index); pSettings->compilerSets().saveDefaultIndex(); } + +void MainWindow::onCompileLog(const QString &msg) +{ + ui->txtCompilerOutput->appendPlainText(msg); +} + +void MainWindow::onCompileError(const QString &msg) +{ + qDebug()<getEditor(); + if (editor != NULL) { + mCompilerManager->compile(editor->filename(),editor->fileEncoding()); + } +} diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index fed75e4c..8a5a441f 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -3,6 +3,7 @@ #include + QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE @@ -10,6 +11,7 @@ QT_END_NAMESPACE class EditorList; class QLabel; class QComboBox; +class CompilerManager; class MainWindow : public QMainWindow { @@ -41,6 +43,13 @@ private slots: // qt will auto bind slots with the prefix "on_" void onCompilerSetChanged(int index); + void on_actionCompile_triggered(); + +public slots: + void onCompileLog(const QString& msg); + + void onCompileError(const QString& msg); + private: void setupActions(); @@ -52,6 +61,8 @@ private: QLabel* mFileInfoStatus; QLabel* mFileEncodingStatus; QComboBox* mCompilerSet; + CompilerManager* mCompilerManager; + // QWidget interface protected: diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index 1dc1816b..2e1ab930 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -41,7 +41,7 @@ 0 - 2 + 1 @@ -151,24 +151,49 @@ 0 - 1 + 0 QTabWidget::South - 1 + 0 - + - Tab 1 - - - - - Tab 2 + Compiler Output + + + 5 + + + 5 + + + 5 + + + 5 + + + + + false + + + QPlainTextEdit::NoWrap + + + true + + + false + + + + @@ -201,7 +226,14 @@ + + + Run + + + + @@ -231,6 +263,18 @@ false + + + toolBar + + + TopToolBarArea + + + false + + + @@ -301,6 +345,22 @@ Options + + + + :/icons/images/newlook24/013-compile.png + + + + Compile + + + Compile + + + F9 + + diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp index 82995c86..89252127 100644 --- a/RedPandaIDE/settings.cpp +++ b/RedPandaIDE/settings.cpp @@ -137,7 +137,6 @@ void Settings::Editor::setAutoIndent(bool indent) Settings::CompilerSet::CompilerSet(const QString& compilerFolder): - mStaticLink(true), mAutoAddCharsetParams(true) { if (!compilerFolder.isEmpty()) { @@ -176,7 +175,6 @@ Settings::CompilerSet::CompilerSet(const Settings::CompilerSet &set): mUseCustomLinkParams(set.mUseCustomLinkParams), mCustomCompileParams(set.mCustomCompileParams), mCustomLinkParams(set.mCustomLinkParams), - mStaticLink(set.mStaticLink), mAutoAddCharsetParams(set.mAutoAddCharsetParams) { // Executables, most are hardcoded @@ -410,16 +408,6 @@ void Settings::CompilerSet::setCustomLinkParams(const QString &value) mCustomLinkParams = value; } -bool Settings::CompilerSet::staticLink() -{ - return mStaticLink; -} - -void Settings::CompilerSet::setStaticLink(bool value) -{ - mStaticLink = value; -} - bool Settings::CompilerSet::autoAddCharsetParams() { return mAutoAddCharsetParams; @@ -526,10 +514,10 @@ void Settings::CompilerSet::setProperties(const QString &binDir) mDumpMachine = getCompilerOutput(binDir, GCC_PROGRAM, arguments); // Add the default directories - addExistingDirectory(mBinDirs, folder + QDir::separator() + "bin"); - addExistingDirectory(mLibDirs, folder + QDir::separator() + "lib"); - addExistingDirectory(mCIncludeDirs, folder + QDir::separator() + "include"); - addExistingDirectory(mCppIncludeDirs, folder + QDir::separator() + "include"); + addExistingDirectory(mBinDirs, includeTrailingPathDelimiter(folder) + "bin"); + addExistingDirectory(mLibDirs, includeTrailingPathDelimiter(folder) + "lib"); + addExistingDirectory(mCIncludeDirs, includeTrailingPathDelimiter(folder) + "include"); + addExistingDirectory(mCppIncludeDirs, includeTrailingPathDelimiter(folder) + "include"); // Find default directories arguments.clear(); @@ -644,59 +632,51 @@ void Settings::CompilerSet::setDirectories(const QString& folder) if (!mDumpMachine.isEmpty()) { //mingw-w64 bin folder addExistingDirectory(mBinDirs, - folder + QDir::separator() + "lib" - + QDir::separator() + "gcc" + mDumpMachine - + QDir::separator() + mVersion); + includeTrailingPathDelimiter(folder) + "lib/" + "gcc/" + mDumpMachine + + "/" + mVersion); // Regular include folder - addExistingDirectory(mCIncludeDirs, folder + QDir::separator() + mDumpMachine + QDir::separator() + "include"); - addExistingDirectory(mCppIncludeDirs, folder + QDir::separator()+ mDumpMachine + QDir::separator() + "include"); + addExistingDirectory(mCIncludeDirs, includeTrailingPathDelimiter(folder) + mDumpMachine + "/include"); + addExistingDirectory(mCppIncludeDirs, includeTrailingPathDelimiter(folder)+ mDumpMachine + "/include"); // Other include folder? addExistingDirectory(mCIncludeDirs, - folder + QDir::separator() + "lib" + QDir::separator() + "gcc" - + QDir::separator() + mDumpMachine + QDir::separator() - + mVersion + QDir::separator() + "include"); + includeTrailingPathDelimiter(folder) + "lib/gcc/" + + mDumpMachine + "/" + mVersion + "/include"); addExistingDirectory(mCppIncludeDirs, - folder + QDir::separator() + "lib" + QDir::separator() + "gcc" - + QDir::separator() + mDumpMachine + QDir::separator() - + mVersion + QDir::separator() + "include"); + includeTrailingPathDelimiter(folder) + "lib/gcc/" + + mDumpMachine + "/" + mVersion + "/include"); addExistingDirectory(mCIncludeDirs, - folder + QDir::separator() + "lib" - + QDir::separator() + "gcc" + QDir::separator() + mDumpMachine - + QDir::separator() + mVersion + QDir::separator() + "include-fixed"); + includeTrailingPathDelimiter(folder) + "lib/gcc/" + + mDumpMachine + "/" + mVersion + "/include-fixed"); addExistingDirectory(mCppIncludeDirs, - folder + QDir::separator() + "lib" - + QDir::separator() + "gcc" + QDir::separator() + mDumpMachine - + QDir::separator() + mVersion + QDir::separator() + "include-fixed"); + includeTrailingPathDelimiter(folder) + "lib/gcc/" + + mDumpMachine + "/" + mVersion + "/include-fixed"); // C++ only folder (mingw.org) addExistingDirectory(mCppIncludeDirs, - folder + QDir::separator() + "lib" + QDir::separator() + "gcc" - + QDir::separator() + mDumpMachine + QDir::separator() + mVersion - + QDir::separator() + "include" + QDir::separator() + "c++"); + includeTrailingPathDelimiter(folder) + "lib/gcc/" + + mDumpMachine + "/" + mVersion + "/include/c++"); addExistingDirectory(mCppIncludeDirs, - folder + QDir::separator() + "lib" + QDir::separator() + "gcc" - + QDir::separator() + mDumpMachine + QDir::separator() + mVersion - + QDir::separator() + "include" + QDir::separator() + "c++" - + QDir::separator() + mDumpMachine ); + includeTrailingPathDelimiter(folder) + "lib/gcc/" + + mDumpMachine + "/" + mVersion + "/include/c++/" + + mDumpMachine); addExistingDirectory(mCppIncludeDirs, - folder + QDir::separator() + "lib" + QDir::separator() + "gcc" - + QDir::separator() + mDumpMachine + QDir::separator() + mVersion - + QDir::separator() + "include" + QDir::separator() + "c++" - + QDir::separator() + "backward"); + includeTrailingPathDelimiter(folder) + "lib/gcc/" + + mDumpMachine + "/" + mVersion + "/include/c++/backward"); // C++ only folder (Mingw-w64) addExistingDirectory(mCppIncludeDirs, - folder + QDir::separator() + "include" + QDir::separator() + "c++" - + QDir::separator() + mVersion ); + includeTrailingPathDelimiter(folder) + "include/c++/" + + mVersion ); addExistingDirectory(mCppIncludeDirs, - folder + QDir::separator() + "include" + QDir::separator() + "c++" - + QDir::separator() + mVersion + QDir::separator() + mDumpMachine ); + includeTrailingPathDelimiter(folder) + "include/c++/" + + mVersion + "/backward"); addExistingDirectory(mCppIncludeDirs, - folder + QDir::separator() + "include" + QDir::separator() + "c++" - + QDir::separator() + mVersion + QDir::separator() + "backward"); + includeTrailingPathDelimiter(folder) + "include/c++/" + + mVersion + "/" + mDumpMachine); } } @@ -704,7 +684,6 @@ void Settings::CompilerSet::setUserInput() { mUseCustomCompileParams = false; mUseCustomLinkParams = false; - mStaticLink = true; mAutoAddCharsetParams = true; } @@ -813,6 +792,8 @@ void Settings::CompilerSet::setOptions() sl.append("GNU C++17=gnu++17"); sl.append("GNU C++20=gnu++20"); addOption(tr("Language standard (-std)"), groupName, true, true, false, 0, "-std=", sl); + addOption(tr("Generate debugging information (-g3)"), groupName, true, true, false, 0, "-g3"); + addOption(tr("Generate profiling info for analysis (-pg)"), groupName, true, true, true, 0, "-pg"); // Warnings groupName = tr("Warnings"); @@ -824,23 +805,19 @@ void Settings::CompilerSet::setOptions() addOption(tr("Make all warnings into errors (-Werror)"), groupName, true, true, false, 0, "-Werror"); addOption(tr("Abort compilation on first error (-Wfatal-errors)"), groupName, true, true, false, 0, "-Wfatal-errors"); - // Profiling - groupName = tr("Profiling"); - addOption(tr("Generate profiling info for analysis (-pg)"), groupName, true, true, true, 0, "-pg"); - // Linker groupName = tr("Linker"); addOption(tr("Link an Objective C program (-lobjc)"), groupName, false, false, true, 0, "-lobjc"); - addOption(tr("Do not use standard system libraries (-nostdlib)"), groupName, true, true, true, 0, "-nostdlib"); - addOption(tr("Do not create a console window (-mwindows)"), groupName,true, true, true, 0, "-mwindows"); + addOption(tr("Do not use standard system libraries (-nostdlib)"), groupName, false, false, true, 0, "-nostdlib"); + addOption(tr("Do not create a console window (-mwindows)"), groupName,false, false, true, 0, "-mwindows"); addOption(tr("Strip executable (-s)"), groupName, false, false, true, 0, "-s"); - addOption(tr("Generate debugging information (-g3)"), groupName, true, true, true, 0, "-g3"); + addOption(tr("Link libraries statically (-static)"), groupName, false, false, true, 0, "-static"); // Output groupName = tr("Output"); addOption(tr("-fverbose-asm"), groupName, true, true, false, 0, "-fverbose-asm"); - addOption(tr("Do not assemble, but output assembler code (-S)"), groupName, true, true, false, 0, "-S"); addOption(tr("Use pipes instead of temporary files during compilation (-pipe)"), groupName, true, true, false, 0, "-pipe"); + addOption(tr("Do not assemble, compile and generate the assemble code (-S)"), groupName, true, true, false, 0, "-S"); } QString Settings::CompilerSet::findProgramInBinDirs(const QString name) @@ -877,7 +854,7 @@ void Settings::CompilerSet::setIniOptions(const QByteArray &value) QByteArray Settings::CompilerSet::getCompilerOutput(const QString &binDir, const QString &binFile, const QStringList &arguments) { - QByteArray result = runAndGetOutput(binDir + QDir::separator()+binFile, binDir, arguments); + QByteArray result = runAndGetOutput(includeTrailingPathDelimiter(binDir)+binFile, binDir, arguments); return result.trimmed(); } @@ -917,6 +894,11 @@ static void setReleaseOptions(Settings::PCompilerSet pSet) { if (pOption) { pSet->setOption(pOption,'1'); } + + pOption = pSet->findOption("-static"); + if (pOption) { + pSet->setOption(pOption,'1'); + } } static void setDebugOptions(Settings::PCompilerSet pSet) { @@ -932,6 +914,10 @@ static void setDebugOptions(Settings::PCompilerSet pSet) { if (pOption) { pSet->setOption(pOption,'1'); } + pOption = pSet->findOption("-static"); + if (pOption) { + pSet->setOption(pOption,'1'); + } } static void setProfileOptions(Settings::PCompilerSet pSet) { @@ -939,6 +925,11 @@ static void setProfileOptions(Settings::PCompilerSet pSet) { if (pOption) { pSet->setOption(pOption,'1'); } + + pOption = pSet->findOption("-static"); + if (pOption) { + pSet->setOption(pOption,'1'); + } } void Settings::CompilerSets::addSets(const QString &folder) @@ -1077,9 +1068,9 @@ void Settings::CompilerSets::savePath(const QString& name, const QString& path) QString s; QString prefix1 = excludeTrailingPathDelimiter(mSettings->mDirs.app()) + "/"; QString prefix2 = excludeTrailingPathDelimiter(mSettings->mDirs.app()) + QDir::separator(); - if (path.startsWith(prefix1, Qt::CaseInsensitive)) { + if (path.startsWith(prefix1, PATH_SENSITIVITY)) { s = "%AppPath%/"+ path.mid(prefix1.length()); - } else if (path.startsWith(prefix2, Qt::CaseInsensitive)) { + } else if (path.startsWith(prefix2, PATH_SENSITIVITY)) { s = "%AppPath%/"+ path.mid(prefix2.length()); } else { s= path; @@ -1093,9 +1084,9 @@ void Settings::CompilerSets::savePathList(const QString& name, const QStringList QString s; QString prefix1 = excludeTrailingPathDelimiter(mSettings->mDirs.app()) + "/"; QString prefix2 = excludeTrailingPathDelimiter(mSettings->mDirs.app()) + QDir::separator(); - if (path.startsWith(prefix1, Qt::CaseInsensitive)) { + if (path.startsWith(prefix1, PATH_SENSITIVITY)) { s = "%AppPath%/"+ path.mid(prefix1.length()); - } else if (path.startsWith(prefix2, Qt::CaseInsensitive)) { + } else if (path.startsWith(prefix2, PATH_SENSITIVITY)) { s = "%AppPath%/" + path.mid(prefix2.length()); } else { s= path; @@ -1125,7 +1116,6 @@ void Settings::CompilerSets::saveSet(int index) mSettings->mSettings.setValue("customCompileParams", pSet->customCompileParams()); mSettings->mSettings.setValue("useCustomLinkParams", pSet->useCustomLinkParams()); mSettings->mSettings.setValue("customLinkParams", pSet->customLinkParams()); - mSettings->mSettings.setValue("StaticLink", pSet->staticLink()); mSettings->mSettings.setValue("AddCharset", pSet->autoAddCharsetParams()); // Misc. properties @@ -1187,7 +1177,6 @@ Settings::PCompilerSet Settings::CompilerSets::loadSet(int index) pSet->setCustomCompileParams(mSettings->mSettings.value("customCompileParams").toString()); pSet->setUseCustomLinkParams(mSettings->mSettings.value("useCustomLinkParams").toBool()); pSet->setCustomLinkParams(mSettings->mSettings.value("customLinkParams").toString()); - pSet->setStaticLink(mSettings->mSettings.value("StaticLink").toBool()); pSet->setAutoAddCharsetParams(mSettings->mSettings.value("AddCharset").toBool()); pSet->setDumpMachine(mSettings->mSettings.value("DumpMachine").toString()); diff --git a/RedPandaIDE/settings.h b/RedPandaIDE/settings.h index c116995a..bb09e4ec 100644 --- a/RedPandaIDE/settings.h +++ b/RedPandaIDE/settings.h @@ -128,8 +128,6 @@ public: void setCustomCompileParams(const QString& value); const QString& customLinkParams(); void setCustomLinkParams(const QString& value); - bool staticLink(); - void setStaticLink(bool value); bool autoAddCharsetParams(); void setAutoAddCharsetParams(bool value); @@ -184,7 +182,6 @@ public: bool mUseCustomLinkParams; QString mCustomCompileParams; QString mCustomLinkParams; - bool mStaticLink; bool mAutoAddCharsetParams; // Options diff --git a/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.cpp b/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.cpp index 3c7268d4..c7b48cc1 100644 --- a/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.cpp +++ b/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.cpp @@ -78,7 +78,7 @@ void CompilerSetDirectoriesWidget::on_btnRemoveInvalid_pressed() for (const QString& folder : dirList() ) { QFileInfo info(folder); if (info.exists() && info.isDir() ) { - lst.append(folder); + lst.append(folder.trimmed()); } } setDirList(lst); diff --git a/RedPandaIDE/settingsdialog/compilersetoptionwidget.cpp b/RedPandaIDE/settingsdialog/compilersetoptionwidget.cpp index f42a2c8c..ebbf017c 100644 --- a/RedPandaIDE/settingsdialog/compilersetoptionwidget.cpp +++ b/RedPandaIDE/settingsdialog/compilersetoptionwidget.cpp @@ -96,7 +96,6 @@ static void loadCompilerSetSettings(Settings::PCompilerSet pSet, Ui::CompilerSet ui->chkUseCustomLinkParams->setChecked(pSet->useCustomLinkParams()); ui->txtCustomLinkParams->setPlainText(pSet->customLinkParams()); ui->txtCustomLinkParams->setEnabled(pSet->useCustomLinkParams()); - ui->chkStaticLink->setChecked(pSet->staticLink()); ui->chkAutoAddCharset->setChecked(pSet->autoAddCharsetParams()); //rest tabs in the options widget @@ -170,18 +169,17 @@ void CompilerSetOptionWidget::saveCurrentCompilerSet() Settings::PCompilerSet pSet = pSettings->compilerSets().defaultSet(); pSet->setUseCustomCompileParams(ui->chkUseCustomCompilerParams->isChecked()); - pSet->setCustomCompileParams(ui->txtCustomCompileParams->toPlainText()); + pSet->setCustomCompileParams(ui->txtCustomCompileParams->toPlainText().trimmed()); pSet->setUseCustomLinkParams(ui->chkUseCustomLinkParams->isChecked()); - pSet->setCustomLinkParams(ui->txtCustomLinkParams->toPlainText()); - pSet->setStaticLink(ui->chkStaticLink->isChecked()); + pSet->setCustomLinkParams(ui->txtCustomLinkParams->toPlainText().trimmed()); pSet->setAutoAddCharsetParams(ui->chkAutoAddCharset->isChecked()); - pSet->setCCompiler(ui->txtCCompiler->text()); - pSet->setCppCompiler(ui->txtCppCompiler->text()); - pSet->setMake(ui->txtMake->text()); - pSet->setDebugger(ui->txtDebugger->text()); - pSet->setResourceCompiler(ui->txtResourceCompiler->text()); - pSet->setProfiler(ui->txtProfiler->text()); + pSet->setCCompiler(ui->txtCCompiler->text().trimmed()); + pSet->setCppCompiler(ui->txtCppCompiler->text().trimmed()); + pSet->setMake(ui->txtMake->text().trimmed()); + pSet->setDebugger(ui->txtDebugger->text().trimmed()); + pSet->setResourceCompiler(ui->txtResourceCompiler->text().trimmed()); + pSet->setProfiler(ui->txtProfiler->text().trimmed()); pSet->binDirs()=mBinDirWidget->dirList(); diff --git a/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui b/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui index a8946716..1df85355 100644 --- a/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui +++ b/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui @@ -125,13 +125,6 @@ - - - - Statically Link - - - diff --git a/RedPandaIDE/systemconsts.h b/RedPandaIDE/systemconsts.h index 370ba2d4..0c807fa7 100644 --- a/RedPandaIDE/systemconsts.h +++ b/RedPandaIDE/systemconsts.h @@ -14,7 +14,17 @@ #define CLEAN_PROGRAM "rm.exe" #define CPP_PROGRAM "cpp.exe" -#define NULL_FILE "NUL" +#ifdef Q_OS_WIN +# define PATH_SENSITIVITY Qt::CaseInsensitive +# define NULL_FILE "NUL" +# define EXECUTABE_EXT ".exe" +#elif Q_OS_LINUX +# define PATH_SENSITIVITY Qt::CaseSensitive +# define NULL_FILE "/dev/null" +# define EXECUTABE_EXT "" +#else +#error "Only support windows and linux now!" +#endif class SystemConsts { diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index 069ec71a..c566d71d 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -1,4 +1,5 @@ #include "utils.h" +#include "systemconsts.h" #include #include #include @@ -9,6 +10,8 @@ #include #include #include +#include +#include const QByteArray GuessTextEncoding(const QByteArray& text){ bool allAscii; @@ -93,8 +96,6 @@ QByteArray runAndGetOutput(const QString &cmd, const QString& workingDir, const process.setProcessEnvironment(QProcessEnvironment()); } process.setWorkingDirectory(workingDir); - process.start(cmd,arguments,QIODevice::ReadOnly); - process.closeWriteChannel(); process.connect(&process,&QProcess::readyReadStandardError, [&](){ result.append(process.readAllStandardError()); @@ -103,7 +104,10 @@ QByteArray runAndGetOutput(const QString &cmd, const QString& workingDir, const [&](){ result.append(process.readAllStandardOutput()); }); - process.waitForFinished(); + process.start(cmd,arguments); + process.closeWriteChannel(); + + process.waitForFinished(-1); return result; } @@ -134,7 +138,7 @@ QString includeTrailingPathDelimiter(const QString &path) if (path.endsWith('/') || path.endsWith(QDir::separator())) { return path; } else { - return path + QDir::separator(); + return path + "/"; } } @@ -145,3 +149,77 @@ QString excludeTrailingPathDelimiter(const QString &path) pos--; return path.mid(0,pos+1); } + +FileType getFileType(const QString &filename) +{ + if (filename.endsWith(".c",PATH_SENSITIVITY)) { + return FileType::CSource; + } + if (filename.endsWith(".cpp",PATH_SENSITIVITY)) { + return FileType::CppSource; + } + if (filename.endsWith(".cc",PATH_SENSITIVITY)) { + return FileType::CppSource; + } + if (filename.endsWith(".cxx",PATH_SENSITIVITY)) { + return FileType::CppSource; + } + if (filename.endsWith(".c++",PATH_SENSITIVITY)) { + return FileType::CppSource; + } + if (filename.endsWith(".h",PATH_SENSITIVITY)) { + return FileType::CHeader; + } + if (filename.endsWith(".hpp",PATH_SENSITIVITY)) { + return FileType::CppHeader; + } + if (filename.endsWith(".hh",PATH_SENSITIVITY)) { + return FileType::CppHeader; + } + if (filename.endsWith(".hxx",PATH_SENSITIVITY)) { + return FileType::CppHeader; + } + if (filename.endsWith(".inl",PATH_SENSITIVITY)) { + return FileType::CppHeader; + } + if (filename.endsWith(".res",PATH_SENSITIVITY)) { + return FileType::WindowsResourceSource; + } + return FileType::Other; +} + + +QString getCompiledExecutableName(const QString filename) +{ + QFileInfo info(filename); + QString baseName = includeTrailingPathDelimiter(info.absolutePath())+info.baseName(); + return baseName + EXECUTABE_EXT; +} + +void splitStringArguments(const QString &arguments, QStringList &argumentList) +{ + QString word; + bool inQuota; + inQuota = false; + for (QChar ch:arguments) { + if (ch == '"') { + inQuota = !inQuota; + } else if (ch == '\n' || ch == ' ' || ch == '\t' || ch == '\r') { + if (!inQuota) { + word = word.trimmed(); + if (!word.isEmpty()) { + argumentList.append(word); + } + word = ""; + } else { + word.append(ch); + } + } else { + word.append(ch); + } + } + word = word.trimmed(); + if (!word.isEmpty()) { + argumentList.append(word); + } +} diff --git a/RedPandaIDE/utils.h b/RedPandaIDE/utils.h index bb9f0365..6477e947 100644 --- a/RedPandaIDE/utils.h +++ b/RedPandaIDE/utils.h @@ -4,7 +4,6 @@ #include #include - class QByteArray; class QString; class QStringList; @@ -15,6 +14,15 @@ class QStringList; #define ENCODING_SYSTEM_DEFAULT "SYSTEM" #define ENCODING_ASCII "ASCII" +enum class FileType{ + CSource, // c source file (.c) + CppSource, // c++ source file (.cpp) + CHeader, // c header (.h) + CppHeader, // c++ header (.hpp) + WindowsResourceSource, // resource source (.res) + Other // any others +}; + typedef void (*LineOutputFunc) (const QString& line); typedef bool (*CheckAbortFunc) (); bool isGreenEdition(); @@ -32,6 +40,9 @@ bool fileExists(const QString& dir, const QString& fileName); bool directoryExists(const QString& file); QString includeTrailingPathDelimiter(const QString& path); QString excludeTrailingPathDelimiter(const QString& path); +FileType getFileType(const QString& filename); +QString getCompiledExecutableName(const QString filename); +void splitStringArguments(const QString& arguments, QStringList& argumentList); template class final_action