Browse Source

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
master
Giacomo Tesio 7 months ago
parent
commit
0c2dabf975
  1. 7
      .gitignore
  2. 19
      .gitmodules
  3. 4
      QA.sh
  4. 1
      bin/.gitignore
  5. 3
      bin/build
  6. 57
      bin/runqemu
  7. 3
      bin/start-u9fs.sh
  8. 3
      bin/template
  9. 26
      buildtools.sh
  10. 11
      continuous-build.sh
  11. 6
      cross/init.sh
  12. 12
      cross/pkgs/build.json
  13. 10
      cross/pkgs/build.sh
  14. 2
      cross/pkgs/gcc/build.sh
  15. 45
      cross/pkgs/gcc/src/fetch.sh
  16. 5
      cross/pkgs/gcc/src/sha256sum.txt
  17. 53
      cross/src/fetch.json
  18. 45
      cross/src/fetch.sh
  19. 5
      cross/src/sha256sum.txt
  20. 10
      devshell.sh
  21. 51
      rcmain
  22. 7
      runOver9P.sh
  23. 0
      src/drawterm
  24. 669
      src/jehanne/cmd/build/build.go
  25. 182
      src/jehanne/cmd/build/codegen.go
  26. 184
      src/jehanne/cmd/build/doc.go
  27. 31
      src/jehanne/cmd/build/paths.go
  28. 17
      src/jehanne/cmd/build/paths_harvey.go
  29. 155
      src/jehanne/cmd/convert/convert.go
  30. 39
      src/jehanne/cmd/data2c/data2c.go
  31. 113
      src/jehanne/cmd/elf2c/elf2c.go
  32. 197
      src/jehanne/cmd/fetch/fetch.go
  33. 53
      src/jehanne/cmd/jsonpretty/jsonpretty.go
  34. 115
      src/jehanne/cmd/kpdump/kpdump.go
  35. 385
      src/jehanne/cmd/ksyscalls/ksyscalls.go
  36. 325
      src/jehanne/cmd/mksys/mksys.go
  37. 107
      src/jehanne/cmd/op2/op2.go
  38. 1
      src/jehanne/cmd/preen/.gitignore
  39. 157
      src/jehanne/cmd/preen/preen.go
  40. 131
      src/jehanne/cmd/profile/profile.go
  41. 78
      src/jehanne/cmd/removemach/removemach.go
  42. 119
      src/jehanne/cmd/runqemu/runqemu.go
  43. 244
      src/jehanne/cmd/telnet/telnet.go
  44. 272
      src/jehanne/cmd/usyscalls/usyscalls.go
  45. 45
      src/jehanne/cmd/vendor/doc.go
  46. 248
      src/jehanne/cmd/vendor/vendor.go
  47. 1
      src/netcat
  48. 1
      src/trampoline
  49. 1
      src/u9fs
  50. 1
      third_party/src/github.com/lionkov/ninep

7
.gitignore

@ -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/

19
.gitmodules

@ -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

@ -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
bin/.gitignore

@ -1,2 +1,3 @@
*
!.gitignore
!build

3
bin/build

@ -0,0 +1,3 @@
#!/bin/sh
rc $JEHANNE/arch/rc/cmd/build $@

57
bin/runqemu

@ -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

3
bin/start-u9fs.sh

@ -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

3
bin/template

@ -0,0 +1,3 @@
#!/bin/sh
$JEHANNE/hacking/bin/rc $JEHANNE/arch/rc/cmd/template $@

26
buildtools.sh

@ -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

11
continuous-build.sh

@ -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

6
cross/init.sh

@ -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 ) &&

12
cross/pkgs/build.json

@ -1,12 +0,0 @@
{
"CrossCompiledPackages": {
"Env": [
"CROSS_PKGS_BUILD=1"
],
"Pre": [
"./newlib/build.sh",
"./mksh/build.sh",
"./gcc/build.sh"
]
}
}

10
cross/pkgs/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

2
cross/pkgs/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"

45
cross/pkgs/gcc/src/fetch.sh

@ -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."

5
cross/pkgs/gcc/src/sha256sum.txt

@ -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

53
cross/src/fetch.json

@ -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": [
]
}
}

45
cross/src/fetch.sh

@ -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."

5
cross/src/sha256sum.txt

@ -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

@ -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-

51
rcmain

@ -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

7
runOver9P.sh

@ -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

0
third_party/src/github.com/0intro/drawterm → src/drawterm

669
src/jehanne/cmd/build/build.go

@ -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
}

182
src/jehanne/cmd/build/codegen.go

@ -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()
}

184
src/jehanne/cmd/build/doc.go

@ -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
Post []string
Cflags []string
Oflags []string
Include []string
SourceFiles []string
ObjectFiles []string
Libs []string
Env []string
SourceFilesCmd []string
Program string
Library string
Install string
Kernel kernel
These are the steps taken, in order:
Env
Include
Projects
Pre
Kernel
[compile] SourceFiles SourceFilesCmd Cflags Program
[link] ObjectFiles Libs Oflags Library
Install
Post
"[compile]" and "[link]" are steps synthesized from the specified keys.
The meaning of the keys is as follows:
"Env" is an array of environment variables to be put in the environment of
every command run in a build. They are expanded once and only available for
use in other steps.
"Include" is an array of buildfiles to "merge" into the current one. This
is done before other projects are built.
"Projects" is an array of buildfiles to build in their entirety before
starting the current build.
"Pre" is an array of commands to run before starting the build.
"Kernel" is a kernel build object. See the kernel object section.
"Cflags" is an array of flags to pass to the C compiler. They are in addition
to the standard flags of
-std=c11 -c -I /$ARCH/include -I /sys/include -I .
The standard include paths are re-rooted to the jehanne tree if not on a jehanne
system.
"SourceFilesCmd" is an array of C files where each one should result in an
executable. If this key is provided, "SourceFiles" and "Program" are ignored.
"SourceFiles" is an array of C files that will ultimately produce a single
binary or library, named by "Program" or "Library" respectively.
"Program" is the name of the final executable for the files specified by
"SourceFiles".
"Oflags" is an array of flags to pass to the linker. They are in addition
to the standard flags of
-o $program $objfiles -L /$ARCH/lib $libs
The lib path is re-rooted to the jehanne tree if not on a jehanne system.
"ObjectFiles" is an array of strings specifying object files to be linked
into the final program specified by "Program". Any object files produced
by the preceeding "[compile]" step are automatically added to this before
beginning the "[link]" step.
"Libs" is a an array of library arguments to pass to the linker.
"Library" is the name of the archive resulting from bundling "SourceFiles"
into a library. The resulting archive has 'ranlib' run on it automatically.
"Install" is a directory where the result of the "[link]" step is moved
to. If it does not exist, it is created.
"Post" is an array of commands to run last during the build.
KERNEL OBJECT
A build object has the following keys and types:
Systab string
Ramfiles map[string]string
Config {
Code []string
Dev []string
Ip []string
Link []string
Sd []string
Uart []string
VGA []string
}
"Systab"<