Rewrite build script in python, use JSON5 for configuration

This commit is contained in:
flysand7 2023-07-27 09:17:57 +11:00
parent 7329ca1f92
commit 7e6066ff85
10 changed files with 318 additions and 574 deletions

6
.gitignore vendored
View File

@ -1,4 +1,5 @@
bin
/bin
/lib
/a
/src/ciabatta.c
a.out
@ -13,6 +14,7 @@ a.out
*.o
*.4coder
*.rdbg
*.iface.h
/.venv
tinyrt-iface.h
test/
test_folder/

228
build.lua
View File

@ -1,228 +0,0 @@
#!/usr/bin/env lua
local path = require 'path'
local argparse = require 'argparse'
local mf_parser = require 'scripts.manifest-parser'
-- Parse command line arguments
local parser = argparse('build.lua', 'Ciabatta build script')
parser:flag('-c --clean', 'Remove all the binaries before recompiling')
parser:flag('-o --only', 'Do not compile ciabatta')
parser:flag('-r --release', 'Compile the release version (without it will compile everything in debug mode)')
parser:option('-p --platform', 'OS to compile for (linux, windows)')
parser:option('-l --library', 'Type of library to compile (static, shared)')
parser:option('-t --test', 'Compile a C file and link the library against it')
parser:option('--options', 'Additional options to provide to the executable')
local args = parser:parse()
local is_clean = args.clean or false
local is_only = args.only or false
local is_release = args.release or false
local platform = args.platform or 'linux'
local library_type = args.library or 'static'
local test_file = args.test
local compiler_options = args.options or ''
-- Clean the build files if needed
function rmdir(p)
if not path.exists(p) then
return
end
path.each(path.join(p,"*"), function(P) path.remove(P) end,
{param = "f",delay = true,recurse = true,reverse = true})
path.remove(p)
end
if is_clean then
print('Cleaning files..')
rmdir('lib')
rmdir('bin')
os.remove('a')
os.remove('a.exe')
end
-- If we only needed to clean the build files, just exit here
if is_only then
os.exit(0)
end
local assembler = 'nasm'
local compiler = 'clang'
local linker = 'ld'
local includes = {'./include'}
local compiler_defines = {}
local compiler_flags = {'-nostdlib'}
local ciabatta_lib = ''
-- Figure out additional flags
if is_release then
table.insert(compiler_flags, '-O2')
table.insert(compiler_defines, 'NDEBUG')
else
table.insert(compiler_flags, '-g')
table.insert(compiler_flags, '-O0')
table.insert(compiler_defines, 'CIA_DEBUG')
end
if library_type == 'static' then
ciabatta_lib = 'ciabatta.a'
if platform == 'windows' then
ciabatta_lib = 'ciabatta.lib'
end
elseif library_type == 'shared' then
ciabatta_lib = 'ciabatta.so'
if platform == 'windows' then
ciabatta_lib = 'ciabatta.dll'
end
else
print('Invalid library type: ' .. library_type)
end
-- Turn flags into table
function map(t, f)
local t1 = {}
local t_len = #t
for i = 1, t_len do
t1[i] = f(t[i])
end
return t1
end
function quote(str)
return '"'..str..'"'
end
function prefix(prefix)
return function(str)
return prefix..str
end
end
function prefix_quote(prefix)
return function(str)
return prefix..'"'..str..'"'
end
end
-- Generate TinyRT interface file for the platform
print('==> Generating TinyRT interface definitions')
local tinyrt_manifest_path = path.join('src', platform, 'tinyrt.mf')
if not path.exists(tinyrt_manifest_path) then
print('ERROR: tinyrt manifest wasnt found: '..tinyrt_manifest_path)
end
tinyrt_iface_hdr = io.open(path.join('src', platform, 'tinyrt.iface.h'), 'wb')
tinyrt_iface_hdr:write('\n')
tinyrt_iface_hdr:write('// This file is AUTO-GENERATED\n')
tinyrt_iface_hdr:write('// See tinyrt.mf\n')
tinyrt_iface_hdr:write('\n')
n = 1
tinyrt_apis = {}
for line in io.lines(tinyrt_manifest_path) do
if line:len() ~= 0 and line:sub(1,1) ~= '#' and line:gsub('%s+', '') ~= '' then
local line_it = line:gmatch('[_a-zA-Z0-9]+')
local api_name = line_it()
local has_impl = line_it()
if has_impl == '0' or has_impl == '1' then
local api_define = '#define ' .. (api_name:upper()) .. ' '..has_impl..'\n'
tinyrt_iface_hdr:write(api_define)
table.insert(tinyrt_apis, api_name)
else
print('SYNTAX ERROR AT LINE '..n..': Expected 1 or 0 for the value')
end
end
n = n+1
end
io.close(tinyrt_iface_hdr)
-- Parse manifest and generate ciabatta.c
local function has_value(tab, val)
for index, value in ipairs(tab) do
if value == val then
return true
end
end
return false
end
print('==> Generating ciabatta.c')
cia_h = io.open(path.join('src', 'ciabatta.c'), 'wb')
mf = parse_mf(path.join('src', 'library.mf'))
cia_h:write('\n')
cia_h:write('// THIS FILE IS AUTO-GENERATED. SEE library.mf FOR DETAILS\n')
cia_h:write('\n// global includes\n')
for index,include in ipairs(mf.includes) do
cia_h:write('#include <'..include..'>\n')
end
for index,decl_platform in ipairs(mf.platforms) do
if decl_platform.name == platform then
cia_h:write(('\n// platform %s\n'):format(decl_platform.name))
for index,include in ipairs(decl_platform.includes) do
cia_h:write('#include "'..include..'"\n')
end
end
end
for index, api in ipairs(mf.apis) do
supported = true
for index, dep in ipairs(api.deps) do
if not has_value(tinyrt_apis, dep) then
supported = false
end
end
if supported then
cia_h:write(('\n// module %s\n'):format(api.name))
print(' - Exporting module: ' .. api.name)
for index, include in ipairs(api.includes) do
cia_h:write('#include "'..include..'"\n')
end
end
end
io.close(cia_h)
-- Figure out compiler flags
local cflags = table.concat(compiler_flags, ' ')..' '..
table.concat(map(compiler_defines, prefix('-D ')), ' ')..' '..
table.concat(map(includes, prefix_quote('-I ')), ' ')..' '
print('==> Compiling ciabatta')
print('Flags: ' .. cflags)
-- Functions for compiling, linking and assembling individual files
function assemble(src, out)
local format = 'elf64'
if platform == 'windows' then
format = 'win64'
end
local cmdline = 'nasm -f '..format..' "'..src..'" -o "'..out..'"'
print('> '..cmdline)
os.execute(cmdline)
end
function compile(srcs, out, additional_flags)
local flags = (additional_flags or '')..' '..cflags
local inputs = table.concat(map(srcs, quote), ' ')
local cmdline = 'clang '..flags..' '..inputs..' -o '..quote(out)..''
print('> '..cmdline)
os.execute(cmdline)
end
function archive(srcs, out)
os.remove(out)
local inputs = table.concat(map(srcs, quote), ' ')
local cmdline = 'llvm-ar -rcs '..quote(out)..' '..inputs
print('> '..cmdline)
os.execute(cmdline)
end
-- Build ciabatta
path.mkdir('lib')
path.mkdir('bin')
assemble('src/linux/crt-entry.asm', 'bin/crt-entry.o')
compile({'src/linux/crt-ctors.c'}, 'bin/crt-ctors.o', '-fpic -c')
compile({'src/ciabatta.c'}, 'bin/ciabatta.o', '-fpic -c')
if library_type == 'static' then
archive({'bin/ciabatta.o', 'bin/crt-ctors.o', 'bin/crt-entry.o'}, 'lib/'..ciabatta_lib)
elseif library_type == 'shared' then
print('SHARED OBJECTS NOT SUPPORTED YET')
os.exit(1)
end
if test_file then
compile({test_file, 'lib/'..ciabatta_lib}, 'a', '-pie')
end

223
build.py Executable file
View File

@ -0,0 +1,223 @@
#!/usr/bin/env python3
import argparse # Parsing command-line args
import platform # Checking current OS
import shutil
import os
import sys
import pyjson5
dependencies = [
'nasm',
'llvm-ar'
]
# Parse command line arguments
arg_parser = argparse.ArgumentParser('build.py')
arg_parser.add_argument('--clean', action='store_true', help='Remove all object files and binaries')
arg_parser.add_argument('--test', help='Compile ciabatta executable with given file')
arg_parser.add_argument('--mode', '-m', choices=['debug', 'release'], default='debug', help='Select build configuration')
arg_parser.add_argument('--target', '-t', help='Select target OS (default=host)')
arg_parser.add_argument('--compiler', '-c', choices=['clang', 'cuik'], default='clang', help='Select compiler')
arg_parser.add_argument('--cflags', nargs='*', default=[], help='Pass additional compiler flags')
args = arg_parser.parse_args()
compiler = args.compiler
print('==> Performing basic checks')
# Perform cleaning if required
if args.clean:
shutil.rmtree('bin')
shutil.rmtree('lib')
os.remove(os.path.join('src', 'ciabatta.c'))
os.remove('a')
sys.exit(0)
# Check host OS
target = args.target
if target is None:
host_os = platform.system().lower()
print(f" -> Compiling for host OS: '{host_os}'")
if not os.path.exists(os.path.join('src', host_os)):
print(f" -> [ERROR] OS '{host_os}' isn't implemented.")
sys.exit(1)
target = host_os
# Add compiler to dependencies
dependencies.append(args.compiler)
# Check dependencies
print('==> Checking dependencies')
for dependency in dependencies:
if shutil.which(dependency) is None:
print(f" -> [ERROR] Missing dependency: '{dependency}'")
sys.exit(1)
print(' -> Everything OK')
# Figure out the flags
includes = ['include']
cc = ''
cc_defines = []
cc_flags = ['-nostdlib']
crt_file = 'crt.lib'
lib_file = 'cia.lib'
cc = args.compiler
if args.mode == 'release':
cc_flags.append('-O2')
cc_defines.append('NDEBUG')
else: # 'debug'
cc_flags.append('-g')
cc_flags.append('-O0')
cc_defines.append('DEBUG')
# Generate TinyRT headers for the target platform
print(f"==> Generating TinyRT header for {target}")
tinyrt_config_path = os.path.join('src', target, 'tinyrt.json')
tinyrt_apis = []
try:
print(f" -> Reading file '{tinyrt_config_path}'")
with open(tinyrt_config_path, 'r') as tinyrt_config_file:
tinyrt_config = pyjson5.load(tinyrt_config_file)
except Exception as error:
print(f" -> [ERROR] reading file '{tinyrt_config_path}'")
print(f" * {error}")
sys.exit(1)
tinyrt_header_path = os.path.join('src', target, 'tinyrt-iface.h')
try:
print(f" -> Writing to file '{tinyrt_header_path}'")
with open(tinyrt_header_path, 'w') as tinyrt_header_file:
tinyrt_header_file.write('\n')
tinyrt_header_file.write(f'// This file is AUTO-GENERATED from {tinyrt_config_path}\n')
tinyrt_header_file.write('\n')
for tinyrt_api in tinyrt_config:
api_name = tinyrt_api
is_defined = tinyrt_config[tinyrt_api]
if is_defined:
tinyrt_apis.append(api_name)
is_defined_int = 1 if is_defined else 0
tinyrt_header_file.write(f'#define {api_name.upper()} {is_defined_int}\n')
except Exception as error:
print(f" -> [ERROR] writing to file '{tinyrt_header_path}'")
print(f" * {error}")
sys.exit(1)
print(' -> TinyRT header generated')
# Generate ciabatta header for the target platform and configuration
print(f"==> Generating ciabatta.c")
library_config_path = os.path.join('src', 'library.json')
try:
print(f" -> Reading file '{library_config_path}'")
with open(library_config_path, 'r') as library_config_file:
library_config = pyjson5.load(library_config_file)
except Exception as error:
print(f" -> [ERROR] reading file '{library_config_path}'")
print(f" * {error}")
sys.exit(1)
ciabatta_header_path = os.path.join('src', 'ciabatta.c')
try:
print(f" -> Writing to file '{ciabatta_header_path}'")
with open(ciabatta_header_path, 'w') as ciabatta_header:
# Write heading
ciabatta_header.write('\n')
ciabatta_header.write('// This file is AUTO-GENERATED by library.json\n')
ciabatta_header.write('\n')
# Write includes
for include in library_config['includes']:
ciabatta_header.write(f'#include <{include}>\n')
ciabatta_header.write('\n')
# Write platform includes
platform_config = None
for platform in library_config['platforms']:
if platform['name'] == target:
platform_config = platform
if platform_config is None:
print(f" -> [ERROR] library config doesn't contain configuration for platform {target}")
for include in platform_config['includes']:
include_path = os.path.join(platform_config['path'], include)
ciabatta_header.write(f'#include "{include_path}"\n')
ciabatta_header.write(f'#include "{target}/tinyrt-iface.h"\n')
ciabatta_header.write(f'#include "tinyrt.h"\n')
for tinyrt_source in platform_config['tinyrt']:
ciabatta_header.write(f'#include "{target}/{tinyrt_source}"\n')
# Write API includes
ciabatta_header.write('\n')
for api in library_config['apis']:
api_name = api['name']
api_path = api['path']
tinyrt_satisfied = True
for req in api['reqs']:
if not (req in tinyrt_apis):
tinyrt_satisfied = False
break
if not tinyrt_satisfied:
print(f" -> Not exporting API '{api_name}'")
else:
print(f" * Exporting API '{api_name}'")
ciabatta_header.write(f'// Module {api_name}\n')
for include in api['includes']:
ciabatta_header.write(f'#include "{api_path}/{include}"\n')
except Exception as error:
print(f" -> [ERROR] writing file '{ciabatta_header_path}'")
print(f" * {error}")
sys.exit(1)
def quote(s):
return '"' + s + '"'
def prefix(prefix):
return (lambda s: prefix + s)
def prefix_quote(prefix):
return (lambda s: prefix + '"' + s + '"')
cc_flags_str = ' '.join(
cc_flags +
list(map(prefix('-D '), cc_defines)) +
list(map(prefix_quote('-I '), includes)))
print(f"==> Compiling {lib_file}")
print(' * Compiler flags:', cc_flags_str)
def assemble(src, out):
format = 'elf64'
if target == 'windows':
format = 'win64'
cmdline = f'nasm -f "{format}" "{src}" -o "{out}"'
print(' >', cmdline)
code = os.system(cmdline)
if code != 0:
sys.exit(code)
def compile(srcs, out, extra_flags = ''):
flags = cc_flags_str + ' ' + extra_flags + ' '.join(args.cflags)
inputs = ' '.join(map(quote, srcs))
cmdline = f'{compiler} {flags} {inputs} -o {quote(out)}'
print(' >', cmdline)
code = os.system(cmdline)
if code != 0:
sys.exit(code)
def archive(srcs, out):
inputs = ' '.join(map(quote, srcs))
cmdline = f'llvm-ar -rcs {quote(out)} {inputs}'
print(' >', cmdline)
code = os.system(cmdline)
if code != 0:
sys.exit(code)
# Ciabatta build spec
if not os.path.exists('lib'):
os.mkdir('lib')
if not os.path.exists('bin'):
os.mkdir('bin')
p = os.path.join
assemble(p('src', 'linux', 'crt-entry.asm'), p('bin', 'crt-entry.o'))
compile([p('src', 'linux', 'crt-ctors.c')], p('bin', 'crt-ctors.o'), '-fpic -c')
compile([p('src', 'ciabatta.c')], p('bin', 'ciabatta.o'), '-fpic -c')
archive([p('bin', 'ciabatta.o'), p('bin', 'crt-ctors.o'), p('bin', 'crt-entry.o')], p('lib', lib_file))
if args.test:
compile([args.test, p('lib', lib_file)], 'a', '-pie')

View File

@ -44,13 +44,10 @@ Before proceeding please note that ciabatta can only be compiled and used
with `clang`. It may be able to work with `gcc` with some minor adjustments
but I didn't test.
For executing the script you will need lua and some lua dependencies that
you can install with luarocks:
For executing the script you will need at least python 3.3 and the pyjson5 package
```
$ luarocks install luafilesystem
$ luarocks install lua-path
$ luarocks install argparse
$ pip install pyjson5
```
### Building
@ -59,17 +56,17 @@ On linux you can simply run `./build.lua` script. On windows you have to run
it like `lua build.lua`. Reference for command-line options:
```
Usage: build.lua [-h] [-c] [-o] [-r] [-p <platform>] [-l <library>]
[-t <test>] [--options <options>]
Usage: build.py [-h] [--clean] [--test TEST]
[--mode {debug,release}] [--target TARGET]
[--compiler {clang,cuik}] [--cflags [CFLAGS ...]]
Options:
-h, --help Show this help message and exit.
-c, --clean Remove all the binaries before recompiling
-o, --only Do not compile ciabatta
-r, --release Compile the release version (without it will compile everything in debug mode)
-p --platform <platform> OS to compile for (linux, windows)
-l --library <library> Type of library to compile (static, shared)
-t --test <test> Compile a C file and link the library against it
--options <options> Additional options to provide to the executable
-h, --help show this help message and exit
--clean Remove all object files and binaries
--test TEST Compile ciabatta executable with given file
--mode, -m {debug,release} Select build configuration
--target, -t TARGET Select target OS (default=host)
--compiler, -c {clang,cuik} Select compiler
--cflags [CFLAGS ...] Pass additional compiler flags
```
## Usage

View File

@ -1,265 +0,0 @@
#!/usr/bin/env lua
local path = require 'path'
levels = {}
parser_obj = {}
parser_cur_ind = 0
parser_ind_lv = 0
-- Tokens
Token = {}
function Token.new(kind, value)
return {kind = kind, value = value}
end
function Token.keyword(kw) return Token.new('keyword', kw) end
function Token.string(str) return Token.new('string', str) end
function Token.lparen() return Token.new('(', nil) end
function Token.rparen() return Token.new(')', nil) end
function Token.lbrace() return Token.new('{', nil) end
function Token.rbrace() return Token.new('}', nil) end
function Token.colon() return Token.new(':', nil) end
function Token.comma() return Token.new(',', nil) end
function Token.eof() return Token.new('eof', nil) end
Parser = {
file = nil,
filename = nil,
row = 0,
col = 0,
ind_spaces = 0,
ind_levels = {0},
c = nil, -- Last Read Character
t = nil, -- Last Read Token
}
-- Character functions
function Parser.char_next(parser, c)
char = parser.file:read(1)
parser.col = parser.col + 1
if char == '\n' then
parser.row = parser.row + 1
parser.col = 0
end
parser.c = char
end
function Parser.char(parser)
return parser.c
end
function Parser.char_is(parser, pattern)
match = parser:char():match(pattern)
if match then
return true
else
return false
end
end
function Parser.char_match(parser, pattern)
if parser:char_is(pattern) then
parser:char_next()
return true
end
return false
end
-- Token functions
function Parser.token(parser)
return parser.t
end
function Parser.token_next(parser)
-- Skip over the whitespace
while true do
if parser.c == nil then
parser.t = Token.eof()
return
elseif parser:char_match('#') then
while not parser:char_match('\n') do
parser:char_next()
end
elseif parser:char_is('%s') then
parser:char_next()
else
break
end
end
-- print(1+parser.row, 1+parser.col, parser:char())
-- Keyword/identifier
if parser:char_is('[%a-_]') then
ident = ''
while parser:char_is('[%a%d-_]') do
ident = ident .. parser:char()
parser:char_next()
end
parser.t = Token.keyword(ident)
return
-- String
elseif parser:char_match('"') then
string = ''
while not parser:char_match('"') do
string = string .. parser:char()
parser:char_next()
end
parser.t = Token.string(string)
return
-- Single-char tokens
elseif parser:char_match('%(') then
parser.t = Token.lparen()
elseif parser:char_match('%)') then
parser.t = Token.rparen()
elseif parser:char_match('{') then
parser.t = Token.lbrace()
elseif parser:char_match('}') then
parser.t = Token.rbrace()
elseif parser:char_match(':') then
parser.t = Token.colon()
elseif parser:char_match(',') then
parser.t = Token.comma()
end
end
function Parser.token_is(parser, kind)
return parser:token().kind == kind
end
function Parser.token_kw_is(parser, name)
return parser:token().kind == 'keyword' and parser:token().value == name
end
function Parser.token_match(parser, kind)
if parser:token().kind == kind then
parser:token_next()
return true
end
return false
end
function Parser.token_kw_match(parser, name)
if parser:token().kind == 'keyword' and parser:token().value == name then
parser:token_next()
return true
end
return false
end
function Parser.new(filename)
file = io.open(filename, 'rb')
parser = Parser
parser.file = file
parser.filename = filename
parser:char_next()
parser:token_next()
return parser;
end
function parse_mf(mf_path)
parser = Parser.new(mf_path)
includes = {}
platforms = {}
apis = {}
while parser:token().kind ~= 'eof' do
if parser:token().kind ~= 'keyword' then
print(('%s(%d, %d): Expected keyword'):format(parser.filename, 1+parser.row, 1+parser.col))
end
-- TODO: add error handling
if parser:token_kw_match('include') then
parser:token_match('{')
while not parser:token_match('}') do
inc = parser:token().value
table.insert(includes, inc)
parser:token_next()
parser:token_match(',')
end
elseif parser:token_kw_match 'platform' then
platform_name = parser:token().value
parser:token_next()
parser:token_match('(')
platform_path = parser:token().value
if platform_path:sub(1,1) == '/' then
platform_path = platform_path:sub(2, -1)
end
parser:token_next()
parser:token_match(')')
parser:token_match('{')
platform_includes = {}
while not parser:token_match('}') do
if parser:token_kw_match('tinyrt') then
table.insert(platform_includes, path.join(platform_path, 'tinyrt.iface.h'))
table.insert(platform_includes, 'tinyrt.h')
parser:token_match('{')
while not parser:token_match('}') do
inc = parser:token().value
table.insert(platform_includes, path.join(platform_path, inc))
parser:token_next()
end
else
inc = parser:token().value
table.insert(platform_includes, path.join(platform_path, inc))
parser:token_next()
end
parser:token_match(',')
end
table.insert(platforms, {
name = platform_name,
includes = platform_includes
})
elseif parser:token_kw_match 'api' then
api_name = parser:token().value
parser:token_next()
parser:token_match('(')
api_path = parser:token().value
if api_path:sub(1,1) == '/' then
api_path = api_path:sub(2, -1)
end
parser:token_next()
parser:token_match(')')
parser:token_match('{')
api_includes = {}
rt_deps = {}
while not parser:token_match('}') do
if parser:token_kw_match('tinyrt') then
parser:token_match('{')
while not parser:token_match('}') do
dep = parser:token().value
table.insert(rt_deps, dep)
parser:token_next()
end
else
inc = parser:token().value
table.insert(api_includes, path.join(api_path, inc))
parser:token_next()
end
parser:token_match(',')
end
table.insert(apis, {
name = api_name,
deps = rt_deps,
includes = api_includes
})
else
print(('%s(%d, %d): Unknown directive: %s'):format(parser.filename, 1+parser.row, 1+parser.col, parser:token().value))
end
end
io.close(parser.file)
return {
includes = includes,
platforms = platforms,
apis = apis,
}
end
function print_r(arr, indentLevel)
local str = ""
local indentStr = ""
if(indentLevel == nil) then
print(print_r(arr, 0))
return
end
for i = 0, indentLevel do
indentStr = indentStr.." "
end
for index,value in pairs(arr) do
if type(value) == "table" then
str = str..indentStr..index..": \n"..print_r(value, (indentLevel + 1))
else
str = str..indentStr..index..": "..value.."\n"
end
end
return str
end
-- mf = parse_mf('src/library.mf')
-- print(print_r(mf, 0))

66
src/library.json Normal file
View File

@ -0,0 +1,66 @@
{
// Manifest file for the ciabatta build.
// Platform sections describe available platforms and
// which files they need to include to function
// API sections describe API subsets and their TinyRT
// dependencies. If an API requires TinyRT module that
// isn't implemented by the platform that API won't be included
// in the final build
// This file is used to auto-generate ciabatta.c
// `include` section specifies the header files that ciabatta
// implements
// `platform` sections describe platforms, the directories
// where the source code for these platforms resides and the
// files that should be included in the build for that platform
// (relative to "src" dir) as well as the location of TinyRT
// implementation.
// `api` sections describe modules, where the implementation resides,
// the source files and the TinyRT modules, on which this module
// depends. If the platform doesn't implement one of the dependencies
// this module will not be included in the final build
includes: [
"cia-def.h",
"stdlib.h"
],
platforms: [
{
name: "linux",
path: "linux",
includes: [
"syscall.c",
"errno.c",
"entry.c"
],
tinyrt: [
"tinyrt.c"
]
},
{
name: "windows",
path: "windows",
includes: [],
tinyrt: [],
},
],
apis: [
{
name: "stdlib_program",
path: "impl/stdlib-program",
includes: [
"program.c",
],
reqs: [
"rt_api_program",
]
},
]
// END
}

View File

@ -1,48 +0,0 @@
# Manifest file for the ciabatta build.
# Platform sections describe available platforms and
# which files they need to include to function
# API sections describe API subsets and their TinyRT
# dependencies. If an API requires TinyRT module that
# isn't implemented by the platform that API won't be included
# in the final build
# This file is used to auto-generate ciabatta.c
# `include` section specifies the header files that ciabatta
# implements
# `platform` sections describe platforms, the directories
# where the source code for these platforms resides and the
# files that should be included in the build for that platform
# (relative to "src" dir) as well as the location of TinyRT
# implementation.
# `api` sections describe modules, where the implementation resides,
# the source files and the TinyRT modules, on which this module
# depends. If the platform doesn't implement one of the dependencies
# this module will not be included in the final build
include {
"cia-def.h",
"stdlib.h"
}
platform linux("/linux") {
"syscall.c",
"errno.c",
"entry.c",
tinyrt {
"tinyrt.c"
}
}
platform windows("/windows") {
tinyrt {},
}
api stdlib_program("/impl/stdlib-program") {
"program.c",
tinyrt {
rt_api_program,
}
}

12
src/linux/tinyrt.json Normal file
View File

@ -0,0 +1,12 @@
{
// This file contains TinyRT API subsets that are exported
// for this operating system, one name per line. This file
// is used in a build script to generate tinyrt_macro file
// and to resolve higher-level API dependencies
rt_api_file: true,
rt_api_program: true,
rt_api_shell: false,
}

View File

@ -1,15 +0,0 @@
# This file contains TinyRT API subsets that are exported
# for this operating system, one name per line. This file
# is used in a build script to generate tinyrt_macro file
# and to resolve higher-level API dependencies
# For example file = 1 means that the file API is
# implemented on this operating system and during building
# a header file will be generated containing definition of
# the form
# #define RT_API_FILE
rt_api_file = 1
rt_api_program = 1
rt_api_shell = 0

View File

@ -1,5 +1,5 @@
#include <cia_definitions.h>
#include <cia-def.h>
#define STDOUT_FILENO 1
#define SYS_write 1