ksh: ksh fails to compile with tcc

This bug was reported to me by Chase (one of the CDE contributers) via email:

Secondly, I was wondering if you maybe had any insight into why ksh fails to compile with tcc on linux. First, when running CC=tcc ./bin/package make it says it doesn’t like the preprocessor macro #define onexit on_exit in src/lib/libast/comp/atexit.c. When that is fixed (I made an ugly fix by substituting the underscore for a preprocessor macro UNDERSCORE and tcc’s cpp seemed to like that), iffe fails saying that tcc -c doesn’t accept libraries. Since it is only a compiler check testing if int i=1 compiles, I simply took out the -lm the Mamfile was asking for. The last problem is the one that stumps me, pty fails after this and give no helpful debugging output.

I’ve attempted to fix this bug in the patch below, with limited success. It only fixes the compile on Linux and requires a relatively recent version of tcc to build (tcc commit dd60b20c or later). Even with the patch below tcc fails to compile ksh on FreeBSD and it breaks pty on illumos:

diff --git a/src/cmd/INIT/iffe.sh b/src/cmd/INIT/iffe.sh
index 9c0426e5..3647bc43 100644
--- a/src/cmd/INIT/iffe.sh
+++ b/src/cmd/INIT/iffe.sh
@@ -31,10 +31,22 @@ AIX)	unset LIBPATH ;;
 esac
 
 command=iffe
-version=2021-02-03 # update in USAGE too #
+version=2021-03-19 # update in USAGE too #
 
 compile() # $cc ...
 {
+	# tcc can't combine -l* and -c
+	if echo "$@" | grep ' -c' | grep -q ' -l'
+	then
+		for arg
+		do	shift
+			case $arg in
+			-l*) : ;;
+			*) set -- "$@" "$arg"
+			esac
+		done
+	fi
+
 	"$@" 2>$tmp.err
 	_compile_status=$?
 	if	test -s $tmp.err
@@ -753,7 +765,7 @@ set=
 case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
 0123)	USAGE=$'
 [-?
-@(#)$Id: iffe (ksh 93u+m) 2021-02-03 $
+@(#)$Id: iffe (ksh 93u+m) 2021-03-19 $
 ]
 [-author?Glenn Fowler <gsf@research.att.com>]
 [-author?Phong Vo <kpv@research.att.com>]
diff --git a/src/lib/libast/features/lib b/src/lib/libast/features/lib
index 5a9a67b2..de9410b1 100644
--- a/src/lib/libast/features/lib
+++ b/src/lib/libast/features/lib
@@ -28,7 +28,7 @@ lib	getopt,getsubopt,getopt_long,getopt_long_only
 lib	glob,index,iswblank,iswctype,killpg,link,localeconv,madvise
 lib	mbtowc,mbrtowc,memalign,memchr,memcpy,memdup,memmove,memset
 lib	mkdir,mkfifo,mktemp,mktime
-lib	mount,on_exit,onexit,opendir,pathconf
+lib	mount,onexit,opendir,pathconf
 lib	readlink,remove,rename,rewinddir,rindex,rmdir,setlocale
 lib	setpgid,setpgrp,setpgrp2,setreuid,setsid,setuid,sigaction
 lib	sigprocmask,sigsetmask,sigunblock,sigvec,socketpair
@@ -56,6 +56,21 @@ sys	socket,stream,systeminfo,universe,vfork
 typ	ino64_t,off64_t
 typ	struct.dirent64 dirent.h
 
+tst note{ on_exit works and accepts one argument }end output{
+	#include <stdlib.h>
+
+	static void success(void)
+	{
+		printf("#define _lib_on_exit\t1\n");
+	}
+
+	int main(void)
+	{
+		on_exit(success);
+		exit(0);
+	}
+}end
+
 tst	tst_errno note{ errno can be assigned }end link{
 	_BEGIN_EXTERNS_
 	#define error		______error

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 18

Commits related to this issue

Most upvoted comments

I have to agree that finding a workaround isn’t going to be worthwhile (errors related to __dso_handle can be quite difficult to fix). Since the latest version of tcc is now compiling ksh on Linux and FreeBSD without issues, I’m fine with merging the current set of fixes.

Got tcc working on FreeBSD. That took some doing. The ports package does nothing but crash, so I got the latest git code. It requires gcc and gmake to compile. 😕

Anyway, I tried simply undefining __GNUC__ in ast.h. The reason why FreeBSD pretends to be gcc on FreeBSD quickly became clear: the system headers break if it doesn’t. Got an obscure syntax error in ctype.h that is probably the result of some botched macro definition.

But if I’m reading your diff above right, it looks like those math builtins are used on gcc 3.0 or later. So that made me think of the following…

--- a/src/lib/libast/include/ast.h
+++ b/src/lib/libast/include/ast.h
@@ -78,6 +78,19 @@ struct _sfio_s;
 #endif
 #endif
 
+/*
+ * tcc on FreeBSD: Avoid using nonexistent math
+ * builtins by pretending to be an ancient gcc.
+ */
+#if __TINYC__ && __GNUC__ >= 3 && __FreeBSD__
+#undef __GNUC__
+#undef __GNUC_MINOR__
+#undef __GNUC_PATCHLEVEL__
+#define __GNUC__ 2
+#define __GNUC_MINOR__ 95
+#define __GNUC_PATCHLEVEL__ 3
+#endif
+
 /*
  * exit() support -- this matches shell exit codes
  */

And presto, when applying this along with your PR, it now compiles on FreeBSD. No regression test failures.