Im deploying a sinatra webapp that makes use of a c library, through Ruby FFI. I need this library to be compiled on the target machine. I do this through a Rakefile normally, but because of Heroku's ephemeral hard drive, any time I run rake the compiled files dissappear. How can I make these libraries persist? Is there a way to push the files to git from heroku?
Possibly related: Whenever I try to access the page, the application crashes with a code=H10 error. The app runs fine locally.
My attempt at customizing a buildpack:
#!/usr/bin/env ruby
# This script compiles an application so it can run on Heroku.
# It will install the application's specified version of Ruby, it's dependencies
# and certain framework specific requirements (such as calling `rake assets:precompile`
# for rails apps). You can see all features described in the devcenter
# https://devcenter.heroku.com/articles/ruby-support
$stdout.sync = true
$:.unshift File.expand_path("../../../lib", __FILE__)
require "language_pack"
require "language_pack/shell_helpers"
begin
# my addition begins here
`mkdir /app/src`
`cd /app && curl -s https://www.astro.com/ftp/swisseph/swe_unix_src_2.10.02.tar.gz | tar xzvf -`
`cd '/app/src' && make libswe.so`
# my addition ends here
LanguagePack::ShellHelpers.initialize_env(ARGV[2])
if pack = LanguagePack.detect(ARGV[0], ARGV[1])
pack.topic("Compiling #{pack.name}")
pack.log("compile") do
pack.compile
end
end
rescue Exception => e
LanguagePack::ShellHelpers.display_error_and_exit(e)
end
Alternatively, I also tried:
#!/usr/bin/env bash
# The actual compilation code lives in `bin/support/ruby_compile`. This file instead
# bootstraps the ruby needed and then executes `bin/support/ruby_compile`
BUILD_DIR=$1
CACHE_DIR=$2
ENV_DIR=$3
BIN_DIR=$(cd $(dirname $0); pwd)
BUILDPACK_DIR=$(dirname $BIN_DIR)
# my addition begins here
mkdir /app/src
cd /app && curl -s https://www.astro.com/ftp/swisseph/swe_unix_src_2.10.02.tar.gz | tar xzvf -
cd '/app/src' && make libswe.so
# my addition ends here
source "$BIN_DIR/support/bash_functions.sh"
heroku_buildpack_ruby_install_ruby "$BIN_DIR" "$BUILDPACK_DIR"
if detect_needs_java "$BUILD_DIR"; then
cat <<EOM
## Warning: Your app needs java
The Ruby buildpack determined your app needs java installed
we recommend you add the jvm buildpack to your application:
$ heroku buildpacks:add heroku/jvm --index=1
-----> Installing Java
EOM
compile_buildpack_v2 "$BUILD_DIR" "$CACHE_DIR" "$ENV_DIR" "https://buildpack-registry.s3.us-east-1.amazonaws.com/buildpacks/heroku/jvm.tgz" "heroku/jvm"
fi
$heroku_buildpack_ruby_dir/bin/ruby $BIN_DIR/support/ruby_compile $@
Both seem to work at first (i.e. compile the C library, output the files I need), but when I run heroku run bash
or the web application Im not able to find the files. This is the specific error, btw:
/app/vendor/bundle/ruby/3.0.0/gems/ffi-1.15.5/lib/ffi/library.rb:145:in `block in ffi_lib': Could not open library '/app/src/libswe.so': /app/src/libswe.so: cannot open shared object file: No such file or directory (LoadError)
I've also tried heroku release phase, but even then the files did not persist. Procfile:
release: bundle exec rake
web: bundle exec thin start -R config.ru -e $RACK_ENV -p ${PORT:-5000}
Rakefile:
#require "bundler/gem_tasks"
task default: [:clean, :c_build, :get_ephe]
task :clean do
`rm ./src/libswe.so`
`rm -rf ephe`
end
task :c_build do
`wget https://www.astro.com/ftp/swisseph/swe_unix_src_2.10.02.tar.gz`
`tar xvf swe_unix_src_2.10.02.tar.gz`
`rm swe_unix_src_2.10.02.tar.gz`
`cd src && make libswe.so && echo "Compiled Library"`
end
task :get_ephe do
`mkdir ephe`
`wget -P ephe https://www.astro.com/ftp/swisseph/ephe/seas_12.se1`
`wget -P ephe https://www.astro.com/ftp/swisseph/ephe/seas_18.se1`
`wget -P ephe https://www.astro.com/ftp/swisseph/ephe/sefstars.txt`
`wget -P ephe https://www.astro.com/ftp/swisseph/ephe/semo_12.se1`
`wget -P ephe https://www.astro.com/ftp/swisseph/ephe/semo_18.se1`
`wget -P ephe https://www.astro.com/ftp/swisseph/ephe/sepl_12.se1`
`wget -P ephe https://www.astro.com/ftp/swisseph/ephe/sepl_18.se1`
end