Skip to content
This repository has been archived by the owner on Dec 14, 2023. It is now read-only.

Commit

Permalink
Add scripts and Makefile for bootstrapping and installing llgo
Browse files Browse the repository at this point in the history
Also update the README.md file.
  • Loading branch information
pcc committed May 6, 2014
1 parent f5009fc commit d7b3a76
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 20 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ cmd/llgo-dist/llgo-dist
cmd/llgo-build/llgo-build
llgo/llgo
llgo/gotest.out*
workdir
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
j = 1
prefix = /usr/local
bootstrap = quick

bootstrap: workdir/.bootstrap-stamp

install: bootstrap
./install.sh $(prefix)

workdir/.bootstrap-stamp: workdir/.update-stamp bootstrap.sh *.go build/*.go cmd/gllgo/*.go debug/*.go
./bootstrap.sh $(bootstrap) -j$(j)

workdir/.update-stamp: update_libgo.sh
./update_libgo.sh

.SUFFIXES:
29 changes: 9 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,20 @@ llgo is under active development, but is still considered experimental. It is no

# Installation

To install llgo, use llgo-dist:
To install llgo, use make:

go get github.com/go-llvm/llgo/cmd/llgo-dist
llgo-dist
go get github.com/go-llvm/llgo
cd $GOPATH/src/github.com/go-llvm/llgo
make install prefix=/path/to/prefix

You should have the latest version of LLVM in your $PATH (3.3 has been confirmed to be compatible). If LLVM is not in $PATH, llgo-dist also has a flag that can specified to point at the LLVM installation: `-llvm-config=<path/to/llvm-config>`.
You may need to build LLVM. See GoLLVM's README.md for more information.

llgo requires Go 1.2+.
llgo requires Go 1.3, or Go 1.2 with a [bug fix](https://codereview.appspot.com/96790047/) applied. See also README.patches for a list of additional patches to apply.

# Running

llgo-dist builds two binaries: there's `llgo`, the compiler; and there's `llgo-build`, which is a poor man's `go build` for llgo.
We install two binaries to `$prefix/bin`: `llgo` and `llgo-go`.

The compiler is comparable with `6g`: it takes a set of Go source files as arguments, and produces an object file. The output is an LLVM bitcode module. There are several flags that alter the behaviour: `-triple=<triple>` specifies the target LLVM triple to compile for; `-dump` causes llgo to dump the module in its textual IR form instead of generating bitcode.
`llgo` is the compiler binary. It has a command line interface that is intended to be compatible to a large extent with `gccgo`.

The `llgo-build` tool accepts either Go filenames, or package names, just like `go build`. If the package is a command, then `llgo-build` will compile it, link in its dependencies, and translate the LLVM bitcode to a native binary. If you want an untranslated module, specify the `-emit-llvm` flag.

`llgo-build` has some additional flags for testing: `-run` causes `llgo-build` to execute and dispose of the resultant binary. Passing `-test` causes `llgo-build` to generate a test program for the specified package, just like `go test -c`.

# Testing

First install llgo using `llgo-dist`, as described above. Then you can run the functional tests like so:

go test -v github.com/go-llvm/llgo/llgo

You can also run the compiler tests from gc's source tree ($GOROOT/test) by specifying the build tag `go_test`:

go test -v -tags go_test github.com/go-llvm/llgo/llgo -run StandardTests
`llgo-go` is a command line wrapper for `go`. It works like the regular `go` command except that it uses llgo to build.
72 changes: 72 additions & 0 deletions bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/bin/sh -e

llgodir=$(dirname "$0")
llgodir=$(cd "$llgodir" && pwd)

workdir=$llgodir/workdir
gofrontenddir=$workdir/gofrontend
gofrontend_builddir=$workdir/gofrontend_build

bootstrap_type="$1"
shift

case "$bootstrap_type" in
quick | full)
;;

*)
echo "Bootstrap type must be 'quick' or 'full'"
exit 1
;;
esac

# Clean up any previous libgo stages.
rm -rf $gofrontend_builddir/libgo*

# Build a stage1 compiler with gc.
(cd $llgodir/cmd/gllgo && go build -o $workdir/gllgo-stage1)

# Build libgo with the stage1 compiler.
mkdir -p $gofrontend_builddir/libgo-stage1
(cd $gofrontend_builddir/libgo-stage1 && $gofrontenddir/libgo/configure GOC="$workdir/gllgo-stage1 -no-prefix")
make -C $gofrontend_builddir/libgo-stage1 "$@"

# Set up a directory which when added to $PATH causes "gccgo" to resolve
# to our stage1 compiler. This is necessary because the logic in "go build"
# for locating the compiler is fixed.
mkdir -p $gofrontend_builddir/stage1-path
ln -sf $workdir/gllgo-stage1 $gofrontend_builddir/stage1-path/gccgo

# Build a stage2 compiler using the stage1 compiler and libgo.
gllgoflags="-no-prefix -L$gofrontend_builddir/libgo-stage1 -L$gofrontend_builddir/libgo-stage1/.libs -static-libgo"
(cd $llgodir/cmd/gllgo && PATH=$gofrontend_builddir/stage1-path:$PATH go build -compiler gccgo -gccgoflags "$gllgoflags" -o $workdir/gllgo-stage2)

# If this is a quick bootstrap, do not rebuild libgo with the stage2 compiler.
# Instead, use the stage1 libgo.

if [ "$bootstrap_type" == "full" ] ; then
# Build libgo with the stage2 compiler.
mkdir -p $gofrontend_builddir/libgo-stage2
(cd $gofrontend_builddir/libgo-stage2 && $gofrontenddir/libgo/configure GOC="$workdir/gllgo-stage2 -no-prefix")
make -C $gofrontend_builddir/libgo-stage2 "$@"

# Set up $gllgoflags to use the stage2 libgo.
gllgoflags="-no-prefix -L$gofrontend_builddir/libgo-stage2 -L$gofrontend_builddir/libgo-stage2/.libs -static-libgo"
fi

# Set up a directory which when added to $PATH causes "gccgo" to resolve
# to our stage2 compiler.
mkdir -p $gofrontend_builddir/stage2-path
ln -sf $workdir/gllgo-stage2 $gofrontend_builddir/stage2-path/gccgo

# Build the stage3 compiler.
(cd $llgodir/cmd/gllgo && PATH=$gofrontend_builddir/stage2-path:$PATH go build -compiler gccgo -gccgoflags "$gllgoflags" -o $workdir/gllgo-stage3)

# Strip the compiler binaries. The binaries are currently only
# expected to compare equal modulo debug info.
strip -o $workdir/gllgo-stage2.stripped $workdir/gllgo-stage2
strip -o $workdir/gllgo-stage3.stripped $workdir/gllgo-stage3

cmp $workdir/gllgo-stage2.stripped $workdir/gllgo-stage3.stripped && \
echo "Bootstrap completed successfully" && touch $workdir/.bootstrap-stamp && exit 0 || \
echo "Bootstrap failed, binaries differ" && exit 1
29 changes: 29 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/sh -e

prefix="$1"
mkdir -p "$prefix"
prefix=$(cd "$prefix" && pwd)

llgodir=$(dirname "$0")

workdir=$llgodir/workdir
gofrontend_builddir=$workdir/gofrontend_build

# Install the compiler binary.
mkdir -p "$prefix/bin"
cp $workdir/gllgo-stage3 "$prefix/bin/llgo"

# Install llgo-go.
cp $llgodir/llgo-go.sh "$prefix/bin/llgo-go"
chmod +x "$prefix/bin/llgo-go"

# Install libgo. If we did a quick bootstrap, only the stage1 libgo will exist.
if [ -d "$gofrontend_builddir/libgo-stage2" ] ; then
make -C $gofrontend_builddir/libgo-stage2 install "prefix=$prefix"
else
make -C $gofrontend_builddir/libgo-stage1 install "prefix=$prefix"
fi

# Set up the symlink required by llgo-go.
mkdir -p "$prefix/lib/llgo/go-path"
ln -sf ../../../bin/llgo "$prefix/lib/llgo/go-path/gccgo"
19 changes: 19 additions & 0 deletions llgo-go.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh -e

scriptpath=$(which "$0")
scriptpath=$(readlink -f "$scriptpath")
bindir=$(dirname "$scriptpath")
prefix=$(dirname "$bindir")

cmd="$1"

case "$cmd" in
build | get | install | run | test)
shift
PATH="$prefix/lib/llgo/go-path:$PATH" exec go "$cmd" -compiler gccgo "$@"
;;

*)
exec go "$@"
;;
esac
48 changes: 48 additions & 0 deletions update_libgo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/sh -e

# Fetch libgo and its dependencies, and build the dependencies.
# We build libgo itself while bootstrapping.

llgodir=$(dirname "$0")
llgodir=$(cd "$llgodir" && pwd)

gofrontendrepo=https://code.google.com/p/gofrontend/
gofrontendrev=93286dc73be0

gccrepo=svn://gcc.gnu.org/svn/gcc/trunk
gccrev=209880

workdir=$llgodir/workdir
gofrontenddir=$workdir/gofrontend
gofrontend_builddir=$workdir/gofrontend_build

mkdir -p $workdir
if [ -d $gofrontenddir/.hg ] ; then
(cd $gofrontenddir && hg pull)
else
hg clone $gofrontendrepo $gofrontenddir
fi
(cd $gofrontenddir && hg update -r $gofrontendrev)

# Some dependencies are stored in the gcc repository.
# TODO(pcc): Ask iant about mirroring these dependencies into gofrontend.

mkdir -p $gofrontenddir/include
mkdir -p $gofrontenddir/libgcc
for f in config.guess config-ml.in config.sub depcomp \
install-sh ltmain.sh missing move-if-change \
include/dwarf2.{def,h} libgcc/unwind-pe.h ; do
svn cat -r $gccrev $gccrepo/$f > $gofrontenddir/$f
done

# Avoid pulling in a bunch of unneeded gcc headers.
echo "#define IS_ABSOLUTE_PATH(path) ((path)[0] == '/')" > $gofrontenddir/include/filenames.h

for d in libatomic libbacktrace libffi ; do
svn co -r $gccrev $gccrepo/$d $gofrontenddir/$d
mkdir -p $gofrontend_builddir/$d
(cd $gofrontend_builddir/$d && $gofrontenddir/$d/configure CFLAGS=-fPIC)
make -C $gofrontend_builddir/$d -j4
done

touch $workdir/.update-stamp

0 comments on commit d7b3a76

Please sign in to comment.