Skip to content

[android] Add support for natively building on Android #23208

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

Merged
merged 1 commit into from
Aug 5, 2019
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
22 changes: 18 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,13 @@ if(SWIFT_HOST_VARIANT_SDK)
set(SWIFT_HOST_VARIANT_SDK_default "${SWIFT_HOST_VARIANT_SDK}")
else()
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(SWIFT_HOST_VARIANT_SDK_default "LINUX")
# CMake on an Android host sets this to Linux, so check for the ANDROID_DATA
# environment variable to see if we're building on Android.
if(NOT "$ENV{ANDROID_DATA}" STREQUAL "")
set(SWIFT_HOST_VARIANT_SDK_default "ANDROID")
else()
set(SWIFT_HOST_VARIANT_SDK_default "LINUX")
endif()
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
set(SWIFT_HOST_VARIANT_SDK_default "FREEBSD")
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
Expand All @@ -613,6 +619,7 @@ else()
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Haiku")
set(SWIFT_HOST_VARIANT_SDK_default "HAIKU")
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
# CMAKE_SYSTEM_NAME might be set this way when cross-compiling to Android.
set(SWIFT_HOST_VARIANT_SDK_default "ANDROID")
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
set(SWIFT_HOST_VARIANT_SDK_default "OSX")
Expand Down Expand Up @@ -677,7 +684,7 @@ endif()

# FIXME: the parameters we specify in SWIFT_SDKS are lacking architecture specifics,
# so we need to hard-code it. For example, the SDK for Android is just 'ANDROID',
# which we assume below to be armv7.
# and we have to specify SWIFT_SDK_ANDROID_ARCHITECTURES separately.
# The iOS SDKs all have their architectures hardcoded because they are just specified by name (e.g. 'IOS' or 'WATCHOS').
# We can't cross-compile the standard library for another linux architecture,
# because the SDK list would just be 'LINUX' and we couldn't disambiguate it from the host.
Expand Down Expand Up @@ -739,9 +746,16 @@ elseif("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "HAIKU")
elseif("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "ANDROID")

set(SWIFT_HOST_VARIANT "android" CACHE STRING
"Deployment OS for Swift host tools (the compiler) [android].")
"Deployment OS for Swift host tools (the compiler) [android]")

configure_sdk_unix("Android" "${SWIFT_HOST_VARIANT_ARCH}")
set(SWIFT_ANDROID_NATIVE_SYSROOT "/data/data/com.termux/files" CACHE STRING
"Path to Android sysroot, default initialized to the Termux app's layout")

if("${SWIFT_SDK_ANDROID_ARCHITECTURES}" STREQUAL "")
set(SWIFT_SDK_ANDROID_ARCHITECTURES ${SWIFT_HOST_VARIANT_ARCH})
endif()

configure_sdk_unix("Android" "${SWIFT_SDK_ANDROID_ARCHITECTURES}")
set(SWIFT_PRIMARY_VARIANT_SDK_default "${SWIFT_HOST_VARIANT_SDK}")
set(SWIFT_PRIMARY_VARIANT_ARCH_default "${SWIFT_HOST_VARIANT_ARCH}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's another configure_sdk_unix("Android"… below around L774.

If you are cross-compiling the host tools, wouldn’t this branch and the branch below be hit? Wouldn’t that configure twice the same SDK? That probably will create duplicated targets, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure if I needed to disable that second configure_sdk_unix when cross-compiling and SWIFT_HOST_VARIANT is "android," as I haven't cross-compiled the host tools for Android yet, so I punted on it for now. I will submit a separate pull when I actually get the Swift host tools cross-compiled for Android.

This pull is primarily about natively compiling this project on an Android host and though it tries to anticipate that cross-compilation pull and lay some groundwork, because they have some CMake config in common, this CMake config will probably require further patches then.


Expand Down
30 changes: 13 additions & 17 deletions cmake/modules/AddSwift.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ function(_add_variant_c_compile_link_flags)
# lld can handle targeting the android build. However, if lld is not
# enabled, then fallback to the linker included in the android NDK.
if(NOT SWIFT_ENABLE_LLD_LINKER)
list(APPEND result "-B" "${SWIFT_SDK_ANDROID_ARCH_${CFLAGS_ARCH}_NDK_PREBUILT_PATH}/${SWIFT_SDK_ANDROID_ARCH_${CFLAGS_ARCH}_NDK_TRIPLE}/bin")
swift_android_tools_path(${CFLAGS_ARCH} tools_path)
list(APPEND result "-B" "${tools_path}")
endif()
endif()

Expand Down Expand Up @@ -482,22 +483,9 @@ function(_add_variant_link_flags)
# We need to add the math library, which is linked implicitly by libc++
list(APPEND result "-lm")

if("${LFLAGS_ARCH}" MATCHES armv7)
set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a")
elseif("${LFLAGS_ARCH}" MATCHES aarch64)
set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/arm64-v8a")
elseif("${LFLAGS_ARCH}" MATCHES i686)
set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/x86")
elseif("${LFLAGS_ARCH}" MATCHES x86_64)
set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/x86_64")
else()
message(SEND_ERROR "unknown architecture (${LFLAGS_ARCH}) for android")
endif()

# link against the custom C++ library
list(APPEND link_libraries
${android_libcxx_path}/libc++abi.a
${android_libcxx_path}/libc++_shared.so)
swift_android_cxx_libraries_for_arch(${LFLAGS_ARCH} cxx_link_libraries)
list(APPEND link_libraries ${cxx_link_libraries})

# link against the ICU libraries
list(APPEND link_libraries
Expand Down Expand Up @@ -1104,7 +1092,7 @@ function(_add_swift_library_single target name)
set_target_properties("${target}"
PROPERTIES
INSTALL_NAME_DIR "${install_name_dir}")
elseif("${SWIFTLIB_SINGLE_SDK}" STREQUAL "LINUX" AND NOT "${SWIFTLIB_SINGLE_SDK}" STREQUAL "ANDROID")
elseif("${SWIFTLIB_SINGLE_SDK}" STREQUAL "LINUX")
set_target_properties("${target}"
PROPERTIES
INSTALL_RPATH "$ORIGIN:/usr/lib/swift/linux")
Expand All @@ -1116,6 +1104,14 @@ function(_add_swift_library_single target name)
# CMake generates incorrect rule `$SONAME_FLAG $INSTALLNAME_DIR$SONAME` for Android build on macOS cross-compile host.
# Proper linker flags constructed manually. See below variable `swiftlib_link_flags_all`.
set_target_properties("${target}" PROPERTIES NO_SONAME TRUE)
# Only set the install RPATH if cross-compiling the host tools, in which
# case both the NDK and Sysroot paths must be set.
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "" AND
NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
set_target_properties("${target}"
PROPERTIES
INSTALL_RPATH "$ORIGIN")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just updated to remove the native sysroot's library directory from this rpath list, as the clang in the new Termux environment adds it already. Once there's a Swift Termux package and it's decided where it will store libraries, I'll probably add that path here.

endif()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things:

  • Please don’t apply RPATH when building with the NDK. Let's try not to change the behaviour when cross-compiling. Also, I don't think the RPATH for cross-compiling can refer to ${SWIFT_ANDROID_NATIVE_SYSROOT}, because that variable will be empty, and /usr/lib doesn't exist in Android (also, the system library paths should not be added to the RPATH, because they are already searched anyway).
  • I'm very bad with logic, but I don’t think this branch is going to be taken at all, writing it in a more common language, you are doing if (swift_android_ndk_path != "" and swift_android_native_sysroot != ""), that is, when both SWIFT_ANDROID_NDK_PATH and SWIFT_ANDROID_NATIVE_SYSROOT are set to something. I would recommend changing the check to only check for the native sysroot.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the comment I had written above in this file: this is only going to kick in when the Android NDK is being used to cross-compile the host tools, ie the Swift compiler itself, to run on an Android host, ie Termux. As such, it shouldn't affect you when cross-compiling the Swift runtime/stdlib nor will it add the Android system library paths you mention.

If it wasn't clear already, here's the full Boolean truth table for how SWIFT_ANDROID_NDK_PATH and SWIFT_ANDROID_NATIVE_SYSROOT are used throughout this pull:
Both unset - Android is not being used
only NDK path set - cross-compiling the runtime/stdlib alone
only Sysroot path set - natively compiling the compiler and runtime/stdlib on an Android host, ie in the Termux app like I've been doing
both NDK and Sysroot paths set - cross-compiling both the host tools and runtime/stdlib for an Android host

I only want this install rpath set for that last case, which is how the official Termux packages are built, which is why I check that both are set. Since you only care about the second case, where you don't set the new Android Sysroot path I added for Android host tools, this shouldn't affect you at all.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide a link to some document about how Termux packages are supposed to be built? I find some minimal documentation in the wiki, but nothing related to rpath. If I understand correctly, they are trying to move away from LD_LIBRARY_PATH to use RUNPATH, which (IMO) is not the right thing to do, but if you can point me to any documentation, I will try to understand.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The move to rpath is pretty new, I think the best doc is the README link I gave you above, along with the github issue it links to:

It is highly recommended to try to execute programs without
LD_LIBRARY_PATH set. Most of them should continue to run since
DT_RUNPATH field compiled-in ELF binary is used. Though, some
programs are not working due to missing DT_RUNPATH, please
check list in the related issue

That rpath github issue was just closed yesterday, saying that it's all working now.

That said, I'm mainly adding this rpath because that's what this project does for other OS's, as Saleem noted above, though of course Termux is moving to rpath also. As such, this INSTALL_RPATH patch is done speculatively, as I have not cross-compiled the Swift host tools yet.

endif()

set_target_properties("${target}" PROPERTIES BUILD_WITH_INSTALL_RPATH YES)
Expand Down
9 changes: 7 additions & 2 deletions cmake/modules/AddSwiftUnittests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,14 @@ function(add_swift_unittest test_dirname)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
set_property(TARGET "${test_dirname}" APPEND_STRING PROPERTY
LINK_FLAGS " -Xlinker -rpath -Xlinker ${SWIFT_LIBRARY_OUTPUT_INTDIR}/swift/macosx")
elseif("${SWIFT_HOST_VARIANT}" STREQUAL "android")
swift_android_lib_for_arch(${SWIFT_HOST_VARIANT_ARCH} android_system_libs)
set_property(TARGET "${test_dirname}" APPEND PROPERTY LINK_DIRECTORIES
"${android_system_libs}")
set_property(TARGET "${test_dirname}" APPEND PROPERTY LINK_LIBRARIES "log")
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use CMAKE_SYSTEM_NAME and not SWIFT_HOST_VARIANT here? The two seem to be inconsistently used in some places.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CMAKE_SYSTEM_NAME is the name of the system we are targeting. That should be preferred to enable cross-compilation. The SWIFT_HOST_VARIANT is the target for the runtime components IIRC, but, we should be aiming to reduce that usage (as it prevents cross-compilation).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the docs say SWIFT_HOST_VARIANT is the "Deployment OS for Swift host tools (the compiler)" and it is used that way in a few places. However, counting it up now, I see CMAKE_SYSTEM_NAME used much more in this repo.

A decision probably needs to be made on whether SWIFT_HOST_VARIANT should be defined at all, as right now its basically just an alias for CMAKE_SYSTEM_NAME. This pull actually tries to use SWIFT_HOST_VARIANT though, since CMAKE_HOST_SYSTEM_NAME/CMAKE_SYSTEM_NAME are set to "Linux" by default on Android.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CMAKE_SYSTEM_NAME should/must be Android: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android. Switching to CMAKE_SYSTEM_NAME seems like an improvement.

Copy link
Member Author

@finagolfin finagolfin Mar 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First off, I'm still not sure if you understand exactly what I'm doing here, take a look at my latest long comment answering @drodriguez's questions. That CMake manual link you give is irrelevant because it's about cross-compiling with the NDK, which I'm not using here.

As for using CMAKE_SYSTEM_NAME instead to cross-compile the host tools, it is a possibility. However, someone, presumably @gribozavr in 6670bb7, chose to use SWIFT_HOST_VARIANT_SDK/SWIFT_HOST_VARIANT, presumably to give this project more flexibility in how it names and deals with the host OS in CMake.

I'm simply following that precedent by using SWIFT_HOST_VARIANT more. For example, build-script always sets the SWIFT_HOST_VARIANT* variables and never CMAKE_SYSTEM_NAME.

However, both are being used all over this project's CMake config now, so it will break if you actually try to cross-compile the host tools for another OS someday, unless you set both CMAKE_SYSTEM_NAME and SWIFT_HOST_VARIANT*. 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@compnerd: I looked a little to setting CMAKE_SYSTEM_NAME to Android, and it will work for cross-compiling with the NDK, but it might not work with the Termux environment. It supposes that you are using the NDK, so the search paths might not work for what they want to do.

This is why I’m asking to try to use the NDK itself inside Termux. It will make the changes minimal.

Copy link
Member Author

@finagolfin finagolfin Mar 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@drodriguez,

I looked a little to setting CMAKE_SYSTEM_NAME to Android, and it will work for cross-compiling with the NDK, but it might not work with the Termux environment.

Can you elaborate a bit more on what you did? What did you set the SWIFT_HOST_VARIANT_SDK and SWIFT_HOST_VARIANT to when you set the CMAKE_SYSTEM_NAME to Android? Given that this project doesn't use the CMake Android toolchain that @compnerd linked and rolls its own NDK support, I suspect the two will clash and not actually work. Maybe CMake didn't error out, but I suspect it would at least fail when building.

It supposes that you are using the NDK, so the search paths might not work for what they want to do.

Depending on what you set the SWIFT_HOST_VARIANT* variables to and the aforementioned potential conflicts with CMake's built-in Android toolchain config, I suspect it wouldn't work for you with the NDK either.

This is why I’m asking to try to use the NDK itself inside Termux. It will make the changes minimal.

I think they're already minimal enough. Take a look at my latest commit, which makes it easy to tell when the NDK is being used. Since you understandably care much more about the NDK paths being easy to follow, I think the latest iteration of this pull does that.

set_property(TARGET "${test_dirname}" APPEND_STRING PROPERTY
LINK_FLAGS " -latomic")
set_property(TARGET "${test_dirname}" APPEND PROPERTY LINK_LIBRARIES
"atomic")
endif()

find_program(LDLLD_PATH "ld.lld")
Expand Down
102 changes: 84 additions & 18 deletions cmake/modules/SwiftAndroidSupport.cmake
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
function(swift_android_libcxx_include_paths var)
set(${var}
"${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/include"
"${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++abi/include"
PARENT_SCOPE)
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
set(${var}
"${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/include"
"${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++abi/include"
PARENT_SCOPE)
elseif(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
set(${var}
"${SWIFT_ANDROID_NATIVE_SYSROOT}/usr/include/c++/v1"
PARENT_SCOPE)
else()
message(SEND_ERROR "Couldn't set libc++ include paths for Android")
endif()
endfunction()

function(swift_android_include_for_arch arch var)
set(paths)
list(APPEND paths
"${SWIFT_ANDROID_NDK_PATH}/sources/android/support/include"
"${SWIFT_ANDROID_NDK_PATH}/sysroot/usr/include"
"${SWIFT_ANDROID_NDK_PATH}/sysroot/usr/include/${SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE}")
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
list(APPEND paths
"${SWIFT_ANDROID_NDK_PATH}/sources/android/support/include"
"${SWIFT_ANDROID_NDK_PATH}/sysroot/usr/include"
"${SWIFT_ANDROID_NDK_PATH}/sysroot/usr/include/${SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE}")
elseif(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
list(APPEND paths
"${SWIFT_ANDROID_NATIVE_SYSROOT}/usr/include"
"${SWIFT_ANDROID_NATIVE_SYSROOT}/usr/include/${SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE}")
else()
message(SEND_ERROR "Couldn't set ${arch} include paths for Android")
endif()
set(${var} ${paths} PARENT_SCOPE)
endfunction()

Expand All @@ -19,18 +35,68 @@ function(swift_android_lib_for_arch arch var)
set(_host "${SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE}")

set(paths)
if(arch STREQUAL armv7)
list(APPEND paths "${_prebuilt}/${_host}/lib/armv7-a")
elseif(arch STREQUAL aarch64)
list(APPEND paths "${_prebuilt}/${_host}/lib64")
elseif(arch STREQUAL i686)
list(APPEND paths "${_prebuilt}/${_host}/lib")
elseif(arch STREQUAL x86_64)
list(APPEND paths "${_prebuilt}/${_host}/lib64")
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
if(arch STREQUAL armv7)
list(APPEND paths "${_prebuilt}/${_host}/lib/armv7-a")
elseif(arch STREQUAL aarch64)
list(APPEND paths "${_prebuilt}/${_host}/lib64")
elseif(arch STREQUAL i686)
list(APPEND paths "${_prebuilt}/${_host}/lib")
elseif(arch STREQUAL x86_64)
list(APPEND paths "${_prebuilt}/${_host}/lib64")
else()
message(SEND_ERROR "unknown architecture (${arch}) for android")
endif()
list(APPEND paths "${_prebuilt}/lib/gcc/${_host}/${SWIFT_ANDROID_NDK_GCC_VERSION}.x")
elseif(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
list(APPEND paths "${SWIFT_ANDROID_NATIVE_SYSROOT}/usr/lib")
if("${arch}" MATCHES armv7)
list(APPEND paths "/system/lib")
elseif("${arch}" MATCHES aarch64)
list(APPEND paths "/system/lib64")
else()
message(SEND_ERROR "unknown architecture (${arch}) when compiling for Android host")
endif()
else()
message(SEND_ERROR "unknown architecture (${arch}) for android")
message(SEND_ERROR "Couldn't set ${arch} library paths for Android")
endif()
list(APPEND paths "${_prebuilt}/lib/gcc/${_host}/${SWIFT_ANDROID_NDK_GCC_VERSION}.x")

set(${var} ${paths} PARENT_SCOPE)
endfunction()

function(swift_android_tools_path arch path_var_name)
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
set(${path_var_name} "${SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_PREBUILT_PATH}/${SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE}/bin" PARENT_SCOPE)
elseif(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
set(${path_var_name} "${SWIFT_ANDROID_NATIVE_SYSROOT}/usr/bin" PARENT_SCOPE)
else()
message(SEND_ERROR "Couldn't set ${arch} tools path for Android")
endif()
endfunction ()

function(swift_android_cxx_libraries_for_arch arch libraries_var_name)
set(link_libraries)
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
if("${arch}" MATCHES armv7)
set(cxx_arch armeabi-v7a)
elseif("${arch}" MATCHES aarch64)
set(cxx_arch arm64-v8a)
elseif("${arch}" MATCHES i686)
set(cxx_arch x86)
elseif("${arch}" MATCHES x86_64)
set(cxx_arch x86_64)
else()
message(SEND_ERROR "unknown architecture (${arch}) when cross-compiling for Android")
endif()

set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/${cxx_arch}")
list(APPEND link_libraries ${android_libcxx_path}/libc++abi.a
${android_libcxx_path}/libc++_shared.so)
elseif(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
list(APPEND link_libraries "${SWIFT_ANDROID_NATIVE_SYSROOT}/usr/lib/libc++_shared.so")
else()
message(SEND_ERROR "Couldn't set ${arch} libc++ libraries needed for Android")
endif()

set(${libraries_var_name} ${link_libraries} PARENT_SCOPE)
endfunction()
34 changes: 29 additions & 5 deletions cmake/modules/SwiftConfigureSDK.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ function(_report_sdk prefix)
message(STATUS " ${arch} LIB: ${${arch}_LIB}")
endforeach()
elseif("${prefix}" STREQUAL "ANDROID")
message(STATUS " NDK: $ENV{SWIFT_ANDROID_NDK_PATH}")
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
message(STATUS " NDK: $ENV{SWIFT_ANDROID_NDK_PATH}")
endif()
if(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
message(STATUS " Sysroot: ${SWIFT_ANDROID_NATIVE_SYSROOT}")
endif()
foreach(arch ${SWIFT_SDK_${prefix}_ARCHITECTURES})
swift_android_include_for_arch(${arch} ${arch}_INCLUDE)
swift_android_lib_for_arch(${arch} ${arch}_LIB)
Expand Down Expand Up @@ -204,18 +209,37 @@ macro(configure_sdk_unix name architectures)

foreach(arch ${architectures})
if("${prefix}" STREQUAL "ANDROID")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_LIBC_INCLUDE_DIRECTORY "${SWIFT_ANDROID_NDK_PATH}/sysroot/usr/include" CACHE STRING "Path to C library headers")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_LIBC_ARCHITECTURE_INCLUDE_DIRECTORY "${SWIFT_ANDROID_NDK_PATH}/sysroot/usr/include" CACHE STRING "Path to C library architecture headers")
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_LIBC_INCLUDE_DIRECTORY "${SWIFT_ANDROID_NDK_PATH}/sysroot/usr/include" CACHE STRING "Path to C library headers")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_LIBC_ARCHITECTURE_INCLUDE_DIRECTORY "${SWIFT_ANDROID_NDK_PATH}/sysroot/usr/include" CACHE STRING "Path to C library architecture headers")
elseif(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_LIBC_INCLUDE_DIRECTORY "${SWIFT_ANDROID_NATIVE_SYSROOT}/usr/include" CACHE STRING "Path to C library headers")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_LIBC_ARCHITECTURE_INCLUDE_DIRECTORY "${SWIFT_ANDROID_NATIVE_SYSROOT}/usr/include" CACHE STRING "Path to C library architecture headers")
else()
message(SEND_ERROR "Couldn't find LIBC_INCLUDE_DIRECTORY for Android")
endif()

if("${arch}" STREQUAL "armv7")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE "arm-linux-androideabi")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_ALT_SPELLING "arm")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NDK_PATH}/platforms/android-${SWIFT_ANDROID_API_LEVEL}/arch-arm")
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NDK_PATH}/platforms/android-${SWIFT_ANDROID_API_LEVEL}/arch-arm")
elseif(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NATIVE_SYSROOT}")
else()
message(SEND_ERROR "Couldn't find SWIFT_SDK_ANDROID_ARCH_armv7_PATH")
endif()
set(SWIFT_SDK_ANDROID_ARCH_${arch}_TRIPLE "armv7-none-linux-androideabi")
elseif("${arch}" STREQUAL "aarch64")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE "aarch64-linux-android")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_ALT_SPELLING "aarch64")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NDK_PATH}/platforms/android-${SWIFT_ANDROID_API_LEVEL}/arch-arm64")
if(NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NDK_PATH}/platforms/android-${SWIFT_ANDROID_API_LEVEL}/arch-arm64")
elseif(NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NATIVE_SYSROOT}")
else()
message(SEND_ERROR "Couldn't find SWIFT_SDK_ANDROID_ARCH_aarch64_PATH")
endif()
set(SWIFT_SDK_ANDROID_ARCH_${arch}_TRIPLE "aarch64-unknown-linux-android")
elseif("${arch}" STREQUAL "i686")
set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE "i686-linux-android")
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/stubs/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {

return outBuf;
}
#else // __ANDROID__; Add your favorite arch's command line arg grabber here.
#else // Add your favorite OS's command line arg grabber here.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__linux__ is defined on Android, so the above block is used.

SWIFT_RUNTIME_STDLIB_API
char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
Expand Down
4 changes: 3 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,9 @@ _Block_release(void) { }\n")
if("${SDK}" STREQUAL "IOS" OR "${SDK}" STREQUAL "TVOS" OR "${SDK}" STREQUAL "WATCHOS")
# These are supported testing SDKs, but their implementation of
# `command_upload_stdlib` is hidden.
elseif("${SDK}" STREQUAL "ANDROID")
elseif("${SDK}" STREQUAL "ANDROID" AND NOT "${SWIFT_HOST_VARIANT}" STREQUAL "android")
# This adb setup is only needed when cross-compiling for Android, so the
# second check above makes sure we don't bother when the host is Android.
if("${SWIFT_ANDROID_DEPLOY_DEVICE_PATH}" STREQUAL "")
message(FATAL_ERROR
"When running Android host tests, you must specify the directory on the device "
Expand Down
17 changes: 15 additions & 2 deletions test/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,10 @@ elif platform.system() == 'Linux':
if swift_test_mode != 'only_non_executable':
config.available_features.add('swift_interpreter')

# The global environment in Android sets ANDROID_DATA, so if that variable is
# set, we are probably running in Android.
kIsAndroid = 'ANDROID_DATA' in os.environ

# swift-remoteast-test requires the ability to compile and run code
# for the system we compiled the swift-remoteast-test executable on.
# This is potentially a stronger constraint than just "can we interpret",
Expand Down Expand Up @@ -966,8 +970,11 @@ elif run_os in ['windows-msvc']:
('%r -modulewrap -target %s' % (config.swiftc, config.variant_triple))


elif run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'windows-gnu']:
# Linux/FreeBSD/Cygwin
elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'windows-gnu'] or
(kIsAndroid and run_os in ['linux-android', 'linux-androideabi'])):
# Running lit and the compiler on Android itself is more like running on Linux,
# ie the NDK and adb aren't needed, so use this instead.
# Linux/FreeBSD/Cygwin/Android
if run_os == 'windows-cygnus':
lit_config.note("Testing Cygwin " + config.variant_triple)
config.target_object_format = "coff"
Expand All @@ -986,6 +993,12 @@ elif run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'wi
config.target_shared_library_prefix = 'lib'
config.target_shared_library_suffix = ".so"
config.target_sdk_name = "freebsd"
elif kIsAndroid:
lit_config.note("Testing Android " + config.variant_triple)
config.target_object_format = "elf"
config.target_shared_library_prefix = 'lib'
config.target_shared_library_suffix = ".so"
config.target_sdk_name = "android"
else:
lit_config.note("Testing Linux " + config.variant_triple)
config.target_object_format = "elf"
Expand Down