Skip to content

Commit

Permalink
build: new target using system provided libtcc
Browse files Browse the repository at this point in the history
tested using Debian's libtcc-dev and tcc packages which seem rather
outdated and present some bugs on path handling for which now we have
workarounds.
  • Loading branch information
jaromil committed Jan 6, 2025
1 parent e48e6f2 commit e0dd8dd
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 17 deletions.
8 changes: 8 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ apple-osx: ## 🍎 Build cjit.command for Apple/OSX using clang static
@rm -f .build_done*
date | tee .build_done_osx

meson-release:
[ -r meson ] && rm -rf meson
meson setup meson build \
--buildtype release --backend ninja
ninja -C meson
cp meson/cjit .

_: ##
------: ## __ Debugging targets

Expand Down Expand Up @@ -106,3 +113,4 @@ install: ## 🔌 Install the built binaries in PREFIX
clean: ## 🧹 Clean the source from all built objects
$(MAKE) -f build/deps.mk clean
@rm -f cjit cjit.exe cjit.command
@rm -rf meson
97 changes: 97 additions & 0 deletions build/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
project(
'cjit',
'c',
version: run_command('./meson_version.sh', capture:true, check: true).stdout().strip(),
license: 'GPL3',
meson_version: '>=1.1',
default_options: [
'warning_level=2',
],
)

message('Building project version: @0@'.format(meson.project_version()))

# Define the source files

src = files( '../src/cjit.c', '../src/file.c', '../src/elflinker.c',
'../src/main.c', '../src/cwalk.c', '../src/array.c',
'../src/muntar.c', '../src/tinflate.c', '../src/tinfgzip.c')

# Check for tcc command
tcc_exe = find_program('tcc', required: true)
if tcc_exe.found()
tcc_found = true
endif

# Detect system architecture
arch = host_machine.cpu()

# Construct the path based on architecture
lib_paths = []
if arch == 'x86_64'
lib_paths += [
'/usr/lib/x86_64-linux-gnu/tcc/'
]
elif arch == 'i686'
lib_paths += [
'/usr/lib/i386-linux-gnu/libtcc1.a',
'/usr/lib/i386-linux-gnu/tcc/libtcc1.a'
]
elif arch == 'arm'
lib_paths += [
'/usr/lib/arm-linux-gnueabihf/libtcc1.a',
'/usr/lib/arm-linux-gnueabihf/tcc/libtcc1.a'
]
elif arch == 'aarch64'
lib_paths += [
'/usr/lib/aarch64-linux-gnu/libtcc1.a',
'/usr/lib/aarch64-linux-gnu/tcc/libtcc1.a'
]
elif arch == 'riscv'
lib_paths += [
'/usr/lib/riscv64-linux-gnu/libtcc1.a',
'/usr/lib/riscv64-linux-gnu/tcc/libtcc1.a'
]
# Add other architectures as needed
else
error('Unsupported architecture: @0@'.format(arch))
endif

libtcc_found = 'no'
# Check if libtcc1.a exists in the constructed paths
foreach path : lib_paths
libtcc = meson.get_compiler('c').find_library('tcc1',
dirs : path,
required : false,
static : true)
if libtcc.found()
libtcc_found = path
break
endif
endforeach

# Error out if tcc or libtcc1.a is not found
if not tcc_found or libtcc_found == 'no'
error('tcc command and libtcc1.a library are required but not found')
else
message('using system provided @[email protected]'.format(libtcc_found))
endif



# Define variables
prefix = get_option('prefix')
version = meson.project_version()

# Compiler arguments
c_args = [ '-I../src',
'-DSHAREDTCC="@[email protected]"'.format(libtcc_found),
'-DPREFIX="@0@"'.format(prefix),
'-DVERSION="@0@"'.format(version), ]

# Build the executable
executable('cjit', src,
dependencies: [libtcc],
link_args: ['-ltcc'],
install: true,
c_args: c_args)
2 changes: 2 additions & 0 deletions build/meson_version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
git describe --tags | cut -d- -f1
20 changes: 15 additions & 5 deletions src/cjit.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,13 @@ static bool cjit_setup(CJITState *cjit) {
_err("Warning: cjit_setup called twice or more times");
return(true);
}
#if !defined(SHAREDTCC)
// extract all runtime assets to tmpdir
if(!extract_assets(cjit,NULL)) {
fail("error extracting assets in temp dir");
return(NULL);
}
#endif
tcc_set_output_type(tcc(cjit), cjit->tcc_output);
#if defined(LIBC_MUSL)
tcc_add_libc_symbols(tcc(cjit));
Expand All @@ -209,17 +211,19 @@ static bool cjit_setup(CJITState *cjit) {
// where is libtcc1.a found
// add(libpaths,cjit->tmpdir);
// tinyCC needs libtcc1.a in library path (not added as file)
#if !defined(SHAREDTCC)
tcc_add_library_path(tcc(cjit),cjit->tmpdir);
tcc_add_sysinclude_path(tcc(cjit), cjit->tmpdir);
tcc_add_sysinclude_path(tcc(cjit), ".");
tcc_add_sysinclude_path(tcc(cjit), "include"); // TODO: check if exists
#endif
{ // search libs also in current dir
char pwd[MAX_PATH];
// Get the current working directory
if(getcwd(pwd, MAX_PATH)) {
add(libpaths,pwd);
}
}
tcc_add_sysinclude_path(tcc(cjit), cjit->tmpdir);
tcc_add_sysinclude_path(tcc(cjit), ".");
tcc_add_sysinclude_path(tcc(cjit), "include"); // TODO: check if exists

#if defined(WINDOWS)
{
Expand Down Expand Up @@ -290,7 +294,9 @@ bool cjit_status(CJITState *cjit) {
#if !(defined TCC_TARGET_PE || defined TCC_TARGET_MACHO)
_err("ELF interpreter: %s",CONFIG_TCC_ELFINTERP);
#endif

#if defined(SHAREDTCC)
_err("System libtcc: %s",SHAREDTCC);
#endif
////////////////////////
// call cjit_setup here
setup;
Expand Down Expand Up @@ -554,7 +560,11 @@ int cjit_exec(CJITState *cjit, int argc, char **argv) {
int res = 1;
int (*_ep)(int, char**);
// relocate the code (link symbols)
#if defined(SHAREDTCC)
if (tcc_relocate(tcc(cjit), TCC_RELOCATE_AUTO) < 0) {
#else
if (tcc_relocate(tcc(cjit)) < 0) {
#endif
_err("%s: TCC linker error",__func__);
_err("Library functions missing.");
return -1;
Expand Down Expand Up @@ -655,7 +665,7 @@ void cjit_add_library_path(CJITState *cjit, const char *path) {
}
#if defined(UNIX)
add(libpaths,toadd);
#else
#elif !defined(SHAREDTCC)
tcc_add_library_path(tcc(cjit), toadd);
#endif
debug("+L %s",toadd);
Expand Down
6 changes: 6 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ const char cli_help[] =
" -e fun\t run starting from entry function (-) main\n"
" -p pid\t write execution process ID to (+) pid\n"
" --verb\t don't go quiet, verbose logs\n"
#if defined(SHAREDTCC)
" --xass\t just extract runtime assets (=) to path\n"
#endif
#if defined(SELFHOST)
" --src\t extract source code to cjit_source\n"
#endif
Expand All @@ -101,7 +103,9 @@ int main(int argc, char **argv) {
#if defined(SELFHOST)
{ "src", ko_no_argument, 311 },
#endif
#if !defined(SHAREDTCC)
{ "xass", ko_optional_argument, 401 },
#endif
{ "xtgz", ko_required_argument, 501 },
{ NULL, 0, 0 }
};
Expand Down Expand Up @@ -172,6 +176,7 @@ int main(int argc, char **argv) {
cjit_free(CJIT);
exit(0);
#endif
#if !defined(SHAREDTCC)
} else if (c == 401) { // --xass
if(opt.arg) {
_err("Extracting runtime assets to:",opt.arg);
Expand All @@ -182,6 +187,7 @@ int main(int argc, char **argv) {
_out(CJIT->tmpdir);
cjit_free(CJIT);
exit(0);
#endif
} else if (c == 501) { // --xtgz
cjit_free(CJIT);
unsigned int len = 0;
Expand Down
5 changes: 4 additions & 1 deletion test/bats_setup
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ setup() {
>&2 echo "CJIT is not built, cannot run test suite"
exit 1
}
rm -rf `${CJIT} --xass`
${CJIT} -v 2>&1| grep 'System libtcc' >/dev/null && SYSTCC=1
if [ -z $SYSTCC ]; then
rm -rf `${CJIT} --xass`
fi
TCC="${R}/lib/tinycc/tcc"
[ -r "$TCC" ] || TCC="${R}/lib/tinycc/tcc.exe"
}
32 changes: 21 additions & 11 deletions test/cli.bats
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,30 @@ load bats_setup
assert_output --partial 'Please compile with -DALLOWED=1'
}

## This and the following test fail when using Debian's libtcc1 for
## execution, maybe because object files aren't supported , as it
## fails in tcc_add_file() calls inside cjit_add_file()
@test "Compile to object and execute" {
run ${CJIT} -c test/hello.c
assert_success
run ${CJIT} hello.o
assert_success
assert_output 'Hello World!'
set +e
test -z $SYSTCC && {
set -e
run ${CJIT} -c test/hello.c
assert_success
run ${CJIT} hello.o
assert_success
assert_output 'Hello World!'
}
}

@test "Compile to custom object and execute" {
run ${CJIT} -o world.o -c test/hello.c
assert_success
run ${CJIT} world.o
assert_success
assert_output 'Hello World!'
set +e
test -z $SYSTCC && {
set -e
run ${CJIT} -o world.o -c test/hello.c
assert_success
run ${CJIT} world.o
assert_success
assert_output 'Hello World!'
}
}

@test "Compile and link to executable and run" {
Expand Down

0 comments on commit e0dd8dd

Please sign in to comment.