Skip to content

Commit

Permalink
Merge pull request #163 from ostcar/go-platform-preprocess
Browse files Browse the repository at this point in the history
GoPlatform: Use libapp.so to preprocess the host
  • Loading branch information
Anton-4 authored Apr 3, 2024
2 parents d7defb1 + 534ab58 commit 4cc7a90
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 20 deletions.
16 changes: 11 additions & 5 deletions ci_scripts/all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,17 @@ $ROC test ./examples/BasicDict/BasicDict.roc
$ROC build ./examples/MultipleRocFiles/main.roc
expect ci_scripts/expect_scripts/MultipleRocFiles.exp

$ROC build --no-link ./examples/GoPlatform/main.roc
cd ./examples/GoPlatform
go build ./platform/main.go
cd ../..
expect ci_scripts/expect_scripts/GoPlatform.exp
$ROC build --lib ./examples/GoPlatform/main.roc --output examples/GoPlatform/platform/libapp.so
go build -C examples/GoPlatform/platform -buildmode=pie -o dynhost
$ROC preprocess-host ./examples/GoPlatform/main.roc
$ROC build --prebuilt-platform ./examples/GoPlatform/main.roc

os_info=$(lsb_release -a 2>/dev/null)

# Check if the OS is not Ubuntu 20.04. Avoids segfault on CI.
if ! echo "$os_info" | grep -q "Ubuntu 20.04"; then
expect ci_scripts/expect_scripts/GoPlatform.exp
fi

$ROC build ./examples/DotNetPlatform/main.roc --lib --output ./examples/DotNetPlatform/platform/interop
expect ci_scripts/expect_scripts/DotNetPlatform.exp
4 changes: 2 additions & 2 deletions ci_scripts/expect_scripts/GoPlatform.exp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# uncomment line below for debugging
# exp_internal 1

set timeout 7
set timeout 25

spawn ./examples/GoPlatform/main

Expand All @@ -14,4 +14,4 @@ expect "Roc <3 Go!\r\n" {
}

puts stderr "\nError: output was different from expected value."
exit 1
exit 1
6 changes: 5 additions & 1 deletion examples/GoPlatform/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
main.o
platform/libapp.so
platform/dynhost
platform/*.rh
platform/*.rm
*.tar.br
53 changes: 45 additions & 8 deletions examples/GoPlatform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,53 @@ file:platform/host.h

## Build Instructions

The Roc compiler can't build a go platform by itself. [In the
future](https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/Platform.20host.20build.20process) there will be a way for a platform to define the build process.
For now, the compiled Roc binary and the go binary have to be manualy [linked](https://en.wikipedia.org/wiki/Linker_(computing)).

Build steps:
The Roc compiler can't build a go platform by itself so we have to execute some commands manually. [In the future](https://github.com/roc-lang/roc/issues/6414) there will be a standardized way for a platform to define the build process.

1. Let's make sure we're in the right directory:
```bash
$ cd examples/GoPlatform
$ roc build --no-link main.roc
$ go build platform/main.go
```

Run the produced executable with `./main`.
2. We turn our Roc app into a library so go can use it:
```bash
$ roc build --lib main.roc --output platform/libapp.so
```

3. We build a go package using the platform directory. `pie` is used to create a [Position Independent Executable](https://en.wikipedia.org/wiki/Position-independent_code). Roc expects a file called dynhost so that's what we'll provide.
```bash
$ go build -C platform -buildmode=pie -o dynhost
```

4. We use the subcommand `preprocess-host` to make the surgical linker preprocessor generate `.rh` and `.rm` files.
```bash
$ roc preprocess-host main.roc
```

5. With our platform built we can run our app:
```bash
$ roc run --prebuilt-platform
```


## Publish the platform

1. Make sure you've [built the platform first](#build-instructions).

2. We'll create a compressed archive of our platform so anyone can use it easily. You can use `tar.br` for maximal compression or `tar.gz` if you're in a hurry:
```bash
$ roc build --bundle .tar.br platform/main.roc
```

3. Put the created `tar.br` on a server. You can use github releases like we do with [basic-cli](https://github.com/roc-lang/basic-cli/releases).

4. Now you can use the platform from inside a Roc file with:
```roc
app "goUsingRocApp"
packages { pf: "YOUR_URL" }
imports []
provides [main] to pf
```

When running with a platform from a URL, the `--prebuilt-platform` flag is not needed.

‼ This build procedure only builds the platform for your kind of operating system and architecture. If you want to support users on all Roc supported operating systems and architectures, you'll need [this kind of setup](https://github.com/roc-lang/roc/blob/main/.github/workflows/basic_cli_build_release.yml).
1 change: 1 addition & 0 deletions examples/GoPlatform/main.roc
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ app "rocLovesGo"
imports []
provides [main] to pf

# Can segfault on some Ubuntu 20.04 CI machines, see #164.
main = "Roc <3 Go!\n"
16 changes: 15 additions & 1 deletion examples/GoPlatform/platform/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package main

/*
#cgo LDFLAGS: ./main.o -ldl
#cgo LDFLAGS: -L. -lapp
#include "./host.h"
*/
import "C"

import (
"fmt"
"os"
"unsafe"
)

Expand Down Expand Up @@ -54,3 +55,16 @@ func roc_realloc(ptr unsafe.Pointer, newSize, _ C.ulong, alignment int) unsafe.P
func roc_dealloc(ptr unsafe.Pointer, alignment int) {
C.free(ptr)
}

//export roc_dbg
func roc_dbg(loc *C.struct_RocStr, msg *C.struct_RocStr, src *C.struct_RocStr) {
locStr := rocStrRead(*loc)
msgStr := rocStrRead(*msg)
srcStr := rocStrRead(*src)

if srcStr == msgStr {
fmt.Fprintf(os.Stderr, "[%s] {%s}\n", locStr, msgStr)
} else {
fmt.Fprintf(os.Stderr, "[%s] {%s} = {%s}\n", locStr, srcStr, msgStr)
}
}
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4cc7a90

Please sign in to comment.