1. 一键安装包 (build-release.ps1) - 打包 pcc.exe + 标准头文件 + Windows 头文件 + 运行时库 - 生成 pcc.bat 启动器,自动设置 include/lib 路径 - 输出: release/pcc-0.9.28-win32.zip (594 KB) 2. GUI 程序支持验证 - -Wl,-subsystem=windows 正确生成 GUI 程序 (PE Subsystem=2) - MessageBox 弹窗测试通过 3. VS Code 插件 (vscode-extension/) - C 语法高亮 (TextMate grammar) - PCC: Build (Ctrl+Shift+B) / PCC: Build & Run (Ctrl+F5) - 可配置 include/lib 路径和 pcc 可执行文件位置 4. Windows API 头文件验证 - 系统信息/时间/注册表/控制台/文件 API 编译运行正常 - PE 导入表格式正确 (kernel32.dll, msvcrt.dll) 5. 测试套件验证 - tests2 基础测试 48/53 通过 - 其余为测试框架差异 (stderr 合并/参数传递),非编译器 bug
165 行
4.7 KiB
JavaScript
165 行
4.7 KiB
JavaScript
// PCC - Paze C Compiler VS Code extension
|
|
// Provides build and run commands for C files using pcc
|
|
|
|
const vscode = require('vscode');
|
|
const path = require('path');
|
|
const { execSync } = require('child_process');
|
|
|
|
/**
|
|
* Find the pcc executable.
|
|
* Search order:
|
|
* 1. Setting "pcc.executable"
|
|
* 2. "pcc" / "pcc.exe" in PATH
|
|
* 3. Common install locations
|
|
*/
|
|
function findPcc() {
|
|
// 1. User setting
|
|
const configured = vscode.workspace.getConfiguration('pcc').get('executable');
|
|
if (configured && configured.trim()) {
|
|
return configured.trim();
|
|
}
|
|
|
|
// 2. PATH lookup
|
|
try {
|
|
execSync('pcc --version', { stdio: 'ignore' });
|
|
return 'pcc';
|
|
} catch (e) {
|
|
// not in PATH
|
|
}
|
|
|
|
// 3. Common locations
|
|
const candidates = [
|
|
'C:\\pcc\\pcc.exe',
|
|
'C:\\Program Files\\pcc\\pcc.exe',
|
|
'C:\\Program Files (x86)\\pcc\\pcc.exe',
|
|
'F:\\Paze C Compiler\\win32\\pcc.exe'
|
|
];
|
|
for (const c of candidates) {
|
|
try {
|
|
if (require('fs').existsSync(c)) {
|
|
return c;
|
|
}
|
|
} catch (e) { }
|
|
}
|
|
return 'pcc';
|
|
}
|
|
|
|
function getPccArgs(extraArgs) {
|
|
const cfg = vscode.workspace.getConfiguration('pcc');
|
|
const includePath = cfg.get('includePath', []);
|
|
const libPath = cfg.get('libPath', []);
|
|
const extra = cfg.get('args', []);
|
|
const args = [];
|
|
|
|
// Add include paths
|
|
for (const inc of includePath) {
|
|
args.push('-I', inc);
|
|
}
|
|
// Add lib paths
|
|
for (const lib of libPath) {
|
|
args.push('-L', lib);
|
|
}
|
|
// User extra args
|
|
args.push(...extra);
|
|
// Extra args passed from command
|
|
args.push(...extraArgs);
|
|
return args;
|
|
}
|
|
|
|
function getOutputPath(sourceFile) {
|
|
const cfg = vscode.workspace.getConfiguration('pcc');
|
|
const outputDir = cfg.get('outputDir', '');
|
|
const baseName = path.basename(sourceFile, path.extname(sourceFile));
|
|
if (outputDir) {
|
|
return path.join(outputDir, baseName + '.exe');
|
|
}
|
|
return path.join(path.dirname(sourceFile), baseName + '.exe');
|
|
}
|
|
|
|
function runPcc(args) {
|
|
const pcc = findPcc();
|
|
const cmd = `"${pcc}" ${args.join(' ')}`;
|
|
return new Promise((resolve, reject) => {
|
|
const cp = require('child_process').exec(cmd, {
|
|
cwd: vscode.workspace.rootPath || path.dirname(vscode.window.activeTextEditor.document.fileName),
|
|
env: process.env
|
|
}, (error, stdout, stderr) => {
|
|
resolve({ stdout, stderr, error });
|
|
});
|
|
});
|
|
}
|
|
|
|
async function getActiveCFile() {
|
|
const editor = vscode.window.activeTextEditor;
|
|
if (!editor) {
|
|
vscode.window.showWarningMessage('No active editor.');
|
|
return null;
|
|
}
|
|
const doc = editor.document;
|
|
if (doc.languageId !== 'c' && !doc.fileName.endsWith('.c')) {
|
|
vscode.window.showWarningMessage('Active file is not a C file.');
|
|
return null;
|
|
}
|
|
await doc.save();
|
|
return doc.fileName;
|
|
}
|
|
|
|
async function build(file) {
|
|
const output = getOutputPath(file);
|
|
const args = getPccArgs([file, '-o', output]);
|
|
const result = await runPcc(args);
|
|
return { output, result };
|
|
}
|
|
|
|
async function cmdBuild() {
|
|
const file = await getActiveCFile();
|
|
if (!file) return;
|
|
|
|
const status = vscode.window.setStatusBarMessage('$(sync~spin) PCC: compiling...');
|
|
const { output, result } = await build(file);
|
|
status.dispose();
|
|
|
|
if (result.error) {
|
|
vscode.window.showErrorMessage('PCC: Build failed');
|
|
vscode.window.showInformationMessage('See output for details.');
|
|
const outputChannel = vscode.window.createOutputChannel('PCC');
|
|
outputChannel.appendLine(result.stderr || result.stdout);
|
|
outputChannel.show(true);
|
|
} else {
|
|
vscode.window.showInformationMessage(`PCC: Build OK -> ${output}`);
|
|
}
|
|
}
|
|
|
|
async function cmdRun() {
|
|
const file = await getActiveCFile();
|
|
if (!file) return;
|
|
|
|
const status = vscode.window.setStatusBarMessage('$(sync~spin) PCC: compiling...');
|
|
const { output, result } = await build(file);
|
|
status.dispose();
|
|
|
|
if (result.error) {
|
|
vscode.window.showErrorMessage('PCC: Build failed');
|
|
const outputChannel = vscode.window.createOutputChannel('PCC');
|
|
outputChannel.appendLine(result.stderr || result.stdout);
|
|
outputChannel.show(true);
|
|
return;
|
|
}
|
|
|
|
const terminal = vscode.window.createTerminal('PCC Run');
|
|
terminal.show();
|
|
terminal.sendText(`"${output}"`);
|
|
}
|
|
|
|
function activate(context) {
|
|
context.subscriptions.push(
|
|
vscode.commands.registerCommand('pcc.build', cmdBuild),
|
|
vscode.commands.registerCommand('pcc.run', cmdRun)
|
|
);
|
|
console.log('PCC extension activated');
|
|
}
|
|
|
|
function deactivate() { }
|
|
|
|
module.exports = { activate, deactivate };
|