Skip to content

Commit 158bb0f

Browse files
committed
improve: add code action for gcc stubs missed warning
1 parent 837670f commit 158bb0f

7 files changed

Lines changed: 321 additions & 5 deletions

File tree

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,11 @@
538538
}
539539
],
540540
"commands": [
541+
{
542+
"command": "eide.project.create_sys_stubs",
543+
"category": "eide",
544+
"title": "Create gcc system stubs for project"
545+
},
541546
{
542547
"command": "eide.debug.start",
543548
"category": "eide",

res/data/gcc_posix_stubs.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#include <errno.h>
2+
#include <sys/types.h>
3+
#include <sys/stat.h>
4+
#include <sys/times.h>
5+
6+
__attribute__((weak)) int _chown(const char *path, uid_t owner, gid_t group)
7+
{
8+
errno = ENOSYS;
9+
return -1;
10+
}
11+
12+
__attribute__((weak)) int _execve(char *name, char **argv, char **env)
13+
{
14+
errno = ENOSYS;
15+
return -1;
16+
}
17+
18+
__attribute__((weak)) int _fork(void)
19+
{
20+
errno = ENOSYS;
21+
return -1;
22+
}
23+
24+
__attribute__((weak)) int _fstat(int fildes, struct stat *st)
25+
{
26+
errno = ENOSYS;
27+
return -1;
28+
}
29+
30+
__attribute__((weak)) int _getpid(void)
31+
{
32+
errno = ENOSYS;
33+
return -1;
34+
}
35+
36+
struct timeval;
37+
38+
__attribute__((weak)) int _gettimeofday(struct timeval *ptimeval, void *ptimezone)
39+
{
40+
errno = ENOSYS;
41+
return -1;
42+
}
43+
44+
__attribute__((weak)) int _isatty(int file)
45+
{
46+
errno = ENOSYS;
47+
return 0;
48+
}
49+
50+
__attribute__((weak)) int _kill(int pid, int sig)
51+
{
52+
errno = ENOSYS;
53+
return -1;
54+
}
55+
56+
__attribute__((weak)) int _link(char *existing, char *new)
57+
{
58+
errno = ENOSYS;
59+
return -1;
60+
}
61+
62+
__attribute__((weak)) int _lseek(int file, int ptr, int dir)
63+
{
64+
errno = ENOSYS;
65+
return -1;
66+
}
67+
68+
__attribute__((weak)) int _open(char *file, int flags, int mode)
69+
{
70+
errno = ENOSYS;
71+
return -1;
72+
}
73+
74+
__attribute__((weak)) int _close(int fildes)
75+
{
76+
errno = ENOSYS;
77+
return -1;
78+
}
79+
80+
__attribute__((weak)) int _read(int file, char *ptr, int len)
81+
{
82+
errno = ENOSYS;
83+
return -1;
84+
}
85+
86+
__attribute__((weak)) int _readlink(const char *path, char *buf, size_t bufsize)
87+
{
88+
errno = ENOSYS;
89+
return -1;
90+
}
91+
92+
__attribute__((weak)) int _stat(const char *file, struct stat *st)
93+
{
94+
errno = ENOSYS;
95+
return -1;
96+
}
97+
98+
__attribute__((weak)) int _symlink(const char *path1, const char *path2)
99+
{
100+
errno = ENOSYS;
101+
return -1;
102+
}
103+
104+
__attribute__((weak)) clock_t _times(struct tms *buf)
105+
{
106+
errno = ENOSYS;
107+
return -1;
108+
}
109+
110+
__attribute__((weak)) int _unlink(char *name)
111+
{
112+
errno = ENOSYS;
113+
return -1;
114+
}
115+
116+
__attribute__((weak)) int _wait(int *status)
117+
{
118+
errno = ENOSYS;
119+
return -1;
120+
}
121+
122+
__attribute__((weak)) int _write(int file, char *ptr, int len)
123+
{
124+
errno = ENOSYS;
125+
return -1;
126+
}

src/EIDEProject.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,9 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr
12661266
return (<FileGroup[]>this.sourceRoots.getFileGroups()).concat(this.virtualSource.getFileGroups());
12671267
}
12681268

1269+
/**
1270+
* @note Not contains excluded source files. if you want to list all sources, please use getFileGroups
1271+
*/
12691272
getAllSources(): { path: string, virtualPath?: string; }[] {
12701273

12711274
const srcList: { path: string, virtualPath?: string; }[] = [];

src/EIDEProjectExplorer.ts

Lines changed: 124 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ import {
8888
txt_no,
8989
remove_this_item,
9090
view_str$prompt$filesOptionsComment,
91-
view_str$virual_doc_provider_banner
91+
view_str$virual_doc_provider_banner,
92+
view_str$missed_stubs_added
9293
} from './StringTable';
9394
import { CodeBuilder, BuildOptions } from './CodeBuilder';
9495
import { ExceptionToMessage, newMessage } from './Message';
@@ -128,7 +129,7 @@ import {
128129
} from 'vscode-cpptools';
129130
import * as eclipseParser from './EclipseProjectParser';
130131
import { isArray } from 'util';
131-
import { parseIarCompilerLog, CompilerDiagnostics, parseGccCompilerLog, parseArmccCompilerLog, parseKeilc51CompilerLog, parseSdccCompilerLog, parseCosmicStm8CompilerLog } from './ProblemMatcher';
132+
import { parseIarCompilerLog, CompilerDiagnostics, parseGccCompilerLog, parseArmccCompilerLog, parseKeilc51CompilerLog, parseSdccCompilerLog, parseCosmicStm8CompilerLog, EideDiagnosticCode } from './ProblemMatcher';
132133
import * as iarParser from './IarProjectParser';
133134
import * as ArmCpuUtils from './ArmCpuUtils';
134135
import { ShellFlasherIndexItem } from './WebInterface/WebInterface';
@@ -3488,6 +3489,16 @@ export class ProjectExplorer implements CustomConfigurationProvider {
34883489
this._event.emit(event, arg);
34893490
}
34903491

3492+
/**
3493+
*
3494+
* @param callbk return true to break foreach
3495+
*/
3496+
foreachProjects(callbk: (val: AbstractProject, index: number) => boolean | undefined) {
3497+
this.dataProvider.traverseProjects((prj, idx) => {
3498+
return callbk(prj, idx);
3499+
});
3500+
}
3501+
34913502
getProjectByTreeItem(prjItem?: ProjTreeItem): AbstractProject | undefined {
34923503
return prjItem instanceof ProjTreeItem ?
34933504
this.dataProvider.GetProjectByIndex(prjItem.val.projectIndex) :
@@ -3518,6 +3529,36 @@ export class ProjectExplorer implements CustomConfigurationProvider {
35183529

35193530
// -------
35203531

3532+
createSysStubs(prjuid: string | undefined) {
3533+
3534+
const prj = prjuid
3535+
? this.dataProvider.getProjectByUid(prjuid)
3536+
: this.dataProvider.getActiveProject();
3537+
if (!prj)
3538+
return; // no project
3539+
3540+
const tarFile = File.from(prj.getRootDir().path, 'sys_stubs.c');
3541+
for (const grp of prj.getFileGroups()) {
3542+
for (const e of grp.files) {
3543+
if (tarFile.path === e.file.path)
3544+
return; // it's existed, abort.
3545+
}
3546+
}
3547+
3548+
try {
3549+
const srcFile = File.from(ResManager.instance().getAppDataDir().path, 'gcc_posix_stubs.c');
3550+
tarFile.Write(srcFile.Read());
3551+
const vSrcManger = prj.getVirtualSourceManager();
3552+
vSrcManger.addFile(VirtualSource.rootName, tarFile.path);
3553+
// clear diags
3554+
const uri = vscode.Uri.file(File.from(prj.getOutputFolder().path, 'compiler.log').path);
3555+
this.compiler_diags.get(prj.getUid())?.delete(uri);
3556+
GlobalEvent.show_msgbox('Info', view_str$missed_stubs_added.replace('{}', tarFile.name));
3557+
} catch (error) {
3558+
GlobalEvent.show_msgbox('Error', error);
3559+
}
3560+
}
3561+
35213562
openLibsGeneratorConfig(prjItem?: ProjTreeItem) {
35223563

35233564
const proj = this.getProjectByTreeItem(prjItem);
@@ -3871,13 +3912,52 @@ export class ProjectExplorer implements CustomConfigurationProvider {
38713912
}
38723913
}
38733914

3915+
private parseLdLogs(file: File): {content: string, idx: number}[] {
3916+
3917+
const logLines: {content: string, idx: number}[] = [];
3918+
3919+
try {
3920+
3921+
const fileLines = file.Read().split(/\r\n|\n/);
3922+
3923+
let logStarted = false;
3924+
let logEnd = false;
3925+
3926+
fileLines.forEach((line, idx) => {
3927+
3928+
if (logEnd)
3929+
return;
3930+
3931+
if (!logStarted) {
3932+
if (line.startsWith('>>> ld')) {
3933+
logStarted = true;
3934+
}
3935+
} else {
3936+
if (line.startsWith('>>>')) {
3937+
logEnd = true;
3938+
} else {
3939+
logLines.push({
3940+
content: line,
3941+
idx
3942+
});
3943+
}
3944+
}
3945+
});
3946+
3947+
} catch (error) {
3948+
// nothing todo
3949+
}
3950+
3951+
return logLines;
3952+
}
3953+
38743954
private updateCompilerDiagsAfterBuild(prj: AbstractProject) {
38753955

38763956
let diag_res: CompilerDiagnostics | undefined;
38773957

3878-
try {
3958+
const logFile = File.from(prj.getOutputFolder().path, 'compiler.log');
38793959

3880-
const logFile = File.fromArray([prj.getOutputFolder().path, 'compiler.log']);
3960+
try {
38813961

38823962
switch (prj.getToolchain().name) {
38833963
case 'IAR_ARM':
@@ -3906,6 +3986,46 @@ export class ProjectExplorer implements CustomConfigurationProvider {
39063986
GlobalEvent.log_warn(error);
39073987
}
39083988

3989+
if (isGccFamilyToolchain(prj.toolchainName())) {
3990+
// examples:
3991+
// >>> ld
3992+
// ....
3993+
// warning: _getpid is not implemented and will always fail
3994+
const allStubs = [
3995+
'_chown', '_execve', '_fork', '_fstat', '_getpid',
3996+
'_gettimeofday', '_isatty', '_kill', '_link', '_lseek',
3997+
'_open', '_close', '_read', '_readlink', '_stat', '_symlink', '_times', '_unlink', '_wait', '_write',
3998+
];
3999+
const missedStubs: {name: string, lineIdx: number}[] = [];
4000+
4001+
this.parseLdLogs(logFile).forEach(line => {
4002+
const m = /warning: (\w+) is not implemented and will always fail/.exec(line.content);
4003+
if (m && m.length > 1) {
4004+
const name = m[1];
4005+
if (allStubs.includes(name))
4006+
missedStubs.push({ name, lineIdx: line.idx });
4007+
}
4008+
});
4009+
4010+
if (missedStubs.length > 0) {
4011+
if (diag_res == undefined)
4012+
diag_res = {};
4013+
const diags: vscode.Diagnostic[] = [];
4014+
for (const ele of missedStubs) {
4015+
const range = new vscode.Range(
4016+
new vscode.Position(ele.lineIdx, 0),
4017+
new vscode.Position(ele.lineIdx, 54));
4018+
const diag = new vscode.Diagnostic(range,
4019+
`warning: ${ele.name} is not implemented and will always fail`,
4020+
vscode.DiagnosticSeverity.Warning);
4021+
diag.source = "eide";
4022+
diag.code = EideDiagnosticCode.GCC_SYS_STUB_MISSED;
4023+
diags.push(diag);
4024+
}
4025+
diag_res[logFile.path] = diags;
4026+
}
4027+
}
4028+
39094029
if (diag_res) {
39104030

39114031
const uid = prj.getUid();

src/ProblemMatcher.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ function newVscFileRange(line: number, start: number, len: number): vscode.Range
9999

100100
//////////////////////////////////////////////////////////////////////
101101

102+
export enum EideDiagnosticCode {
103+
GCC_SYS_STUB_MISSED = 10,
104+
};
105+
102106
export type CompilerDiagnostics = { [path: string]: vscode.Diagnostic[]; }
103107

104108
export function parseArmccCompilerLog(projApi: ProjectBaseApi, logFile: File): CompilerDiagnostics {

src/StringTable.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,16 @@ export const view_str$env_desc$py3_cmd = [
459459

460460
//---------------Other---------------
461461

462+
export const view_str$missed_stubs_added = [
463+
'桩函数源文件 {} 已经添加到项目。',
464+
'The stubs file "{}" has been added to the project.'
465+
][langIndex];
466+
467+
export const view_str$add_missed_stubs = [
468+
'添加缺失的桩函数',
469+
'Add missed stubs'
470+
][langIndex];
471+
462472
export const view_str$prompt$migrationFailed = [
463473
`迁移旧项目失败!路径:{}`,
464474
`Migrate Old Project Failed ! Path: {}`

0 commit comments

Comments
 (0)