detached 1a4ea67

all: add FreeBSD support (#155)

This change adds FreeBSD AMD64 and ARM64 targets.

Includes:

* github actions workflow with FreeBSD test unit:
The FreeBSD test needs to run in its own space because it's
executed as a virtualbox VM in macOS. vmactions/freebsd-vm only
supports a single step block where it exits the VM process once
the unit completse. All the run commands therefore need to be
clumped together.

The setup-go library doesn't support FreeBSD, so different
versions of Go are manually fetched directly from the Go repo
instead of using FreeBSD's pkg, which is limited to only a single
version of Go.

* environ and __progname variables to enable cross-compilation
which libc.so relies on. Cross-compile requires
`-gcflags="github.com/ebitengine/purego/internal/fakecgo=-std"`
to make the the symbols appear in the binary.

Sponsored by: Rubicon Communications LLC (Netgate)
commit
1a4ea678b5a7598275a28e787179da1b7a058b11
author
ldnetgate · · 2023-08-24 23:20 UTC
committer
GitHub · · 2023-08-24 23:20 UTC
parent
388daa1
signature
GPG Unverified4AEE18F83AFDEB23 The key is unknown
40 files · +418 -40
M .github/workflows/test.yml +91 -4
@@ -46,14 +46,20 @@ jobs:
4646 env GOOS=windows GOARCH=amd64 go build -v ./...
4747 env GOOS=windows GOARCH=arm go build -v ./...
4848 env GOOS=windows GOARCH=arm64 go build -v ./...
49-
49+
5050 # Check cross-compiling macOS binaries.
5151 env GOOS=darwin GOARCH=amd64 go build -v ./...
52- env GOOS=darwin GOARCH=arm64 go build -v ./...
53-
52+ env GOOS=darwin GOARCH=arm64 go build -v ./...
53+
5454 # Check cross-compiling Linux binaries.
5555 env GOOS=linux GOARCH=amd64 go build -v ./...
56- env GOOS=linux GOARCH=arm64 go build -v ./...
56+ env GOOS=linux GOARCH=arm64 go build -v ./...
57+
58+ # Check cross-compiling FreeBSD binaries.
59+ # gcflags -std is necessary to make fakecgo the Cgo for
60+ # FreeBSD to add the symbols that libc.so depends on.
61+ env GOOS=freebsd GOARCH=amd64 go build -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -v ./...
62+ env GOOS=freebsd GOARCH=arm64 go build -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -v ./...
5763
5864 - name: go mod vendor
5965 if: runner.os != 'Linux'
@@ -82,3 +88,84 @@ jobs:
8288 if: ${{ !startsWith(matrix.go, '1.18.') && !startsWith(matrix.go, '1.19.') }}
8389 run: |
8490 go test -race -shuffle=on -v -count=10 ./...
91+
92+ freebsd:
93+ strategy:
94+ matrix:
95+ go: ['1.18.10', '1.19.12', '1.20.7', '1.21.0']
96+ name: Test with Go ${{ matrix.go }} on FreeBSD
97+ runs-on: macos-12
98+ defaults:
99+ run:
100+ shell: bash
101+ steps:
102+ - uses: actions/checkout@v3
103+ - name: Run in freebsd
104+ uses: vmactions/freebsd-vm@v0
105+ with:
106+ usesh: true
107+ prepare: |
108+ fetch https://go.dev/dl/go${{matrix.go}}.freebsd-amd64.tar.gz
109+ rm -fr /usr/local/go && tar -C /usr/local -xf go${{matrix.go}}.freebsd-amd64.tar.gz
110+ ln -s /usr/local/go/bin/go /usr/local/bin
111+ run: |
112+ # FreeBSD tests run within a virtualbox VM on macOS.
113+ # vmactions/freebsd-vm only supports a single "step" where it
114+ # brings down the VM at the end of the step, so all
115+ # the commands to run need to be put into this single block.
116+
117+ echo "Running tests on $(uname -a) at $PWD"
118+
119+ # verify Go is available
120+ go version
121+
122+ echo "=> go build"
123+ go build -v ./...
124+ # Compile without optimization to check potential stack overflow.
125+ # The option '-gcflags=all=-N -l' is often used at Visual Studio Code.
126+ # See also https://go.googlesource.com/vscode-go/+/HEAD/docs/debugging.md#launch and the issue hajimehoshi/ebiten#2120.
127+ go build "-gcflags=all=-N -l" -v ./...
128+
129+ # Check cross-compiling Windows binaries.
130+ env GOOS=windows GOARCH=386 go build -v ./...
131+ env GOOS=windows GOARCH=amd64 go build -v ./...
132+ env GOOS=windows GOARCH=arm go build -v ./...
133+ env GOOS=windows GOARCH=arm64 go build -v ./...
134+
135+ # Check cross-compiling macOS binaries.
136+ env GOOS=darwin GOARCH=amd64 go build -v ./...
137+ env GOOS=darwin GOARCH=arm64 go build -v ./...
138+
139+ # Check cross-compiling Linux binaries.
140+ env GOOS=linux GOARCH=amd64 go build -v ./...
141+ env GOOS=linux GOARCH=arm64 go build -v ./...
142+
143+ # Check cross-compiling FreeBSD binaries.
144+ env GOOS=freebsd GOARCH=amd64 go build -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -v ./...
145+ env GOOS=freebsd GOARCH=arm64 go build -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -v ./...
146+
147+ echo "=> go mod vendor"
148+ mkdir /tmp/vendoring
149+ cd /tmp/vendoring
150+ go mod init foo
151+ echo 'package main' > main.go
152+ echo 'import (' >> main.go
153+ echo ' _ "github.com/ebitengine/purego"' >> main.go
154+ echo ')' >> main.go
155+ echo 'func main() {}' >> main.go
156+ go mod edit -replace github.com/ebitengine/purego=$GITHUB_WORKSPACE
157+ go mod tidy
158+ go mod vendor
159+ go build -v .
160+
161+ cd $GITHUB_WORKSPACE
162+ echo "=> go test CGO_ENABLED=0"
163+ env CGO_ENABLED=0 go test -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -shuffle=on -v -count=10 ./...
164+
165+ echo "=> go test CGO_ENABLED=1"
166+ env CGO_ENABLED=1 go test -shuffle=on -v -count=10 ./...
167+
168+ if [ -z "$(echo ${{matrix.go}} | grep '^1.1')" ]; then
169+ echo "=> go test race"
170+ go test -race -shuffle=on -v -count=10 ./...
171+ fi
@@ -46,14 +46,20 @@ jobs:
46 env GOOS=windows GOARCH=amd64 go build -v ./...46 env GOOS=windows GOARCH=amd64 go build -v ./...
47 env GOOS=windows GOARCH=arm go build -v ./...47 env GOOS=windows GOARCH=arm go build -v ./...
48 env GOOS=windows GOARCH=arm64 go build -v ./...48 env GOOS=windows GOARCH=arm64 go build -v ./...
49- 49+
50 # Check cross-compiling macOS binaries.50 # Check cross-compiling macOS binaries.
51 env GOOS=darwin GOARCH=amd64 go build -v ./...51 env GOOS=darwin GOARCH=amd64 go build -v ./...
52- env GOOS=darwin GOARCH=arm64 go build -v ./... 52+ env GOOS=darwin GOARCH=arm64 go build -v ./...
53- 53+
54 # Check cross-compiling Linux binaries.54 # Check cross-compiling Linux binaries.
55 env GOOS=linux GOARCH=amd64 go build -v ./...55 env GOOS=linux GOARCH=amd64 go build -v ./...
56- env GOOS=linux GOARCH=arm64 go build -v ./... 56+ env GOOS=linux GOARCH=arm64 go build -v ./...
57+
58+ # Check cross-compiling FreeBSD binaries.
59+ # gcflags -std is necessary to make fakecgo the Cgo for
60+ # FreeBSD to add the symbols that libc.so depends on.
61+ env GOOS=freebsd GOARCH=amd64 go build -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -v ./...
62+ env GOOS=freebsd GOARCH=arm64 go build -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -v ./...
57 63
58 - name: go mod vendor64 - name: go mod vendor
59 if: runner.os != 'Linux'65 if: runner.os != 'Linux'
@@ -82,3 +88,84 @@ jobs:
82 if: ${{ !startsWith(matrix.go, '1.18.') && !startsWith(matrix.go, '1.19.') }}88 if: ${{ !startsWith(matrix.go, '1.18.') && !startsWith(matrix.go, '1.19.') }}
83 run: |89 run: |
84 go test -race -shuffle=on -v -count=10 ./...90 go test -race -shuffle=on -v -count=10 ./...
91+
92+ freebsd:
93+ strategy:
94+ matrix:
95+ go: ['1.18.10', '1.19.12', '1.20.7', '1.21.0']
96+ name: Test with Go ${{ matrix.go }} on FreeBSD
97+ runs-on: macos-12
98+ defaults:
99+ run:
100+ shell: bash
101+ steps:
102+ - uses: actions/checkout@v3
103+ - name: Run in freebsd
104+ uses: vmactions/freebsd-vm@v0
105+ with:
106+ usesh: true
107+ prepare: |
108+ fetch https://go.dev/dl/go${{matrix.go}}.freebsd-amd64.tar.gz
109+ rm -fr /usr/local/go && tar -C /usr/local -xf go${{matrix.go}}.freebsd-amd64.tar.gz
110+ ln -s /usr/local/go/bin/go /usr/local/bin
111+ run: |
112+ # FreeBSD tests run within a virtualbox VM on macOS.
113+ # vmactions/freebsd-vm only supports a single "step" where it
114+ # brings down the VM at the end of the step, so all
115+ # the commands to run need to be put into this single block.
116+
117+ echo "Running tests on $(uname -a) at $PWD"
118+
119+ # verify Go is available
120+ go version
121+
122+ echo "=> go build"
123+ go build -v ./...
124+ # Compile without optimization to check potential stack overflow.
125+ # The option '-gcflags=all=-N -l' is often used at Visual Studio Code.
126+ # See also https://go.googlesource.com/vscode-go/+/HEAD/docs/debugging.md#launch and the issue hajimehoshi/ebiten#2120.
127+ go build "-gcflags=all=-N -l" -v ./...
128+
129+ # Check cross-compiling Windows binaries.
130+ env GOOS=windows GOARCH=386 go build -v ./...
131+ env GOOS=windows GOARCH=amd64 go build -v ./...
132+ env GOOS=windows GOARCH=arm go build -v ./...
133+ env GOOS=windows GOARCH=arm64 go build -v ./...
134+
135+ # Check cross-compiling macOS binaries.
136+ env GOOS=darwin GOARCH=amd64 go build -v ./...
137+ env GOOS=darwin GOARCH=arm64 go build -v ./...
138+
139+ # Check cross-compiling Linux binaries.
140+ env GOOS=linux GOARCH=amd64 go build -v ./...
141+ env GOOS=linux GOARCH=arm64 go build -v ./...
142+
143+ # Check cross-compiling FreeBSD binaries.
144+ env GOOS=freebsd GOARCH=amd64 go build -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -v ./...
145+ env GOOS=freebsd GOARCH=arm64 go build -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -v ./...
146+
147+ echo "=> go mod vendor"
148+ mkdir /tmp/vendoring
149+ cd /tmp/vendoring
150+ go mod init foo
151+ echo 'package main' > main.go
152+ echo 'import (' >> main.go
153+ echo ' _ "github.com/ebitengine/purego"' >> main.go
154+ echo ')' >> main.go
155+ echo 'func main() {}' >> main.go
156+ go mod edit -replace github.com/ebitengine/purego=$GITHUB_WORKSPACE
157+ go mod tidy
158+ go mod vendor
159+ go build -v .
160+
161+ cd $GITHUB_WORKSPACE
162+ echo "=> go test CGO_ENABLED=0"
163+ env CGO_ENABLED=0 go test -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" -shuffle=on -v -count=10 ./...
164+
165+ echo "=> go test CGO_ENABLED=1"
166+ env CGO_ENABLED=1 go test -shuffle=on -v -count=10 ./...
167+
168+ if [ -z "$(echo ${{matrix.go}} | grep '^1.1')" ]; then
169+ echo "=> go test race"
170+ go test -race -shuffle=on -v -count=10 ./...
171+ fi
M README.md +3 -2
@@ -19,7 +19,7 @@ born to bring that same vision to the other platforms supported by Ebitengine.
1919
2020 ## Example
2121
22-This example only works on macOS and Linux. For a complete example look at [libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports Windows.
22+This example only works on macOS and Linux. For a complete example look at [libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports Windows and FreeBSD.
2323
2424 ```go
2525 package main
@@ -68,6 +68,7 @@ This is a list of the copied files:
6868 * `internal/fakecgo/callbacks.go` from package `runtime/cgo`
6969 * `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo`
7070 * `internal/fakecgo/iscgo.go` from package `runtime/cgo`
71-* `internal/fakecgo/setenv.go` from package `runtime/cgo
71+* `internal/fakecgo/setenv.go` from package `runtime/cgo`
72+* `internal/fakecgo/freebsd.go` from package `runtime/cgo`
7273
7374 The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636))
@@ -19,7 +19,7 @@ born to bring that same vision to the other platforms supported by Ebitengine.
19 19
20 ## Example20 ## Example
21 21
22-This example only works on macOS and Linux. For a complete example look at [libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports Windows.22+This example only works on macOS and Linux. For a complete example look at [libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports Windows and FreeBSD.
23 23
24 ```go24 ```go
25 package main25 package main
@@ -68,6 +68,7 @@ This is a list of the copied files:
68 * `internal/fakecgo/callbacks.go` from package `runtime/cgo`68 * `internal/fakecgo/callbacks.go` from package `runtime/cgo`
69 * `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo`69 * `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo`
70 * `internal/fakecgo/iscgo.go` from package `runtime/cgo`70 * `internal/fakecgo/iscgo.go` from package `runtime/cgo`
71-* `internal/fakecgo/setenv.go` from package `runtime/cgo71+* `internal/fakecgo/setenv.go` from package `runtime/cgo`
72+* `internal/fakecgo/freebsd.go` from package `runtime/cgo`
72 73
73 The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636))74 The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636))
M cgo.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build cgo && (darwin || linux)
4+//go:build cgo && (darwin || linux || freebsd)
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build cgo && (darwin || linux)4+//go:build cgo && (darwin || linux || freebsd)
5 5
6 package purego6 package purego
7 7
M dlerror.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 package purego6 package purego
7 7
M dlfcn.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 package purego6 package purego
7 7
A dlfcn_freebsd.go +18 -0
@@ -0,0 +1,18 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package purego
5+
6+// Constants as defined in https://github.com/freebsd/freebsd-src/blob/main/include/dlfcn.h
7+const (
8+ RTLD_DEFAULT = ^uintptr(0) - 2 // Pseudo-handle for dlsym so search for any loaded symbol
9+ RTLD_LAZY = 0x00001 // Relocations are performed at an implementation-dependent time.
10+ RTLD_NOW = 0x00002 // Relocations are performed when the object is loaded.
11+ RTLD_LOCAL = 0x00000 // All symbols are not made available for relocation processing by other modules.
12+ RTLD_GLOBAL = 0x00100 // All symbols are available for relocation processing of other modules.
13+)
14+
15+//go:cgo_import_dynamic purego_dlopen dlopen "libc.so.7"
16+//go:cgo_import_dynamic purego_dlsym dlsym "libc.so.7"
17+//go:cgo_import_dynamic purego_dlerror dlerror "libc.so.7"
18+//go:cgo_import_dynamic purego_dlclose dlclose "libc.so.7"
@@ -0,0 +1,18 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package purego
5+
6+// Constants as defined in https://github.com/freebsd/freebsd-src/blob/main/include/dlfcn.h
7+const (
8+ RTLD_DEFAULT = ^uintptr(0) - 2 // Pseudo-handle for dlsym so search for any loaded symbol
9+ RTLD_LAZY = 0x00001 // Relocations are performed at an implementation-dependent time.
10+ RTLD_NOW = 0x00002 // Relocations are performed when the object is loaded.
11+ RTLD_LOCAL = 0x00000 // All symbols are not made available for relocation processing by other modules.
12+ RTLD_GLOBAL = 0x00100 // All symbols are available for relocation processing of other modules.
13+)
14+
15+//go:cgo_import_dynamic purego_dlopen dlopen "libc.so.7"
16+//go:cgo_import_dynamic purego_dlsym dlsym "libc.so.7"
17+//go:cgo_import_dynamic purego_dlerror dlerror "libc.so.7"
18+//go:cgo_import_dynamic purego_dlclose dlclose "libc.so.7"
M dlfcn_stubs.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || (linux && !cgo)
4+//go:build darwin || freebsd || (linux && !cgo)
55
66 #include "textflag.h"
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || (linux && !cgo)4+//go:build darwin || freebsd || (linux && !cgo)
5 5
6 #include "textflag.h"6 #include "textflag.h"
7 7
M dlfcn_test.go +7 -2
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 package purego_test
77
@@ -52,7 +52,12 @@ func buildSharedLib(compilerEnv, libFile string, sources ...string) error {
5252 return errors.New("compiler not found")
5353 }
5454
55- args := []string{"-shared", "-Wall", "-Werror", "-o", libFile}
55+ var args []string
56+ if runtime.GOOS == "freebsd" {
57+ args = []string{"-shared", "-Wall", "-Werror", "-fPIC", "-o", libFile}
58+ } else {
59+ args = []string{"-shared", "-Wall", "-Werror", "-o", libFile}
60+ }
5661
5762 // macOS arm64 can run amd64 tests through Rossetta.
5863 // Build the shared library based on the GOARCH and not
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 package purego_test6 package purego_test
7 7
@@ -52,7 +52,12 @@ func buildSharedLib(compilerEnv, libFile string, sources ...string) error {
52 return errors.New("compiler not found")52 return errors.New("compiler not found")
53 }53 }
54 54
55- args := []string{"-shared", "-Wall", "-Werror", "-o", libFile}55+ var args []string
56+ if runtime.GOOS == "freebsd" {
57+ args = []string{"-shared", "-Wall", "-Werror", "-fPIC", "-o", libFile}
58+ } else {
59+ args = []string{"-shared", "-Wall", "-Werror", "-o", libFile}
60+ }
56 61
57 // macOS arm64 can run amd64 tests through Rossetta.62 // macOS arm64 can run amd64 tests through Rossetta.
58 // Build the shared library based on the GOARCH and not63 // Build the shared library based on the GOARCH and not
M examples/libc/main.go +3 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux || windows
4+//go:build darwin || linux || windows || freebsd
55
66 package main
77
@@ -18,6 +18,8 @@ func getSystemLibrary() string {
1818 return "/usr/lib/libSystem.B.dylib"
1919 case "linux":
2020 return "libc.so.6"
21+ case "freebsd":
22+ return "libc.so.7"
2123 case "windows":
2224 return "ucrtbase.dll"
2325 default:
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux || windows4+//go:build darwin || linux || windows || freebsd
5 5
6 package main6 package main
7 7
@@ -18,6 +18,8 @@ func getSystemLibrary() string {
18 return "/usr/lib/libSystem.B.dylib"18 return "/usr/lib/libSystem.B.dylib"
19 case "linux":19 case "linux":
20 return "libc.so.6"20 return "libc.so.6"
21+ case "freebsd":
22+ return "libc.so.7"
21 case "windows":23 case "windows":
22 return "ucrtbase.dll"24 return "ucrtbase.dll"
23 default:25 default:
M examples/libc/main_unix.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 package main
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 package main6 package main
7 7
M func.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux || windows
4+//go:build darwin || linux || windows || freebsd
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux || windows4+//go:build darwin || linux || windows || freebsd
5 5
6 package purego6 package purego
7 7
M func_test.go +2 -0
@@ -23,6 +23,8 @@ func getSystemLibrary() (string, error) {
2323 return "/usr/lib/libSystem.B.dylib", nil
2424 case "linux":
2525 return "libc.so.6", nil
26+ case "freebsd":
27+ return "libc.so.7", nil
2628 case "windows":
2729 return "ucrtbase.dll", nil
2830 default:
@@ -23,6 +23,8 @@ func getSystemLibrary() (string, error) {
23 return "/usr/lib/libSystem.B.dylib", nil23 return "/usr/lib/libSystem.B.dylib", nil
24 case "linux":24 case "linux":
25 return "libc.so.6", nil25 return "libc.so.6", nil
26+ case "freebsd":
27+ return "libc.so.7", nil
26 case "windows":28 case "windows":
27 return "ucrtbase.dll", nil29 return "ucrtbase.dll", nil
28 default:30 default:
M go_runtime.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux || windows
4+//go:build darwin || linux || windows || freebsd
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux || windows4+//go:build darwin || linux || windows || freebsd
5 5
6 package purego6 package purego
7 7
R internal/cgo/syscall_cgo_linux.go → internal/cgo/syscall_cgo_unix.go +2 -0 renamed, 98% similar
@@ -1,6 +1,8 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4+//go:build linux || freebsd
5+
46 package cgo
57
68 // this file is placed inside internal/cgo and not package purego
@@ -1,6 +1,8 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4+//go:build linux || freebsd
5+
4 package cgo6 package cgo
5 7
6 // this file is placed inside internal/cgo and not package purego8 // this file is placed inside internal/cgo and not package purego
M internal/fakecgo/callbacks.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin || linux
5+//go:build darwin || linux || freebsd
66
77 package fakecgo
88
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin || linux5+//go:build darwin || linux || freebsd
6 6
7 package fakecgo7 package fakecgo
8 8
M internal/fakecgo/doc.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || freebsd
55
66 // Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.
77 // This allows code that calls into C to function properly when CGO_ENABLED=0.
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || freebsd
5 5
6 // Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.6 // Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.
7 // This allows code that calls into C to function properly when CGO_ENABLED=0.7 // This allows code that calls into C to function properly when CGO_ENABLED=0.
A internal/fakecgo/freebsd.go +27 -0
@@ -0,0 +1,27 @@
1+// Copyright 2010 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+//go:build freebsd && !cgo
6+
7+package fakecgo
8+
9+import _ "unsafe" // for go:linkname
10+
11+// Supply environ and __progname, because we don't
12+// link against the standard FreeBSD crt0.o and the
13+// libc dynamic library needs them.
14+
15+// Note: when building with cross-compiling or CGO_ENABLED=0, add
16+// the following argument to `go` so that these symbols are defined by
17+// making fakecgo the Cgo.
18+// -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std"
19+
20+//go:linkname _environ environ
21+//go:linkname _progname __progname
22+
23+//go:cgo_export_dynamic environ
24+//go:cgo_export_dynamic __progname
25+
26+var _environ uintptr
27+var _progname uintptr
@@ -0,0 +1,27 @@
1+// Copyright 2010 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+//go:build freebsd && !cgo
6+
7+package fakecgo
8+
9+import _ "unsafe" // for go:linkname
10+
11+// Supply environ and __progname, because we don't
12+// link against the standard FreeBSD crt0.o and the
13+// libc dynamic library needs them.
14+
15+// Note: when building with cross-compiling or CGO_ENABLED=0, add
16+// the following argument to `go` so that these symbols are defined by
17+// making fakecgo the Cgo.
18+// -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std"
19+
20+//go:linkname _environ environ
21+//go:linkname _progname __progname
22+
23+//go:cgo_export_dynamic environ
24+//go:cgo_export_dynamic __progname
25+
26+var _environ uintptr
27+var _progname uintptr
M internal/fakecgo/gen.go +8 -4
@@ -20,7 +20,7 @@ const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT
2020 // SPDX-License-Identifier: Apache-2.0
2121 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
2222
23-//go:build darwin || linux
23+//go:build darwin || linux || freebsd
2424
2525 package fakecgo
2626
@@ -75,7 +75,7 @@ call5({{.Name}}ABI0,
7575 {{- end}}
7676 }
7777
78-{{end}}
78+{{end}}
7979 {{- range . }}
8080 //go:linkname _{{.Name}} _{{.Name}}
8181 var _{{.Name}} uintptr
@@ -88,7 +88,7 @@ const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go
8888 // SPDX-License-Identifier: Apache-2.0
8989 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
9090
91-//go:build darwin || linux
91+//go:build darwin || linux || freebsd
9292
9393 #include "textflag.h"
9494
@@ -176,7 +176,7 @@ func run() error {
176176 if err := t.Execute(f, allSymbols); err != nil {
177177 return err
178178 }
179- for _, goos := range []string{"darwin", "linux"} {
179+ for _, goos := range []string{"darwin", "linux", "freebsd"} {
180180 f, err = os.Create(fmt.Sprintf("symbols_%s.go", goos))
181181 defer f.Close()
182182 if err != nil {
@@ -196,7 +196,11 @@ package fakecgo
196196 if goos == "linux" {
197197 libcSO = "libc.so.6"
198198 pthreadSO = "libpthread.so.0"
199+ } else if goos == "freebsd" {
200+ libcSO = "libc.so.7"
201+ pthreadSO = "libpthread.so"
199202 }
203+
200204 for _, sym := range libcSymbols {
201205 f.WriteString(fmt.Sprintf(importPragma, sym.Name, sym.Name, libcSO))
202206 }
@@ -20,7 +20,7 @@ const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT
20 // SPDX-License-Identifier: Apache-2.020 // SPDX-License-Identifier: Apache-2.0
21 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors21 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
22 22
23-//go:build darwin || linux23+//go:build darwin || linux || freebsd
24 24
25 package fakecgo25 package fakecgo
26 26
@@ -75,7 +75,7 @@ call5({{.Name}}ABI0,
75 {{- end}}75 {{- end}}
76 }76 }
77 77
78-{{end}} 78+{{end}}
79 {{- range . }}79 {{- range . }}
80 //go:linkname _{{.Name}} _{{.Name}}80 //go:linkname _{{.Name}} _{{.Name}}
81 var _{{.Name}} uintptr81 var _{{.Name}} uintptr
@@ -88,7 +88,7 @@ const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go
88 // SPDX-License-Identifier: Apache-2.088 // SPDX-License-Identifier: Apache-2.0
89 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors89 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
90 90
91-//go:build darwin || linux91+//go:build darwin || linux || freebsd
92 92
93 #include "textflag.h"93 #include "textflag.h"
94 94
@@ -176,7 +176,7 @@ func run() error {
176 if err := t.Execute(f, allSymbols); err != nil {176 if err := t.Execute(f, allSymbols); err != nil {
177 return err177 return err
178 }178 }
179- for _, goos := range []string{"darwin", "linux"} {179+ for _, goos := range []string{"darwin", "linux", "freebsd"} {
180 f, err = os.Create(fmt.Sprintf("symbols_%s.go", goos))180 f, err = os.Create(fmt.Sprintf("symbols_%s.go", goos))
181 defer f.Close()181 defer f.Close()
182 if err != nil {182 if err != nil {
@@ -196,7 +196,11 @@ package fakecgo
196 if goos == "linux" {196 if goos == "linux" {
197 libcSO = "libc.so.6"197 libcSO = "libc.so.6"
198 pthreadSO = "libpthread.so.0"198 pthreadSO = "libpthread.so.0"
199+ } else if goos == "freebsd" {
200+ libcSO = "libc.so.7"
201+ pthreadSO = "libpthread.so"
199 }202 }
203+
200 for _, sym := range libcSymbols {204 for _, sym := range libcSymbols {
201 f.WriteString(fmt.Sprintf(importPragma, sym.Name, sym.Name, libcSO))205 f.WriteString(fmt.Sprintf(importPragma, sym.Name, sym.Name, libcSO))
202 }206 }
A internal/fakecgo/go_freebsd_amd64.go +93 -0
@@ -0,0 +1,93 @@
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+package fakecgo
6+
7+import "unsafe"
8+
9+//go:nosplit
10+func _cgo_sys_thread_start(ts *ThreadStart) {
11+ var attr pthread_attr_t
12+ var ign, oset sigset_t
13+ var p pthread_t
14+ var size size_t
15+ var err int
16+
17+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18+ sigfillset(&ign)
19+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
20+
21+ pthread_attr_init(&attr)
22+ pthread_attr_getstacksize(&attr, &size)
23+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
24+ ts.g.stackhi = uintptr(size)
25+
26+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
27+
28+ pthread_sigmask(SIG_SETMASK, &oset, nil)
29+
30+ if err != 0 {
31+ print("fakecgo: pthread_create failed: ")
32+ println(err)
33+ abort()
34+ }
35+}
36+
37+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
38+//
39+//go:linkname x_threadentry_trampoline threadentry_trampoline
40+var x_threadentry_trampoline byte
41+var threadentry_trampolineABI0 = &x_threadentry_trampoline
42+
43+//go:nosplit
44+func threadentry(v unsafe.Pointer) unsafe.Pointer {
45+ ts := *(*ThreadStart)(v)
46+ free(v)
47+
48+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
49+
50+ // faking funcs in go is a bit a... involved - but the following works :)
51+ fn := uintptr(unsafe.Pointer(&ts.fn))
52+ (*(*func())(unsafe.Pointer(&fn)))()
53+
54+ return nil
55+}
56+
57+// here we will store a pointer to the provided setg func
58+var setg_func uintptr
59+
60+//go:nosplit
61+func x_cgo_init(g *G, setg uintptr) {
62+ var size size_t
63+ var attr *pthread_attr_t
64+
65+ /* The memory sanitizer distributed with versions of clang
66+ before 3.8 has a bug: if you call mmap before malloc, mmap
67+ may return an address that is later overwritten by the msan
68+ library. Avoid this problem by forcing a call to malloc
69+ here, before we ever call malloc.
70+
71+ This is only required for the memory sanitizer, so it's
72+ unfortunate that we always run it. It should be possible
73+ to remove this when we no longer care about versions of
74+ clang before 3.8. The test for this is
75+ misc/cgo/testsanitizers.
76+
77+ GCC works hard to eliminate a seemingly unnecessary call to
78+ malloc, so we actually use the memory we allocate. */
79+
80+ setg_func = setg
81+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
82+ if attr == nil {
83+ println("fakecgo: malloc failed")
84+ abort()
85+ }
86+ pthread_attr_init(attr)
87+ pthread_attr_getstacksize(attr, &size)
88+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
89+ // but this should be OK since we are taking the address of the first variable in this function.
90+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
91+ pthread_attr_destroy(attr)
92+ free(unsafe.Pointer(attr))
93+}
@@ -0,0 +1,93 @@
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+package fakecgo
6+
7+import "unsafe"
8+
9+//go:nosplit
10+func _cgo_sys_thread_start(ts *ThreadStart) {
11+ var attr pthread_attr_t
12+ var ign, oset sigset_t
13+ var p pthread_t
14+ var size size_t
15+ var err int
16+
17+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18+ sigfillset(&ign)
19+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
20+
21+ pthread_attr_init(&attr)
22+ pthread_attr_getstacksize(&attr, &size)
23+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
24+ ts.g.stackhi = uintptr(size)
25+
26+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
27+
28+ pthread_sigmask(SIG_SETMASK, &oset, nil)
29+
30+ if err != 0 {
31+ print("fakecgo: pthread_create failed: ")
32+ println(err)
33+ abort()
34+ }
35+}
36+
37+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
38+//
39+//go:linkname x_threadentry_trampoline threadentry_trampoline
40+var x_threadentry_trampoline byte
41+var threadentry_trampolineABI0 = &x_threadentry_trampoline
42+
43+//go:nosplit
44+func threadentry(v unsafe.Pointer) unsafe.Pointer {
45+ ts := *(*ThreadStart)(v)
46+ free(v)
47+
48+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
49+
50+ // faking funcs in go is a bit a... involved - but the following works :)
51+ fn := uintptr(unsafe.Pointer(&ts.fn))
52+ (*(*func())(unsafe.Pointer(&fn)))()
53+
54+ return nil
55+}
56+
57+// here we will store a pointer to the provided setg func
58+var setg_func uintptr
59+
60+//go:nosplit
61+func x_cgo_init(g *G, setg uintptr) {
62+ var size size_t
63+ var attr *pthread_attr_t
64+
65+ /* The memory sanitizer distributed with versions of clang
66+ before 3.8 has a bug: if you call mmap before malloc, mmap
67+ may return an address that is later overwritten by the msan
68+ library. Avoid this problem by forcing a call to malloc
69+ here, before we ever call malloc.
70+
71+ This is only required for the memory sanitizer, so it's
72+ unfortunate that we always run it. It should be possible
73+ to remove this when we no longer care about versions of
74+ clang before 3.8. The test for this is
75+ misc/cgo/testsanitizers.
76+
77+ GCC works hard to eliminate a seemingly unnecessary call to
78+ malloc, so we actually use the memory we allocate. */
79+
80+ setg_func = setg
81+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
82+ if attr == nil {
83+ println("fakecgo: malloc failed")
84+ abort()
85+ }
86+ pthread_attr_init(attr)
87+ pthread_attr_getstacksize(attr, &size)
88+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
89+ // but this should be OK since we are taking the address of the first variable in this function.
90+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
91+ pthread_attr_destroy(attr)
92+ free(unsafe.Pointer(attr))
93+}
A internal/fakecgo/go_freebsd_arm64.go +96 -0
@@ -0,0 +1,96 @@
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+package fakecgo
6+
7+import "unsafe"
8+
9+//go:nosplit
10+func _cgo_sys_thread_start(ts *ThreadStart) {
11+ var attr pthread_attr_t
12+ var ign, oset sigset_t
13+ var p pthread_t
14+ var size size_t
15+ var err int
16+
17+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18+ sigfillset(&ign)
19+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
20+
21+ pthread_attr_init(&attr)
22+ pthread_attr_getstacksize(&attr, &size)
23+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
24+ ts.g.stackhi = uintptr(size)
25+
26+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
27+
28+ pthread_sigmask(SIG_SETMASK, &oset, nil)
29+
30+ if err != 0 {
31+ print("fakecgo: pthread_create failed: ")
32+ println(err)
33+ abort()
34+ }
35+}
36+
37+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
38+//
39+//go:linkname x_threadentry_trampoline threadentry_trampoline
40+var x_threadentry_trampoline byte
41+var threadentry_trampolineABI0 = &x_threadentry_trampoline
42+
43+//go:nosplit
44+func threadentry(v unsafe.Pointer) unsafe.Pointer {
45+ ts := *(*ThreadStart)(v)
46+ free(v)
47+
48+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
49+
50+ // faking funcs in go is a bit a... involved - but the following works :)
51+ fn := uintptr(unsafe.Pointer(&ts.fn))
52+ (*(*func())(unsafe.Pointer(&fn)))()
53+
54+ return nil
55+}
56+
57+// here we will store a pointer to the provided setg func
58+var setg_func uintptr
59+
60+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
61+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
62+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
63+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
64+//
65+//go:nosplit
66+func x_cgo_init(g *G, setg uintptr) {
67+ var size size_t
68+ var attr *pthread_attr_t
69+
70+ /* The memory sanitizer distributed with versions of clang
71+ before 3.8 has a bug: if you call mmap before malloc, mmap
72+ may return an address that is later overwritten by the msan
73+ library. Avoid this problem by forcing a call to malloc
74+ here, before we ever call malloc.
75+
76+ This is only required for the memory sanitizer, so it's
77+ unfortunate that we always run it. It should be possible
78+ to remove this when we no longer care about versions of
79+ clang before 3.8. The test for this is
80+ misc/cgo/testsanitizers.
81+
82+ GCC works hard to eliminate a seemingly unnecessary call to
83+ malloc, so we actually use the memory we allocate. */
84+
85+ setg_func = setg
86+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
87+ if attr == nil {
88+ println("fakecgo: malloc failed")
89+ abort()
90+ }
91+ pthread_attr_init(attr)
92+ pthread_attr_getstacksize(attr, &size)
93+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
94+ pthread_attr_destroy(attr)
95+ free(unsafe.Pointer(attr))
96+}
@@ -0,0 +1,96 @@
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+package fakecgo
6+
7+import "unsafe"
8+
9+//go:nosplit
10+func _cgo_sys_thread_start(ts *ThreadStart) {
11+ var attr pthread_attr_t
12+ var ign, oset sigset_t
13+ var p pthread_t
14+ var size size_t
15+ var err int
16+
17+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18+ sigfillset(&ign)
19+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
20+
21+ pthread_attr_init(&attr)
22+ pthread_attr_getstacksize(&attr, &size)
23+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
24+ ts.g.stackhi = uintptr(size)
25+
26+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
27+
28+ pthread_sigmask(SIG_SETMASK, &oset, nil)
29+
30+ if err != 0 {
31+ print("fakecgo: pthread_create failed: ")
32+ println(err)
33+ abort()
34+ }
35+}
36+
37+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
38+//
39+//go:linkname x_threadentry_trampoline threadentry_trampoline
40+var x_threadentry_trampoline byte
41+var threadentry_trampolineABI0 = &x_threadentry_trampoline
42+
43+//go:nosplit
44+func threadentry(v unsafe.Pointer) unsafe.Pointer {
45+ ts := *(*ThreadStart)(v)
46+ free(v)
47+
48+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
49+
50+ // faking funcs in go is a bit a... involved - but the following works :)
51+ fn := uintptr(unsafe.Pointer(&ts.fn))
52+ (*(*func())(unsafe.Pointer(&fn)))()
53+
54+ return nil
55+}
56+
57+// here we will store a pointer to the provided setg func
58+var setg_func uintptr
59+
60+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
61+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
62+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
63+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
64+//
65+//go:nosplit
66+func x_cgo_init(g *G, setg uintptr) {
67+ var size size_t
68+ var attr *pthread_attr_t
69+
70+ /* The memory sanitizer distributed with versions of clang
71+ before 3.8 has a bug: if you call mmap before malloc, mmap
72+ may return an address that is later overwritten by the msan
73+ library. Avoid this problem by forcing a call to malloc
74+ here, before we ever call malloc.
75+
76+ This is only required for the memory sanitizer, so it's
77+ unfortunate that we always run it. It should be possible
78+ to remove this when we no longer care about versions of
79+ clang before 3.8. The test for this is
80+ misc/cgo/testsanitizers.
81+
82+ GCC works hard to eliminate a seemingly unnecessary call to
83+ malloc, so we actually use the memory we allocate. */
84+
85+ setg_func = setg
86+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
87+ if attr == nil {
88+ println("fakecgo: malloc failed")
89+ abort()
90+ }
91+ pthread_attr_init(attr)
92+ pthread_attr_getstacksize(attr, &size)
93+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
94+ pthread_attr_destroy(attr)
95+ free(unsafe.Pointer(attr))
96+}
M internal/fakecgo/go_libinit.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/go_setenv.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/go_util.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/iscgo.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin || linux
5+//go:build darwin || linux || freebsd
66
77 // The runtime package contains an uninitialized definition
88 // for runtime·iscgo. Override it to tell the runtime we're here.
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin || linux5+//go:build darwin || linux || freebsd
6 6
7 // The runtime package contains an uninitialized definition7 // The runtime package contains an uninitialized definition
8 // for runtime·iscgo. Override it to tell the runtime we're here.8 // for runtime·iscgo. Override it to tell the runtime we're here.
M internal/fakecgo/libcgo.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 package fakecgo6 package fakecgo
7 7
A internal/fakecgo/libcgo_freebsd.go +14 -0
@@ -0,0 +1,14 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package fakecgo
5+
6+type (
7+ pthread_cond_t uintptr
8+ pthread_mutex_t uintptr
9+)
10+
11+var (
12+ PTHREAD_COND_INITIALIZER = pthread_cond_t(0)
13+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0)
14+)
@@ -0,0 +1,14 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package fakecgo
5+
6+type (
7+ pthread_cond_t uintptr
8+ pthread_mutex_t uintptr
9+)
10+
11+var (
12+ PTHREAD_COND_INITIALIZER = pthread_cond_t(0)
13+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0)
14+)
M internal/fakecgo/setenv.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin || linux
5+//go:build darwin || linux || freebsd
66
77 package fakecgo
88
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin || linux5+//go:build darwin || linux || freebsd
6 6
7 package fakecgo7 package fakecgo
8 8
M internal/fakecgo/symbols.go +1 -1
@@ -3,7 +3,7 @@
33 // SPDX-License-Identifier: Apache-2.0
44 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
55
6-//go:build darwin || linux
6+//go:build darwin || linux || freebsd
77
88 package fakecgo
99
@@ -3,7 +3,7 @@
3 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5 5
6-//go:build darwin || linux6+//go:build darwin || linux || freebsd
7 7
8 package fakecgo8 package fakecgo
9 9
A internal/fakecgo/symbols_freebsd.go +27 -0
@@ -0,0 +1,27 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+package fakecgo
7+
8+//go:cgo_import_dynamic purego_malloc malloc "libc.so.7"
9+//go:cgo_import_dynamic purego_free free "libc.so.7"
10+//go:cgo_import_dynamic purego_setenv setenv "libc.so.7"
11+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.7"
12+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.7"
13+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.7"
14+//go:cgo_import_dynamic purego_abort abort "libc.so.7"
15+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so"
16+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
17+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
18+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
19+//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so"
20+//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so"
21+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
22+//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so"
23+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
24+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
25+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
26+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
27+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
@@ -0,0 +1,27 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+package fakecgo
7+
8+//go:cgo_import_dynamic purego_malloc malloc "libc.so.7"
9+//go:cgo_import_dynamic purego_free free "libc.so.7"
10+//go:cgo_import_dynamic purego_setenv setenv "libc.so.7"
11+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.7"
12+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.7"
13+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.7"
14+//go:cgo_import_dynamic purego_abort abort "libc.so.7"
15+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so"
16+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
17+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
18+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
19+//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so"
20+//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so"
21+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
22+//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so"
23+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
24+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
25+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
26+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
27+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
M internal/fakecgo/trampolines_amd64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || linux || freebsd
55
66 /*
77 trampoline for emulating required C functions for cgo in go (see cgo.go)
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || linux || freebsd
5 5
6 /*6 /*
7 trampoline for emulating required C functions for cgo in go (see cgo.go)7 trampoline for emulating required C functions for cgo in go (see cgo.go)
M internal/fakecgo/trampolines_arm64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux
4+//go:build darwin || freebsd || linux
55
66 #include "textflag.h"
77 #include "go_asm.h"
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux4+//go:build darwin || freebsd || linux
5 5
6 #include "textflag.h"6 #include "textflag.h"
7 #include "go_asm.h"7 #include "go_asm.h"
M internal/fakecgo/trampolines_stubs.s +1 -1
@@ -3,7 +3,7 @@
33 // SPDX-License-Identifier: Apache-2.0
44 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
55
6-//go:build darwin || linux
6+//go:build darwin || linux || freebsd
77
88 #include "textflag.h"
99
@@ -3,7 +3,7 @@
3 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5 5
6-//go:build darwin || linux6+//go:build darwin || linux || freebsd
7 7
8 #include "textflag.h"8 #include "textflag.h"
9 9
M nocgo.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build !cgo && (darwin || linux)
4+//go:build !cgo && (darwin || linux || freebsd)
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build !cgo && (darwin || linux)4+//go:build !cgo && (darwin || linux || freebsd)
5 5
6 package purego6 package purego
7 7
M sys_amd64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || (!cgo && linux)
4+//go:build darwin || freebsd || (!cgo && linux)
55
66 #include "textflag.h"
77 #include "abi_amd64.h"
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || (!cgo && linux)4+//go:build darwin || freebsd || (!cgo && linux)
5 5
6 #include "textflag.h"6 #include "textflag.h"
7 #include "abi_amd64.h"7 #include "abi_amd64.h"
M sys_arm64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || (!cgo && linux) || windows
4+//go:build darwin || freebsd || (!cgo && linux) || windows
55
66 #include "textflag.h"
77 #include "go_asm.h"
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || (!cgo && linux) || windows4+//go:build darwin || freebsd || (!cgo && linux) || windows
5 5
6 #include "textflag.h"6 #include "textflag.h"
7 #include "go_asm.h"7 #include "go_asm.h"
M sys_unix_arm64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
33
4-//go:build darwin || (!cgo && linux)
4+//go:build darwin || freebsd || (!cgo && linux)
55
66 #include "textflag.h"
77 #include "go_asm.h"
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
3 3
4-//go:build darwin || (!cgo && linux)4+//go:build darwin || freebsd || (!cgo && linux)
5 5
6 #include "textflag.h"6 #include "textflag.h"
7 #include "go_asm.h"7 #include "go_asm.h"
M syscall.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || windows || linux
4+//go:build darwin || windows || linux || freebsd
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || windows || linux4+//go:build darwin || windows || linux || freebsd
5 5
6 package purego6 package purego
7 7
M syscall_sysv.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || (!cgo && linux && (amd64 || arm64))
4+//go:build darwin || freebsd || (!cgo && linux && (amd64 || arm64))
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || (!cgo && linux && (amd64 || arm64))4+//go:build darwin || freebsd || (!cgo && linux && (amd64 || arm64))
5 5
6 package purego6 package purego
7 7
M zcallback_amd64.s +1 -1
@@ -1,6 +1,6 @@
11 // Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
22
3-//go:build darwin || (!cgo && linux)
3+//go:build darwin || freebsd || (!cgo && linux)
44
55 // runtime·callbackasm is called by external code to
66 // execute Go implemented callback function. It is not
@@ -1,6 +1,6 @@
1 // Code generated by wincallback.go using 'go generate'. DO NOT EDIT.1 // Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
2 2
3-//go:build darwin || (!cgo && linux)3+//go:build darwin || freebsd || (!cgo && linux)
4 4
5 // runtime·callbackasm is called by external code to5 // runtime·callbackasm is called by external code to
6 // execute Go implemented callback function. It is not6 // execute Go implemented callback function. It is not
M zcallback_arm64.s +1 -1
@@ -1,6 +1,6 @@
11 // Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
22
3-//go:build darwin || (!cgo && linux)
3+//go:build darwin || freebsd || (!cgo && linux)
44
55 // External code calls into callbackasm at an offset corresponding
66 // to the callback index. Callbackasm is a table of MOV and B instructions.
@@ -1,6 +1,6 @@
1 // Code generated by wincallback.go using 'go generate'. DO NOT EDIT.1 // Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
2 2
3-//go:build darwin || (!cgo && linux)3+//go:build darwin || freebsd || (!cgo && linux)
4 4
5 // External code calls into callbackasm at an offset corresponding5 // External code calls into callbackasm at an offset corresponding
6 // to the callback index. Callbackasm is a table of MOV and B instructions.6 // to the callback index. Callbackasm is a table of MOV and B instructions.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close