Merge pull request #15969 from Greenliff/support/xamarin

Xamarin.Android: add support
pull/16096/head
Jan Tattermusch 7 years ago committed by GitHub
commit a207a042b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/csharp/Grpc.Core/Grpc.Core.csproj
  2. 24
      src/csharp/Grpc.Core/Internal/NativeExtension.cs
  3. 33
      src/csharp/Grpc.Core/Internal/PlatformApis.cs
  4. 21
      src/csharp/Grpc.Core/build/MonoAndroid/Grpc.Core.targets
  5. 0
      src/csharp/Grpc.Core/build/net45/Grpc.Core.targets
  6. 24
      src/csharp/experimental/build_native_ext_for_android.sh
  7. 31
      tools/dockerfile/grpc_artifact_android_ndk/Dockerfile
  8. 13
      tools/run_tests/artifacts/artifact_targets.py
  9. 1
      tools/run_tests/artifacts/build_artifact_csharp_android.sh

@ -46,10 +46,22 @@
<PackagePath>runtimes/win/native/grpc_csharp_ext.x86.dll</PackagePath>
<Pack>true</Pack>
</Content>
<Content Include="Grpc.Core.targets">
<Content Include="..\nativelibs\csharp_ext_linux_android_armeabi-v7a\libgrpc_csharp_ext.so">
<PackagePath>runtimes/monoandroid/armeabi-v7a/libgrpc_csharp_ext.so</PackagePath>
<Pack>true</Pack>
</Content>
<Content Include="..\nativelibs\csharp_ext_linux_android_arm64-v8a\libgrpc_csharp_ext.so">
<PackagePath>runtimes/monoandroid/arm64-v8a/libgrpc_csharp_ext.so</PackagePath>
<Pack>true</Pack>
</Content>
<Content Include="build\net45\Grpc.Core.targets">
<PackagePath>build/net45/</PackagePath>
<Pack>true</Pack>
</Content>
<Content Include="build\MonoAndroid\Grpc.Core.targets">
<PackagePath>build/MonoAndroid/</PackagePath>
<Pack>true</Pack>
</Content>
</ItemGroup>
<ItemGroup>

@ -106,7 +106,15 @@ namespace Grpc.Core.Internal
/// </summary>
private static NativeMethods LoadNativeMethods()
{
return PlatformApis.IsUnity ? LoadNativeMethodsUnity() : new NativeMethods(LoadUnmanagedLibrary());
if (PlatformApis.IsUnity)
{
return LoadNativeMethodsUnity();
}
if (PlatformApis.IsXamarin)
{
return LoadNativeMethodsXamarin();
}
return new NativeMethods(LoadUnmanagedLibrary());
}
/// <summary>
@ -128,6 +136,20 @@ namespace Grpc.Core.Internal
}
}
/// <summary>
/// Return native method delegates when running on the Xamarin platform.
/// WARNING: Xamarin support is experimental and work-in-progress. Don't expect it to work.
/// </summary>
private static NativeMethods LoadNativeMethodsXamarin()
{
if (PlatformApis.IsXamarinAndroid)
{
return new NativeMethods(new NativeMethods.DllImportsFromSharedLib());
}
// not tested yet
return new NativeMethods(new NativeMethods.DllImportsFromStaticLib());
}
private static string GetAssemblyPath()
{
var assembly = typeof(NativeExtension).GetTypeInfo().Assembly;

@ -33,12 +33,17 @@ namespace Grpc.Core.Internal
internal static class PlatformApis
{
const string UnityEngineApplicationClassName = "UnityEngine.Application, UnityEngine";
const string XamarinAndroidActivityClassName = "Android.App.Activity, Mono.Android";
const string XamariniOSEnumClassName = "Mono.CSharp.Enum, Mono.CSharp";
static readonly bool isLinux;
static readonly bool isMacOSX;
static readonly bool isWindows;
static readonly bool isMono;
static readonly bool isNetCore;
static readonly bool isUnity;
static readonly bool isXamarin;
static readonly bool isXamariniOS;
static readonly bool isXamarinAndroid;
static PlatformApis()
{
@ -58,6 +63,9 @@ namespace Grpc.Core.Internal
#endif
isMono = Type.GetType("Mono.Runtime") != null;
isUnity = Type.GetType(UnityEngineApplicationClassName) != null;
isXamariniOS = Type.GetType(XamariniOSEnumClassName) != null;
isXamarinAndroid = Type.GetType(XamarinAndroidActivityClassName) != null;
isXamarin = isXamariniOS || isXamarinAndroid;
}
public static bool IsLinux
@ -88,6 +96,31 @@ namespace Grpc.Core.Internal
get { return isUnity; }
}
/// <summary>
/// true if running on a Xamarin platform (either Xamarin.Android or Xamarin.iOS),
/// false otherwise.
/// </summary>
public static bool IsXamarin
{
get { return isXamarin; }
}
/// <summary>
/// true if running on Xamarin.iOS, false otherwise.
/// </summary>
public static bool IsXamariniOS
{
get { return isXamariniOS; }
}
/// <summary>
/// true if running on Xamarin.Android, false otherwise.
/// </summary>
public static bool IsXamarinAndroid
{
get { return isXamarinAndroid; }
}
/// <summary>
/// true if running on .NET Core (CoreCLR), false otherwise.
/// </summary>

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_GrpcCoreNugetNativePath Condition="'$(_GrpcCoreNugetNativePath)' == ''">$(MSBuildThisFileDirectory)..\..\</_GrpcCoreNugetNativePath>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == 'MonoAndroid'">
<AndroidNativeLibrary Include="$(_GrpcCoreNugetNativePath)runtimes\monoandroid\arm64-v8a\libgrpc_csharp_ext.so">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Abi>arm64-v8a</Abi>
</AndroidNativeLibrary>
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == 'MonoAndroid'">
<AndroidNativeLibrary Include="$(_GrpcCoreNugetNativePath)runtimes\monoandroid\armeabi-v7a\libgrpc_csharp_ext.so">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Abi>armeabi-v7a</Abi>
</AndroidNativeLibrary>
</ItemGroup>
</Project>

@ -23,17 +23,29 @@ mkdir -p build
cd build
# set to the location where Android SDK is installed
# e.g. ANDROID_NDK_PATH="$HOME/android-ndk-r16b"
# e.g. ANDROID_SDK_PATH="$HOME/Android/Sdk"
cmake ../.. \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=15 \
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \
# set to location where Android NDK is installed, usually a subfolder of Android SDK
# to install the Android NKD, use the "sdkmanager" tool
# e.g. ANDROID_NDK_PATH=${ANDROID_SDK_PATH}/ndk-bundle
# set to location of the cmake executable from the Android SDK
# to install cmake, use the "sdkmanager" tool
# e.g. ANDROID_SDK_CMAKE=${ANDROID_SDK_PATH}/cmake/3.6.4111459/bin/cmake
# ANDROID_ABI in ('arm64-v8a', 'armeabi-v7a')
# e.g. ANDROID_ABI=armeabi-v7a
${ANDROID_SDK_CMAKE} ../.. \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_PATH}/build/cmake/android.toolchain.cmake" \
-DCMAKE_ANDROID_NDK="${ANDROID_NDK_PATH}" \
-DCMAKE_ANDROID_STL_TYPE=c++_static \
-DRUN_HAVE_POSIX_REGEX=0 \
-DRUN_HAVE_STD_REGEX=0 \
-DRUN_HAVE_STEADY_CLOCK=0 \
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_PLATFORM=android-28 \
-DANDROID_ABI="${ANDROID_ABI}" \
-DANDROID_NDK="${ANDROID_NDK_PATH}"
make -j4 grpc_csharp_ext

@ -12,9 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Docker file for building gRPC artifacts.
# Docker file for building gRPC artifacts for Android.
# Recent enough cmake (>=3.9) needed by Android SDK
FROM debian:sid
RUN apt-get update && apt-get install -y debian-keyring && apt-key update
@ -47,20 +46,26 @@ RUN apt-get update && apt-key update && apt-get install -y \
wget \
zip && apt-get clean
# Cmake for cross-compilation
RUN apt-get update && apt-get install -y cmake golang && apt-get clean
# golang needed to build BoringSSL with cmake
RUN apt-get update && apt-get install -y golang && apt-get clean
##################
# Android NDK
# Java required by Android SDK
RUN apt-get update && apt-get -y install openjdk-8-jdk && apt-get clean
# Download and install Android NDK
RUN wget -q https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip -O android_ndk.zip \
&& unzip -q android_ndk.zip \
&& rm android_ndk.zip \
&& mv ./android-ndk-r16b /opt
ENV ANDROID_NDK_PATH /opt/android-ndk-r16b
# Install Android SDK
ENV ANDROID_SDK_VERSION 4333796
RUN mkdir -p /opt/android-sdk && cd /opt/android-sdk && \
wget -q https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_VERSION}.zip && \
unzip -q sdk-tools-linux-${ANDROID_SDK_VERSION}.zip && \
rm sdk-tools-linux-${ANDROID_SDK_VERSION}.zip
ENV ANDROID_SDK_PATH /opt/android-sdk
RUN apt-get update && apt-get install -y libpthread-stubs0-dev && apt-get clean
# Install Android NDK and cmake using sdkmanager
RUN mkdir -p ~/.android && touch ~/.android/repositories.cfg
RUN yes | ${ANDROID_SDK_PATH}/tools/bin/sdkmanager --licenses # accept all licenses
RUN ${ANDROID_SDK_PATH}/tools/bin/sdkmanager ndk-bundle 'cmake;3.6.4111459'
ENV ANDROID_NDK_PATH ${ANDROID_SDK_PATH}/ndk-bundle
ENV ANDROID_SDK_CMAKE ${ANDROID_SDK_PATH}/cmake/3.6.4111459/bin/cmake
RUN mkdir /var/local/jenkins

@ -212,11 +212,15 @@ class RubyArtifact:
class CSharpExtArtifact:
"""Builds C# native extension library"""
def __init__(self, platform, arch):
def __init__(self, platform, arch, arch_abi=None):
self.name = 'csharp_ext_%s_%s' % (platform, arch)
self.platform = platform
self.arch = arch
self.arch_abi = arch_abi
self.labels = ['artifact', 'csharp', platform, arch]
if arch_abi:
self.name += '_%s' % arch_abi
self.labels.append(arch_abi)
def pre_build_jobspecs(self):
return []
@ -227,7 +231,9 @@ class CSharpExtArtifact:
self.name,
'tools/dockerfile/grpc_artifact_android_ndk',
'tools/run_tests/artifacts/build_artifact_csharp_android.sh',
environ={})
environ={
'ANDROID_ABI': self.arch_abi
})
elif self.platform == 'windows':
cmake_arch_option = 'Win32' if self.arch == 'x86' else self.arch
return create_jobspec(
@ -348,7 +354,8 @@ def targets():
for Cls in (CSharpExtArtifact, ProtocArtifact)
for platform in ('linux', 'macos', 'windows') for arch in ('x86', 'x64')
] + [
CSharpExtArtifact('linux', 'android'),
CSharpExtArtifact('linux', 'android', arch_abi='arm64-v8a'),
CSharpExtArtifact('linux', 'android', arch_abi='armeabi-v7a'),
PythonArtifact('linux', 'x86', 'cp27-cp27m'),
PythonArtifact('linux', 'x86', 'cp27-cp27mu'),
PythonArtifact('linux', 'x86', 'cp34-cp34m'),

@ -17,6 +17,7 @@ set -ex
cd "$(dirname "$0")/../../.."
# ANDROID_ABI is set by the job definition in artifact_targets.py
src/csharp/experimental/build_native_ext_for_android.sh
mkdir -p "${ARTIFACTS_OUT}"

Loading…
Cancel
Save