Last active
May 17, 2021 09:39
-
-
Save egasimus/0254dcd67f95f262aa6e133794738392 to your computer and use it in GitHub Desktop.
Building Arcan on NixOS, 2020 version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
See also: | |
* https://github.com/NixOS/nixpkgs/issues/49626 | |
* https://gist.github.com/telent/4a92294a767656759959006fe8440122 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ lib, newScope, stdenv, pkgs }: let | |
# nicer aliases | |
derive = stdenv.mkDerivation; | |
concat = builtins.concatStringsSep " "; | |
# vendored libuvc: don't build, just make sources available | |
libuvc-src = derive { | |
name = "libuvc-src"; | |
# using fetchgit instead fetchFromGitHub because | |
# the .git directory is needed by arcan's cmake scripts | |
src = pkgs.fetchgit { | |
leaveDotGit = true; | |
url = "https://github.com/letoram/libuvc.git"; | |
rev = "v0.0.6"; | |
sha256 = "1jdmiinsd91nnli5hgcn9c6ifj0s6ngbyjwm0z6fim4f8krnh0sf"; | |
}; | |
nativeBuildInputs = with pkgs; [ git ]; | |
# fetchgit strips all refs, leaving just a fetchgit branch | |
# but cmake needs to check out the ref called 'master': | |
installPhase = '' | |
git tag master | |
cp -r . $out/ | |
cd $out | |
''; | |
}; | |
# cmake flags pointing to locations of arcan headers | |
arcanIncludeDirs = arcan: [ | |
"-DARCAN_SHMIF_INCLUDE_DIR=${arcan}/include/arcan/shmif" | |
"-DARCAN_TUI_INCLUDE_DIR=${arcan}/include/arcan" | |
]; | |
# cmake flags pointing to locations of libusb1 headers and binaries | |
libusbDirs = libusb1: [ | |
"-DLIBUSB_1_INCLUDE_DIRS=${libusb1.dev}/include/libusb-1.0" | |
"-DLIBUSB_1_LIBRARIES=${libusb1}/lib/libusb-1.0.so" | |
]; | |
in lib.makeScope newScope (self: with self; let | |
mkArcanAppl = { name, src, applRoot }: callPackage ({ pkgs }: derive { | |
name = name; | |
src = src; | |
nativeBuildInputs = with pkgs; [ envsubst ]; | |
buildInputs = [ arcan ]; | |
installPhase = '' | |
mkdir -p $out/${name} $out/bin | |
cp -r ./${applRoot}/* $out/${name}/ | |
Arcan=${arcan} Appls=$out Appl=${name} envsubst \ | |
< ${./Arcan.wrapper} \ | |
> $out/bin/arcan.${name} | |
chmod +x $out/bin/arcan.${name} | |
''; | |
}) {}; | |
arcanRev = "280bb2f1b39da4465e391158d7debba4a8c168c6"; | |
arcanCoreSrc = pkgs.fetchgit { | |
leaveDotGit = true; | |
url = "https://github.com/letoram/arcan.git"; | |
rev = arcanRev; | |
sha256 = "0pzgb8s74na9wr8dy3bgvv23fry2zny4w6kzjyq1q5lnsgma0zqn"; | |
}; | |
in { | |
# arcan core: | |
arcan = callPackage ({ pkgs }: derive { | |
name = "arcan"; | |
src = arcanCoreSrc; | |
patches = [ ./Arcan.nosuid.patch ]; # nix refuses to build suid binaries | |
postUnpack = '' # add vendored libuvc | |
mkdir -p ./arcan/external/git/libuvc | |
pushd ./arcan/external/git/ | |
shopt -s dotglob nullglob # bashism: * now also matches dotfiles | |
cp -r ${libuvc-src}/* libuvc/ | |
shopt -u dotglob nullglob # phases are stateful | |
popd | |
''; | |
nativeBuildInputs = with pkgs; [ cmake gcc git ]; | |
buildInputs = with pkgs; [ | |
apr | |
espeak-classic | |
file | |
ffmpeg-full | |
freetype | |
harfbuzzFull | |
leptonica | |
libGL | |
libdrm | |
libjpeg | |
libusb1 | |
libvncserver | |
libxkbcommon | |
luajit | |
lzma | |
mesa | |
openal | |
SDL2 | |
sqlite | |
tesseract | |
vlc | |
wayland | |
wayland-protocols | |
xorg.libxcb | |
xorg.xcbutil | |
xorg.xcbutilwm | |
]; | |
PKG_CONFIG_PATH = concat [ # make wayland protocols available | |
"${pkgs.wayland-protocols}/share/pkgconfig" | |
"${pkgs.libusb1.dev}/lib/pkgconfig" | |
]; | |
CFLAGS = concat [ # don't warn on read()/write() without a format | |
"-Wno-format" # (Arcan code uses them on SHMIFs) | |
"-Wno-format-security" | |
]; | |
cmakeFlags = concat ( | |
# cmake won't be able to find these paths on its own: | |
(libusbDirs pkgs.libusb) ++ [ | |
"-DDRM_INCLUDE_DIR=${pkgs.libdrm.dev}/include/libdrm" | |
"-DGBM_INCLUDE_DIR=${pkgs.libGL.dev}/include" | |
"-DWAYLANDPROTOCOLS_PATH=${pkgs.wayland-protocols}/share/wayland-protocols" | |
# enable features: | |
"-DVIDEO_PLATFORM=egl-dri" | |
"-DSHMIF_TUI_ACCEL=ON" | |
"-DENABLE_LWA=ON" | |
"-DNO_BUILTIN_OPENHMD=ON" | |
"-DHYBRID_SDL=On" | |
"-DHYBRID_HEADLESS=On" | |
"-DFSRV_DECODE_UVC=Off" | |
# optional | |
"-DVERBOSE=ON" | |
#"--debug-output" | |
#"--trace" | |
"../src" | |
]); | |
}) {}; | |
# arcan utilities: | |
acfgfs = callPackage ({ pkgs }: derive { | |
name = "acfgfs"; | |
src = arcanCoreSrc; | |
nativeBuildInputs = with pkgs; [ cmake gcc git ]; | |
buildInputs = [ arcan ] ++ (with pkgs; [ fuse3 ]); | |
cmakeFlags = concat ((arcanIncludeDirs arcan) ++ [ "../src/tools/acfgfs" ]); | |
}) {}; | |
aclip = callPackage ({ pkgs }: derive { | |
name = "aclip"; | |
src = arcanCoreSrc; | |
nativeBuildInputs = with pkgs; [ cmake gcc git pkg-config ]; | |
buildInputs = [ arcan ]; | |
PKG_CONFIG_PATH = concat [ "${arcan}/lib/pkgconfig" ]; | |
cmakeFlags = concat ((arcanIncludeDirs arcan) ++ [ "../src/tools/aclip" ]); | |
}) {}; | |
aloadimage = callPackage ({ pkgs }: derive { | |
name = "aloadimage"; | |
src = arcanCoreSrc; | |
nativeBuildInputs = with pkgs; [ cmake gcc git ]; | |
buildInputs = [ arcan ]; | |
cmakeFlags = concat ((arcanIncludeDirs arcan) ++ [ "../src/tools/aloadimage" ]); | |
}) {}; | |
shmmon = callPackage ({ pkgs }: derive { | |
name = "shmmon"; | |
src = arcanCoreSrc; | |
nativeBuildInputs = with pkgs; [ cmake gcc git ]; | |
buildInputs = [ arcan ]; | |
cmakeFlags = concat ((arcanIncludeDirs arcan) ++ [ "../src/tools/shmmon" ]); | |
}) {}; | |
# TODO: provide <hidapi/hidapi.h> include path | |
#vrbridge = callPackage ({ pkgs }: derive { | |
#name = "vrbridge"; | |
#src = ./arcan; | |
#nativeBuildInputs = with pkgs; [ cmake gcc git pkg-config ]; | |
#buildInputs = [ arcan ] ++ (with pkgs; [ libusb1 ]); | |
#cmakeFlags = concat ( | |
#(arcanIncludeDirs arcan) ++ | |
#(libusbDirs pkgs.libusb1) ++ | |
#[ "../src/tools/vrbridge" ] | |
#); | |
#}) {}; | |
# arcan appls | |
awb = mkArcanAppl { | |
name = "awb"; | |
src = pkgs.fetchgit { | |
leaveDotGit = true; | |
url = "https://github.com/letoram/awb.git"; | |
rev = "271ef7ffd7f24569d2f836198e4c96b8c617e372"; | |
sha256 = "1jdmiinsd91nnli5hgcn9c6ifj0s6ngbyjwm0z6fim4f8krnh0s8"; | |
}; | |
applRoot = ""; | |
}; | |
prio = mkArcanAppl { | |
name = "prio"; | |
src = pkgs.fetchgit { | |
leaveDotGit = true; | |
url = "https://github.com/letoram/prio.git"; | |
rev = "c3f97491339d15f063d6937d5f89bcfaea774dd1"; | |
sha256 = "0igsbzp0df24f856sfwzcgcfanxlvxmw5v94gqq2p42kwardfmm9"; | |
}; | |
applRoot = ""; | |
}; | |
durden = mkArcanAppl { | |
name = "durden"; | |
src = pkgs.fetchgit { | |
leaveDotGit = true; | |
url = "https://github.com/letoram/durden.git"; | |
rev = "bfbfe68bc325a5fb06ea1869a99404e277291a89"; | |
sha256 = "11zfd1cf0sh63a9wrm5n129jmb5m0ibfh51ryjjjgxgx901k2qhi"; | |
}; | |
applRoot = "durden"; | |
}; | |
safespaces = mkArcanAppl { | |
name = "safespaces"; | |
src = pkgs.fetchgit { | |
leaveDotGit = true; | |
url = "https://github.com/letoram/safespaces.git"; | |
rev = "https://github.com/letoram/safespaces/commit/58eef59afba091293cab4d2b156e725f75d92eaf"; | |
sha256 = "1jdmiinsd91nnli5hgcn9c6ifj0s6ngbyjwm0z6fim4f8krnh0s9"; | |
}; | |
applRoot = "safespaces"; | |
}; | |
})) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt | |
index 34a0d20a..f90ce0a6 100644 | |
--- a/src/CMakeLists.txt | |
+++ b/src/CMakeLists.txt | |
@@ -740,7 +740,6 @@ if (VIDEO_PLATFORM STREQUAL "egl-dri") | |
amsg("${CL_YEL}egl-dri+privsep${CL_RST}\t${CL_GRN}installing SUID${CL_RST}") | |
install(TARGETS arcan DESTINATION bin | |
PERMISSIONS | |
- SETUID | |
OWNER_WRITE OWNER_READ OWNER_EXECUTE | |
GROUP_READ GROUP_EXECUTE | |
WORLD_READ WORLD_EXECUTE |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
pushd $Arcan/bin # otherwise `arcan doesn't find system-binaries` | |
trap "popd" EXIT # let's not leave the user stranded, though | |
./arcan \ | |
-T ../share/arcan/scripts \ | |
-p ../share/arcan/resources \ | |
-t $Appls $@ $Appl |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A minimal configuration.nix containing just Arcan. | |
{pkgs,...}:{ | |
environment.systemPackages = let | |
arcan = (pkgs.callPackage (import ./Arcan.nix) {}); | |
in [ | |
arcan.arcan | |
arcan.acfgfs | |
arcan.aloadimage | |
arcan.aclip | |
arcan.shmmon | |
arcan.prio | |
arcan.durden | |
]; | |
users.groups.input.members = ["user"]; | |
} |
Hi! @letoram linked this gist in Discord. I've just pushed a commit with a Nix expression what enables building arcan. I haven't tested it out yet, so I don't know if there's any bugs. :)
It's very a WIP, so I just wanted to commit and push as a backup.
EDIT: And it builds arcan_lwa
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
First - a problem with the NixOS module itself:
It does not build arcan_lwa (which is used under the hood to run arcan applications inside of other arcan applications). The reason for that is, most likely, that the in-source version of OpenAL is ignored (external/clone.sh). That one has patches which adds an 'arcan' audio backend that should not be upstreamed or be integrated with system OpenAL (which normal arcan uses). The dependency will eventually be refactored out and swapped for something slimmer, but not today.
Second, as to your general remarks:
The development style in Lua is very much up to the engine integration, hence why it is rarely a standalone language itself and does not fit very well with such a mold. Arcan forces a more functional/event-driven nature rather than giving you control over an imperative main loop - you are almost guaranteed to screw up something like a while(true){ process_input(); move_things_around(); if (time_to_draw) draw_frame(); }. Regular game developers do so repeatedly (locking animations and logic to %30Hz or so and breaking spectacularly on variable frame rate displays and so on). On a system graphics level, this problem is much more complex with many soft failure modes.
The applname() entry point is a substitution for the '.html' file in your normal web application -- any up-front loading of resources and necessary allocations should be done there. Before that point none of the actual APIs are exposed - leaving much less room for obfuscation and funny tricks for concealing intent. As a side note, that is also one of the reasons why normal "loadstring(str)()" kind of functions are not exposed. If you harden the setup a bit (separate appl, appl-out namespaces, block the .so form of system_load()) dynamic coding tricks for packers/unpackers and other shady tactics are closed off.
The Lua part isn't simply a language that is substitutable by anything else, in reality it is treated as a 'safe' keyword for C. Lua itself (as in arcan_lua.c) is a bit of a misnomer as quite a few functions in that behemoth do provide additional abstractions and encode idioms that evolved over time. There is a lot of work behind how its specific VM interface interacts with the rest of the engine when it comes to error and crash recovery, as well as GC cadence and so on.
If anything, other language support should be done as part of the scripting space and keep actual execution out of process more akin to how WMs work in X11. A single appl or hookscript that uses open_nonblock to create an socket, then generate bindings from doc/*.lua. Unfortunately those files were not written with the intent of being used as an IDL, and it is a slow burn task reworking that format in this direction where the overloaded arguments each have their expected types explicitly written out and so on. What helps is that the macro in the arcan_lua.c that marks every entry-point also has a #define hack at the top of the source unit to emit a trace, so running that against something like durden/pipeworld would give decent statistics of the more useful functions versus the edge case ones.
store as myapp/myapp.lua, shove logo.png into the myapp folder or somewhere accessible with arcan -p /path/to/resource/base myapp and done.
This would have your logo move from the left edge to the right edge indefinitely (though missing a myapp_display_state handler to deal with window resizes changing the VRESW/VRESH constants). It was never a strong intent that the Lua API would be used directly (albeit that's basically what I do), but rather emitted by a translator from something else. I have reconsidered somewhat since then, and a 'REPL-' style wrapper for easier experimentation is on the todo along with something that targets pine* and RPI400 etc. specifically to get back to a sort of "power on" 10 print "hello world" kind of computing.