Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AArch64 Android support #13065

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
#
# ```terminal-session
# $ find src/lib_c -maxdepth 1 -mindepth 1 -type d -printf '%P\n' | sort
# aarch64-android
# aarch64-darwin
# aarch64-linux-gnu
# aarch64-linux-musl
# arm-linux-gnueabihf
# i386-linux-gnu
# i386-linux-musl
# wasm32-wasi
# x86_64-darwin
# x86_64-dragonfly
# x86_64-freebsd
Expand Down Expand Up @@ -43,6 +45,7 @@ jobs:
fail-fast: false
matrix:
target:
- aarch64-linux-android
- aarch64-darwin
- arm-linux-gnueabihf
- i386-linux-gnu
Expand Down
12 changes: 9 additions & 3 deletions spec/compiler/loader/unix_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ describe Crystal::Loader do
end

it "parses file paths" do
exc = expect_raises(Crystal::Loader::LoadError, /no such file|image not found|cannot open/i) do
exc = expect_raises(Crystal::Loader::LoadError, /no such file|not found|cannot open/i) do
Crystal::Loader.parse(["foobar.o"], search_paths: [] of String)
end
exc.message.should contain File.join(Dir.current, "foobar.o")
exc = expect_raises(Crystal::Loader::LoadError, /no such file|image not found|cannot open/i) do
exc = expect_raises(Crystal::Loader::LoadError, /no such file|not found|cannot open/i) do
Crystal::Loader.parse(["-l", "foo/bar.o"], search_paths: [] of String)
end
exc.message.should contain File.join(Dir.current, "foo", "bar.o")
Expand All @@ -52,7 +52,11 @@ describe Crystal::Loader do
search_paths.should eq ["/usr/lib", "/usr/local/lib"]
{% else %}
search_paths[0, 2].should eq ["ld1", "ld2"]
search_paths[-2..].should eq ["/lib", "/usr/lib"]
{% if flag?(:android) %}
search_paths[-2..].should eq ["/vendor/lib", "/system/lib"]
{% else %}
search_paths[-2..].should eq ["/lib", "/usr/lib"]
{% end %}
{% end %}
end
end
Expand All @@ -63,6 +67,8 @@ describe Crystal::Loader do
{% if flag?(:darwin) %}
search_paths[0, 2].should eq ["ld1", "ld2"]
search_paths[-2..].should eq ["/usr/lib", "/usr/local/lib"]
{% elsif flag?(:android) %}
search_paths[-2..].should eq ["/vendor/lib", "/system/lib"]
{% else %}
search_paths[-2..].should eq ["/lib", "/usr/lib"]
{% end %}
Expand Down
21 changes: 12 additions & 9 deletions spec/std/file_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,20 @@ describe "File" do
end
end

describe "link" do
it "creates a hard link" do
with_tempfile("hard_link_source.txt", "hard_link_target.txt") do |in_path, out_path|
File.write(in_path, "")
File.link(in_path, out_path)
File.exists?(out_path).should be_true
File.symlink?(out_path).should be_false
File.same?(in_path, out_path).should be_true
# hard links are practically unavailable on Android
{% unless flag?(:android) %}
describe "link" do
it "creates a hard link" do
with_tempfile("hard_link_source.txt", "hard_link_target.txt") do |in_path, out_path|
File.write(in_path, "")
File.link(in_path, out_path)
File.exists?(out_path).should be_true
File.symlink?(out_path).should be_false
File.same?(in_path, out_path).should be_true
end
end
end
end
{% end %}

describe "same?" do
it "compares following symlinks only if requested" do
Expand Down
101 changes: 52 additions & 49 deletions spec/std/file_utils_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -549,75 +549,78 @@ describe "FileUtils" do
end
end

describe ".ln" do
it "creates a hardlink" do
with_tempfile("ln_src", "ln_dst") do |path1, path2|
test_with_string_and_path(path1, path2) do |arg1, arg2|
FileUtils.touch(path1)
FileUtils.ln(arg1, arg2)
File.exists?(path2).should be_true
File.symlink?(path2).should be_false
FileUtils.rm_rf([path1, path2])
# hard links are practically unavailable on Android
{% unless flag?(:android) %}
describe ".ln" do
it "creates a hardlink" do
with_tempfile("ln_src", "ln_dst") do |path1, path2|
test_with_string_and_path(path1, path2) do |arg1, arg2|
FileUtils.touch(path1)
FileUtils.ln(arg1, arg2)
File.exists?(path2).should be_true
File.symlink?(path2).should be_false
FileUtils.rm_rf([path1, path2])
end
end
end
end

it "creates a hardlink inside a destination dir" do
with_tempfile("ln_src", "ln_dst_dir") do |path1, path2|
path2 += File::SEPARATOR
path3 = File.join(path2, File.basename(path1))
test_with_string_and_path(path1, path2) do |arg1, arg2|
FileUtils.touch(path1)
FileUtils.mkdir(path2)
FileUtils.ln(arg1, arg2)
File.exists?(path3).should be_true
File.symlink?(path3).should be_false
FileUtils.rm_rf([path1, path2])
it "creates a hardlink inside a destination dir" do
with_tempfile("ln_src", "ln_dst_dir") do |path1, path2|
path2 += File::SEPARATOR
path3 = File.join(path2, File.basename(path1))
test_with_string_and_path(path1, path2) do |arg1, arg2|
FileUtils.touch(path1)
FileUtils.mkdir(path2)
FileUtils.ln(arg1, arg2)
File.exists?(path3).should be_true
File.symlink?(path3).should be_false
FileUtils.rm_rf([path1, path2])
end
end
end
end

it "creates multiple hardlinks inside a destination dir" do
with_tempfile("ln_src_1", "ln_src_2", "ln_src_3", "ln_dst_dir") do |path1, path2, path3, dir_path|
paths = [path1, path2, path3]
dir_path += File::SEPARATOR
test_with_string_and_path(path1, path2, path3, dir_path) do |arg1, arg2, arg3, arg4|
paths.each { |path| FileUtils.touch(path) }
FileUtils.mkdir(dir_path)
FileUtils.ln([arg1, arg2, arg3], arg4)
it "creates multiple hardlinks inside a destination dir" do
with_tempfile("ln_src_1", "ln_src_2", "ln_src_3", "ln_dst_dir") do |path1, path2, path3, dir_path|
paths = [path1, path2, path3]
dir_path += File::SEPARATOR
test_with_string_and_path(path1, path2, path3, dir_path) do |arg1, arg2, arg3, arg4|
paths.each { |path| FileUtils.touch(path) }
FileUtils.mkdir(dir_path)
FileUtils.ln([arg1, arg2, arg3], arg4)

paths.each do |path|
link_path = File.join(dir_path, File.basename(path))
File.exists?(link_path).should be_true
File.symlink?(link_path).should be_false
paths.each do |path|
link_path = File.join(dir_path, File.basename(path))
File.exists?(link_path).should be_true
File.symlink?(link_path).should be_false
end
FileUtils.rm_rf(dir_path)
end
FileUtils.rm_rf(dir_path)
end
end
end

it "fails with a nonexistent source" do
with_tempfile("ln_src_missing", "ln_dst_missing") do |path1, path2|
test_with_string_and_path(path1, path2) do |arg1, arg2|
expect_raises(File::NotFoundError, "Error creating link: '#{path1.inspect_unquoted}' -> '#{path2.inspect_unquoted}'") do
FileUtils.ln(arg1, arg2)
it "fails with a nonexistent source" do
with_tempfile("ln_src_missing", "ln_dst_missing") do |path1, path2|
test_with_string_and_path(path1, path2) do |arg1, arg2|
expect_raises(File::NotFoundError, "Error creating link: '#{path1.inspect_unquoted}' -> '#{path2.inspect_unquoted}'") do
FileUtils.ln(arg1, arg2)
end
end
end
end
end

it "fails with an extant destination" do
with_tempfile("ln_src", "ln_dst_exists") do |path1, path2|
FileUtils.touch([path1, path2])
it "fails with an extant destination" do
with_tempfile("ln_src", "ln_dst_exists") do |path1, path2|
FileUtils.touch([path1, path2])

test_with_string_and_path(path1, path2) do |arg1, arg2|
expect_raises(File::AlreadyExistsError, "Error creating link: '#{path1.inspect_unquoted}' -> '#{path2.inspect_unquoted}'") do
FileUtils.ln(arg1, arg2)
test_with_string_and_path(path1, path2) do |arg1, arg2|
expect_raises(File::AlreadyExistsError, "Error creating link: '#{path1.inspect_unquoted}' -> '#{path2.inspect_unquoted}'") do
FileUtils.ln(arg1, arg2)
end
end
end
end
end
end
{% end %}

describe ".ln_s" do
it "creates a symlink" do
Expand Down
2 changes: 1 addition & 1 deletion spec/std/process_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ describe Process do
{% end %}

describe ".chroot" do
{% if flag?(:unix) %}
{% if flag?(:unix) && !flag?(:android) %}
it "raises when unprivileged" do
status, output, _ = compile_and_run_source <<-'CRYSTAL'
begin
Expand Down
12 changes: 11 additions & 1 deletion spec/std/socket/tcp_server_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ describe TCPServer, tags: "network" do
error = expect_raises(Socket::Addrinfo::Error) do
TCPServer.new(address, -12)
end
error.os_error.should eq({% if flag?(:linux) %}Errno.new(LibC::EAI_SERVICE){% elsif flag?(:win32) %}WinError::WSATYPE_NOT_FOUND{% else %}Errno.new(LibC::EAI_NONAME){% end %})
error.os_error.should eq({% if flag?(:win32) %}
WinError::WSATYPE_NOT_FOUND
{% elsif flag?(:linux) && !flag?(:android) %}
Errno.new(LibC::EAI_SERVICE)
{% else %}
Errno.new(LibC::EAI_NONAME)
{% end %})
end

describe "reuse_port" do
Expand Down Expand Up @@ -91,6 +97,8 @@ describe TCPServer, tags: "network" do
# FIXME: Resolve special handling for win32. The error code handling should be identical.
{% if flag?(:win32) %}
[WinError::WSAHOST_NOT_FOUND, WinError::WSATRY_AGAIN].should contain err.os_error
{% elsif flag?(:android) %}
err.os_error.should eq(Errno.new(LibC::EAI_NODATA))
{% else %}
[Errno.new(LibC::EAI_NONAME), Errno.new(LibC::EAI_AGAIN)].should contain err.os_error
{% end %}
Expand All @@ -103,6 +111,8 @@ describe TCPServer, tags: "network" do
# FIXME: Resolve special handling for win32. The error code handling should be identical.
{% if flag?(:win32) %}
[WinError::WSAHOST_NOT_FOUND, WinError::WSATRY_AGAIN].should contain err.os_error
{% elsif flag?(:android) %}
err.os_error.should eq(Errno.new(LibC::EAI_NODATA))
{% else %}
[Errno.new(LibC::EAI_NONAME), Errno.new(LibC::EAI_AGAIN)].should contain err.os_error
{% end %}
Expand Down
12 changes: 11 additions & 1 deletion spec/std/socket/tcp_socket_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ describe TCPSocket, tags: "network" do
error = expect_raises(Socket::Addrinfo::Error) do
TCPSocket.new(address, -12)
end
error.os_error.should eq({% if flag?(:win32) %}WinError::WSATYPE_NOT_FOUND{% elsif flag?(:linux) %}Errno.new(LibC::EAI_SERVICE){% else %}Errno.new(LibC::EAI_NONAME){% end %})
error.os_error.should eq({% if flag?(:win32) %}
WinError::WSATYPE_NOT_FOUND
{% elsif flag?(:linux) && !flag?(:android) %}
Errno.new(LibC::EAI_SERVICE)
{% else %}
Errno.new(LibC::EAI_NONAME)
{% end %})
end

it "raises when port is zero" do
Expand Down Expand Up @@ -70,6 +76,8 @@ describe TCPSocket, tags: "network" do
# FIXME: Resolve special handling for win32. The error code handling should be identical.
{% if flag?(:win32) %}
[WinError::WSAHOST_NOT_FOUND, WinError::WSATRY_AGAIN].should contain err.os_error
{% elsif flag?(:android) %}
err.os_error.should eq(Errno.new(LibC::EAI_NODATA))
{% else %}
[Errno.new(LibC::EAI_NONAME), Errno.new(LibC::EAI_AGAIN)].should contain err.os_error
{% end %}
Expand All @@ -82,6 +90,8 @@ describe TCPSocket, tags: "network" do
# FIXME: Resolve special handling for win32. The error code handling should be identical.
{% if flag?(:win32) %}
[WinError::WSAHOST_NOT_FOUND, WinError::WSATRY_AGAIN].should contain err.os_error
{% elsif flag?(:android) %}
err.os_error.should eq(Errno.new(LibC::EAI_NODATA))
{% else %}
[Errno.new(LibC::EAI_NONAME), Errno.new(LibC::EAI_AGAIN)].should contain err.os_error
{% end %}
Expand Down
2 changes: 1 addition & 1 deletion spec/std/static_array_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ describe "StaticArray" do
# StaticArray#sort_by and #sort_by! don't compile on aarch64-darwin and
# aarch64-linux-musl due to a codegen error caused by LLVM < 13.0.0.
# See https://github.com/crystal-lang/crystal/issues/11358 for details.
{% unless compare_versions(Crystal::LLVM_VERSION, "13.0.0") < 0 && flag?(:aarch64) && (flag?(:musl) || flag?(:darwin)) %}
{% unless compare_versions(Crystal::LLVM_VERSION, "13.0.0") < 0 && flag?(:aarch64) && (flag?(:musl) || flag?(:darwin) || flag?(:android)) %}
describe "{{ sort }}_by" do
it "sorts by" do
a = StaticArray["foo", "a", "hello"]
Expand Down
14 changes: 8 additions & 6 deletions spec/std/system/group_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
require "spec"
require "system/group"

GROUP_NAME = {{ `id -gn`.stringify.chomp }}
GROUP_ID = {{ `id -g`.stringify.chomp }}
GROUP_NAME = {{ `id -gn`.stringify.chomp }}
GROUP_ID = {{ `id -g`.stringify.chomp }}
INVALID_GROUP_NAME = "this_group_does_not_exist"
INVALID_GROUP_ID = {% if flag?(:android) %}"8888"{% else %}"1234567"{% end %}

describe System::Group do
describe ".find_by(*, name)" do
Expand All @@ -18,7 +20,7 @@ describe System::Group do

it "raises on nonexistent group" do
expect_raises System::Group::NotFoundError, "No such group" do
System::Group.find_by(name: "this_group_does_not_exist")
System::Group.find_by(name: INVALID_GROUP_NAME)
end
end
end
Expand All @@ -34,7 +36,7 @@ describe System::Group do

it "raises on nonexistent group name" do
expect_raises System::Group::NotFoundError, "No such group" do
System::Group.find_by(id: "1234567")
System::Group.find_by(id: INVALID_GROUP_ID)
end
end
end
Expand All @@ -49,7 +51,7 @@ describe System::Group do
end

it "returns nil on nonexistent group" do
group = System::Group.find_by?(name: "this_group_does_not_exist")
group = System::Group.find_by?(name: INVALID_GROUP_NAME)
group.should eq(nil)
end
end
Expand All @@ -64,7 +66,7 @@ describe System::Group do
end

it "returns nil on nonexistent group id" do
group = System::Group.find_by?(id: "1234567")
group = System::Group.find_by?(id: INVALID_GROUP_ID)
group.should eq(nil)
end
end
Expand Down
14 changes: 8 additions & 6 deletions spec/std/system/user_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
require "spec"
require "system/user"

USER_NAME = {{ `id -un`.stringify.chomp }}
USER_ID = {{ `id -u`.stringify.chomp }}
USER_NAME = {{ `id -un`.stringify.chomp }}
USER_ID = {{ `id -u`.stringify.chomp }}
INVALID_USER_NAME = "this_user_does_not_exist"
INVALID_USER_ID = {% if flag?(:android) %}"8888"{% else %}"1234567"{% end %}

describe System::User do
describe ".find_by(*, name)" do
Expand All @@ -18,7 +20,7 @@ describe System::User do

it "raises on a nonexistent user" do
expect_raises System::User::NotFoundError, "No such user" do
System::User.find_by(name: "this_user_does_not_exist")
System::User.find_by(name: INVALID_USER_NAME)
end
end
end
Expand All @@ -34,7 +36,7 @@ describe System::User do

it "raises on nonexistent user id" do
expect_raises System::User::NotFoundError, "No such user" do
System::User.find_by(id: "1234567")
System::User.find_by(id: INVALID_USER_ID)
end
end
end
Expand All @@ -49,7 +51,7 @@ describe System::User do
end

it "returns nil on nonexistent user" do
user = System::User.find_by?(name: "this_user_does_not_exist")
user = System::User.find_by?(name: INVALID_USER_NAME)
user.should eq(nil)
end
end
Expand All @@ -64,7 +66,7 @@ describe System::User do
end

it "returns nil on nonexistent user id" do
user = System::User.find_by?(id: "1234567")
user = System::User.find_by?(id: INVALID_USER_ID)
user.should eq(nil)
end
end
Expand Down
Loading