Skip to content

Instantly share code, notes, and snippets.

@nikomartn
Created November 13, 2022 18:49
Show Gist options
  • Save nikomartn/13337ddf6885b1c45000bfb4861dbf26 to your computer and use it in GitHub Desktop.
Save nikomartn/13337ddf6885b1c45000bfb4861dbf26 to your computer and use it in GitHub Desktop.
cgo for windows!
The go experience in windows is very suboptimal, you need to install MSYS2 and mingw and what else..
And cross your fingers to get it working.
But, wsl2 comes to the rescue, even for things like go-gl!
1. Install wsl2
2. (Ubuntu) sudo apt update && sudo apt install mingw-w64
3. .bashrc => alias wingo='GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 go'
4. wingo build
And thats it, you can make WSL your toolchain for Windows go executables.
As an example, try to wingo build the attached opengl example found in this tutorial:
https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
It will take some time to mingw to compile and link the whole opengl libraries, but after the first compilation, go sould
cache the artefacts, consecuent builds will be faster.
This could be extended with Docker for more complex deployments.
package main
import (
"fmt"
"log"
"runtime"
"strings"
"github.com/go-gl/gl/v4.1-core/gl" // OR: github.com/go-gl/gl/v2.1/gl
"github.com/go-gl/glfw/v3.2/glfw"
)
const (
width = 500
height = 500
vertexShaderSource = `
#version 410
in vec3 vp;
void main() {
gl_Position = vec4(vp, 1.0);
}
` + "\x00"
fragmentShaderSource = `
#version 410
out vec4 frag_colour;
void main() {
frag_colour = vec4(1, 1, 1, 1.0);
}
` + "\x00"
)
var (
triangle = []float32{
0, 0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0,
}
)
func main() {
runtime.LockOSThread()
window := initGlfw()
defer glfw.Terminate()
program := initOpenGL()
vao := makeVao(triangle)
for !window.ShouldClose() {
draw(vao, window, program)
}
}
func draw(vao uint32, window *glfw.Window, program uint32) {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.UseProgram(program)
gl.BindVertexArray(vao)
gl.DrawArrays(gl.TRIANGLES, 0, int32(len(triangle)/3))
glfw.PollEvents()
window.SwapBuffers()
}
// initGlfw initializes glfw and returns a Window to use.
func initGlfw() *glfw.Window {
if err := glfw.Init(); err != nil {
panic(err)
}
glfw.WindowHint(glfw.Resizable, glfw.False)
glfw.WindowHint(glfw.ContextVersionMajor, 4)
glfw.WindowHint(glfw.ContextVersionMinor, 1)
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
window, err := glfw.CreateWindow(width, height, "Conway's Game of Life", nil, nil)
if err != nil {
panic(err)
}
window.MakeContextCurrent()
return window
}
// initOpenGL initializes OpenGL and returns an intiialized program.
func initOpenGL() uint32 {
if err := gl.Init(); err != nil {
panic(err)
}
version := gl.GoStr(gl.GetString(gl.VERSION))
log.Println("OpenGL version", version)
vertexShader, err := compileShader(vertexShaderSource, gl.VERTEX_SHADER)
if err != nil {
panic(err)
}
fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
if err != nil {
panic(err)
}
prog := gl.CreateProgram()
gl.AttachShader(prog, vertexShader)
gl.AttachShader(prog, fragmentShader)
gl.LinkProgram(prog)
return prog
}
// makeVao initializes and returns a vertex array from the points provided.
func makeVao(points []float32) uint32 {
var vbo uint32
gl.GenBuffers(1, &vbo)
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
gl.BufferData(gl.ARRAY_BUFFER, 4*len(points), gl.Ptr(points), gl.STATIC_DRAW)
var vao uint32
gl.GenVertexArrays(1, &vao)
gl.BindVertexArray(vao)
gl.EnableVertexAttribArray(0)
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, nil)
return vao
}
func compileShader(source string, shaderType uint32) (uint32, error) {
shader := gl.CreateShader(shaderType)
csources, free := gl.Strs(source)
gl.ShaderSource(shader, 1, csources, nil)
free()
gl.CompileShader(shader)
var status int32
gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
if status == gl.FALSE {
var logLength int32
gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength)
log := strings.Repeat("\x00", int(logLength+1))
gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log))
return 0, fmt.Errorf("failed to compile %v: %v", source, log)
}
return shader, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment