messing with odin lang on alpine

so i was binging gingerbill's writeups on various memory allocation strategies (very informative, definitely go check them out!)

and realized this fella made a programming language!

odin is pretty cool

sewndo they have a doc between odin vs go
sewnbecause this just looks like go
notchoccan't find a comparison page
notchocno gc tho
sewnahhhh
notchocidk about goroutines
sewnoooooo
sewnooowowwoowowowo
sewnwwawhahwhahehawhh
sewnweeewwweeeweeee

setting up

odin is packaged on alpine so that's convenient (it's split into odin and odin-vendor)

unfortunately the lsp isn't (as of 05/02/2024) but we can always compile from source, just a ./build.sh away

getting started

following this Breakout tutorial by Karl Zylinski

nice, helix formats it when i save

muscle memory keeps trying to append semicolons aaaAAAAUGH

compiling

seems like sublime text just compiles it for ya

unfortunately im using helix so no fancy integrations (yet) so let's compile it manually!

contents of breakout.odin:

package breakout

import rl "vendor:raylib"

main :: proc() {
	rl.InitWindow(480, 360, "breakout")

	for !rl.WindowShouldClose() {
		rl.BeginDrawing()
		rl.ClearBackground({192, 192, 255, 255})
		rl.EndDrawing()
	}

	rl.CloseWindow()
}

run odin build . and...

breakout.odin(3:1) Syntax Error: Path does not exist: vendor:raylib 
	import rl "vendor:raylib" 
	^ 

what?

attempt 1: vendorception

odin root says it's looking in /usr/lib/odin

% ls
base/   core/   shared/ vendor/ odin

seems pretty reasonable

but...

% ls vendor/
vendor/

% ls vendor/vendor/
ENet/        commonmark/  fontstash/   microui/     sdl2/        x11/
OpenEXRCore/ compress/    ggpo/        miniaudio/   stb/         zlib/
OpenGL/      darwin/      glfw/        nanovg/      vulkan/      README.md
box2d/       directx/     libc/        portmidi/    wasm/
cgltf/       egl/         lua/         raylib/      wgpu/

is there supposed to be a nested vendor/ directory? that doesn't fit with the others

apk info -L odin-vendor lists everything as being in usr/lib/odin/vendor/vendor/ so this was installed correctly...

i checked the arch package which lists them in usr/lib/odin/vendor/ so seems it's unintentional

let's take a look at the odin APKBUILD

vendor() {
	pkgdesc="Vendor collection for Odin programming language"

	mkdir -p "$subpkgdir"/usr/lib/odin/vendor
	cp -r "$builddir"/vendor "$subpkgdir"/usr/lib/odin/vendor
}

oh.

so it's making the vendor/ directory then copying our built vendor/ directory into that which gives us vendor/vendor/

the fix would be to either:

went with #2, made a MR and HOLY SHIT that was fast

ughhhh is there no squash in gitlab web ui????

cloned, squashed, force-pushed, ok back to messing around

for now im too lazy to actually build it so sudo su time!!

# cd /usr/lib/odin/vendor
# mv vendor/* .
# rm -r vendor/  # there's a hidden .gitkeep file
% ls /usr/lib/odin/vendor
ENet/        commonmark/  fontstash/   microui/     sdl2/        x11/
OpenEXRCore/ compress/    ggpo/        miniaudio/   stb/         zlib/
OpenGL/      darwin/      glfw/        nanovg/      vulkan/      README.md
box2d/       directx/     libc/        portmidi/    wasm/
cgltf/       egl/         lua/         raylib/      wgpu/

fixed :DD

attempt 2: precompiled libraries

run odin build . once again...

/usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find -l:/usr/lib/odin/vendor/raylib//linux/libraylib.a: No such file or directory
clang: error: linker command failed with exit code 1 (use -v to see invocation)

sure enough, /usr/lib/odin/vendor/raylib/linux/ is completely empty

checking odin's github repo it seems they are indeed shipping precompiled libraries(why?????)

but alpine's APKBUILD strips them all out

prepare() {
	default_prepare

	find "$builddir"/vendor \
		\( \
			-name windows -o \
			-name macos -o \
			-name macos-arm64 -o \
			-name darwin \
			-name "*.lib" -o \
			-name "*.dll" -o \
			-name "*.a" -o \
			-name "*.dylib" -o \
			-name "*.so.*" -o \
			-name "*.so" -o \
		\) \
		-exec rm -rf {} +
}

interesting

im gonna manually install raylib.a back

# curl https://github.com/odin-lang/Odin/raw/refs/heads/master/vendor/raylib/linux/libraylib.a -o /usr/lib/odin/vendor/raylib/linux/libraylib.a

attempt 3: glibc

run odin build . yet again...

/usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/../../../../x86_64-alpine-linux-musl/bin/ld: ///usr/lib/odin/vendor/raylib/linux/libraylib.a(rcore.o): in function `sinfl_refill':
rcore.c:(.text+0x6c78): undefined reference to `__memcpy_chk'
/usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/../../../../x86_64-alpine-linux-musl/bin/ld: ///usr/lib/odin/vendor/raylib/linux/libraylib.a(rcore.o): in function `sdefl_flush':
...
[an entire screenful of "undefined reference to `__.*_chk'"]
...
clang: error: linker command failed with exit code 1 (use -v to see invocation)

of course, the precompiled binaries are linked against glibc...

gcompat should fix this though! just gotta explicitly link it

% odin build . -extra-linker-flags:-l:/lib/libgcompat.so.0
% ls
breakout*      breakout.odin
% ./breakout

and we finally have a nice blurple window :D

ok back to the tutorial

TBC


made with <3 and /.gen.sh