new-build: get rid of Go(ogle) with few rc scripts
Also, in binutils: fix inlining compilation error, see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242053
This commit is contained in:
parent
6b473cd28f
commit
0c2dabf975
|
@ -1,6 +1,3 @@
|
|||
third_party/pkg/
|
||||
third_party/src/github.com/kr/
|
||||
third_party/src/github.com/creack/
|
||||
third_party/src/golang.org/
|
||||
|
||||
*.build.log
|
||||
|
||||
lib/
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
[submodule "third_party/src/github.com/lionkov/ninep"]
|
||||
path = third_party/src/github.com/lionkov/ninep
|
||||
url = https://github.com/JehanneOS/devtools-ninep.git
|
||||
branch = master
|
||||
[submodule "third_party/src/github.com/0intro/drawterm"]
|
||||
path = third_party/src/github.com/0intro/drawterm
|
||||
url = https://github.com/JehanneOS/devtools-drawterm.git
|
||||
[submodule "cross/pkgs/newlib/src"]
|
||||
path = cross/pkgs/newlib/src
|
||||
url = https://github.com/JehanneOS/newlib.git
|
||||
[submodule "cross/pkgs/mksh"]
|
||||
path = cross/pkgs/mksh/src
|
||||
url = https://github.com/JehanneOS/mksh.git
|
||||
[submodule "src/trampoline"]
|
||||
path = src/trampoline
|
||||
url = https://tesio@bitbucket.org/tesio/trampoline.git
|
||||
[submodule "src/u9fs"]
|
||||
path = src/u9fs
|
||||
url = https://bitbucket.org/plan9-from-bell-labs/u9fs.git
|
||||
[submodule "src/drawterm"]
|
||||
path = src/drawterm
|
||||
url = https://github.com/JehanneOS/devtools-drawterm.git
|
||||
[submodule "src/netcat"]
|
||||
path = src/netcat
|
||||
url = https://git.code.sf.net/p/nc110/git
|
||||
|
|
4
QA.sh
4
QA.sh
|
@ -11,7 +11,7 @@ fi
|
|||
|
||||
trap : 2
|
||||
|
||||
$JEHANNE/hacking/bin/ufs -d=0 -root=$JEHANNE &
|
||||
$JEHANNE/hacking/bin/nc -p 5640 -l -e $JEHANNE/hacking/bin/start-u9fs.sh &
|
||||
ufspid=$!
|
||||
|
||||
export machineflag=pc
|
||||
|
@ -76,6 +76,6 @@ EOF
|
|||
echo $cmd
|
||||
eval $cmd
|
||||
|
||||
kill $ufspid
|
||||
# kill $ufspid # not needed anymore thank to netcat
|
||||
wait
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
*
|
||||
!.gitignore
|
||||
!build
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env rc
|
||||
# poor man portable expect
|
||||
|
||||
QPROMPT='10.0.2.15# '
|
||||
INFILE=/tmp/runqemu.$pid.in
|
||||
OUTFILE=/tmp/runqemu.$pid.out
|
||||
|
||||
cd $JEHANNE/arch/amd64/kern
|
||||
echo -n > $INFILE
|
||||
echo -n > $OUTFILE
|
||||
|
||||
@{tail -f $INFILE | $JEHANNE/hacking/QA.sh >> $OUTFILE} &
|
||||
QPID=$apid
|
||||
|
||||
tail -f $OUTFILE &
|
||||
TPID=$apid
|
||||
|
||||
ifs='
|
||||
'
|
||||
INPUT=`{cat}
|
||||
|
||||
fn descendants {
|
||||
if( ! ~ 0 $#1 ) {
|
||||
echo $1;
|
||||
ps -o pid= --ppid $1|xargs -n 1 rc -c 'descendants $1'
|
||||
}
|
||||
}
|
||||
|
||||
fn quit {
|
||||
kill -2 `{descendants $QPID}
|
||||
kill -2 $TPID
|
||||
wait
|
||||
rm $INFILE
|
||||
rm $OUTFILE
|
||||
exit $1
|
||||
}
|
||||
|
||||
fn failOnError {
|
||||
if( ! ~ 0 `{cat $OUTFILE | grep FAIL | wc -c}){
|
||||
quit 1
|
||||
}
|
||||
}
|
||||
|
||||
for(cmd in $INPUT){
|
||||
while( ~ 0 `{tail -n 1 $OUTFILE | sed -n '/'$QPROMPT'/p' | wc -c}){
|
||||
sleep 2
|
||||
}
|
||||
failOnError
|
||||
echo $cmd >> $INFILE
|
||||
sleep 2
|
||||
}
|
||||
|
||||
while( ~ 0 `{tail -n 1 $OUTFILE | sed -n '/'$QPROMPT'/p' | wc -c}){
|
||||
sleep 2
|
||||
}
|
||||
failOnError
|
||||
quit
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
# U9FS_LOG="-l $JEHANNE/hacking/lib/u9fs.log -z -D"
|
||||
$JEHANNE/hacking/bin/u9fs $U9FS_LOG -a none -u $USER $JEHANNE
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
$JEHANNE/hacking/bin/rc $JEHANNE/arch/rc/cmd/template $@
|
|
@ -4,16 +4,16 @@
|
|||
#
|
||||
# Copyright (C) 2016-2017 Giacomo Tesio <giacomo@tesio.it>
|
||||
|
||||
BUILD_GO_TOOLS=true
|
||||
BUILD_TRAMPOLINE=true
|
||||
BUILD_DRAWTERM=true
|
||||
|
||||
while test $# -gt 0
|
||||
do
|
||||
case "$1" in
|
||||
--help) echo "$0 [ --no-tools | --no-drawterm | --help ]"
|
||||
--help) echo "$0 [ --no-trampoline | --no-drawterm | --help ]"
|
||||
exit 0
|
||||
;;
|
||||
--no-tools) BUILD_GO_TOOLS=false
|
||||
--no-tools) BUILD_TRAMPOLINE=false
|
||||
;;
|
||||
--no-drawterm) BUILD_DRAWTERM=false
|
||||
;;
|
||||
|
@ -29,10 +29,10 @@ cd `dirname $0`
|
|||
if [ -z "$UTILITIES" ]; then
|
||||
UTILITIES=`pwd`
|
||||
fi
|
||||
if [ "$BUILD_GO_TOOLS$BUILD_DRAWTERM" = "truetrue" ]; then
|
||||
if [ "$BUILD_TRAMPOLINE$BUILD_DRAWTERM" = "truetrue" ]; then
|
||||
git clean -x -d -f $UTILITIES/bin
|
||||
fi
|
||||
if [ "$BUILD_GO_TOOLS" = "true" ]; then
|
||||
if [ "$BUILD_TRAMPOLINE" = "true" ]; then
|
||||
echo -n Building development tools.
|
||||
(
|
||||
# Inside parentheses, and therefore a subshell . . .
|
||||
|
@ -44,18 +44,20 @@ if [ "$BUILD_GO_TOOLS" = "true" ]; then
|
|||
) &
|
||||
dotter=$!
|
||||
(
|
||||
GOBIN="$UTILITIES/bin" GOPATH="$UTILITIES/third_party:$UTILITIES" go get -d jehanne/cmd/... &&
|
||||
GOBIN="$UTILITIES/bin" GOPATH="$UTILITIES/third_party:$UTILITIES" go install jehanne/cmd/... &&
|
||||
GOBIN="$UTILITIES/bin" GOPATH="$UTILITIES/third_party:$UTILITIES" go install github.com/lionkov/ninep/srv/examples/ufs
|
||||
)
|
||||
(cd $UTILITIES/src/trampoline/ && ./build.sh)
|
||||
(cd $UTILITIES/src/netcat && XLIB=-lresolv DFLAGS=-DGAPING_SECURITY_HOLE make linux && mv nc $UTILITIES/bin && git clean -xdf .)
|
||||
(cd $UTILITIES/src/u9fs && make && mv u9fs $UTILITIES/bin && git clean -xdf .)
|
||||
) > $UTILITIES/src/utils.build.log 2>&1
|
||||
STATUS="$?"
|
||||
kill $dotter
|
||||
wait $dotter 2>/dev/null
|
||||
if [ ! $STATUS -eq "0" ]
|
||||
then
|
||||
echo "FAIL"
|
||||
cat utils.build.log
|
||||
exit $STATUS
|
||||
else
|
||||
rm $UTILITIES/src/utils.build.log
|
||||
echo "done."
|
||||
fi
|
||||
fi
|
||||
|
@ -72,7 +74,7 @@ if [ "$BUILD_DRAWTERM" = "true" ]; then
|
|||
) &
|
||||
dotter=$!
|
||||
(
|
||||
cd $UTILITIES/third_party/src/github.com/0intro/drawterm/ &&
|
||||
cd $UTILITIES/src/drawterm/ &&
|
||||
git clean -xdf > ../drawterm.build.log 2>&1 &&
|
||||
CONF=unix make >> ../drawterm.build.log 2>&1 &&
|
||||
mv drawterm $UTILITIES/bin
|
||||
|
@ -82,11 +84,11 @@ if [ "$BUILD_DRAWTERM" = "true" ]; then
|
|||
wait $dotter 2>/dev/null
|
||||
if [ $STATUS -eq "0" ]
|
||||
then
|
||||
rm $UTILITIES/third_party/src/github.com/0intro/drawterm.build.log
|
||||
rm $UTILITIES/src/drawterm.build.log
|
||||
echo "done."
|
||||
else
|
||||
echo "FAIL"
|
||||
cat $UTILITIES/third_party/src/github.com/0intro/drawterm.build.log
|
||||
cat $$UTILITIES/src/drawterm.build.log
|
||||
exit $STATUS
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -54,16 +54,7 @@ if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then
|
|||
export TOOLPREFIX=x86_64-jehanne-
|
||||
export CC=x86_64-jehanne-gcc
|
||||
|
||||
echo
|
||||
echo "Vendorized code verification..."
|
||||
echo
|
||||
for v in `find $JEHANNE -type f|grep vendor.json`; do
|
||||
echo "cd `dirname $v`"
|
||||
(cd `dirname $v`; vendor -check)
|
||||
done
|
||||
echo
|
||||
|
||||
build all
|
||||
build
|
||||
|
||||
if [ "$TRAVIS_BUILD_DIR" != "" ]; then
|
||||
if [ "$QA_CHECKS" != "" ]; then
|
||||
|
|
|
@ -51,7 +51,7 @@ function dynpatch {
|
|||
|
||||
|
||||
# setup Jehanne's headers
|
||||
usyscalls header $JEHANNE/sys/src/sysconf.json > $JEHANNE/arch/amd64/include/syscalls.h
|
||||
cat $JEHANNE/sys/src/lib/jehanne/syscallh.rc.template | template | rc | sed 's/ ,/,/g; s/ )/)/g' > $JEHANNE/arch/amd64/include/syscalls.h
|
||||
|
||||
mkdir -p $WORKING_DIR
|
||||
date > $LOG
|
||||
|
@ -63,7 +63,7 @@ failOnError $? "libtool installation check"
|
|||
|
||||
cp -fpr $JEHANNE/hacking/cross/src $WORKING_DIR
|
||||
cd $WORKING_DIR/src
|
||||
fetch >> $LOG
|
||||
./fetch.sh >> $LOG
|
||||
failOnError $? "fetching sources"
|
||||
|
||||
mkdir -p $WORKING_DIR/build
|
||||
|
@ -76,10 +76,12 @@ echo -n Building binutils...
|
|||
export BINUTILS_BUILD_DIR=$WORKING_DIR/build/binutils
|
||||
mkdir -p $BINUTILS_BUILD_DIR
|
||||
|
||||
# for libctf/swap.h patch see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242053
|
||||
( ( grep -q jehanne $WORKING_DIR/src/binutils/config.sub || (
|
||||
cd $WORKING_DIR &&
|
||||
sed -i '/jehanne/b; /ELF_TARGET_ID/,/elf_backend_can_gc_sections/s/0x200000/0x1000 \/\/ jehanne hack/g' src/binutils/bfd/elf64-x86-64.c &&
|
||||
sed -i '/jehanne/b; s/| midnightbsd\*/| midnightbsd* | jehanne*/g' src/binutils/config.sub &&
|
||||
sed -i 's/inline/static inline/g' src/binutils/libctf/swap.h &&
|
||||
dynpatch 'binutils/bfd/config.bfd' '\# END OF targmatch.h' &&
|
||||
dynpatch 'binutils/gas/configure.tgt' ' i386-\*-darwin\*)' &&
|
||||
( grep -q jehanne src/binutils/ld/configure.tgt || patch -p1 < $CROSS_DIR/patch/binutils/ld/configure.tgt ) &&
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"CrossCompiledPackages": {
|
||||
"Env": [
|
||||
"CROSS_PKGS_BUILD=1"
|
||||
],
|
||||
"Pre": [
|
||||
"./newlib/build.sh",
|
||||
"./mksh/build.sh",
|
||||
"./gcc/build.sh"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
export IFS="$ifs"
|
||||
export CROSS_PKGS_BUILD=1
|
||||
export CFLAGS=''
|
||||
export CC=''
|
||||
|
||||
./newlib/build.sh
|
||||
./mksh/build.sh
|
||||
./gcc/build.sh
|
|
@ -50,7 +50,7 @@ ln -s `which echo` $JEHANNE/hacking/bin/makeinfo
|
|||
libtool --version >> /dev/null
|
||||
failOnError $? "libtool installation check"
|
||||
|
||||
(cd $JEHANNE_TOOLCHAIN/src && fetch) >> $LOG
|
||||
(cd $JEHANNE_TOOLCHAIN/src && ./fetch.sh) >> $LOG
|
||||
failOnError $? "fetching sources"
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
download () {
|
||||
TARGET=$(basename $1)
|
||||
if [ -f $TARGET ]; then
|
||||
echo "fetch: skip $TARGET (already present)"
|
||||
elif command -v curl >/dev/null 2>&1; then
|
||||
curl -s --fail "$1" > $TARGET
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -O- "$1" > $TARGET
|
||||
else
|
||||
echo "ERROR: Unable to find either curl or wget" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
extract () {
|
||||
TARGET=$1
|
||||
ARCHIVE=$2
|
||||
if [ -d $TARGET ]; then
|
||||
echo "fetch: skip $TARGET (already present)"
|
||||
else
|
||||
mkdir -p $TARGET
|
||||
(cd $TARGET && tar xf ../$ARCHIVE --strip-components=1)
|
||||
fi
|
||||
}
|
||||
|
||||
echo "fetch: downloading..."
|
||||
download 'https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2'
|
||||
download 'https://www.mpfr.org/mpfr-4.0.1/mpfr-4.0.1.tar.bz2'
|
||||
download 'https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz'
|
||||
download 'http://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2'
|
||||
download 'https://ftp.gnu.org/gnu/gcc/gcc-9.2.0/gcc-9.2.0.tar.gz'
|
||||
|
||||
echo "fetch: check sum..."
|
||||
sha256sum -c sha256sum.txt
|
||||
|
||||
echo "fetch: extract archive..."
|
||||
extract libgmp gmp-6.1.2.tar.bz2
|
||||
extract libmpfr mpfr-4.0.1.tar.bz2
|
||||
extract libmpc mpc-1.1.0.tar.gz
|
||||
extract binutils binutils-2.33.1.tar.bz2
|
||||
extract gcc gcc-9.2.0.tar.gz
|
||||
|
||||
echo "fetch: done."
|
|
@ -0,0 +1,5 @@
|
|||
0cb4843da15a65a953907c96bad658283f3c4419d6bcc56bf2789db16306adb2 binutils-2.33.1.tar.bz2
|
||||
a931a750d6feadacbeecb321d73925cd5ebb6dfa7eff0802984af3aef63759f4 gcc-9.2.0.tar.gz
|
||||
5275bb04f4863a13516b2f39392ac5e272f5e1bb8057b18aec1c9b79d73d8fb2 gmp-6.1.2.tar.bz2
|
||||
6985c538143c1208dcb1ac42cedad6ff52e267b47e5f970183a3e75125b43c2e mpc-1.1.0.tar.gz
|
||||
a4d97610ba8579d380b384b225187c250ef88cfe1d5e7226b89519374209b86b mpfr-4.0.1.tar.bz2
|
|
@ -1,53 +0,0 @@
|
|||
{
|
||||
"libgmp" : {
|
||||
"Upstream":"https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2",
|
||||
"Digest": {
|
||||
"sha256":"5275bb04f4863a13516b2f39392ac5e272f5e1bb8057b18aec1c9b79d73d8fb2"
|
||||
},
|
||||
"Compress":"bzip2",
|
||||
"RemovePrefix": true,
|
||||
"Exclude": [
|
||||
]
|
||||
},
|
||||
"libmpfr" : {
|
||||
"Upstream":"https://www.mpfr.org/mpfr-4.0.1/mpfr-4.0.1.tar.bz2",
|
||||
"Digest": {
|
||||
"sha256":"a4d97610ba8579d380b384b225187c250ef88cfe1d5e7226b89519374209b86b"
|
||||
},
|
||||
"Compress":"bzip2",
|
||||
"RemovePrefix": true,
|
||||
"Exclude": [
|
||||
]
|
||||
},
|
||||
"libmpc" : {
|
||||
"Upstream":"https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz",
|
||||
"Digest": {
|
||||
"sha256":"6985c538143c1208dcb1ac42cedad6ff52e267b47e5f970183a3e75125b43c2e"
|
||||
},
|
||||
"Compress":"gzip",
|
||||
"RemovePrefix": true,
|
||||
"Exclude": [
|
||||
]
|
||||
},
|
||||
"binutils": {
|
||||
"Upstream":"http://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2",
|
||||
"Digest": {
|
||||
"sha256":"0cb4843da15a65a953907c96bad658283f3c4419d6bcc56bf2789db16306adb2"
|
||||
},
|
||||
"Compress":"bzip2",
|
||||
"RemovePrefix": true,
|
||||
"Exclude": [
|
||||
]
|
||||
},
|
||||
"gcc": {
|
||||
"Upstream":"https://ftp.gnu.org/gnu/gcc/gcc-9.2.0/gcc-9.2.0.tar.gz",
|
||||
"Digest": {
|
||||
"sha256":"a931a750d6feadacbeecb321d73925cd5ebb6dfa7eff0802984af3aef63759f4"
|
||||
},
|
||||
"Compress":"gzip",
|
||||
"RemovePrefix": true,
|
||||
"Exclude": [
|
||||
]
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
download () {
|
||||
TARGET=$(basename $1)
|
||||
if [ -f $TARGET ]; then
|
||||
echo "fetch: skip $TARGET (already present)"
|
||||
elif command -v curl >/dev/null 2>&1; then
|
||||
curl -s --fail "$1" > $TARGET
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -O- "$1" > $TARGET
|
||||
else
|
||||
echo "ERROR: Unable to find either curl or wget" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
extract () {
|
||||
TARGET=$1
|
||||
ARCHIVE=$2
|
||||
if [ -d $TARGET ]; then
|
||||
echo "fetch: skip $TARGET (already present)"
|
||||
else
|
||||
mkdir -p $TARGET
|
||||
(cd $TARGET && tar xf ../$ARCHIVE --strip-components=1)
|
||||
fi
|
||||
}
|
||||
|
||||
echo "fetch: downloading..."
|
||||
download 'https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2'
|
||||
download 'https://www.mpfr.org/mpfr-4.0.1/mpfr-4.0.1.tar.bz2'
|
||||
download 'https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz'
|
||||
download 'http://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2'
|
||||
download 'https://ftp.gnu.org/gnu/gcc/gcc-9.2.0/gcc-9.2.0.tar.gz'
|
||||
|
||||
echo "fetch: check sum..."
|
||||
sha256sum -c sha256sum.txt
|
||||
|
||||
echo "fetch: extract archive..."
|
||||
extract libgmp gmp-6.1.2.tar.bz2
|
||||
extract libmpfr mpfr-4.0.1.tar.bz2
|
||||
extract libmpc mpc-1.1.0.tar.gz
|
||||
extract binutils binutils-2.33.1.tar.bz2
|
||||
extract gcc gcc-9.2.0.tar.gz
|
||||
|
||||
echo "fetch: done."
|
|
@ -0,0 +1,5 @@
|
|||
0cb4843da15a65a953907c96bad658283f3c4419d6bcc56bf2789db16306adb2 binutils-2.33.1.tar.bz2
|
||||
a931a750d6feadacbeecb321d73925cd5ebb6dfa7eff0802984af3aef63759f4 gcc-9.2.0.tar.gz
|
||||
5275bb04f4863a13516b2f39392ac5e272f5e1bb8057b18aec1c9b79d73d8fb2 gmp-6.1.2.tar.bz2
|
||||
6985c538143c1208dcb1ac42cedad6ff52e267b47e5f970183a3e75125b43c2e mpc-1.1.0.tar.gz
|
||||
a4d97610ba8579d380b384b225187c250ef88cfe1d5e7226b89519374209b86b mpfr-4.0.1.tar.bz2
|
10
devshell.sh
10
devshell.sh
|
@ -9,10 +9,16 @@ REPONAME=`basename $JEHANNE`
|
|||
JEHANNE_TOOLCHAIN=`dirname $JEHANNE`
|
||||
JEHANNE_TOOLCHAIN="$JEHANNE_TOOLCHAIN/$REPONAME.TOOLCHAIN"
|
||||
export JEHANNE_TOOLCHAIN
|
||||
JEHANNE_TOOLCHAIN_CROSS="$JEHANNE_TOOLCHAIN/cross"
|
||||
export JEHANNE_TOOLCHAIN_CROSS
|
||||
JEHANNE_HACKING=$JEHANNE/hacking
|
||||
export JEHANNE_HACKING
|
||||
|
||||
export PATH="$JEHANNE/hacking/bin:$PATH"
|
||||
export PATH="$JEHANNE_TOOLCHAIN/cross/posix/bin:$PATH"
|
||||
#export CPATH="$JEHANNE_TOOLCHAIN/cross/posix/lib/gcc/x86_64-jehanne/9.2.0/include:$JEHANNE_TOOLCHAIN/cross/posix/lib/gcc/x86_64-jehanne/9.2.0/include-fixed"
|
||||
export PATH="$JEHANNE_HACKING/bin:$PATH"
|
||||
export PATH_CLONE=$PATH
|
||||
|
||||
|
||||
export ARCH=amd64
|
||||
|
||||
export TOOLPREFIX=x86_64-jehanne-
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# rcmain: Plan 9 on Unix version
|
||||
if(~ $#home 0) home=$HOME
|
||||
if(~ $#home 0) home=/
|
||||
if(~ $#ifs 0) ifs='
|
||||
'
|
||||
switch($#prompt){
|
||||
case 0
|
||||
prompt=('% ' ' ')
|
||||
case 1
|
||||
prompt=($prompt ' ')
|
||||
}
|
||||
if(~ $rcname ?.out ?.rc */?.rc */?.out) prompt=('broken! ' ' ')
|
||||
if(flag p) path=(/bin /usr/bin)
|
||||
if not{
|
||||
finit
|
||||
# should be taken care of by rc now, but leave just in case
|
||||
}
|
||||
fn sigexit
|
||||
if(! ~ $#cflag 0){
|
||||
if(flag l && test -r $home/lib/profile) . $home/lib/profile
|
||||
status=''
|
||||
eval $cflag
|
||||
exit $status
|
||||
}
|
||||
if(flag i){
|
||||
if(~ $termprog 9term || ~ $termprog win){
|
||||
fn cd {
|
||||
# builtin cd $1 && flag i && awd
|
||||
# is not sufficient when running in a subshell
|
||||
# that is rc -e (like mk uses!)
|
||||
if(builtin cd $1){
|
||||
if(flag i) $PLAN9/bin/9 awd || status=''
|
||||
status=''
|
||||
}
|
||||
}
|
||||
$PLAN9/bin/9 awd
|
||||
}
|
||||
if(flag l && test -r $home/lib/profile) . $home/lib/profile
|
||||
status=''
|
||||
if(! ~ $#* 0) . $*
|
||||
. -i '/dev/stdin'
|
||||
exit $status
|
||||
}
|
||||
if(flag l && test -r $home/lib/profile) . $home/lib/profile
|
||||
if(~ $#* 0){
|
||||
. /dev/stdin
|
||||
exit $status
|
||||
}
|
||||
status=''
|
||||
. $*
|
||||
exit $status
|
|
@ -13,8 +13,7 @@ fi
|
|||
|
||||
trap : 2
|
||||
|
||||
$JEHANNE/hacking/bin/ufs -root=$JEHANNE &
|
||||
# To debug ufs add: -d 5 > $JEHANNE/../ufs.log 2>&1
|
||||
$JEHANNE/hacking/bin/nc -p 5640 -l -e $JEHANNE/hacking/bin/start-u9fs.sh &
|
||||
ufspid=$!
|
||||
|
||||
export machineflag=pc
|
||||
|
@ -53,7 +52,7 @@ QEMU_USER=`whoami`
|
|||
|
||||
cd $KERNDIR
|
||||
read -r cmd <<EOF
|
||||
$kvmdo qemu-system-x86_64 -s -cpu Haswell -smp $NCPU -m 2048 $kvmflag \
|
||||
$kvmdo qemu-system-x86_64 -s -cpu max -smp $NCPU -m 2048 $kvmflag \
|
||||
-rtc clock=vm \
|
||||
-no-reboot -serial mon:stdio \
|
||||
--machine $machineflag \
|
||||
|
@ -74,5 +73,5 @@ EOF
|
|||
echo $cmd
|
||||
eval $cmd
|
||||
|
||||
kill $ufspid
|
||||
# kill $ufspid # not needed anymore thank to netcat
|
||||
wait
|
||||
|
|
|
@ -1,669 +0,0 @@
|
|||
// Build builds code as directed by json files.
|
||||
// We slurp in the JSON, and recursively process includes.
|
||||
// At the end, we issue a single cc command for all the files.
|
||||
// Compilers are fast.
|
||||
//
|
||||
// ENVIRONMENT
|
||||
//
|
||||
// Needed: JEHANNE, ARCH
|
||||
//
|
||||
// JEHANNE should point to a Jehanne root.
|
||||
// Currently only "amd64" is a valid ARCH.
|
||||
// A best-effort to autodetect the Jehanne root is made if not explicitly set.
|
||||
//
|
||||
// Optional: CC, AR, LD, RANLIB, STRIP, SH, TOOLPREFIX
|
||||
//
|
||||
// These all control how the needed tools are found.
|
||||
//
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type kernconfig struct {
|
||||
Code []string
|
||||
Dev []string
|
||||
Ip []string
|
||||
Link []string
|
||||
Sd []string
|
||||
Uart []string
|
||||
VGA []string
|
||||
}
|
||||
|
||||
type kernel struct {
|
||||
CodeFile string
|
||||
Systab string
|
||||
Config kernconfig
|
||||
Ramfiles map[string]string
|
||||
}
|
||||
|
||||
type build struct {
|
||||
// jsons is unexported so can not be set in a .json file
|
||||
jsons map[string]bool
|
||||
path string
|
||||
name string
|
||||
// Projects name a whole subproject which is built independently of
|
||||
// this one. We'll need to be able to use environment variables at some point.
|
||||
Projects []string
|
||||
Pre []string
|
||||
Post []string
|
||||
Cflags []string
|
||||
Oflags []string
|
||||
Include []string
|
||||
SourceFiles []string
|
||||
ObjectFiles []string
|
||||
Libs []string
|
||||
Env []string
|
||||
// cmd's
|
||||
SourceFilesCmd []string
|
||||
// Targets.
|
||||
Program string
|
||||
Library string
|
||||
Install string // where to place the resulting binary/lib
|
||||
Kernel *kernel
|
||||
}
|
||||
|
||||
type buildfile map[string]build
|
||||
|
||||
// UnmarshalJSON works like the stdlib unmarshal would, except it adjusts all
|
||||
// paths.
|
||||
func (bf *buildfile) UnmarshalJSON(s []byte) error {
|
||||
r := make(map[string]build)
|
||||
if err := json.Unmarshal(s, &r); err != nil {
|
||||
return err
|
||||
}
|
||||
for k, b := range r {
|
||||
// we're getting a copy of the struct, remember.
|
||||
b.jsons = make(map[string]bool)
|
||||
b.Projects = adjust(b.Projects)
|
||||
b.Libs = adjust(b.Libs)
|
||||
b.Cflags = adjust(b.Cflags)
|
||||
b.SourceFiles = b.SourceFiles
|
||||
b.SourceFilesCmd = b.SourceFilesCmd
|
||||
b.ObjectFiles = b.ObjectFiles
|
||||
b.Include = adjust(b.Include)
|
||||
b.Install = fromRoot(b.Install)
|
||||
for i, e := range b.Env {
|
||||
b.Env[i] = os.ExpandEnv(e)
|
||||
}
|
||||
r[k] = b
|
||||
}
|
||||
*bf = r
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
cwd string
|
||||
jehanne string
|
||||
regexpAll = []*regexp.Regexp{regexp.MustCompile(".")}
|
||||
|
||||
// findTools looks at all env vars and absolutizes these paths
|
||||
// also respects TOOLPREFIX
|
||||
tools = map[string]string{
|
||||
"cc": "gcc",
|
||||
"ar": "ar",
|
||||
"ld": "ld",
|
||||
"ranlib": "ranlib",
|
||||
"strip": "strip",
|
||||
"sh": "sh",
|
||||
}
|
||||
arch = map[string]bool{
|
||||
"amd64": true,
|
||||
}
|
||||
debugPrint = flag.Bool("debug", false, "enable debug prints")
|
||||
shellhack = flag.Bool("shellhack", false, "spawn every command in a shell (forced on if LD_PRELOAD is set)")
|
||||
)
|
||||
|
||||
func debug(fmt string, s ...interface{}) {
|
||||
if *debugPrint {
|
||||
log.Printf(fmt, s...)
|
||||
}
|
||||
}
|
||||
|
||||
// fail with message, if err is not nil
|
||||
func failOn(err error) {
|
||||
if err != nil {
|
||||
log.Fatalf("%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func isValueInList(value string, list []string) bool {
|
||||
for _, v := range list {
|
||||
if v == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func adjust(s []string) []string {
|
||||
for i, v := range s {
|
||||
s[i] = fromRoot(v)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func buildEnv(b *build) func(string) string{
|
||||
return func(v string) string {
|
||||
search := v + "="
|
||||
for _, s := range b.Env {
|
||||
if strings.Index(s, search) == 0 {
|
||||
return strings.Replace(s, search, "", 1)
|
||||
}
|
||||
}
|
||||
return os.Getenv(v)
|
||||
}
|
||||
}
|
||||
|
||||
// return the given absolute path as an absolute path rooted at the jehanne tree.
|
||||
func fromRoot(p string) string {
|
||||
p = os.ExpandEnv(p)
|
||||
if path.IsAbs(p) {
|
||||
return path.Join(jehanne, p)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Sh sends cmd to a shell. It's needed to enable $LD_PRELOAD tricks,
|
||||
// see https://github.com/Harvey-OS/jehanne/issues/8#issuecomment-131235178
|
||||
func sh(cmd *exec.Cmd) {
|
||||
shell := exec.Command(tools["sh"])
|
||||
shell.Env = cmd.Env
|
||||
|
||||
if cmd.Args[0] == tools["sh"] && cmd.Args[1] == "-c" {
|
||||
cmd.Args = cmd.Args[2:]
|
||||
}
|
||||
commandString := strings.Join(cmd.Args, " ")
|
||||
if shStdin, e := shell.StdinPipe(); e == nil {
|
||||
go func() {
|
||||
defer shStdin.Close()
|
||||
io.WriteString(shStdin, commandString)
|
||||
}()
|
||||
} else {
|
||||
log.Fatalf("cannot pipe [%v] to %s: %v", commandString, tools["sh"], e)
|
||||
}
|
||||
shell.Stderr = os.Stderr
|
||||
shell.Stdout = os.Stdout
|
||||
|
||||
debug("%q | sh\n", commandString)
|
||||
failOn(shell.Run())
|
||||
}
|
||||
|
||||
func mergeKernel(k *kernel, defaults *kernel) *kernel {
|
||||
if k == nil {
|
||||
return defaults
|
||||
}
|
||||
if defaults == nil {
|
||||
return k
|
||||
}
|
||||
|
||||
// The custom kernel Code will be added after the default from includes
|
||||
// so that it has a chance to change de default behaviour.
|
||||
k.Config.Code = append(defaults.Config.Code, k.Config.Code...)
|
||||
|
||||
k.Config.Dev = append(k.Config.Dev, defaults.Config.Dev...)
|
||||
k.Config.Ip = append(k.Config.Ip, defaults.Config.Ip...)
|
||||
k.Config.Link = append(k.Config.Link, defaults.Config.Link...)
|
||||
k.Config.Sd = append(k.Config.Sd, defaults.Config.Sd...)
|
||||
k.Config.Uart = append(k.Config.Uart, defaults.Config.Uart...)
|
||||
k.Config.VGA = append(k.Config.VGA, defaults.Config.VGA...)
|
||||
|
||||
if k.CodeFile == "" {
|
||||
k.CodeFile = defaults.CodeFile
|
||||
}
|
||||
if k.Systab == "" {
|
||||
k.Systab = defaults.Systab
|
||||
}
|
||||
for name, path := range defaults.Ramfiles {
|
||||
if _, ok := k.Ramfiles[name]; ok == false {
|
||||
k.Ramfiles[name] = path
|
||||
}
|
||||
}
|
||||
|
||||
return k
|
||||
}
|
||||
|
||||
func include(f string, b *build) {
|
||||
if b.jsons[f] {
|
||||
return
|
||||
}
|
||||
b.jsons[f] = true
|
||||
log.Printf("Including %v", f)
|
||||
d, err := ioutil.ReadFile(f)
|
||||
failOn(err)
|
||||
var builds buildfile
|
||||
failOn(json.Unmarshal(d, &builds))
|
||||
|
||||
for n, build := range builds {
|
||||
log.Printf("Merging %v", n)
|
||||
b.SourceFiles = append(b.SourceFiles, build.SourceFiles...)
|
||||
b.Cflags = append(b.Cflags, build.Cflags...)
|
||||
b.Oflags = append(b.Oflags, build.Oflags...)
|
||||
b.Pre = append(b.Pre, build.Pre...)
|
||||
b.Post = append(b.Post, build.Post...)
|
||||
b.Libs = append(b.Libs, build.Libs...)
|
||||
b.Projects = append(b.Projects, build.Projects...)
|
||||
b.Env = append(b.Env, build.Env...)
|
||||
b.SourceFilesCmd = append(b.SourceFilesCmd, build.SourceFilesCmd...)
|
||||
b.Program += build.Program
|
||||
b.Library += build.Library
|
||||
b.Kernel = mergeKernel(b.Kernel, build.Kernel)
|
||||
if build.Install != "" {
|
||||
if b.Install != "" {
|
||||
log.Fatalf("In file %s (target %s) included by %s (target %s): redefined Install.", f, n, build.path, build.name)
|
||||
}
|
||||
b.Install = build.Install
|
||||
}
|
||||
b.ObjectFiles = append(b.ObjectFiles, build.ObjectFiles...)
|
||||
// For each source file, assume we create an object file with the last char replaced
|
||||
// with 'o'. We can get smarter later.
|
||||
for _, v := range build.SourceFiles {
|
||||
f := path.Base(v)
|
||||
o := f[:len(f)-1] + "o"
|
||||
b.ObjectFiles = append(b.ObjectFiles, o)
|
||||
}
|
||||
|
||||
for _, v := range build.Include {
|
||||
if !path.IsAbs(v) {
|
||||
wd := path.Dir(f)
|
||||
v = path.Join(wd, v)
|
||||
}
|
||||
include(v, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func appendIfMissing(s []string, v string) []string {
|
||||
for _, a := range s {
|
||||
if a == v {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return append(s, v)
|
||||
}
|
||||
|
||||
func process(f string, r []*regexp.Regexp) []build {
|
||||
log.Printf("Processing %v", f)
|
||||
var builds buildfile
|
||||
var results []build
|
||||
d, err := ioutil.ReadFile(f)
|
||||
failOn(err)
|
||||
failOn(json.Unmarshal(d, &builds))
|
||||
|
||||
// Sort keys alphabetically (GoLang does not preserve the JSON order)
|
||||
var keys []string
|
||||
for n := range builds {
|
||||
keys = append(keys, n)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, n := range keys {
|
||||
build := builds[n]
|
||||
build.name = n
|
||||
build.jsons = make(map[string]bool)
|
||||
skip := true
|
||||
for _, re := range r {
|
||||
if re.MatchString(build.name) {
|
||||
skip = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
log.Printf("Run %v", build.name)
|
||||
build.jsons[f] = true
|
||||
build.path = path.Dir(f)
|
||||
|
||||
// For each source file, assume we create an object file with the last char replaced
|
||||
// with 'o'. We can get smarter later.
|
||||
for _, v := range build.SourceFiles {
|
||||
f := path.Base(v)
|
||||
o := f[:len(f)-1] + "o"
|
||||
build.ObjectFiles = appendIfMissing(build.ObjectFiles, o)
|
||||
}
|
||||
|
||||
for _, v := range build.Include {
|
||||
include(v, &build)
|
||||
}
|
||||
results = append(results, build)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
func buildkernel(b *build) {
|
||||
if b.Kernel == nil {
|
||||
return
|
||||
}
|
||||
envFunc := buildEnv(b)
|
||||
for name, path := range b.Kernel.Ramfiles {
|
||||
b.Kernel.Ramfiles[name] = os.Expand(path, envFunc);
|
||||
}
|
||||
codebuf := confcode(b.path, b.Kernel)
|
||||
if b.Kernel.CodeFile == "" {
|
||||
log.Fatalf("Missing Kernel.CodeFile in %v\n", b.path)
|
||||
}
|
||||
failOn(ioutil.WriteFile(b.Kernel.CodeFile, codebuf, 0666))
|
||||
}
|
||||
|
||||
func wrapInQuote(args []string) []string {
|
||||
var res []string
|
||||
for _, a := range(args){
|
||||
if strings.Contains(a, "=") {
|
||||
res = append(res, "'" + a + "'")
|
||||
} else {
|
||||
res = append(res, a)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func convertLibPathsToArgs(b *build) []string {
|
||||
libLocations := make([]string, 0)
|
||||
args := make([]string, 0)
|
||||
defaultLibLocation := fromRoot("/arch/$ARCH/lib")
|
||||
for _, lib := range b.Libs {
|
||||
ldir := filepath.Dir(lib)
|
||||
if ldir != defaultLibLocation {
|
||||
if !isValueInList(ldir, libLocations) {
|
||||
libLocations = append(libLocations, ldir)
|
||||
args = append(args, "-L", ldir)
|
||||
}
|
||||
}
|
||||
lib = strings.Replace(lib, ldir + "/lib", "-l", 1)
|
||||
lib = strings.Replace(lib, ".a", "", 1)
|
||||
args = append(args, lib)
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func compile(b *build) {
|
||||
log.Printf("Building %s\n", b.name)
|
||||
// N.B. Plan 9 has a very well defined include structure, just three things:
|
||||
// /amd64/include, /sys/include, .
|
||||
args := b.SourceFiles
|
||||
args = append(args, b.Cflags...)
|
||||
if !isValueInList("-c", b.Cflags) {
|
||||
args = append(args, convertLibPathsToArgs(b)...)
|
||||
args = append(args, b.Oflags...)
|
||||
}
|
||||
if len(b.SourceFilesCmd) > 0 {
|
||||
for _, i := range b.SourceFilesCmd {
|
||||
largs := make([]string, 3)
|
||||
largs[0] = i
|
||||
largs[1] = "-o"
|
||||
largs[2] = strings.Replace(filepath.Base(i), filepath.Ext(i), "", 1)
|
||||
cmd := exec.Command(tools["cc"], append(largs, args...)...)
|
||||
run(b, *shellhack, cmd)
|
||||
}
|
||||
return
|
||||
}
|
||||
if !isValueInList("-c", b.Cflags) {
|
||||
args = append(args, "-o", b.Program)
|
||||
}
|
||||
cmd := exec.Command(tools["cc"], args...)
|
||||
run(b, *shellhack, cmd)
|
||||
}
|
||||
|
||||
func link(b *build) {
|
||||
if !isValueInList("-c", b.Cflags) {
|
||||
return
|
||||
}
|
||||
log.Printf("Linking %s\n", b.name)
|
||||
if len(b.SourceFilesCmd) > 0 {
|
||||
for _, n := range b.SourceFilesCmd {
|
||||
// Split off the last element of the file
|
||||
var ext = filepath.Ext(n)
|
||||
if len(ext) == 0 {
|
||||
log.Fatalf("refusing to overwrite extension-less source file %v", n)
|
||||
continue
|
||||
}
|
||||
n = n[:len(n)-len(ext)]
|
||||
f := path.Base(n)
|
||||
o := f[:len(f)] + ".o"
|
||||
args := []string{"-o", n, o}
|
||||
args = append(args, b.Oflags...)
|
||||
args = append(args, b.Libs...)
|
||||
run(b, *shellhack, exec.Command(tools["ld"], args...))
|
||||
}
|
||||
return
|
||||
}
|
||||
args := []string{"-o", b.Program}
|
||||
args = append(args, b.ObjectFiles...)
|
||||
args = append(args, b.Oflags...)
|
||||
args = append(args, b.Libs...)
|
||||
run(b, *shellhack, exec.Command(tools["ld"], args...))
|
||||
}
|
||||
|
||||
func install(b *build) {
|
||||
if b.Install == "" {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Installing %s\n", b.name)
|
||||
failOn(os.MkdirAll(b.Install, 0755))
|
||||
|
||||
switch {
|
||||
case len(b.SourceFilesCmd) > 0:
|
||||
for _, n := range b.SourceFilesCmd {
|
||||
ext := filepath.Ext(n)
|
||||
exe := n[:len(n)-len(ext)]
|
||||
move(exe, b.Install)
|
||||
}
|
||||
case len(b.Program) > 0:
|
||||
move(b.Program, b.Install)
|
||||
case len(b.Library) > 0:
|
||||
ofiles := []string{}
|
||||
for _, o := range b.ObjectFiles {
|
||||
os.Rename(o, b.Library + "-" + o)
|
||||
ofiles = append(ofiles, b.Library + "-" + o)
|
||||
}
|
||||
libpath := path.Join(b.Install, b.Library)
|
||||
|
||||
args := append([]string{"-rs", libpath}, ofiles...)
|
||||
run(b, *shellhack, exec.Command(tools["ar"], args...))
|
||||
run(b, *shellhack, exec.Command(tools["ranlib"], libpath))
|
||||
}
|
||||
}
|
||||
|
||||
func move(from, to string) {
|
||||
final := path.Join(to, from)
|
||||
log.Printf("move %s %s\n", from, final)
|
||||
_ = os.Remove(final)
|
||||
failOn(os.Link(from, final))
|
||||
failOn(os.Remove(from))
|
||||
}
|
||||
|
||||
func run(b *build, pipe bool, cmd *exec.Cmd) {
|
||||
if b != nil {
|
||||
cmd.Env = append(os.Environ(), b.Env...)
|
||||
}
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if pipe {
|
||||
// Sh sends cmd to a shell. It's needed to enable $LD_PRELOAD tricks, see https://github.com/Harvey-OS/jehanne/issues/8#issuecomment-131235178
|
||||
shell := exec.Command(tools["sh"])
|
||||
shell.Env = cmd.Env
|
||||
shell.Stderr = os.Stderr
|
||||
shell.Stdout = os.Stdout
|
||||
|
||||
commandString := cmd.Args[0]
|
||||
commandString += " " + strings.Join(wrapInQuote(cmd.Args[1:]), " ")
|
||||
shStdin, err := shell.StdinPipe()
|
||||
if err != nil {
|
||||
log.Fatalf("cannot pipe [%v] to %s: %v", commandString, tools["sh"], err)
|
||||
}
|
||||
go func() {
|
||||
defer shStdin.Close()
|
||||
io.WriteString(shStdin, commandString)
|
||||
}()
|
||||
|
||||
log.Printf("%q | %s\n", commandString, tools["sh"])
|
||||
failOn(shell.Run())
|
||||
return
|
||||
}
|
||||
log.Println(strings.Join(cmd.Args, " "))
|
||||
failOn(cmd.Run())
|
||||
}
|
||||
|
||||
func projects(b *build, r []*regexp.Regexp) {
|
||||
for _, v := range b.Projects {
|
||||
f, _ := findBuildfile(v)
|
||||
log.Printf("Doing %s\n", f)
|
||||
project(f, r, b)
|
||||
}
|
||||
}
|
||||
|
||||
// assumes we are in the wd of the project.
|
||||
func project(bf string, which []*regexp.Regexp, container *build) {
|
||||
cwd, err := os.Getwd()
|
||||
failOn(err)
|
||||
debug("Start new project cwd is %v", cwd)
|
||||
defer os.Chdir(cwd)
|
||||
dir := path.Dir(bf)
|
||||
root := path.Base(bf)
|
||||
debug("CD to %v and build using %v", dir, root)
|
||||
failOn(os.Chdir(dir))
|
||||
builds := process(root, which)
|
||||
debug("Processing %v: %d target", root, len(builds))
|
||||
for _, b := range builds {
|
||||
debug("Processing %v: %v", b.name, b)
|
||||
if container != nil {
|
||||
b.Env = append(container.Env, b.Env...)
|
||||
}
|
||||
projects(&b, regexpAll)
|
||||
for _, c := range b.Pre {
|
||||
// this is a hack: we just pass the command through as an exec.Cmd
|
||||
run(&b, true, exec.Command(c))
|
||||
}
|
||||
envFunc := buildEnv(&b);
|
||||
b.Program = os.Expand(b.Program, envFunc)
|
||||
for i, s := range b.SourceFiles {
|
||||
b.SourceFiles[i] = fromRoot(os.Expand(s, envFunc));
|
||||
}
|
||||
for i, s := range b.SourceFilesCmd {
|
||||
b.SourceFilesCmd[i] = fromRoot(os.Expand(s, envFunc));
|
||||
}
|
||||
for i, s := range b.ObjectFiles {
|
||||
b.ObjectFiles[i] = fromRoot(os.Expand(s, envFunc));
|
||||
}
|
||||
buildkernel(&b)
|
||||
if len(b.SourceFiles) > 0 || len(b.SourceFilesCmd) > 0 {
|
||||
compile(&b)
|
||||
}
|
||||
if b.Program != "" || len(b.SourceFilesCmd) > 0 {
|
||||
link(&b)
|
||||
}
|
||||
install(&b)
|
||||
for _, c := range b.Post {
|
||||
run(&b, true, exec.Command(c))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// A small amount of setup is done in the paths*.go files. They are
|
||||
// OS-specific path setup/manipulation. "jehanne" is set there and $PATH is
|
||||
// adjusted.
|
||||
var err error
|
||||
findTools(os.Getenv("TOOLPREFIX"))
|
||||
flag.Parse()
|
||||
cwd, err = os.Getwd()
|
||||
failOn(err)
|
||||
|
||||
a := os.Getenv("ARCH")
|
||||
if a == "" || !arch[a] {
|
||||
s := []string{}
|
||||
for i := range arch {
|
||||
s = append(s, i)
|
||||
}
|
||||
log.Fatalf("You need to set the ARCH environment variable from: %v", s)
|
||||
}
|
||||
|
||||
// ensure this is exported, in case we used a default value
|
||||
os.Setenv("JEHANNE", jehanne)
|
||||
|
||||
if os.Getenv("LD_PRELOAD") != "" {
|
||||
log.Println("Using shellhack")
|
||||
*shellhack = true
|
||||
}
|
||||
|
||||
// If no args, assume 'build.json'
|
||||
// Otherwise the first argument is either
|
||||
// - the path to a json file
|
||||
// - a directory containing a 'build.json' file
|
||||
// - a regular expression to apply assuming 'build.json'
|
||||
// Further arguments are regular expressions.
|
||||
consumedArgs := 0;
|
||||
bf := ""
|
||||
if len(flag.Args()) == 0 {
|
||||
f, err := findBuildfile("build.json")
|
||||
failOn(err)
|
||||
bf = f
|
||||
} else {
|
||||
f, err := findBuildfile(flag.Arg(0))
|
||||
failOn(err)
|
||||
|
||||
if f == "" {
|
||||
f, err := findBuildfile("build.json")
|
||||
failOn(err)
|
||||
bf = f
|
||||
} else {
|
||||
consumedArgs = 1
|
||||
bf = f
|
||||
}
|
||||
}
|
||||
|
||||
re := []*regexp.Regexp{regexp.MustCompile(".")}
|
||||
if len(flag.Args()) > consumedArgs {
|
||||
re = re[:0]
|
||||
for _, r := range flag.Args()[consumedArgs:] {
|
||||
rx, err := regexp.Compile(r)
|
||||
failOn(err)
|
||||
re = append(re, rx)
|
||||
}
|
||||
}
|
||||
project(bf, re, nil)
|
||||
}
|
||||
|
||||
func findTools(toolprefix string) {
|
||||
var err error
|
||||
for k, v := range tools {
|
||||
if x := os.Getenv(strings.ToUpper(k)); x != "" {
|
||||
v = x
|
||||
}
|
||||
if toolprefix != "" && v != "sh" && !strings.Contains(v, toolprefix) {
|
||||
v = toolprefix + v;
|
||||
}
|
||||
v, err = exec.LookPath(v)
|
||||
failOn(err)
|
||||
tools[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// disambiguate the buildfile argument
|
||||
func findBuildfile(f string) (string, error) {
|
||||
if strings.HasSuffix(f, ".json"){
|
||||
if fi, err := os.Stat(f); err == nil && !fi.IsDir() {
|
||||
return f, nil
|
||||
}
|
||||
return "", fmt.Errorf("unable to find buildfile %s", f)
|
||||
}
|
||||
if strings.Contains(f, "/") {
|
||||
return findBuildfile(path.Join(f, "build.json"))
|
||||
}
|
||||
return "", nil
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"debug/elf"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const kernconfTmpl = `
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
#include "io.h"
|
||||
|
||||
void
|
||||
rdb(void)
|
||||
{
|
||||
splhi();
|
||||
iprint("rdb...not installed\n");
|
||||
for(;;);
|
||||
}
|
||||
|
||||
{{ range .Rootcodes }}
|
||||
{{ . }}
|
||||
{{ end }}
|
||||
|
||||
{{ range .Config.Dev }}extern Dev {{ . }}devtab;
|
||||
{{ end }}
|
||||
Dev *devtab[] = {
|
||||
{{ range .Config.Dev }}
|
||||
&{{ . }}devtab,
|
||||
{{ end }}
|
||||
nil,
|
||||
};
|
||||
|
||||
{{ range .Config.Link }}extern void {{ . }}link(void);
|
||||
{{ end }}
|
||||
void
|
||||
links(void)
|
||||
{
|
||||
{{ range .Rootnames }}addbootfile("{{ . }}", ramfs_{{ . }}_code, ramfs_{{ . }}_len);
|
||||
{{ end }}
|
||||
{{ range .Config.Link }}{{ . }}link();
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
#include "../ip/ip.h"
|
||||
{{ range .Config.Ip }}extern void {{ . }}init(Fs*);
|
||||
{{ end }}
|
||||
void (*ipprotoinit[])(Fs*) = {
|
||||
{{ range .Config.Ip }} {{ . }}init,
|
||||
{{ end }}
|
||||
nil,
|
||||
};
|
||||
|
||||
#include "../port/sd.h"
|
||||
{{ range .Config.Sd }}extern SDifc {{ . }}ifc;
|
||||
{{ end }}
|
||||
SDifc* sdifc[] = {
|
||||
{{ range .Config.Sd }} &{{ . }}ifc,
|
||||
{{ end }}
|
||||
nil,
|
||||
};
|
||||
|
||||
{{ range .Config.Uart }}extern PhysUart {{ . }}physuart;
|
||||
{{ end }}
|
||||
PhysUart* physuart[] = {
|
||||
{{ range .Config.Uart }} &{{ . }}physuart,
|
||||
{{ end }}
|
||||
nil,
|
||||
};
|
||||
|
||||
#define Image IMAGE
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include <cursor.h>
|
||||
#include "screen.h"
|
||||
{{ range .Config.VGA }}extern VGAdev {{ . }}dev;
|
||||
{{ end }}
|
||||
VGAdev* vgadev[] = {
|
||||
{{ range .Config.VGA }} &{{ . }}dev,
|
||||
{{ end }}
|
||||
nil,
|
||||
};
|
||||
|
||||
{{ range .Config.VGA }}extern VGAcur {{ . }}cur;
|
||||
{{ end }}
|
||||
VGAcur* vgacur[] = {
|
||||
{{ range .Config.VGA }} &{{ . }}cur,
|
||||
{{ end }}
|
||||
nil,
|
||||
};
|
||||
|
||||
{{ range .Config.Code }}{{ . }}
|
||||
{{ end }}
|
||||
|
||||
char* conffile = "{{ .Path }}";
|
||||
|
||||
`
|
||||
|
||||
// These are the two big code generation functions.
|
||||
|
||||
// data2c takes the file at path and creates a C byte array containing it.
|
||||
func data2c(name string, path string) string {
|
||||
var out []byte
|
||||
var in []byte
|
||||
|
||||
if elf, err := elf.Open(path); err == nil {
|
||||
elf.Close()
|
||||
cwd, err := os.Getwd()
|
||||
tmpf, err := ioutil.TempFile(cwd, name)
|
||||
failOn(err)
|
||||
|
||||
run(nil, *shellhack, exec.Command(tools["strip"], "-o", tmpf.Name(), path))
|
||||
|
||||
in, err = ioutil.ReadAll(tmpf)
|
||||
failOn(err)
|
||||
|
||||
tmpf.Close()
|
||||
os.Remove(tmpf.Name())
|
||||
} else {
|
||||
var file *os.File
|
||||
var err error
|
||||
|
||||
file, err = os.Open(path)
|
||||
failOn(err)
|
||||
|
||||
in, err = ioutil.ReadAll(file)
|
||||
failOn(err)
|
||||
|
||||
file.Close()
|
||||
}
|
||||
|
||||
total := len(in)
|
||||
|
||||
out = []byte(fmt.Sprintf("static unsigned char ramfs_%s_code[] = {\n", name))
|
||||
for len(in) > 0 {
|
||||
for j := 0; j < 16 && len(in) > 0; j++ {
|
||||
out = append(out, []byte(fmt.Sprintf("0x%02x, ", in[0]))...)
|
||||
in = in[1:]
|
||||
}
|
||||
out = append(out, '\n')
|
||||
}
|
||||
|
||||
out = append(out, []byte(fmt.Sprintf("0,\n};\nint ramfs_%s_len = %v;\n", name, total))...)
|
||||
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// confcode creates a kernel configuration header.
|
||||
func confcode(path string, kern *kernel) []byte {
|
||||
var rootcodes []string
|
||||
var rootnames []string
|
||||
for name, path := range kern.Ramfiles {
|
||||
code := data2c(name, fromRoot(path))
|
||||
rootcodes = append(rootcodes, code)
|
||||
rootnames = append(rootnames, name)
|
||||
}
|
||||
|
||||
vars := struct {
|
||||
Path string
|
||||
Config kernconfig
|
||||
Rootnames []string
|
||||
Rootcodes []string
|
||||
}{
|
||||
path,
|
||||
kern.Config,
|
||||
rootnames,
|
||||
rootcodes,
|
||||
}
|
||||
tmpl := template.Must(template.New("kernconf").Parse(kernconfTmpl))
|
||||
codebuf := &bytes.Buffer{}
|
||||
failOn(tmpl.Execute(codebuf, vars))
|
||||
return codebuf.Bytes()
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
BUILDFILE FORMAT
|
||||
|
||||
A buildfile is a json object containing build objects. By convention, it's
|
||||
broken out onto multiple lines indented by tabs, and the keys are TitleCased.
|
||||
|
||||
The environment varibles JEHANNE and ARCH are guarenteed to be set for the
|
||||
buildfile. PATH is modified so that "$JEHANNE/hacking" is included.
|
||||
|
||||
Any key that takes a path or array of paths as its value has absolute paths
|
||||
re-rooted to the jehanne tree and variables in the string expanded once.
|
||||
|
||||
The shell commands in the "Pre" and "Post" steps must be in the subset of
|
||||
syntax that's accepted by both POSIX sh and rc. Practically, this means
|
||||
arguments with a "=" must be single-quoted, "test" must be called as
|
||||
"test" (not "["), "if" statements may not have an "else" clause, "switch"
|
||||
statements may not be used, "for" statements may only have one body command,
|
||||
and redirection to a file descriptor cannont be used.
|
||||
|
||||
BUILD OBJECT
|
||||
|
||||
A build object has the following keys and types:
|
||||
|
||||
Projects []string
|
||||
Pre []string
|
||||