diff --git a/ci_scripts/all_tests.sh b/ci_scripts/all_tests.sh index ee79d71..bb2d5f8 100755 --- a/ci_scripts/all_tests.sh +++ b/ci_scripts/all_tests.sh @@ -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 diff --git a/ci_scripts/expect_scripts/GoPlatform.exp b/ci_scripts/expect_scripts/GoPlatform.exp index 2fa02df..6258764 100644 --- a/ci_scripts/expect_scripts/GoPlatform.exp +++ b/ci_scripts/expect_scripts/GoPlatform.exp @@ -3,7 +3,7 @@ # uncomment line below for debugging # exp_internal 1 -set timeout 7 +set timeout 25 spawn ./examples/GoPlatform/main @@ -14,4 +14,4 @@ expect "Roc <3 Go!\r\n" { } puts stderr "\nError: output was different from expected value." -exit 1 \ No newline at end of file +exit 1 diff --git a/examples/GoPlatform/.gitignore b/examples/GoPlatform/.gitignore index 0487f44..5e9b945 100644 --- a/examples/GoPlatform/.gitignore +++ b/examples/GoPlatform/.gitignore @@ -1 +1,5 @@ -main.o +platform/libapp.so +platform/dynhost +platform/*.rh +platform/*.rm +*.tar.br diff --git a/examples/GoPlatform/README.md b/examples/GoPlatform/README.md index e809384..da963f8 100644 --- a/examples/GoPlatform/README.md +++ b/examples/GoPlatform/README.md @@ -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). diff --git a/examples/GoPlatform/main.roc b/examples/GoPlatform/main.roc index 3cdc9c7..c81b118 100644 --- a/examples/GoPlatform/main.roc +++ b/examples/GoPlatform/main.roc @@ -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" diff --git a/examples/GoPlatform/platform/main.go b/examples/GoPlatform/platform/main.go index 2024eea..7b2555a 100644 --- a/examples/GoPlatform/platform/main.go +++ b/examples/GoPlatform/platform/main.go @@ -1,13 +1,14 @@ package main /* -#cgo LDFLAGS: ./main.o -ldl +#cgo LDFLAGS: -L. -lapp #include "./host.h" */ import "C" import ( "fmt" + "os" "unsafe" ) @@ -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) + } +} diff --git a/flake.lock b/flake.lock index ccd75da..9728ff4 100644 --- a/flake.lock +++ b/flake.lock @@ -120,11 +120,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1709568631, - "narHash": "sha256-Of6/H1GKEQe5KoxjnSnEcGkyG9L7RGvezLrtvbhJsgY=", + "lastModified": 1712059092, + "narHash": "sha256-IQlyTyOh9/AE0tH3SRkzjUWzE6PPpg5X7/p3j+SEaYg=", "owner": "roc-lang", "repo": "roc", - "rev": "8a170efa9bf722e43934d24723edd9c9c21f029d", + "rev": "ab34bb93e53014a04ee38d9787a17a02bb8e22c3", "type": "github" }, "original": {