zmk/lambda/compiler.rb
Chris Andreae c7fc3432cd
Docker container and lambda function for performing firmware builds
Provides an entry point that builds and returns a combined LH + RH keyboard
firmware when provided a keymap via a POST body.

Wraps compilation with ccache, and includes a pre-warmed cache of the build in /tmp/ccache.
To maximize chance of a direct cache hit, changes the lambda driver to always build in /tmp/build.

some back of the envelope measurements (2012 xeon e3-1230v2, nixos)
clean build, no cache -> 21.308
clean build, cache -> 7.145
modified keymap, clean build, cache -> 12.127
2022-12-24 13:00:14 +09:00

59 lines
1.4 KiB
Ruby

# frozen_string_literal: true
require 'tmpdir'
require 'json'
require 'base64'
class Compiler
class CompileError < RuntimeError
attr_reader :status, :log
def initialize(message, status: 400, log:)
super(message)
@status = status
@log = log
end
end
def compile(keymap_data)
in_build_dir do
File.open('build.keymap', 'w') do |io|
io.write(keymap_data)
end
compile_output = nil
IO.popen(['compileZmk', './build.keymap'], err: [:child, :out]) do |io|
compile_output = io.read
end
compile_output = compile_output.split("\n")
unless $?.success?
status = $?.exitstatus
raise CompileError.new("Compile failed with exit status #{status}", log: compile_output)
end
unless File.exist?('zephyr/combined.uf2')
raise CompileError.new('Compile failed to produce result binary', status: 500, log: compile_output)
end
result = File.read('zephyr/combined.uf2')
[result, compile_output]
end
end
# Lambda is single-process per container, and we get substantial speedups
# from ccache by always building in the same path
BUILD_DIR = '/tmp/build'
def in_build_dir
FileUtils.remove_entry(BUILD_DIR, true)
Dir.mkdir(BUILD_DIR)
Dir.chdir(BUILD_DIR)
yield
ensure
FileUtils.remove_entry(BUILD_DIR, true) rescue nil
end
end