Skip to content
This repository was archived by the owner on Mar 11, 2019. It is now read-only.

Commit 67a807e

Browse files
committed
Add README
1 parent e1176fd commit 67a807e

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

README.markdown

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# TinyGo
2+
3+
## What is this?
4+
5+
A runtime for the [Go programming language](https://golang.org/) that is very
6+
small in size and doesn't rely as much on an OS.
7+
8+
**Note**: This project is unrelated to the now-dead [Tiny
9+
runtime](https://code.google.com/archive/p/tinygo/) of the Go language, see
10+
below.
11+
12+
## Why was it created?
13+
14+
I wanted to be able to run Go on a microcontroller. While this goal hasn't been
15+
reached yet, the resulting binary can be _very_ small.
16+
17+
Inside `src/hello/hello.go`:
18+
19+
```go
20+
// Simple program with the bare minimum of Go.
21+
package main
22+
23+
func main() {
24+
println("hello, world!")
25+
}
26+
```
27+
28+
Running on an ARM machine (Raspberry Pi 3):
29+
30+
```
31+
$ make PKG=hello LTO=1
32+
[lots of build output]
33+
34+
$ strip build/hello
35+
36+
$ ./build/hello
37+
hello, world!
38+
39+
$ /bin/ls -lh build/hello
40+
-rwxrwxr-x 1 ayke ayke 5,5K mrt 9 23:43 build/hello
41+
42+
$ size build/hello
43+
text data bss dec hex filename
44+
1961 316 20 2297 8f9 build/hello
45+
```
46+
47+
As you can see, this produces a file that's just 5.5kB in size and contains
48+
about 2kB of machine code. The same source compiled by the official Go compiler
49+
(1.7.4) produces an executable that is about 564kB in size after stripping, most
50+
of which is also `.text`.
51+
52+
Of course, this is a bit cheating. The small 'hello' program does not include
53+
most of the runtime, that's all stripped away by the linker. A somewhat more
54+
realistic example is the
55+
[channel](https://github.com/aykevl/tinygo/blob/master/src/channel/channel.go)
56+
example, which produces an executable of 18kB. That runtime contains the
57+
scheduler, memory allocator (no GC yet) and channel send/receive primitives.
58+
59+
## Limitations
60+
61+
There are many.
62+
63+
* No support for anything except ARM.
64+
* Works with gccgo 6.3 (Debian stretch), no other compiler versions have been
65+
tested.
66+
* Source files must be placed in a subdirectory of src/.
67+
* No `recover()`
68+
* No function names or line numbers in the `panic()` output. I would like to
69+
fix this at some time, but it will increase the binary size if it must work
70+
after stripping. It currently outputs the function addresses, which you can
71+
look up with `nm` (e.g. `nm -S ./build/example | egrep ' [tT] main\.'`).
72+
* No garbage collector, yet. Allocated memory is never freed.
73+
* Many types might not be implemented, but support will probably be pretty
74+
easy to add by including the correct files from `gofrontend/libgo/runtime`.
75+
* The scheduler is pretty dumb right now. Passing messages between two
76+
goroutines is fast (on the Raspberry Pi 3 slightly faster than the standard
77+
Go compiler!) but any extra goroutine that is started will slow down any
78+
blocking operation.
79+
* No support for running multiple goroutines on different threads. I don't
80+
really have an intention to implement this as it will complicate the
81+
scheduler and I don't want a complicated scheduler.
82+
* Most of the standard library doesn't build yet, in particular the `fmt`
83+
package (which depends on a whole slew of other packages). Some leaf
84+
packages will work when added to the Makefile manually.
85+
* No automatic dependency installation, except for a few defined in the
86+
Makefile.
87+
* ... probably many more.
88+
89+
## Current status
90+
91+
I mainly developed this as a proof of concept so I'm not sure how I'll continue,
92+
but I'm happy that it works (to some degree). I'm interested in microcontrollers
93+
and really like the Go language so may actually use it in the future, in which
94+
case I surely will improve it.
95+
96+
Also, it depends on gccgo and gccgo seems to be moving to a runtime written in
97+
Go, so I might need to adjust to that in the future.
98+
99+
## Building
100+
101+
Dependencies:
102+
103+
* An ARM machine, like a Raspberry Pi. Making it work on anything else
104+
(without backtrace support) should not be very difficult.
105+
* GCCGO, tested version 6.3.
106+
* An initialized gofrontend, run `git submodule update --init`.
107+
108+
Then just execute `make PKG=<dirname>` where dirname is the name of the
109+
directory (under `src/`), for example `make PKG=myproject`. You have to put your
110+
source files under `src/`. The executable is then put in the `build/` directory.
111+
You may want to enable link-time optimization with the `LTO=1` flag.
112+
113+
## License
114+
115+
The license is the same BSD 3-clause license as the one used for Go. See the
116+
LICENSE file for details.
117+
118+
## Bare metal support
119+
120+
Requirements for porting this to bare-metal processors (e.g. ARM Cortex-M):
121+
122+
* Replace all calls to `printf()` with something that logs to a serial
123+
console.
124+
* Implement a memory allocator, for example by copying [the one from
125+
MicroPython](https://github.com/micropython/micropython/blob/master/py/gc.c).
126+
* Implement context switching, probably using setjmp/longjmp (take a look at
127+
how MicroPython does it).
128+
129+
## About the 'other' TinyGo
130+
131+
There is another (now dead) project called 'tinygo' [over
132+
here](https://code.google.com/archive/p/tinygo/) and
133+
[here](https://github.com/jackmanlabs/tinygo) that tried to run a very old
134+
variant of the runtime bare-metal. I only discovered it the moment I wanted to
135+
push this project to GitHub.

0 commit comments

Comments
 (0)