From 78ff319a75ee7f6d54591a85016173cfb8b3db41 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Wed, 8 Feb 2023 21:07:41 +0800 Subject: [PATCH] - enhancement: Support compile asm files using nasm in the project. --- NEWS.md | 1 + RedPandaIDE/compiler/projectcompiler.cpp | 59 ++++-- RedPandaIDE/project.cpp | 5 + RedPandaIDE/settings.cpp | 20 ++ RedPandaIDE/settings.h | 7 +- .../compilersetoptionwidget.cpp | 15 ++ .../settingsdialog/compilersetoptionwidget.h | 1 + .../settingsdialog/compilersetoptionwidget.ui | 173 ++++++++++-------- RedPandaIDE/systemconsts.h | 3 + RedPandaIDE/utils.cpp | 3 + RedPandaIDE/utils.h | 1 + 11 files changed, 196 insertions(+), 92 deletions(-) diff --git a/NEWS.md b/NEWS.md index ce2e3209..582a7439 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,7 @@ Red Panda C++ Version 2.11 - enhancement: Auto reload openned project files that use "Project Default" as the encoding, when the project encoding setting is changed in the project options dialog. - fix: Correctly handle files whose name contains spaces in the generated makefile. - fix: Correctly handle custom obj folder in the generated makefile. + - enhancement: Support compile asm files using nasm in the project. Red Panda C++ Version 2.10 diff --git a/RedPandaIDE/compiler/projectcompiler.cpp b/RedPandaIDE/compiler/projectcompiler.cpp index 8a1f06fa..5978d2cc 100644 --- a/RedPandaIDE/compiler/projectcompiler.cpp +++ b/RedPandaIDE/compiler/projectcompiler.cpp @@ -156,7 +156,11 @@ void ProjectCompiler::writeMakeDefines(QFile &file) // Only process source files QString RelativeName = extractRelativePath(mProject->directory(), unit->fileName()); FileType fileType = getFileType(RelativeName); - if (fileType == FileType::CSource || fileType == FileType::CppSource) { + if (fileType==FileType::ASM && !compilerSet()->canAssemble()) + continue; + + if (fileType == FileType::CSource || fileType == FileType::CppSource + || fileType == FileType::ASM) { if (!mProject->options().objectOutput.isEmpty()) { // ofile = C:\MyProgram\obj\main.o QString fullObjFile = includeTrailingPathDelimiter(mProject->options().objectOutput) @@ -201,11 +205,11 @@ void ProjectCompiler::writeMakeDefines(QFile &file) QString relativeResFile = extractRelativePath(mProject->directory(), fullResFile); objResFile = genMakePath1(relativeResFile); objResFile2 = genMakePath2(relativeResFile); - cleanRes += ' ' + genMakePath1(changeFileExt(relativeResFile, OBJ_EXT)).replace("/",QDir::separator()); + cleanRes += ' ' + genMakePath1(changeFileExt(relativeResFile, RES_EXT)).replace("/",QDir::separator()); } else { objResFile = genMakePath1(changeFileExt(mProject->options().privateResource, RES_EXT)); objResFile2 = genMakePath2(changeFileExt(mProject->options().privateResource, RES_EXT)); - cleanRes += ' ' + genMakePath1(changeFileExt(mProject->options().privateResource, OBJ_EXT)).replace("/",QDir::separator()); + cleanRes += ' ' + genMakePath1(changeFileExt(mProject->options().privateResource, RES_EXT)).replace("/",QDir::separator()); } } #endif @@ -229,6 +233,8 @@ void ProjectCompiler::writeMakeDefines(QFile &file) cppCompileArguments+= " -D__DEBUG__"; } + if (compilerSet()->canAssemble()) + writeln(file,"ASM = " + extractFileName(compilerSet()->assembler())); writeln(file,"CPP = " + extractFileName(compilerSet()->cppCompiler())); writeln(file,"CC = " + extractFileName(compilerSet()->CCompiler())); #ifdef Q_OS_WIN @@ -279,7 +285,21 @@ void ProjectCompiler::writeMakeDefines(QFile &file) #ifdef Q_OS_WIN writeln(file,"WINDRESFLAGS = " + mProject->options().resourceCmd); #endif - +#ifdef Q_OS_WIN + if (compilerSet()->canAssemble() && + Settings::CompilerSets::isTarget64Bit(compilerSet()->target())) { + if (mProject->getCompileOption(CC_CMD_OPT_POINTER_SIZE)=="32") + writeln(file,"ASMFLAGS = -f win32"); + else + writeln(file,"ASMFLAGS = -f win64"); + } else { + writeln(file,"ASMFLAGS = -f win32"); + } +#elif defined(Q_OS_LINUX) + writeln(file,"ASMFLAGS = -f elf64"); +#elif defined(Q_OS_MACOS) + writeln(file,"ASMFLAGS = -f macho64"); +#endif // This needs to be put in before the clean command. if (mProject->options().type == ProjectType::DynamicLib) { @@ -354,9 +374,12 @@ void ProjectCompiler::writeMakeObjFilesRules(QFile &file) QList projectUnits=mProject->unitList(); foreach(const PProjectUnit &unit, projectUnits) { + if (!unit->compile()) + continue; FileType fileType = getFileType(unit->fileName()); // Only process source files - if (fileType!=FileType::CSource && fileType!=FileType::CppSource) + if (fileType!=FileType::CSource && fileType!=FileType::CppSource + && fileType!=FileType::ASM) continue; QString shortFileName = extractRelativePath(mProject->makeFileName(),unit->fileName()); @@ -459,16 +482,22 @@ void ProjectCompiler::writeMakeObjFilesRules(QFile &file) } } - if (mOnlyCheckSyntax) { - if (unit->compileCpp()) - writeln(file, "\t$(CPP) -c " + genMakePath1(shortFileName) + " $(CXXFLAGS) " + encodingStr); - else - writeln(file, "\t(CC) -c " + genMakePath1(shortFileName) + " $(CFLAGS) " + encodingStr); - } else { - if (unit->compileCpp()) - writeln(file, "\t$(CPP) -c " + genMakePath1(shortFileName) + " -o " + objFileName2 + " $(CXXFLAGS) " + encodingStr); - else - writeln(file, "\t$(CC) -c " + genMakePath1(shortFileName) + " -o " + objFileName2 + " $(CFLAGS) " + encodingStr); + if (fileType==FileType::CppSource || fileType==FileType::CppSource) { + if (mOnlyCheckSyntax) { + if (unit->compileCpp()) + writeln(file, "\t$(CPP) -c " + genMakePath1(shortFileName) + " $(CXXFLAGS) " + encodingStr); + else + writeln(file, "\t(CC) -c " + genMakePath1(shortFileName) + " $(CFLAGS) " + encodingStr); + } else { + if (unit->compileCpp()) + writeln(file, "\t$(CPP) -c " + genMakePath1(shortFileName) + " -o " + objFileName2 + " $(CXXFLAGS) " + encodingStr); + else + writeln(file, "\t$(CC) -c " + genMakePath1(shortFileName) + " -o " + objFileName2 + " $(CFLAGS) " + encodingStr); + } + } else if (fileType==FileType::ASM) { + if (!mOnlyCheckSyntax) { + writeln(file, "\t$(ASM) $(ASMFLAGS) " + genMakePath1(shortFileName) + " -o " + objFileName2); + } } } } diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index 72007f55..ade981a2 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -1261,6 +1261,11 @@ PProjectUnit Project::internalAddUnit(const QString &inFileName, PProjectModelNo // Determine compilation flags switch(getFileType(inFileName)) { + case FileType::ASM: + newUnit->setCompile(true); + newUnit->setCompileCpp(false); + newUnit->setLink(true); + break; case FileType::CSource: newUnit->setCompile(true); newUnit->setCompileCpp(false); diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp index 46f0ccb9..7ea9a806 100644 --- a/RedPandaIDE/settings.cpp +++ b/RedPandaIDE/settings.cpp @@ -1692,6 +1692,7 @@ Settings::CompilerSet::CompilerSet(const Settings::CompilerSet &set): mProfiler(set.mProfiler), mResourceCompiler(set.mResourceCompiler), mDebugServer(set.mDebugServer), + mAssembler(set.assembler()), mBinDirs(set.mBinDirs), mCIncludeDirs(set.mCIncludeDirs), @@ -2329,6 +2330,7 @@ void Settings::CompilerSet::setExecutables() mMake = findProgramInBinDirs(MAKE_PROGRAM); mResourceCompiler = findProgramInBinDirs(WINDRES_PROGRAM); mProfiler = findProgramInBinDirs(GPROF_PROGRAM); + mAssembler = findProgramInBinDirs(ASSEMBLER); } void Settings::CompilerSet::setDirectories(const QString& binDir,CompilerType compilerType) @@ -2506,6 +2508,11 @@ bool Settings::CompilerSet::canDebug() return fileExists(mDebugger); } +bool Settings::CompilerSet::canAssemble() +{ + return fileExists(mAssembler); +} + void Settings::CompilerSet::setUserInput() { mUseCustomCompileParams = false; @@ -2551,6 +2558,16 @@ QByteArray Settings::CompilerSet::getCompilerOutput(const QString &binDir, const return result.trimmed(); } +const QString &Settings::CompilerSet::assembler() const +{ + return mAssembler; +} + +void Settings::CompilerSet::setAssembler(const QString &newAssembler) +{ + mAssembler = newAssembler; +} + Settings::CompilerSet::CompilationStage Settings::CompilerSet::compilationStage() const { return mCompilationStage; @@ -3073,6 +3090,8 @@ void Settings::CompilerSets::saveSet(int index) savePath("make", pSet->make()); savePath("windres", pSet->resourceCompiler()); savePath("profiler", pSet->profiler()); + savePath("assembler", pSet->assembler()); + mSettings->mSettings.remove("Options"); foreach(const PCompilerOption& option, CompilerInfoManager::getInstance()->getCompilerOptions(pSet->compilerType())) { @@ -3151,6 +3170,7 @@ Settings::PCompilerSet Settings::CompilerSets::loadSet(int index) pSet->setMake(loadPath("make")); pSet->setResourceCompiler(loadPath("windres")); pSet->setProfiler(loadPath("profiler")); + pSet->setAssembler(loadPath("assembler")); pSet->setDumpMachine(mSettings->mSettings.value("DumpMachine").toString()); pSet->setVersion(mSettings->mSettings.value("Version").toString()); diff --git a/RedPandaIDE/settings.h b/RedPandaIDE/settings.h index b4c7a987..677417eb 100644 --- a/RedPandaIDE/settings.h +++ b/RedPandaIDE/settings.h @@ -1300,6 +1300,7 @@ public: bool canCompileCPP(); bool canMake(); bool canDebug(); + bool canAssemble(); // bool dirsValid(QString& msg); // bool validateExes(QString& msg); //properties @@ -1389,6 +1390,9 @@ public: QString getOutputFilename(const QString& sourceFilename,Settings::CompilerSet::CompilationStage stage); bool isOutputExecutable(); bool isOutputExecutable(Settings::CompilerSet::CompilationStage stage); + const QString &assembler() const; + void setAssembler(const QString &newAssembler); + private: void setDirectories(const QString& binDir, CompilerType mCompilerType); //load hard defines @@ -1409,6 +1413,7 @@ public: QString mProfiler; QString mResourceCompiler; QString mDebugServer; + QString mAssembler; // Directories, mostly hardcoded too QStringList mBinDirs; @@ -1471,6 +1476,7 @@ public: QString getKeyFromCompilerCompatibleIndex(int idx) const; + static bool isTarget64Bit(const QString &target); private: PCompilerSet addSet(const QString& folder, const QString& c_prog); PCompilerSet addSet(const PCompilerSet &pSet); @@ -1482,7 +1488,6 @@ public: void loadPathList(const QString& name, QStringList& list); PCompilerSet loadSet(int index); void prepareCompatibleIndex(); - static bool isTarget64Bit(const QString &target); private: CompilerSetList mList; int mDefaultIndex; diff --git a/RedPandaIDE/settingsdialog/compilersetoptionwidget.cpp b/RedPandaIDE/settingsdialog/compilersetoptionwidget.cpp index a8abedda..b7096a24 100644 --- a/RedPandaIDE/settingsdialog/compilersetoptionwidget.cpp +++ b/RedPandaIDE/settingsdialog/compilersetoptionwidget.cpp @@ -99,6 +99,7 @@ static void loadCompilerSetSettings(Settings::PCompilerSet pSet, Ui::CompilerSet ui->txtGDBServer->setText(pSet->debugServer()); ui->txtResourceCompiler->setText(pSet->resourceCompiler()); ui->txtProfiler->setText(pSet->profiler()); + ui->txtAssembler->setText(pSet->assembler()); if (pSet->execCharset() == ENCODING_AUTO_DETECT || pSet->execCharset() == ENCODING_SYSTEM_DEFAULT @@ -208,6 +209,7 @@ void CompilerSetOptionWidget::saveCurrentCompilerSet() pSet->setDebugServer(ui->txtGDBServer->text().trimmed()); pSet->setResourceCompiler(ui->txtResourceCompiler->text().trimmed()); pSet->setProfiler(ui->txtProfiler->text().trimmed()); + pSet->setAssembler(ui->txtAssembler->text().trimmed()); pSet->binDirs()=mBinDirWidget->dirList(); @@ -334,6 +336,7 @@ void CompilerSetOptionWidget::updateIcons(const QSize& /*size*/) pIconsManager->setIcon(ui->btnChooseGDBServer, IconsManager::ACTION_FILE_OPEN_FOLDER); pIconsManager->setIcon(ui->btnChooseMake, IconsManager::ACTION_FILE_OPEN_FOLDER); pIconsManager->setIcon(ui->btnChooseProfiler, IconsManager::ACTION_FILE_OPEN_FOLDER); + pIconsManager->setIcon(ui->btnChooseAssembler, IconsManager::ACTION_FILE_OPEN_FOLDER); pIconsManager->setIcon(ui->btnChooseResourceCompiler, IconsManager::ACTION_FILE_OPEN_FOLDER); } @@ -445,3 +448,15 @@ void CompilerSetOptionWidget::on_btnChooseProfiler_clicked() ui->txtProfiler->setText(fileName); } + +void CompilerSetOptionWidget::on_btnChooseAssembler_clicked() +{ + QString fileName = QFileDialog::getOpenFileName( + this, + tr("Locate nasm"), + getBinDir(), + tr("Executable files (*.exe)")); + if (fileExists(fileName)) + ui->txtAssembler->setText(fileName); +} + diff --git a/RedPandaIDE/settingsdialog/compilersetoptionwidget.h b/RedPandaIDE/settingsdialog/compilersetoptionwidget.h index 6348796b..31bb261f 100644 --- a/RedPandaIDE/settingsdialog/compilersetoptionwidget.h +++ b/RedPandaIDE/settingsdialog/compilersetoptionwidget.h @@ -71,6 +71,7 @@ private slots: void on_btnChooseGDBServer_clicked(); void on_btnChooseResourceCompiler_clicked(); void on_btnChooseProfiler_clicked(); + void on_btnChooseAssembler_clicked(); }; #endif // COMPILERSETOPTIONWIDGET_H diff --git a/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui b/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui index b7e8e99d..afc6694c 100644 --- a/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui +++ b/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui @@ -110,7 +110,7 @@ - 0 + 3 false @@ -249,10 +249,10 @@ QFrame::Raised - - + + - Choose make + Choose Resource Compiler ... @@ -264,17 +264,10 @@ - - - - C Compiler(gcc) - - - - - + + - Choose Profiler + Choose C Compiler ... @@ -286,8 +279,11 @@ - - + + + + + @@ -296,6 +292,20 @@ + + + + ... + + + + :/icons/images/newlook24/053-open.png:/icons/images/newlook24/053-open.png + + + + + + @@ -311,20 +321,18 @@ - - - - Profiler(gprof) + + + + Choose Profiler - - - - - - - - make + ... + + + + :/icons/images/newlook24/053-open.png + @@ -343,54 +351,15 @@ - - - - - - - - - - Choose C Compiler - + + - ... - - - - :/icons/images/newlook24/053-open.png - + make - - - - - - - gdb - - - - - - - Choose Resource Compiler - - - ... - - - - :/icons/images/newlook24/053-open.png - - - - - - + + @@ -399,6 +368,44 @@ + + + + + + + C Compiler(gcc) + + + + + + + + + + Choose make + + + ... + + + + :/icons/images/newlook24/053-open.png + + + + + + + + Profiler(gprof) + + + + + + @@ -406,11 +413,25 @@ - - + + + + gdb + + - - + + + + Assembler + + + + + + + + ... diff --git a/RedPandaIDE/systemconsts.h b/RedPandaIDE/systemconsts.h index a57059ac..b8f1a53f 100644 --- a/RedPandaIDE/systemconsts.h +++ b/RedPandaIDE/systemconsts.h @@ -22,6 +22,7 @@ #define APP_SETTSINGS_FILENAME "redpandacpp.ini" #ifdef Q_OS_WIN #define CONSOLE_PAUSER "consolepauser.exe" +#define ASSEMBLER "nasm.exe" #define GCC_PROGRAM "gcc.exe" #define GPP_PROGRAM "g++.exe" #define GDB_PROGRAM "gdb.exe" @@ -39,6 +40,7 @@ #define LLDB_SERVER_PROGRAM "lldb-server.exe" #elif defined(Q_OS_LINUX) #define CONSOLE_PAUSER "consolepauser" +#define ASSEMBLER "nasm" #define GCC_PROGRAM "gcc" #define GPP_PROGRAM "g++" #define GDB_PROGRAM "gdb" @@ -55,6 +57,7 @@ #define LLDB_MI_PROGRAM "lldb-mi" #define LLDB_SERVER_PROGRAM "lldb-server" #elif defined(Q_OS_MACOS) +#define ASSEMBLER "nasm" #define GCC_PROGRAM "gcc" #define GPP_PROGRAM "g++" #define GDB_PROGRAM "gdb" diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index 6ea19f98..7790a7fa 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -83,6 +83,9 @@ QStringList splitProcessCommand(const QString &cmd) FileType getFileType(const QString &filename) { + if (filename.endsWith(".asm",PATH_SENSITIVITY)) { + return FileType::ASM; + } if (filename.endsWith(".dev",PATH_SENSITIVITY)) { return FileType::Project; } diff --git a/RedPandaIDE/utils.h b/RedPandaIDE/utils.h index 678012b8..0b4042b4 100644 --- a/RedPandaIDE/utils.h +++ b/RedPandaIDE/utils.h @@ -32,6 +32,7 @@ using SimpleIni = CSimpleIniA; using PSimpleIni = std::shared_ptr; enum class FileType{ + ASM, // asm source file (.asm) CSource, // c source file (.c) CppSource, // c++ source file (.cpp) CHeader, // c header (.h)