mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Re-written android.rake task for latest Android NDK clang. Currently loses support for GCC and mips, mips64. Addresses issue #3208
This commit is contained in:
+168
-156
@@ -1,16 +1,21 @@
|
||||
class MRuby::Toolchain::Android
|
||||
DEFAULT_ARCH = 'armeabi'
|
||||
DEFAULT_PLATFORM = 'android-14'
|
||||
DEFAULT_TOOLCHAIN = :gcc
|
||||
|
||||
DEFAULT_ARCH = 'armeabi' # TODO : Revise if arch should have a default
|
||||
|
||||
DEFAULT_TOOLCHAIN = :clang
|
||||
|
||||
DEFAULT_NDK_HOMES = %w{
|
||||
/usr/local/opt/android-ndk
|
||||
/usr/local/opt/android-sdk/ndk-bundle
|
||||
%LOCALAPPDATA%/Android/android-sdk/ndk-bundle
|
||||
}
|
||||
TOOLCHAINS = [:gcc, :clang]
|
||||
|
||||
TOOLCHAINS = [:clang] # TODO : Add gcc support
|
||||
|
||||
ARCHITECTURES = %w{
|
||||
armeabi armeabi-v7a arm64-v8a
|
||||
mips mips64
|
||||
x86 x86_64
|
||||
}
|
||||
} # TODO : Add mips mips64 support
|
||||
|
||||
class AndroidNDKHomeNotFound < StandardError
|
||||
def message
|
||||
@@ -21,196 +26,203 @@ Set ANDROID_NDK_HOME environment variable or set :ndk_home parameter
|
||||
end
|
||||
end
|
||||
|
||||
class PlatformDirNotFound < StandardError
|
||||
def message
|
||||
<<-EOM
|
||||
Couldn't find Android NDK platform directories.
|
||||
Set ANDROID_PLATFORM environment variable or set :platform parameter
|
||||
EOM
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :params
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def home_path
|
||||
@home_path ||= Pathname(
|
||||
params[:ndk_home] ||
|
||||
ENV['ANDROID_NDK_HOME'] ||
|
||||
DEFAULT_NDK_HOMES.find{ |path| File.directory?(path) } ||
|
||||
raise(AndroidNDKHomeNotFound)
|
||||
)
|
||||
end
|
||||
def bin_gcc(command)
|
||||
case toolchain
|
||||
when :gcc then bin(command)
|
||||
when :clang
|
||||
command = command.to_s
|
||||
|
||||
def arch
|
||||
params.fetch(:arch){ DEFAULT_ARCH }
|
||||
end
|
||||
command = case arch
|
||||
when /armeabi/, /armeabi-v7a/ then 'arm-linux-androideabi-'
|
||||
when /arm64-v8a/ then 'aarch64-linux-android-'
|
||||
when /x86/ then 'i686-linux-android-'
|
||||
when /x86_64/ then 'x86_64-linux-android-'
|
||||
when /mips/ then 'mipsel-linux-android-'
|
||||
when /mips64/ then 'mips64el-linux-android-'
|
||||
end + command
|
||||
|
||||
def platform
|
||||
params.fetch(:platform){ DEFAULT_PLATFORM }
|
||||
end
|
||||
|
||||
def toolchain
|
||||
params.fetch(:toolchain){ DEFAULT_TOOLCHAIN }
|
||||
end
|
||||
|
||||
def toolchain_version
|
||||
params.fetch(:toolchain_version) do
|
||||
test = case toolchain
|
||||
when :gcc
|
||||
case arch
|
||||
when /armeabi/
|
||||
'arm-linux-androideabi-*'
|
||||
when /arm64/
|
||||
'aarch64-linux-android-*'
|
||||
when /mips64/
|
||||
'mips64el-linux-android-*'
|
||||
when /mips/
|
||||
'mipsel-linux-android-*'
|
||||
when /x86_64/
|
||||
'x86_64-*'
|
||||
when /x86/
|
||||
'x86-*'
|
||||
prefix = case arch
|
||||
when /armeabi/, /armeabi-v7a/ then 'arm-linux-androideabi-'
|
||||
when /arm64-v8a/ then 'aarch64-linux-android-'
|
||||
when /x86/ then 'x86-'
|
||||
when /x86_64/ then 'x86_64-'
|
||||
when /mips/ then 'mipsel-linux-android-'
|
||||
when /mips64/ then 'mips64el-linux-android-'
|
||||
end
|
||||
when :clang
|
||||
'llvm-*'
|
||||
end
|
||||
|
||||
Dir[home_path.join('toolchains',test)].map{|t| t.match(/-(\d+\.\d+)$/); $1.to_f }.max
|
||||
test = case arch
|
||||
when /armeabi/, /armeabi-v7a/ then 'arm-linux-androideabi-*'
|
||||
when /arm64-v8a/ then 'aarch64-linux-android-*'
|
||||
when /x86/ then 'x86-*'
|
||||
when /x86_64/ then 'x86_64-*'
|
||||
when /mips/ then 'mipsel-linux-android-*'
|
||||
when /mips64/ then 'mips64el-linux-android-*'
|
||||
end
|
||||
|
||||
gcc_toolchain_version = Dir[home_path.join('toolchains', test)].map{|t| t.match(/-(\d+\.\d+)$/); $1.to_f }.max
|
||||
gcc_toolchain_path = home_path.join('toolchains', prefix + gcc_toolchain_version.to_s, 'prebuilt', host_platform)
|
||||
gcc_toolchain_path.join('bin', command).to_s
|
||||
end
|
||||
end
|
||||
|
||||
def toolchain_path
|
||||
prefix = case toolchain
|
||||
when :clang then 'llvm-'
|
||||
when :gcc
|
||||
case arch
|
||||
when /armeabi/ then 'arm-linux-androideabi-'
|
||||
when /arm64/ then 'aarch64-linux-android-'
|
||||
when /x86_64/ then 'x86_64-'
|
||||
when /x86/ then 'x86-'
|
||||
when /mips64/ then 'mips64el-linux-android-'
|
||||
when /mips/ then 'mipsel-linux-android-'
|
||||
end
|
||||
end
|
||||
home_path.join('toolchains', prefix + toolchain_version.to_s, 'prebuilt', host_platform)
|
||||
end
|
||||
|
||||
def sysroot
|
||||
path = case arch
|
||||
when /armeabi/ then 'arch-arm'
|
||||
when /arm64/ then 'arch-arm64'
|
||||
when /x86_64/ then 'arch-x86_64'
|
||||
when /x86/ then 'arch-x86'
|
||||
when /mips64/ then 'arch-mips64'
|
||||
when /mips/ then 'arch-mips'
|
||||
end
|
||||
|
||||
home_path.join('platforms', platform, path).to_s
|
||||
end
|
||||
|
||||
def bin(command)
|
||||
command = command.to_s
|
||||
toolchain_path.join('bin', command).to_s
|
||||
end
|
||||
|
||||
if toolchain == :gcc
|
||||
command = case arch
|
||||
when /armeabi/ then 'arm-linux-androideabi-'
|
||||
when /arm64/ then 'aarch64-linux-android-'
|
||||
when /x86_64/ then 'x86_64-linux-android-'
|
||||
when /x86/ then 'i686-linux-android-'
|
||||
when /mips64/ then 'mips64el-linux-android-'
|
||||
when /mips/ then 'mipsel-linux-android-'
|
||||
end + command
|
||||
def home_path
|
||||
@home_path ||= Pathname(
|
||||
params[:ndk_home] ||
|
||||
ENV['ANDROID_NDK_HOME'] ||
|
||||
DEFAULT_NDK_HOMES.find { |path|
|
||||
path.gsub! '%LOCALAPPDATA%', ENV['LOCALAPPDATA'] || '%LOCALAPPDATA%'
|
||||
path.gsub! '\\', '/'
|
||||
File.directory?(path)
|
||||
} || raise(AndroidNDKHomeNotFound)
|
||||
)
|
||||
end
|
||||
|
||||
def toolchain
|
||||
@toolchain ||= params.fetch(:toolchain){ DEFAULT_TOOLCHAIN }
|
||||
end
|
||||
|
||||
def toolchain_path
|
||||
@toolchain_path ||= case toolchain
|
||||
when :clang
|
||||
home_path.join('toolchains', 'llvm' , 'prebuilt', host_platform)
|
||||
end
|
||||
end
|
||||
|
||||
def host_platform
|
||||
@host_platform ||= case RUBY_PLATFORM
|
||||
when /cygwin|mswin|mingw|bccwin|wince|emx/i
|
||||
path = home_path.join('toolchains', 'llvm' , 'prebuilt', 'windows*')
|
||||
Dir.glob(path.to_s){ |item|
|
||||
next if File.file?(item)
|
||||
path = Pathname(item)
|
||||
break
|
||||
}
|
||||
path.basename
|
||||
when /x86_64-darwin/i
|
||||
'darwin-x86_64'
|
||||
when /darwin/i
|
||||
'darwin-x86'
|
||||
when /x86_64-linux/i
|
||||
'linux-x86_64'
|
||||
when /linux/i
|
||||
'linux-x86'
|
||||
else
|
||||
raise NotImplementedError, "Unknown host platform (#{RUBY_PLATFORM})"
|
||||
end
|
||||
end
|
||||
|
||||
def arch
|
||||
@arch ||= (params[:arch] || ENV['ANDROID_ARCH'] || DEFAULT_ARCH).to_s
|
||||
end
|
||||
|
||||
def sysroot
|
||||
@sysroot ||= home_path.join('platforms', platform,
|
||||
case arch
|
||||
when /armeabi/, /armeabi-v7a/ then 'arch-arm'
|
||||
when /arm64-v8a/ then 'arch-arm64'
|
||||
when /x86/ then 'arch-x86'
|
||||
when /x86_64/ then 'arch-x86_64'
|
||||
when /mips/ then 'arch-mips'
|
||||
when /mips64/ then 'arch-mips64'
|
||||
end
|
||||
).to_s
|
||||
end
|
||||
|
||||
def platform
|
||||
if @platform === nil then
|
||||
@platform = params[:platform] || ENV['ANDROID_PLATFORM'] || nil
|
||||
if @platform === nil
|
||||
Dir.glob(home_path.join('platforms/android-*').to_s){ |item|
|
||||
next if File.file?(item)
|
||||
if @platform === nil
|
||||
@platform = Integer(item.rpartition('-')[2])
|
||||
else
|
||||
platform = Integer(item.rpartition('-')[2])
|
||||
@platform = platform > @platform ? platform : @platform
|
||||
end
|
||||
}
|
||||
if @platform === nil
|
||||
raise(PlatformDirNotFound)
|
||||
else
|
||||
@platform = "android-#{@platform}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
toolchain_path.join('bin',command).to_s
|
||||
if Integer(@platform.rpartition('-')[2]) < 21
|
||||
case arch
|
||||
when /arm64-v8a/, /x86_64/, /mips64/
|
||||
raise NotImplementedError, "Platform (#{@platform}) has no implementation for architecture (#{arch})"
|
||||
end
|
||||
end
|
||||
@platform
|
||||
end
|
||||
|
||||
def cc
|
||||
case toolchain
|
||||
when :gcc then bin(:gcc)
|
||||
when :clang then bin(:clang)
|
||||
when :clang then bin('clang')
|
||||
end
|
||||
end
|
||||
|
||||
def ar
|
||||
case toolchain
|
||||
when :clang then bin_gcc('ar')
|
||||
end
|
||||
end
|
||||
|
||||
def cflags
|
||||
flags = []
|
||||
|
||||
flags += %W(-D__android__ --sysroot="#{sysroot}")
|
||||
case toolchain
|
||||
when :gcc
|
||||
flags += %W(-ffunction-sections -funwind-tables -no-canonical-prefixes)
|
||||
flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}")
|
||||
case arch
|
||||
when /arm64/
|
||||
flags += %W(-fpic -fstack-protector-strong)
|
||||
when 'armeabi-v7a-hard'
|
||||
flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mhard-float -D_NDK_MATH_NO_SOFTFP=1 -mfpu=vfpv3-d16)
|
||||
when 'armeabi-v7a'
|
||||
flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16)
|
||||
when /arm/
|
||||
flags += %W(-fpic -fstack-protector-strong -march=armv5te -mtune=xscale -msoft-float)
|
||||
when /mips/
|
||||
flags += %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers)
|
||||
when /x86/
|
||||
flags += %W(-fstack-protector-strong)
|
||||
end
|
||||
when :clang
|
||||
end
|
||||
|
||||
flags
|
||||
end
|
||||
|
||||
def ld
|
||||
cc
|
||||
end
|
||||
|
||||
def ldflags
|
||||
flags = []
|
||||
case toolchain
|
||||
when :gcc
|
||||
flags += %W(-no-canonical-prefixes)
|
||||
flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}")
|
||||
flags += %W(-gcc-toolchain #{toolchain_path.to_s})
|
||||
case arch
|
||||
when 'armeabi-v7a-hard'
|
||||
flags += %W(-march=armv7-a -Wl,--fix-cortex-a8 -Wl,--no-warn-mismatch -lm_hard)
|
||||
when 'armeabi-v7a'
|
||||
flags += %W(-march=armv7-a -Wl,--fix-cortex-a8)
|
||||
when /armeabi/ then flags += %W(-target armv5te-none-linux-androideabi)
|
||||
when /armeabi-v7a/ then flags += %W(-target armv7-none-linux-androideabi)
|
||||
when /arm64-v8a/ then flags += %W(-target aarch64-none-linux-android)
|
||||
when /x86/ then flags += %W(-target i686-none-linux-android)
|
||||
when /x86_64/ then flags += %W(-target x86_64-none-linux-android)
|
||||
when /mips/ then flags += %W(-target mipsel-none-linux-android)
|
||||
when /mips64/ then flags += %W(-target mips64el-none-linux-android)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
flags
|
||||
end
|
||||
|
||||
def ar
|
||||
case toolchain
|
||||
when :gcc then bin(:ar)
|
||||
when :clang then bin('llvm-ar')
|
||||
end
|
||||
end
|
||||
|
||||
def host_platform
|
||||
case RUBY_PLATFORM
|
||||
when /cygwin|mswin|mingw|bccwin|wince|emx/i
|
||||
'windows'
|
||||
when /x86_64-darwin/i
|
||||
'darwin-x86_64'
|
||||
when /darwin/i
|
||||
'darwin-x86'
|
||||
when /x86_64-linux/i
|
||||
'linux-x86_64'
|
||||
when /linux/i
|
||||
'linux-x86'
|
||||
else
|
||||
raise NotImplementedError, "Unknown host platform (#{RUBY_PLATFORM})"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
MRuby::Toolchain.new(:android) do |conf, params|
|
||||
ndk = MRuby::Toolchain::Android.new(params)
|
||||
android = MRuby::Toolchain::Android.new(params)
|
||||
|
||||
toolchain ndk.toolchain
|
||||
toolchain android.toolchain
|
||||
|
||||
[conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc|
|
||||
cc.command = ndk.cc
|
||||
cc.flags = ndk.cflags
|
||||
cc.command = android.cc
|
||||
cc.flags = android.cflags
|
||||
end
|
||||
conf.linker.command = ndk.ld
|
||||
conf.linker.flags = ndk.ldflags
|
||||
conf.archiver.command = ndk.ar
|
||||
end
|
||||
|
||||
conf.archiver.command = android.ar
|
||||
conf.linker.command = android.cc
|
||||
conf.linker.flags = []
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user