Cfront bootstrap on a year-2014-ish Linux. Generation of the compiler binaries. No warranties. 2015-05-16 Copyright (C) 2014, 2015 RL @ Aetey Global Technologies AB LICENSE: BSD 2-clause. This description is manually derived from a formal procedure which is specific to the author's build environment. Adjust for your situation. Assuming cfront 3.0.3 sources, which seem to exist in a single (partly broken) incarnation, licensed for computer history research: http://www.softwarepreservation.org/projects/c_plus_plus/cfront/release_3.0.3/source/cfront_3_0_3.tgz The author used pcc-1.1.0+ as the target C compiler and g++ 4.2.3 for bootstrapping which was carried out on ia32. Assuming reader proficiency in unix scripting and C. Using below leading space to indicate comments/directions, actual commands when shown start at the beginning of the line. Unpack. Rename to get rid of the space in "C++ 3.0.3" :) cd C++3.0.3/source For clarity/generality we preserve and use the original copy, identically patching twice below, instead a single patch application would suffice before doing this copy. cp -a src src.ori Collect the knowledge about the C-environment: Patch szal for long long (the patch is not included here) cc -o szal szal.c ./szal >szal.result cd src chmod u+w * Apply the "long long" patch (the patch is not included here) cfront.h: insert "#include " template.h: comment out "enum bool", replace "typename" member name with a different word template.c: replace "typename" member name with the different word dcl.c: put parentheses around "new texpr(G_CAST,nt,init)" expr2.c: insert "extern Pname has_templ_instance(Pname, Pexpr, bit);" expr3.c: insert "extern Pname has_templ_instance(Pname, Pexpr, bit);" hash.c: insert "#include " main.c: comment out "#include ", "#include ", lines with SIGEMT tree_copy.c: replace member name "ia" with some other word generate y.tab.c with heirloom yacc (or ask someone who can do this for you) Prepare some extra headers in a separate directory: generic.h: ---- #ifndef GENERICH #define GENERICH 1 #define name2(a,b) _name2_aux(a,b) #define _name2_aux(a,b) a##b #define name3(a,b,c) _name3_aux(a,b,c) #define _name3_aux(a,b,c) a##b##c #define name4(a,b,c,d) _name4_aux(a,b,c,d) #define _name4_aux(a,b,c,d) a##b##c##d #define declare(a,t) name2(a,declare)(t) #define implement(a,t) name2(a,implement)(t) #define declare2(a,t1,t2) name2(a,declare2)(t1,t2) #define implement2(a,t1,t2) name2(a,implement2)(t1,t2) extern int genericerror(int,char*); typedef int (*GPT)(int,char*); #define set_handler(generic,type,x) name4(set_,type,generic,_handler)(x) #define errorhandler(generic,type) name3(type,generic,handler) #define callerror(generic,type,a,b) (*errorhandler(generic,type))(a,b) #endif ---- new.h: ---- #ifndef __NEW_H #define __NEW_H #include extern void (*set_new_handler (void(*)()))(); void *operator new(size_t, void*); #endif ---- make \ CC=g++ \ CCFLAGS="-O -fno-for-scope -fpermissive -fno-operator-names -DSYSV -I" We have got a minimally "working" cfront, now let it bootstrap itself. cp cfront .. cd .. mv src src.patched-for-g++ cp -a src.ori/. src cd src chmod u+w * Apply the "long long" patch (the patch is not included here) add the same y.tab.c as mentioned above cfront.h: insert "#include " hash.c: insert "#include " main.c: comment out "#include ", "#include " cd ../scratch/src ########### some explanation of the choice of the arguments below: # cpp: # -Dwchar_t=long libc does not define this type with __cplusplus # and cfront did not anticipate to builtin it # -U__GNUC__ __GNUC__ is predefined in pcc's cpp, # some weird gcc-related stuff can come out of libc # headers and confuse cfront, better not # -D__cplusplus=1 to tell the c library headers we are C++ not C # (adjust for you libc if necessary) # -I where the libc headers actually are # -I to pick the small necessary additions not # present in the libc headers nor defined by pcc, # prepared by us above # cfront: # +L to use "# line ...." not the ancient "# ...." # +f"\$A" to reflect the name of the source file somewhere # in the output's metainfo # +x../../szal.result pre-include the file defining the data sizes on # our platform # +a1 use ansi-syntax in the output, not k&r Note you have to put the relevant paths in the script below (look for <.*>) cat >myCC <<____ #!/bin/sh # (c) 2014 RL @ Aetey Global Technologies AB # LICENSE: BSD 2-clause set -e # interpret/discard all arguments besides the last one extradefs= while [ "\$#" -gt 1 ]; do case "\$1" in -D*) extradefs="\$extradefs \$1" ;; esac shift done A="\$1" # take a simplistic approach to TEMPDIR TEMPDIR=/tmp/CCTMP."\$\$" trap 'rm -fr "\$TEMPDIR"; exit' 0 1 2 3 13 15 mkdir "\$TEMPDIR" || exit tmpfile="\$TEMPDIR"/cpptmp cpp \ \$extradefs \ -Dwchar_t=long \ -U__GNUC__ \ -D__cplusplus=1 \ -I \ -I \ "\$A" \ >"\$tmpfile" LD_LIBRARY_PATH= ../../cfront \ +L \ +f"\$A" \ +x../../szal.result \ +a1 \ <"\$tmpfile" \ >"\`basename "\$A" .c\`"..c exit ____ chmod +x myCC Tell make not to try to rebuild y.tab.c touch y.tab.c make CC=./myCC You get a bunch of ..c files. cd ../lib Note the number of ".." below, this is correct. chmod u+w ../../lib/new/* ../../lib/new/_new.c: replace "extern "C" { .... }" with "#include " replace "unsigned(size)" with "size" ../../lib/new/_arr_map.c: insert #ifndef BITSPERBYTE #define BITSPERBYTE 8 #endif #define BITS(type) (BITSPERBYTE * (int)sizeof(type)) make CC=../src/myCC cc -O -c *..c cc -o munch munch..o _new..o _main..o _handler..o _ctor..o cd ../src cc -O -c *..c cc -o precfront \ *..o ../lib/_vec..o ../lib/pure..o \ ../lib/_arr_map..o ../lib/_main..o \ ../lib/_ctor..o nm precfront | ../lib/munch >_ctdt.c cc -O -c _ctdt.c cc -o cfront \ *..o ../lib/_vec..o ../lib/pure..o \ ../lib/_arr_map..o ../lib/_main..o \ _ctdt.o This cfront is no longer related to gcc, let it recompile itself. mv cfront cfrontA rm *..* No longer the need for LD_LIBRARY_PATH. cat >myCC <<____ #!/bin/sh # (c) 2014 RL @ Aetey Global Technologies AB # LICENSE: BSD 2-clause set -e # interpret/discard all arguments besides the last one extradefs= while [ "\$#" -gt 1 ]; do case "\$1" in -D*) extradefs="\$extradefs \$1" ;; esac shift done A="\$1" # take a simplistic approach to TEMPDIR TEMPDIR=/tmp/CCTMP."\$\$" trap 'rm -fr "\$TEMPDIR"; exit' 0 1 2 3 13 15 mkdir "\$TEMPDIR" || exit tmpfile="\$TEMPDIR"/cpptmp cpp \ \$extradefs \ -Dwchar_t=long \ -U__GNUC__ \ -D__cplusplus=1 \ -I \ -I \ "\$A" \ >"\$tmpfile" "`pwd`"/cfrontA \ +L \ +f"\$A" \ +x../../szal.result \ +a1 \ <"\$tmpfile" \ >"\`basename "\$A" .c\`"..c exit ____ chmod +x myCC make CC=./myCC cd ../lib rm *..* make CC=../src/myCC cc -O -c *..c cc -o munch munch..o _new..o _main..o _handler..o _ctor..o cd ../src cc -O -c *..c cc -o precfront \ *..o ../lib/_vec..o ../lib/pure..o \ ../lib/_arr_map..o ../lib/_main..o \ ../lib/_ctor..o nm precfront | ../lib/munch >_ctdt.c cc -O -c _ctdt.c cc -o cfront \ *..o ../lib/_vec..o ../lib/pure..o \ ../lib/_arr_map..o ../lib/_main..o \ _ctdt.o Now one more round! mv cfront cfrontB mv ../lib/munch ../lib/munchB rm *..* _* myCC: replace "cfrontA" with "cfrontB" make CC=./myCC cd ../lib make CC=../src/myCC cc -O -c *..c cc -o munch munch..o _new..o _main..o _handler..o _ctor..o cmp munchB munch && echo "munch is GOOD" || FAILED_BUT_WHY cd ../src cc -O -c *..c cc -o precfront \ *..o ../lib/_vec..o ../lib/pure..o \ ../lib/_arr_map..o ../lib/_main..o \ ../lib/_ctor..o nm precfront | ../lib/munch >_ctdt.c cc -O -c _ctdt.c cc -o cfront \ *..o ../lib/_vec..o ../lib/pure..o \ ../lib/_arr_map..o ../lib/_main..o \ _ctdt.o cmp cfrontB cfront && echo "cfront is GOOD" || FAILED_BUT_WHY cd tools/demangler dem.c: insert #include #include make Got c++filt. Compilation of the libraries and adjustments to the CC front end driver are not covered here.