diff --git a/.gitignore b/.gitignore index e7386fe..4d7134a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ bin +/a a.out *.a *.so diff --git a/build.lua b/build.lua new file mode 100755 index 0000000..7eff5ed --- /dev/null +++ b/build.lua @@ -0,0 +1,152 @@ +#!/usr/bin/env lua + +local path = require 'path' +local argparse = require 'argparse' + +-- 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) + path.each(path.join(p,"*"), function(P) + path.remove(P) + end,{ + param = "f"; -- request full path + delay = true; -- use snapshot of directory + recurse = true; -- include subdirs + reverse = true; -- subdirs at first + }) + 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 + +local cflags = table.concat(compiler_flags, ' ')..' '.. + table.concat(map(compiler_defines, prefix('-D ')), ' ')..' '.. + table.concat(map(includes, prefix_quote('-I ')), ' ')..' ' + +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 + +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 diff --git a/build.ps1 b/build.ps1 deleted file mode 100644 index b6c1da1..0000000 --- a/build.ps1 +++ /dev/null @@ -1,13 +0,0 @@ - -# Generate the resources for UTF8 -windres -o utf8/utf8.obj utf8/utf8.rc - -# Compile chkstk -nasm src\os_win\chkstk.asm -o chkstk.o -fwin64 - -# Compile the rest of the party -clang -Wall src\ciabatta.c -o ciabatta.obj -c -DCIABATTA_WIN -I src -I include -nodefaultlibs -g -mfma -# rem cuik src\ciabatta.c -o ciabatta.obj -c -DCIABATTA_WIN -I src -I inc -nostdlib - -# Package up the .lib file -lib /nologo /out:ciabatta.lib chkstk.o utf8.obj ciabatta.obj diff --git a/build.sh b/build.sh deleted file mode 100755 index 31fef76..0000000 --- a/build.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -[ ! -d "lib" ] && mkdir "lib" -[ ! -d "bin" ] && mkdir "bin" - -[ "$1" != "-shared" ] && echo "static" - -nasm -f elf64 "src/linux/crt_entry.asm" -o "bin/crt_entry.o" -clang -fPIC -nostdlib -I "include" -g "src/linux/crt_ctors.c" -c -o "bin/crt_ctors.o" -clang -fPIC -nostdlib -I "include" -g "src/ciabatta.c" -c -o "bin/ciabatta.o" - -# Create a test executable -clang -pie -nostdlib -Iinclude \ - tests/empty.c bin/ciabatta.o bin/crt_ctors.o bin/crt_entry.o diff --git a/readme.md b/readme.md index cff0791..4b9cdd4 100644 --- a/readme.md +++ b/readme.md @@ -44,18 +44,32 @@ 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. -### Building on windows +For executing the script you will need lua and some lua dependencies that +you can install with luarocks: -Run `./build.ps1` to compile ciabatta -- (Optionally) Run `./test crt` to make sure there are no errors - -### Building and using on linux +``` +# luarocks install lua-path +# luarocks install argparse +``` -There are two options: Use ciabatta as a shared library or as a static -library. +### Building -Run `./build.sh` to compile ciabatta -- If you wish to use shared library instead add `-shared` option to the build script +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 ] [-l ] + [-t ] [--options ] +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 OS to compile for (linux, windows) + -l --library Type of library to compile (static, shared) + -t --test Compile a C file and link the library against it + --options Additional options to provide to the executable +``` ## Usage diff --git a/test.c b/test.c deleted file mode 100644 index bd95da0..0000000 --- a/test.c +++ /dev/null @@ -1,8 +0,0 @@ - -#include - -int main() { - char string[] = "hi"; - printf("%s\n", string); - return 0; -} diff --git a/test.ps1 b/test.ps1 deleted file mode 100644 index a296472..0000000 --- a/test.ps1 +++ /dev/null @@ -1,19 +0,0 @@ - - -$FILENAME = $("tests/" + $args + ".c") - -if(-not $(Test-Path -Path test_folder)) { - New-Item -ItemType Directory test_folder -} - -if(-not $(Test-Path -Path test)) { - New-Item -ItemType Directory test -} - -# Compile the test suite -clang -g $FILENAME -I include utf8.obj -nostdlib -mfma -l ciabatta.lib - -# If succeeded run the test suite -if($?) { - ./a.exe -}