VoiletCStudio v1.0 - 紫罗兰 C 工程配置器

功能特性:
- JSON 格式工程配置文件
- 虚拟目录管理(类似 MDK)
- 跨平台 CMake 自动生成
- 一键编译 Debug/Release
- 拖拽文件打开工程
- 实时编译输出显示

作者:虾哥
日期:2026-04-09
This commit is contained in:
虾哥
2026-04-09 10:18:39 -04:00
commit 19296b7337
24 changed files with 3362 additions and 0 deletions

293
src/cmakegenerator.cpp Normal file
View File

@@ -0,0 +1,293 @@
#include "cmakegenerator.h"
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QDateTime>
CMakeGenerator::CMakeGenerator(QObject *parent)
: QObject(parent)
{
}
bool CMakeGenerator::generate(const ProjectConfig *config, const QString &outputPath)
{
if (!config) {
emit errorOccurred("配置对象为空");
return false;
}
QString content = generateContent(config);
QFileInfo fileInfo(outputPath);
QDir dir = fileInfo.absoluteDir();
if (!dir.exists()) {
dir.mkpath(".");
}
QFile file(outputPath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
emit errorOccurred("无法创建 CMakeLists.txt: " + file.errorString());
return false;
}
QTextStream out(&file);
out.setCodec("UTF-8");
out << content;
file.close();
m_lastGeneratedPath = outputPath;
emit cmakeGenerated(outputPath);
return true;
}
QString CMakeGenerator::getLastGeneratedPath() const
{
return m_lastGeneratedPath;
}
QString CMakeGenerator::generateContent(const ProjectConfig *config)
{
QString content;
content += generateHeader(config);
content += "\n";
content += generateProjectConfig(config);
content += "\n";
content += generateSourceFiles(config);
content += "\n";
content += generateIncludeDirs(config);
content += "\n";
content += generateLibraries(config);
content += "\n";
content += generateDefines(config);
content += "\n";
content += generateCompilerOptions(config);
content += "\n";
content += generateBuildTargets(config);
return content;
}
QString CMakeGenerator::generateHeader(const ProjectConfig *config)
{
QString header;
header += "# ========================================\n";
header += "# CMakeLists.txt - VoiletCStudio 自动生成\n";
header += "# 工程名称:" + config->getProjectName() + "\n";
header += "# 生成时间:" + QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss") + "\n";
header += "# 跨平台支持Windows (MinGW) / Linux (GCC) / macOS (Clang)\n";
header += "# ========================================\n\n";
header += "cmake_minimum_required(VERSION 3.10)\n\n";
return header;
}
QString CMakeGenerator::generateProjectConfig(const ProjectConfig *config)
{
QString content;
QString projectName = config->getProjectName();
if (projectName.isEmpty()) {
projectName = "UntitledProject";
}
content += "# 项目名称\n";
content += "project(" + projectName + " C)\n\n";
content += "# C 标准\n";
content += "set(CMAKE_C_STANDARD 11)\n";
content += "set(CMAKE_C_STANDARD_REQUIRED ON)\n\n";
// 输出目录配置
QString outputDir = config->getOutputDir();
if (outputDir.isEmpty()) {
outputDir = "./build";
}
content += "# 输出目录配置\n";
content += "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/" + outputDir + ")\n";
content += "set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/" + outputDir + ")\n";
content += "set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/" + outputDir + ")\n\n";
// 编译器配置
content += "# 编译器配置\n";
if (!config->getCompilerPath().isEmpty() && config->getCompilerPath() != "gcc") {
content += "set(CMAKE_C_COMPILER \"" + config->getCompilerPath() + "\")\n";
}
content += "\n";
return content;
}
QString CMakeGenerator::generateSourceFiles(const ProjectConfig *config)
{
QString content;
content += "# ========================================\n";
content += "# 源文件配置(虚拟目录结构)\n";
content += "# ========================================\n\n";
QMap<QString, VirtualDir> virtualDirs = config->getVirtualDirs();
if (virtualDirs.isEmpty()) {
content += "# 无源文件\n";
} else {
// 遍历虚拟目录
for (auto it = virtualDirs.begin(); it != virtualDirs.end(); ++it) {
content += "# 分组:" + it.key() + "\n";
QString safeName = it.key();
safeName.replace(" ", "_");
safeName.replace("/", "_");
content += "set(SRCS_" + safeName + "\n";
for (const QString &file : it->files) {
content += " " + file + "\n";
}
content += ")\n\n";
}
// 合并所有源文件
content += "# 合并所有源文件\n";
content += "set(SOURCES\n";
for (auto it = virtualDirs.begin(); it != virtualDirs.end(); ++it) {
for (const QString &file : it->files) {
content += " " + file + "\n";
}
}
content += ")\n\n";
}
content += "# 创建可执行文件\n";
QString outputName = config->getProjectName();
if (outputName.isEmpty()) {
outputName = "output";
}
content += "add_executable(" + outputName + " ${SOURCES})\n\n";
return content;
}
QString CMakeGenerator::generateIncludeDirs(const ProjectConfig *config)
{
QString content;
content += "# 包含目录\n";
QStringList includeDirs = config->getIncludeDirs();
if (includeDirs.isEmpty()) {
content += "# 无额外包含目录\n";
} else {
content += "target_include_directories(" + config->getProjectName() + " PRIVATE\n";
for (const QString &dir : includeDirs) {
content += " " + dir + "\n";
}
content += ")\n";
}
return content;
}
QString CMakeGenerator::generateLibraries(const ProjectConfig *config)
{
QString content;
content += "# 链接库\n";
QStringList libraries = config->getLibraries();
if (libraries.isEmpty()) {
content += "# 无外部库文件\n";
} else {
content += "target_link_libraries(" + config->getProjectName() + " PRIVATE\n";
for (const QString &lib : libraries) {
content += " " + lib + "\n";
}
content += ")\n";
}
return content;
}
QString CMakeGenerator::generateDefines(const ProjectConfig *config)
{
QString content;
content += "# 预编译宏定义\n";
QStringList defines = config->getDefines();
if (defines.isEmpty()) {
content += "# 无额外宏定义\n";
} else {
content += "target_compile_definitions(" + config->getProjectName() + " PRIVATE\n";
for (const QString &def : defines) {
content += " " + def + "\n";
}
content += ")\n";
}
return content;
}
QString CMakeGenerator::generateCompilerOptions(const ProjectConfig *config)
{
QString content;
content += "# 自定义编译选项\n";
QStringList options = config->getCompilerOptions();
if (options.isEmpty()) {
content += "# 无自定义编译选项\n";
} else {
content += "target_compile_options(" + config->getProjectName() + " PRIVATE\n";
for (const QString &opt : options) {
content += " " + opt + "\n";
}
content += ")\n";
}
return content;
}
QString CMakeGenerator::generateBuildTargets(const ProjectConfig *config)
{
QString content;
content += "# ========================================\n";
content += "# 构建类型配置\n";
content += "# ========================================\n\n";
content += "# 默认构建类型Debug\n";
content += "if(NOT CMAKE_BUILD_TYPE)\n";
content += " set(CMAKE_BUILD_TYPE Debug CACHE STRING \"Build type\" FORCE)\n";
content += "endif()\n\n";
content += "# Debug 模式配置(自动添加 DEBUG 宏)\n";
content += "set(CMAKE_C_FLAGS_DEBUG \"-g -O0 -DDEBUG\" CACHE STRING \"Debug flags\" FORCE)\n\n";
content += "# Release 模式配置\n";
content += "set(CMAKE_C_FLAGS_RELEASE \"-O2 -DNDEBUG\" CACHE STRING \"Release flags\" FORCE)\n\n";
content += "# ========================================\n";
content += "# 自定义 Make 目标make debug / make release\n";
content += "# ========================================\n\n";
content += "# make debug - 编译 Debug 版本(自动添加 DEBUG 宏)\n";
content += "add_custom_target(debug\n";
content += " COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}\n";
content += " COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --config Debug\n";
content += " COMMENT \"Building Debug version\"\n";
content += " VERBATIM\n";
content += ")\n\n";
content += "# make release - 编译 Release 版本\n";
content += "add_custom_target(release\n";
content += " COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}\n";
content += " COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --config Release\n";
content += " COMMENT \"Building Release version\"\n";
content += " VERBATIM\n";
content += ")\n\n";
content += "# 使用说明:\n";
content += "# cmake -B build # 配置(默认 Debug\n";
content += "# cmake --build build # 编译(使用当前 CMAKE_BUILD_TYPE\n";
content += "# make debug # 编译 Debug 版本(自动添加 DEBUG 宏)\n";
content += "# make release # 编译 Release 版本\n";
return content;
}