133 lines
4.3 KiB
C++
133 lines
4.3 KiB
C++
#include "compileprocessmanager.h"
|
||
|
||
#include <QDir>
|
||
#include <QFile>
|
||
#include <QFileInfo>
|
||
#include <QTextStream>
|
||
#include <QStringConverter>
|
||
#include <QtGlobal>
|
||
|
||
CompileProcessManager::CompileProcessManager(QObject *parent)
|
||
: QObject(parent)
|
||
{
|
||
m_process = new QProcess(this);
|
||
|
||
connect(m_process,
|
||
&QProcess::finished,
|
||
this,
|
||
&CompileProcessManager::onProcessFinished);
|
||
}
|
||
|
||
void CompileProcessManager::setBackendProgram(const QString &programPath)
|
||
{
|
||
m_backendProgram = programPath;
|
||
}
|
||
|
||
void CompileProcessManager::setProjectRoot(const QString &rootPath)
|
||
{
|
||
m_projectRoot = rootPath;
|
||
}
|
||
|
||
void CompileProcessManager::generateAsm(const QString &inputFileName,
|
||
const QString &outputFileName)
|
||
{
|
||
if (m_backendProgram.isEmpty()) {
|
||
emit processError(tr("mini_c 可执行文件路径未设置"));
|
||
return;
|
||
}
|
||
|
||
// 项目根目录(如果没设就用当前工作目录)
|
||
QDir root(m_projectRoot.isEmpty() ? QDir::currentPath() : m_projectRoot);
|
||
|
||
// 拼出源文件完整路径:root + "test.c"
|
||
QString inputPath = root.filePath(inputFileName);
|
||
if (!QFileInfo::exists(inputPath)) {
|
||
emit processError(tr("源文件不存在: %1").arg(inputPath));
|
||
return;
|
||
}
|
||
|
||
// 若之前还有进程在跑,先结束(简单粗暴版)
|
||
if (m_process->state() != QProcess::NotRunning) {
|
||
m_process->kill();
|
||
m_process->waitForFinished();
|
||
}
|
||
|
||
m_isAsmOperation = true;
|
||
m_pendingInputFile = inputPath;
|
||
m_pendingOutputFile = outputFileName.isEmpty()
|
||
? QStringLiteral("1.s")
|
||
: outputFileName;
|
||
|
||
// 把工作目录设为项目根目录:这样 mini_c 写 "1.s" 就会写到项目根目录
|
||
QString workingDir = root.absolutePath();
|
||
m_process->setWorkingDirectory(workingDir);
|
||
|
||
// mini_c 调用形式:mini_c asm <inputFilename>
|
||
m_process->setProgram(m_backendProgram);
|
||
QStringList args;
|
||
args << QStringLiteral("asm") << inputPath;
|
||
m_process->setArguments(args);
|
||
|
||
m_process->setProcessChannelMode(QProcess::SeparateChannels);
|
||
|
||
m_process->start();
|
||
// 不用 waitForFinished,异步等 finished 信号
|
||
}
|
||
|
||
void CompileProcessManager::onProcessFinished(int exitCode, QProcess::ExitStatus status)
|
||
{
|
||
QString stdoutText = QString::fromUtf8(m_process->readAllStandardOutput());
|
||
QString stderrText = QString::fromUtf8(m_process->readAllStandardError());
|
||
|
||
if (status != QProcess::NormalExit && exitCode == 0) {
|
||
exitCode = -1;
|
||
}
|
||
|
||
QString asmText;
|
||
QString finalOutputPath;
|
||
|
||
if (m_isAsmOperation) {
|
||
// mini_c 当前实现中,汇编输出写到固定文件 "1.s"
|
||
QDir workDir(m_process->workingDirectory());
|
||
QString tmpAsmPath = workDir.filePath(QStringLiteral("1.s"));
|
||
|
||
if (exitCode == 0 && QFileInfo::exists(tmpAsmPath)) {
|
||
// 读出 1.s 内容
|
||
QFile f(tmpAsmPath);
|
||
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||
QTextStream in(&f);
|
||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||
in.setEncoding(QStringConverter::Utf8);
|
||
#endif
|
||
asmText = in.readAll();
|
||
f.close();
|
||
} else {
|
||
stderrText += QStringLiteral(
|
||
"\n[CompileProcessManager] 无法打开汇编输出文件: %1\n"
|
||
).arg(tmpAsmPath);
|
||
}
|
||
|
||
// 如果用户希望输出文件名不是 "1.s",比如 "test.s",就复制一份
|
||
finalOutputPath = workDir.filePath(m_pendingOutputFile);
|
||
if (finalOutputPath != tmpAsmPath) {
|
||
QFile::remove(finalOutputPath); // 不成功也无所谓
|
||
QFile::copy(tmpAsmPath, finalOutputPath); // 覆盖为目标文件名
|
||
}
|
||
} else {
|
||
if (exitCode == 0) {
|
||
stderrText += QStringLiteral(
|
||
"\n[CompileProcessManager] 未找到 mini_c 生成的 1.s 文件。\n"
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 把汇编文本 + 文件路径 + stdout/stderr + exitCode 一次性丢给前端
|
||
emit asmGenerated(asmText, finalOutputPath, stdoutText, stderrText, exitCode);
|
||
|
||
// 重置状态
|
||
m_isAsmOperation = false;
|
||
m_pendingInputFile.clear();
|
||
m_pendingOutputFile.clear();
|
||
}
|