Created
November 10, 2016 19:48
-
-
Save drbrain/179dfbf9655bdbc767efe5f349e8faa7 to your computer and use it in GitHub Desktop.
This file contains 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
require 'rake/tasklib' | |
require 'rake/clean' | |
## | |
# Creates a cross-compiled library that mruby-cli can use to link with | |
# each cross-built command. | |
# | |
# CrossLibrary.new "curl" do |cross| | |
# cross.release_name = "curl-7.28.0" | |
# cross.url = "https://curl.example/download/#{cross.release}.tar.gz" | |
# end | |
# | |
# You must also add the cross-compiled include and library paths to your | |
# build_config.rb: | |
# | |
# MRuby::Build.new do |conf| | |
# # … | |
# | |
# conf.cc.include_paths << "cross/#{name}/include" | |
# conf.linker.library_paths << "cross/#{name}/lib" | |
# | |
# # … | |
class CrossLibrary < Rake::TaskLib | |
## | |
# Extra flags to send to `configure` when building this library. | |
# | |
# These must be specified as an Array: | |
# | |
# cross.configure_flags << '--without-ssl' << '--without-zlib' | |
attr_reader :configure_flags | |
## | |
# The name of the mrbgem that depends upon this library. | |
# | |
# This allows the Rakefile to cross-compile the library when it is needed. | |
attr_accessor :mrbgem_name | |
## | |
# The name of this release package. | |
# | |
# This must uniquely identify this release amongst other libraries of the | |
# same name. Usually this will include the library name and a release | |
# version. | |
# | |
# cross.release_name = "curl-7.28.0" | |
attr_accessor :release_name | |
## | |
# The URL where this release can be downloaded. | |
# | |
# The value should include #release_name in the URL. | |
# | |
# cross.release_name = "curl-7.28.0" | |
# cross.url = "https://curl.example/download/#{cross.release}.tar.gz" | |
attr_accessor :url | |
def initialize(library, mrbgem_name: "mruby-#{library}", &block) | |
@library = library | |
@mrbgem_name = "mruby-#{library}" | |
@configure_flags = [] | |
# Used to re-run configure when the defining rake file changes | |
@task_source = block.source_location.first | |
default_flags = MRuby.targets['host'].cc.flags | |
targets = MRuby.targets.map do |name, build| | |
cflags = build.cc.flags - default_flags | |
env = {} | |
env['CC'] = build.cc.command | |
env['CFLAGS'] = cflags.join ' ' unless cflags.empty? | |
[name, env] | |
end | |
@targets = Hash[targets] | |
yield self | |
raise ArgumentError, "you must set release_name" unless @release_name | |
raise ArgumentError, "you must set url" unless @url | |
@tarball = File.basename @url | |
@download = "tmp/#{@tarball}" | |
@source_dir = "tmp/#{@release_name}" | |
define | |
end | |
## | |
# Defines compilation tasks for cross-compiling on +host+. Use +env+ to set | |
# environment details for the cross-compiled environment (CC, etc). | |
# | |
# The targets and environment are automatically determined from your | |
# build_config.rb so you should not need to edit these values. | |
# | |
# compile_tasks 'x86_64-pc-linux-gnu' | |
# compile_tasks 'i686-pc-linux-gnu', CFLAGS: '-m32' | |
# compile_tasks 'x86_64-apple-darwin14', CC: 'x86_64-apple-darwin14-clang' | |
# compile_tasks 'i386-apple-darwin14', CC: 'i386-apple-darwin14-clang' | |
def compile_tasks(host, env) | |
task_name = "#{@library}:#{host}" | |
# task environment | |
build_dir = File.join 'tmp', @library, 'build', host | |
configure = File.join @source_dir, 'configure' | |
configure = File.expand_path configure | |
install_dir = File.expand_path "cross/#{host}" | |
makefile = File.join build_dir, 'Makefile' | |
library_a = File.join install_dir, 'lib', "lib#{@library}.a" | |
mruby_build = MRuby.targets[host] | |
mrbgem = mruby_build.gems.find { |gem| gem.name == @mrbgem_name } | |
mrbgem_srcs = Rake::FileList["#{mrbgem.dir}/src/*.{c,cpp,cxx,cc,m,asm,s,S}"] | |
# define tasks | |
CLOBBER << install_dir | |
directory build_dir | |
CLEAN << build_dir | |
file makefile => [build_dir, @source_dir, @task_source, __FILE__] do | |
configure_command = [ | |
configure, | |
'--prefix', install_dir, | |
] | |
if host != 'host' then | |
configure_command << '--host' << host | |
end | |
configure_command.concat configure_flags | |
cd build_dir do | |
with_env env do | |
sh(*configure_command) | |
end | |
end | |
end | |
file library_a => makefile do | |
cd build_dir do | |
sh 'make' | |
sh 'make', 'install' | |
end | |
end | |
mrbgem_srcs.each do |src| | |
file src => library_a | |
end | |
desc "Build #{@library} for #{host}" | |
task task_name => library_a | |
task "#{@library}:compile" => task_name | |
task_name | |
end | |
## | |
# Defines all necessary tasks for cross-compiling a library. | |
def define | |
directory 'tmp' | |
CLEAN << 'tmp' | |
file @download => 'tmp' do | |
sh 'curl', '-s', '-L', | |
'--fail', '--retry', '3', '--retry-delay', '1', | |
'-o', @download, | |
@url | |
end | |
CLEAN << @download | |
directory @source_dir => @download do | |
sh 'tar', 'xzf', @download, '-C', 'tmp' | |
end | |
CLEAN << @source_dir | |
desc 'Cross-compile curl for all platforms' | |
task "#{@library}:compile" | |
@targets.each do |target, env| | |
compile_tasks target, env | |
end | |
task compile: "#{@library}:compile" | |
end | |
def with_env(env) | |
orig_env = {} | |
env.each do |key, value| | |
key = key.to_s | |
orig_env[key] = ENV[key] if ENV.include? key | |
ENV[key] = value | |
end | |
begin | |
yield | |
ensure | |
env.each_key do |key| | |
ENV.delete key.to_s | |
end | |
orig_env.each do |key, value| | |
ENV[key] = value | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment