tcc4tcl (Tiny C Compiler for Tcl) is a Tcl extension that provides an interface to [TCC]. It is a fork of [tcltcc] by Mark Janssen. It is licensed under the terms of the [LGPL] v2.1 (or later). Homepage: http://chiselapp.com/user/rkeene/repository/tcc4tcl/index **tcc version** [AMG]: The current version of tcc4tcl (0.30) directly includes a patched copy of tcc 0.9.26 from early 2013. The most recent version of tcc is 0.9.27 from late 2017. I would very much like to upgrade to 0.9.27 because of the many improvements, but doing so breaks virtually all the tcc patches found in [http://chiselapp.com/user/rkeene/repository/tcc4tcl/dir?ci=trunk&name=build/tcc-patches/0.9.26]. **32-bit Windows link failure** [AMG]: With tcc4tcl 0.30 (tcc 0.9.26) compiled with 32-bit MXE GCC 5.4.0, or with the official build [http://teapot.rkeene.org/package/name/tcc4tcl/ver/0.22/arch/win32-ix86/file.zip] (tried with [https://www.activestate.com/products/activetcl/downloads/thank-you/?dl=https://downloads.activestate.com/ActiveTcl/releases/8.5.18.0/ActiveTcl8.5.18.0.298892-win32-ix86-threaded.exe]), I get the following error: ====== % tcc4tcl::cproc test {Tcl_WideInt a int b} Tcl_WideInt {return a << b;} tcc: error: undefined symbol '__ashldi3' relocating failed ====== This is only a problem in Windows, not Linux. The cause is twofold. (1) gcc is prefixing all the symbol names in libtcc1.a with an extra underscore that tcc is not expecting, and (2) gcc is producing PE-format object files, and tcc only knows how to link ELF object files. The solution is to apply this patch: ======none diff -ur tcc4tcl-0.30-old/Makefile.in tcc4tcl-0.30-new/Makefile.in --- tcc4tcl-0.30-old/Makefile.in 2017-10-13 15:37:05.000000000 -0500 +++ tcc4tcl-0.30-new/Makefile.in 2019-03-13 15:04:27.510092464 -0500 @@ -8,6 +8,8 @@ CPP = @CPP@ AR = @AR@ RANLIB = @RANLIB@ +OBJCOPY = @OBJCOPY@ +OBJDUMP = @OBJDUMP@ CFLAGS = @CFLAGS@ @SHOBJFLAGS@ CPPFLAGS = @CPPFLAGS@ -I$(shell cd @srcdir@ && pwd) -I$(shell cd @srcdir@ && pwd)/tcc -I$(shell pwd)/tcc @DEFS@ @SHOBJCPPFLAGS@ LDFLAGS = @LDFLAGS@ @@ -29,7 +31,7 @@ host_os = @host_os@ @SET_MAKE@ -all: $(TARGET) tcc/libtcc1.a +all: $(TARGET) tcc/libtcc1-elf.a tcc/config.h: if [ "$(srcdir)" = "." ]; then \ @@ -46,6 +48,17 @@ -$(MAKE) -C tcc tcc@EXEEXT@ $(MAKE) -C tcc libtcc1.a +# tcc supports dynamically loading object code from ELF, not from PE, so on some +# platforms it is necessary to convert its runtime support library to ELF. +tcc/libtcc1-elf.a: tcc/libtcc1.a + if $(OBJDUMP) -a $< | grep -q ' file format pei\?-x86-64$$'; then \ + $(OBJCOPY) --remove-leading-char -O elf64-x86-64 $< $@; \ + elif $(OBJDUMP) -a $< | grep -q ' file format pei\?-i386$$'; then \ + $(OBJCOPY) --remove-leading-char -O elf32-i386 $< $@; \ + else \ + cp -f $< $@; \ + fi + tcc4tcl.o: $(srcdir)/tcc4tcl.c $(srcdir)/tcc/tcc.h $(srcdir)/tcc/libtcc.h tcc/config.h $(CC) $(CPPFLAGS) $(CFLAGS) -o tcc4tcl.o -c $(srcdir)/tcc4tcl.c @@ -60,7 +73,7 @@ -$(RANLIB) tcc4tcl-static.new.a mv tcc4tcl-static.new.a tcc4tcl-static.a -install: $(TARGET) pkgIndex.tcl $(srcdir)/tcc4tcl.tcl $(srcdir)/tcc4critcl.tcl tcc/libtcc1.a $(shell echo $(srcdir)/tcc/include/*) $(shell echo $(srcdir)/tcc/win32/lib/*.c) $(srcdir)/headers.awk $(srcdir)/patch-headers.sh +install: $(TARGET) pkgIndex.tcl $(srcdir)/tcc4tcl.tcl $(srcdir)/tcc4critcl.tcl tcc/libtcc1-elf.a $(shell echo $(srcdir)/tcc/include/*) $(shell echo $(srcdir)/tcc/win32/lib/*.c) $(srcdir)/headers.awk $(srcdir)/patch-headers.sh $(INSTALL) -d "$(DESTDIR)$(PACKAGE_INSTALL_DIR)" $(INSTALL) -d "$(DESTDIR)$(PACKAGE_INSTALL_DIR)/lib" $(INSTALL) -d "$(DESTDIR)$(PACKAGE_INSTALL_DIR)/include" @@ -68,7 +81,7 @@ $(INSTALL) -m 0644 pkgIndex.tcl "$(DESTDIR)$(PACKAGE_INSTALL_DIR)" $(INSTALL) -m 0644 $(srcdir)/tcc4tcl.tcl "$(DESTDIR)$(PACKAGE_INSTALL_DIR)" $(INSTALL) -m 0644 $(srcdir)/tcc4critcl.tcl "$(DESTDIR)$(PACKAGE_INSTALL_DIR)" - $(INSTALL) -m 0644 tcc/libtcc1.a "$(DESTDIR)$(PACKAGE_INSTALL_DIR)/lib" + $(INSTALL) -m 0644 tcc/libtcc1-elf.a "$(DESTDIR)$(PACKAGE_INSTALL_DIR)/lib/libtcc1.a" $(INSTALL) -m 0644 $(shell echo $(srcdir)/tcc/win32/lib/*.c) "$(DESTDIR)$(PACKAGE_INSTALL_DIR)/lib" $(INSTALL) -m 0644 $(shell echo $(srcdir)/tcc/include/*) "$(DESTDIR)$(PACKAGE_INSTALL_DIR)/include" @if ! echo "_WIN32" | $(CPP) $(CPPFLAGS) - | grep '^_WIN32$$' >/dev/null; then \ diff -ur tcc4tcl-0.30-old/configure.ac tcc4tcl-0.30-new/configure.ac --- tcc4tcl-0.30-old/configure.ac 2017-10-13 15:37:16.000000000 -0500 +++ tcc4tcl-0.30-new/configure.ac 2019-03-13 15:06:59.156101031 -0500 @@ -39,6 +39,7 @@ TARGET="tcc4tcl-static.a" fi +AC_CHECK_TOOL([OBJDUMP], [objdump]) AC_SUBST(TARGET) AC_SUBST(TCC4TCL_TARGET) AC_SUBST(TCC_EXTRA_CFLAGS) diff -ur tcc4tcl-0.30-old/test.tcl tcc4tcl-0.30-new/test.tcl --- tcc4tcl-0.30-old/test.tcl 2017-10-13 15:37:05.000000000 -0500 +++ tcc4tcl-0.30-new/test.tcl 2019-03-13 15:09:06.231108210 -0500 @@ -15,6 +15,9 @@ # This should work tcc4tcl::cproc test3 {int i} int { return(i+42); } +# Check for libtcc1 functionality +tcc4tcl::cproc testlibtcc1 {double x} int { return(x); } + # Multiple arguments tcc4tcl::cproc add {int a int b} int { return(a+b); } ====== Be cautious with this patch since it intentionally contains tabs and end-of-line whitespace, all of which have been stripped off by the wiki. Let me know if you want the original file with correct formatting. After applying the patch, run "autoconf" to regenerate the configure script. I have confirmed that the above patch fixes 32-bit Windows and does not break 64-bit Windows, 32-bit Linux, or 64-bit Linux. **Variadic arguments** [AMG]: Is there any facility to access a cproc command's full objv argument list? **Compilation** [dbohdan] 2015-03-16: As of version 0.23 you can compile tcc4tcl on Linux thus: ======none #!/bin/sh set -e version=0.23 release="tcc4tcl-$version" url="http://rkeene.org/devel/tcc4tcl/${release}.tar.gz" curl "$url" -o "${release}.tar.gz" # -O may not be unavailable. tar zxvf "$release.tar.gz" cd $release ./configure make ====== [dbohdan]: Updated the script once more to hammer [Roy Keene]'s server less. <> Extension