mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-04-19 12:57:17 +00:00
First stop towards compile/verify
This commit is contained in:
parent
c48d80b137
commit
cc79d53dc4
@ -11,6 +11,7 @@ import { ArduinoCommands } from './arduino-commands';
|
||||
import { ConnectedBoards } from './components/connected-boards';
|
||||
import { CoreService } from '../common/protocol/core-service';
|
||||
import { WorkspaceServiceExt } from './workspace-service-ext';
|
||||
import { ToolOutputServiceClient } from '../common/protocol/tool-output-service';
|
||||
|
||||
|
||||
@injectable()
|
||||
@ -28,6 +29,9 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
|
||||
@inject(WorkspaceServiceExt)
|
||||
protected readonly workspaceServiceExt: WorkspaceServiceExt;
|
||||
|
||||
@inject(ToolOutputServiceClient)
|
||||
protected readonly toolOutputServiceClient: ToolOutputServiceClient;
|
||||
|
||||
@postConstruct()
|
||||
protected async init(): Promise<void> {
|
||||
// This is a hack. Otherwise, the backend services won't bind.
|
||||
|
@ -17,8 +17,11 @@ import { BoardsListWidget } from './boards/boards-list-widget';
|
||||
import { BoardsListWidgetFrontendContribution } from './boards/boards-widget-frontend-contribution';
|
||||
import { WorkspaceServiceExt, WorkspaceServiceExtPath } from './workspace-service-ext';
|
||||
import { WorkspaceServiceExtImpl } from './workspace-service-ext-impl';
|
||||
import { ToolOutputServiceClient } from '../common/protocol/tool-output-service';
|
||||
|
||||
import '../../src/browser/style/index.css';
|
||||
import { ToolOutputService } from '../common/protocol/tool-output-service';
|
||||
import { ToolOutputServiceClientImpl } from './tool-output/client-service-impl';
|
||||
|
||||
export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind) => {
|
||||
// Commands and toolbar items
|
||||
@ -58,6 +61,14 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
|
||||
.toDynamicValue(context => WebSocketConnectionProvider.createProxy(context.container, CoreServicePath))
|
||||
.inSingletonScope();
|
||||
|
||||
// Tool output service client
|
||||
bind(ToolOutputServiceClientImpl).toSelf().inSingletonScope();
|
||||
bind(ToolOutputServiceClient).toDynamicValue(context => {
|
||||
const client = context.container.get(ToolOutputServiceClientImpl);
|
||||
WebSocketConnectionProvider.createProxy(context.container, ToolOutputService.SERVICE_PATH, client);
|
||||
return client;
|
||||
}).inSingletonScope();
|
||||
|
||||
// The workspace service extension
|
||||
bind(WorkspaceServiceExt).to(WorkspaceServiceExtImpl).inSingletonScope().onActivation(({ container }, workspaceServiceExt) => {
|
||||
WebSocketConnectionProvider.createProxy(container, WorkspaceServiceExtPath, workspaceServiceExt);
|
||||
|
@ -52,6 +52,7 @@
|
||||
padding: 4px;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
max-height: calc(1em + 4px);
|
||||
}
|
||||
|
||||
.component-list-item .footer {
|
||||
|
@ -0,0 +1,16 @@
|
||||
import { ToolOutputServiceClient } from "../../common/protocol/tool-output-service";
|
||||
import { injectable, inject } from "inversify";
|
||||
import { OutputChannelManager } from "@theia/output/lib/common/output-channel";
|
||||
|
||||
@injectable()
|
||||
export class ToolOutputServiceClientImpl implements ToolOutputServiceClient {
|
||||
|
||||
@inject(OutputChannelManager)
|
||||
protected readonly outputChannelManager: OutputChannelManager;
|
||||
|
||||
onNewOutput(tool: string, chunk: string): void {
|
||||
const channel = this.outputChannelManager.getChannel(`Arduino: ${tool}`);
|
||||
channel.append(chunk);
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
export const CoreServicePath = '/services/core-service';
|
||||
export const CoreService = Symbol('CoreService');
|
||||
export interface CoreService {
|
||||
compile(options: CoreService.Compile.Options): Promise<string>;
|
||||
compile(options: CoreService.Compile.Options): Promise<void>;
|
||||
upload(): Promise<void>;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
import { JsonRpcServer } from "@theia/core";
|
||||
|
||||
export const ToolOutputServiceServer = Symbol("ToolOutputServiceServer");
|
||||
export interface ToolOutputServiceServer extends JsonRpcServer<ToolOutputServiceClient> {
|
||||
publishNewOutput(tool: string, chunk: string): void;
|
||||
disposeClient(client: ToolOutputServiceClient): void;
|
||||
}
|
||||
|
||||
export const ToolOutputServiceClient = Symbol("ToolOutputServiceClient");
|
||||
export interface ToolOutputServiceClient {
|
||||
onNewOutput(tool: string, chunk: string): void;
|
||||
}
|
||||
|
||||
export namespace ToolOutputService {
|
||||
export const SERVICE_PATH = "/tool-output-service";
|
||||
}
|
@ -12,6 +12,9 @@ import { ConnectionContainerModule } from '@theia/core/lib/node/messaging/connec
|
||||
import { WorkspaceServiceExtPath, WorkspaceServiceExt } from '../browser/workspace-service-ext';
|
||||
import { CoreClientProviderImpl } from './core-client-provider-impl';
|
||||
import { CoreClientProviderPath, CoreClientProvider } from './core-client-provider';
|
||||
import { ToolOutputService, ToolOutputServiceClient, ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
import { ConnectionHandler, JsonRpcConnectionHandler } from '@theia/core';
|
||||
import { ToolOutputServiceServerImpl } from './tool-output-service-impl';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(ArduinoDaemon).toSelf().inSingletonScope();
|
||||
@ -51,6 +54,17 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
});
|
||||
bind(ConnectionContainerModule).toConstantValue(connectionConnectionModule);
|
||||
|
||||
// Tool output service -> feedback from the daemon, compile and flash
|
||||
bind(ToolOutputServiceServer).to(ToolOutputServiceServerImpl).inSingletonScope();
|
||||
bind(ConnectionHandler).toDynamicValue(context =>
|
||||
new JsonRpcConnectionHandler<ToolOutputServiceClient>(ToolOutputService.SERVICE_PATH, client => {
|
||||
const server = context.container.get<ToolOutputServiceServer>(ToolOutputServiceServer);
|
||||
server.setClient(client);
|
||||
client.onDidCloseConnection(() => server.disposeClient(client));
|
||||
return server;
|
||||
})
|
||||
).inSingletonScope();
|
||||
|
||||
// Bind the workspace service extension to the backend per Theia connection.
|
||||
// So that we can access the workspace roots of the frontend.
|
||||
const workspaceServiceExtConnectionModule = ConnectionContainerModule.create(({ bindFrontendService }) => {
|
||||
|
@ -6,6 +6,7 @@ import { ILogger } from '@theia/core/lib/common/logger';
|
||||
import { BackendApplicationContribution } from '@theia/core/lib/node';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import { DaemonLog } from './daemon-log';
|
||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
|
||||
const EXECUTABLE_PATH = resolve(join(__dirname, '..', '..', 'build', `arduino-cli.${os.platform()}`))
|
||||
|
||||
@ -16,6 +17,9 @@ export class ArduinoDaemon implements BackendApplicationContribution {
|
||||
@named('daemon')
|
||||
protected readonly logger: ILogger
|
||||
|
||||
@inject(ToolOutputServiceServer)
|
||||
protected readonly toolOutputService: ToolOutputServiceServer;
|
||||
|
||||
protected isReady = new Deferred<boolean>();
|
||||
|
||||
async onStart() {
|
||||
@ -28,10 +32,16 @@ export class ArduinoDaemon implements BackendApplicationContribution {
|
||||
console.log(stdout);
|
||||
});
|
||||
if (daemon.stdout) {
|
||||
daemon.stdout.on('data', data => DaemonLog.log(this.logger, data.toString()));
|
||||
daemon.stdout.on('data', data => {
|
||||
this.toolOutputService.publishNewOutput("daeomn", data.toString());
|
||||
DaemonLog.log(this.logger, data.toString());
|
||||
});
|
||||
}
|
||||
if (daemon.stderr) {
|
||||
daemon.stderr.on('data', data => DaemonLog.log(this.logger, data.toString()));
|
||||
daemon.stderr.on('data', data => {
|
||||
this.toolOutputService.publishNewOutput("daeomn error", data.toString());
|
||||
DaemonLog.log(this.logger, data.toString());
|
||||
});
|
||||
}
|
||||
if (daemon.stderr) {
|
||||
daemon.on('exit', (code, signal) => DaemonLog.log(this.logger, `Daemon exited with code: ${code}. Signal was: ${signal}.`));
|
||||
|
@ -66,10 +66,10 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
const [ platform, boardName ] = board.id.split(":");
|
||||
|
||||
const req = new PlatformInstallReq();
|
||||
req.setInstance(instance);
|
||||
req.setArchitecture(boardName);
|
||||
req.setPlatformPackage(platform);
|
||||
req.setVersion(board.availableVersions[0]);
|
||||
req.setInstance(instance);
|
||||
|
||||
console.info("Starting board installation", board);
|
||||
const resp = client.platformInstall(req);
|
||||
|
@ -84,6 +84,24 @@ export class CoreClientProviderImpl implements CoreClientProvider {
|
||||
updateResp.on('end', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
// {
|
||||
// const installBuiltinPkgReq = new PlatformInstallReq();
|
||||
// installBuiltinPkgReq.setInstance(instance);
|
||||
// installBuiltinPkgReq.setPlatformPackage("builtin");
|
||||
// const resp = client.platformInstall(installBuiltinPkgReq);
|
||||
// resp.on('data', (r: PlatformInstallResp) => {
|
||||
// const prog = r.getProgress();
|
||||
// if (prog) {
|
||||
// console.info(`downloading ${prog.getFile()}: ${prog.getCompleted()}%`)
|
||||
// }
|
||||
// });
|
||||
// await new Promise<void>((resolve, reject) => {
|
||||
// resp.on('end', resolve);
|
||||
// resp.on('error', reject);
|
||||
// });
|
||||
// }
|
||||
|
||||
// TODO: revisit this!!!
|
||||
// `updateResp.on('data'` is called only when running, for instance, `compile`. It does not run eagerly.
|
||||
// await new Promise<void>((resolve, reject) => {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { FileSystem } from '@theia/filesystem/lib/common/filesystem';
|
||||
import { CoreService } from '../common/protocol/core-service';
|
||||
import { CompileReq } from './cli-protocol/compile_pb';
|
||||
import { CompileReq, CompileResp } from './cli-protocol/compile_pb';
|
||||
import { BoardsService } from '../common/protocol/boards-service';
|
||||
import { CoreClientProvider } from './core-client-provider';
|
||||
import { PlatformInstallReq } from './cli-protocol/core_pb';
|
||||
import { LibraryInstallReq } from './cli-protocol/lib_pb';
|
||||
import * as path from 'path';
|
||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
|
||||
@injectable()
|
||||
export class CoreServiceImpl implements CoreService {
|
||||
@ -19,13 +19,17 @@ export class CoreServiceImpl implements CoreService {
|
||||
@inject(BoardsService)
|
||||
protected readonly boardsService: BoardsService;
|
||||
|
||||
async compile(options: CoreService.Compile.Options): Promise<string> {
|
||||
@inject(ToolOutputServiceServer)
|
||||
protected readonly toolOutputService: ToolOutputServiceServer;
|
||||
|
||||
async compile(options: CoreService.Compile.Options): Promise<void> {
|
||||
console.log('compile', options);
|
||||
const { uri } = options;
|
||||
const sketchpath = await this.fileSystem.getFsPath(options.uri);
|
||||
if (!sketchpath) {
|
||||
const sketchFilePath = await this.fileSystem.getFsPath(options.uri);
|
||||
if (!sketchFilePath) {
|
||||
throw new Error(`Cannot resolve filesystem path for URI: ${uri}.`);
|
||||
}
|
||||
const sketchpath = path.dirname(sketchFilePath);
|
||||
|
||||
const { client, instance } = await this.coreClientProvider.getClient(uri);
|
||||
// const boards = await this.boardsService.connectedBoards();
|
||||
@ -34,38 +38,30 @@ export class CoreServiceImpl implements CoreService {
|
||||
// }
|
||||
// https://github.com/cmaglie/arduino-cli/blob/bd5e78701e7546787649d3cca6b21c5d22d0e438/cli/compile/compile.go#L78-L88
|
||||
|
||||
const installLibReq = new LibraryInstallReq();
|
||||
installLibReq.setInstance(instance);
|
||||
installLibReq.setName('arduino:samd');
|
||||
const installResp = client.libraryInstall(installLibReq);
|
||||
const xxx = await new Promise<string>((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
installResp.on('data', (chunk: Buffer) => chunks.push(chunk));
|
||||
installResp.on('error', error => reject(error));
|
||||
installResp.on('end', () => resolve(Buffer.concat(chunks).toString('utf8').trim()))
|
||||
});
|
||||
console.log('xxx', xxx);
|
||||
|
||||
const compilerReq = new CompileReq();
|
||||
compilerReq.setInstance(instance);
|
||||
compilerReq.setSketchpath(sketchpath);
|
||||
compilerReq.setFqbn('arduino:samd'/*boards.current.name*/);
|
||||
compilerReq.setFqbn('arduino:avr:uno'/*boards.current.name*/);
|
||||
// request.setShowproperties(false);
|
||||
// request.setPreprocess(false);
|
||||
compilerReq.setPreprocess(false);
|
||||
// request.setBuildcachepath('');
|
||||
// request.setBuildpath('');
|
||||
// compilerReq.setBuildpath('/tmp/build');
|
||||
// compilerReq.setShowproperties(true);
|
||||
// request.setBuildpropertiesList([]);
|
||||
// request.setWarnings('none');
|
||||
// request.setVerbose(true);
|
||||
// request.setQuiet(false);
|
||||
compilerReq.setVerbose(true);
|
||||
compilerReq.setQuiet(false);
|
||||
// request.setVidpid('');
|
||||
// request.setExportfile('');
|
||||
|
||||
const result = client.compile(compilerReq);
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
result.on('data', (chunk: Buffer) => chunks.push(chunk));
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
result.on('data', (cr: CompileResp) => {
|
||||
this.toolOutputService.publishNewOutput("compile", new Buffer(cr.getOutStream_asU8()).toString());
|
||||
console.error(cr.getErrStream().toString());
|
||||
});
|
||||
result.on('error', error => reject(error));
|
||||
result.on('end', () => resolve(Buffer.concat(chunks).toString('utf8').trim()))
|
||||
result.on('end', () => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
|
28
arduino-ide-extension/src/node/tool-output-service-impl.ts
Normal file
28
arduino-ide-extension/src/node/tool-output-service-impl.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { injectable } from "inversify";
|
||||
import { ToolOutputServiceServer, ToolOutputServiceClient } from "../common/protocol/tool-output-service";
|
||||
|
||||
@injectable()
|
||||
export class ToolOutputServiceServerImpl implements ToolOutputServiceServer {
|
||||
protected clients: ToolOutputServiceClient[] = [];
|
||||
|
||||
publishNewOutput(tool: string, chunk: string): void {
|
||||
this.clients.forEach(c => c.onNewOutput(tool, chunk));
|
||||
}
|
||||
|
||||
setClient(client: ToolOutputServiceClient | undefined): void {
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clients.push(client);
|
||||
}
|
||||
|
||||
disposeClient(client: ToolOutputServiceClient): void {
|
||||
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.clients = [];
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user