1- import fastify from 'fastify' ;
2- import fs from 'fs' ;
31import { mkdirSync , writeFileSync , existsSync , openSync , closeSync , readFileSync , renameSync , rmSync , unlinkSync } from "fs" ;
42import { deflateSync } from "zlib" ;
53import { execSync } from "child_process" ;
64import { z } from 'zod' ;
7- import fastifyCors from 'fastify-cors' ;
8- import fastifyWebSocket from 'fastify-websocket' ;
9-
10- const server = fastify ( ) ;
11-
12- server . register ( fastifyCors , {
13- // put your options here
14- origin : '*'
15- } )
16- server . register ( fastifyWebSocket ) ;
175
186// Compilation code
197const llvmDir = process . cwd ( ) + "/clang/wasi-sdk" ;
208const tempDir = "/tmp" ;
219const sysroot = llvmDir + "/share/wasi-sysroot" ;
10+ const defaultHeaderDir = '/app/clang/includes' ;
2211
2312export interface ResponseData {
2413 success : boolean ;
@@ -35,20 +24,27 @@ export interface Task {
3524 output ?: string ;
3625}
3726
38- const requestBodySchema = z . object ( {
27+ export const requestBodySchema = z . object ( {
3928 output : z . enum ( [ 'wasm' ] ) ,
4029 files : z . array ( z . object ( {
4130 type : z . string ( ) ,
4231 name : z . string ( ) ,
4332 options : z . string ( ) . optional ( ) ,
4433 src : z . string ( )
4534 } ) ) ,
35+ headers : z . array (
36+ z . object ( {
37+ type : z . string ( ) ,
38+ name : z . string ( ) ,
39+ src : z . string ( ) ,
40+ } )
41+ ) . optional ( ) ,
4642 link_options : z . string ( ) . optional ( ) ,
4743 compress : z . boolean ( ) . optional ( ) ,
4844 strip : z . boolean ( ) . optional ( )
4945} ) ;
5046
51- type RequestBody = z . infer < typeof requestBodySchema > ;
47+ export type RequestBody = z . infer < typeof requestBodySchema > ;
5248
5349// Input: JSON in the following format
5450// {
@@ -130,9 +126,12 @@ function get_optimization_options() {
130126 return options . join ( ' ' ) ;
131127}
132128
133- function get_clang_options ( ) {
134- const clang_flags = `--sysroot=${ sysroot } -xc -I/app/clang/includes -fdiagnostics-print-source-range-info -Werror=implicit-function-declaration` ;
129+ function get_include_path ( include_path : string ) {
130+ return `-I${ include_path } ` ;
131+ }
135132
133+ function get_clang_options ( ) {
134+ const clang_flags = `--sysroot=${ sysroot } -xc -fdiagnostics-print-source-range-info -Werror=implicit-function-declaration` ;
136135 return clang_flags ;
137136}
138137
@@ -173,12 +172,10 @@ function validate_filename(name: string) {
173172 return parts ;
174173}
175174
176- function link_c_files ( source_files : string [ ] , link_options : string , cwd : string , output : string , result_obj : Task ) {
175+ function link_c_files ( source_files : string [ ] , include_path : string , link_options : string , cwd : string , output : string , result_obj : Task ) {
177176 const files = source_files . join ( ' ' ) ;
178177 const clang = llvmDir + '/bin/clang' ;
179-
180- const cmd = clang + ' ' + optimization_level + ' ' + get_clang_options ( ) + ' ' + get_lld_options ( link_options ) + ' ' + files + ' -o ' + output ;
181-
178+ const cmd = clang + ' ' + optimization_level + ' ' + get_clang_options ( ) + ' ' + get_lld_options ( link_options ) + ' ' + files + ' -o ' + output + ' ' + get_include_path ( include_path ) ;
182179 const out = shell_exec ( cmd , cwd ) ;
183180 result_obj . console = sanitize_shell_output ( out ) ;
184181 if ( ! existsSync ( output ) ) {
@@ -266,6 +263,7 @@ export function build_project(project: RequestBody, base: string) {
266263 } ;
267264 const dir = base + '.$' ;
268265 const result = base + '.wasm' ;
266+ const customHeadersDir = dir + "/includes" ;
269267
270268 const complete = ( success : boolean , message : string ) => {
271269 rmSync ( dir , { recursive : true } ) ;
@@ -292,7 +290,13 @@ export function build_project(project: RequestBody, base: string) {
292290 mkdirSync ( dir ) ;
293291 }
294292
293+ const headerFiles = project . headers ;
294+ if ( ! existsSync ( customHeadersDir ) ) {
295+ mkdirSync ( customHeadersDir ) ;
296+ }
297+
295298 const sources = [ ] ;
299+ const headers = [ ] ;
296300 let options ;
297301 for ( let file of files ) {
298302 const name = file . name ;
@@ -316,12 +320,30 @@ export function build_project(project: RequestBody, base: string) {
316320
317321 writeFileSync ( fileName , src ) ;
318322 }
323+
324+ if ( headerFiles ) {
325+ for ( let file of headerFiles ) {
326+ const name = file . name ;
327+ if ( ! validate_filename ( name ) ) {
328+ return complete ( false , "Invalid filename " + name ) ;
329+ }
330+ let fileName = customHeadersDir + "/" + name ;
331+ headers . push ( fileName ) ;
332+
333+ const src = file . src ;
334+ if ( ! src ) {
335+ return complete ( false , "Header file " + name + " is empty" ) ;
336+ }
337+ writeFileSync ( fileName , src ) ;
338+ }
339+ }
319340 const link_options = project . link_options ;
320341 const link_result_obj = {
321342 name : 'building wasm'
322343 } ;
323344 build_result . tasks . push ( link_result_obj ) ;
324- if ( ! link_c_files ( sources , link_options || '' , dir , result , link_result_obj ) ) {
345+
346+ if ( ! link_c_files ( sources , headerFiles && headers ?. length ? customHeadersDir : defaultHeaderDir , link_options || '' , dir , result , link_result_obj ) ) {
325347 return complete ( false , 'Build error' ) ;
326348 }
327349
0 commit comments