#!/bin/bash # Собирает Plan9 kencc C-компилятор для арки X (5,6,8,v,q,k) на Linux-хосте. # Использование: PLAN9SRC=.../plan9foundation PLAN9PORT=.../plan9port build_arch.sh 6 # Опц.: MUSL_ENV=.../env.sh (активатор musl-тулчейна), OUT=каталог сборки. set -e X="$1"; [ -z "$X" ] && { echo "usage: $0 "; exit 1; } A="${X}c" : "${PLAN9SRC:?укажи PLAN9SRC — дерево исходников plan9 (plan9foundation)}" : "${PLAN9PORT:?укажи PLAN9PORT — собранный plan9port (bin/9c,9l,9ar,yacc + lib/)}" [ -n "$MUSL_ENV" ] && . "$MUSL_ENV" export PLAN9="$PLAN9PORT"; export PATH="$PLAN9/bin:$PATH" SRC="$PLAN9SRC/sys/src/cmd" OUT="${OUT:-$PWD/build}" B="$OUT/$A" rm -rf "$B"; mkdir -p "$B"; cd "$B" # кодоген арки СНАЧАЛА, потом фронтенд cc/ — cc/ авторитетен при совпадении имён # (у kc свой устаревший bits.c с Fconv — берём cc/bits.c) cp "$SRC/$A"/*.c "$SRC/$A"/*.h "$B"/ cp "$SRC"/cc/*.c "$SRC"/cc/*.h "$B"/ cp "$SRC"/cc/compat "$SRC"/cc/macbody "$SRC"/cc/lexbody "$B"/ 2>/dev/null || true # ---- ПАТЧИ под линукс-хост ---- # 0) выкинуть плановские рантайм-файлы (тянут /sys/... хедеры, не часть компилятора) for c in *.c; do grep -qE '#include[ \t]*[<"]/sys/' "$c" 2>/dev/null && { echo " пропуск рантайм: $c"; rm -f "$c"; }; done # 1) плоская раскладка: убрать относительные ../cc/ ../Xc/ sed -i "s|\"\.\./cc/|\"|g; s|\"\.\./${A}/|\"|g" *.c *.h 2>/dev/null || true # 2) round/log2 конфликтуют с musl math.h -> p9round/p9log2 sed -i -E 's/\bround\b/p9round/g; s/\blog2\b/p9log2/g' *.c *.h compat macbody lexbody 2>/dev/null || true # 3) Runemask нет в plan9port grep -q 'define Runemask' lex.c || sed -i '/#include[ \t]*"y.tab.h"/a #ifndef Runemask\n#define Runemask 0x1FFFFF\n#endif' lex.c # 3b) прототип swcmp -> const (musl qsort-компаратор) sed -i 's/swcmp(void\*, *void\*)/swcmp(const void*, const void*)/' gc.h *.h 2>/dev/null || true # 4) mysbrk: sbrk() на musl отдаёт -1 -> mmap python3 - "$B/compat" <<'PY' import sys p=sys.argv[1]; s=open(p).read() old='void*\nmysbrk(ulong size)\n{\n\treturn sbrk(size);\n}' new='''#include void* mysbrk(ulong size) { \tvoid *p; \tp = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); \tif(p == MAP_FAILED) return (void*)-1; \treturn p; }''' if old in s: open(p,'w').write(s.replace(old,new)); print(" mmap-патч: ок") else: print(" mmap-патч: паттерн не найден") PY # ---- yacc: cc.y -> y.tab.c / y.tab.h ---- yacc -d cc.y 2>/dev/null || yacc -d "$SRC/cc/cc.y" sed -i -E 's/\bround\b/p9round/g; s/\blog2\b/p9log2/g' y.tab.c 2>/dev/null || true # ---- компиляция (-fcommon: tentative-глобалы под gcc -fno-common) ---- ok=0; fail=0; errf=""; rm -f *.o for f in *.c; do if 9c -fcommon -I. "$f" >/tmp/ba_$$ 2>&1; then ok=$((ok+1)); else fail=$((fail+1)); [ -z "$errf" ] && errf="$f" && cp /tmp/ba_$$ /tmp/baf_$$; fi done echo "[$A] компиляция: OK=$ok FAIL=$fail" [ "$fail" != 0 ] && { echo "первая ошибка ($errf):"; head -8 /tmp/baf_$$; exit 2; } # ---- линковка: свой machcap.o -> выкинуть omachcap.o; иначе omachcap и есть machcap ---- if [ -f machcap.o ]; then LINK=$(ls *.o | grep -v '^omachcap.o$'); else LINK=$(ls *.o); fi 9l -o "$A" $LINK echo "[$A] бинарь: $(ls -la $A | awk '{print $5}') байт -> $B/$A"