Skip to content

Commit

Permalink
Merge pull request #729 from elucideye/pr.windows.android.studio
Browse files Browse the repository at this point in the history
AppVeyor: Android Studio build
  • Loading branch information
ruslo authored Sep 14, 2018
2 parents ee86763 + 0f6f93a commit 3787257
Show file tree
Hide file tree
Showing 9 changed files with 299 additions and 71 deletions.
34 changes: 28 additions & 6 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,51 @@ environment:

matrix:

- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLCHAIN: "vs-15-2017"
- TOOLCHAIN: "vs-15-2017"
CONFIG: Release
BUILD_SHARED: ON
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TYPE: polly

- TOOLCHAIN: "vs-14-2015-sdk-8-1"
CONFIG: Release
BUILD_SHARED: OFF
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TYPE: polly

- TOOLCHAIN: "vs-14-2015-win64-sdk-8-1"
CONFIG: Release
BUILD_SHARED: OFF
BUILD_SHARED: OFF
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TYPE: polly

- TOOLCHAIN: "vs-14-2015-win64-sdk-8-1"
CONFIG: Debug
BUILD_SHARED: OFF
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TYPE: polly

- ANDROID_STUDIO_ARCH: arm64-v8a
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TYPE: android-studio

- ANDROID_STUDIO_ARCH: armeabi-v7a
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TYPE: android-studio

install:
- cmd: bin\hunter_env.cmd
# Python 3
- cmd: set PATH=C:\Python34-x64;C:\Python34-x64\Scripts;%PATH%

# Install Python package 'requests', 'gitpython'
- cmd: pip install requests
- cmd: pip install gitpython

# Add '--quiet' to avoid leaking the token to logs
- cmd: git submodule update --init --recursive --quiet

build_script:
- cmd: set APPVEYOR_CMAKE_ARGS=DRISHTI_HAS_GPU=OFF
- cmd: bin\build-appveyor.cmd "%CONFIG%" "%TOOLCHAIN%" "%BUILD_SHARED%"
- cmd: python bin\jenkins.py

artifacts:
- path: _archives\drishti-*.tar.gz
Expand Down
Empty file added bin/__init__.py
Empty file.
21 changes: 0 additions & 21 deletions bin/build-appveyor.cmd

This file was deleted.

128 changes: 128 additions & 0 deletions bin/detail/android_studio_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import os
import subprocess
import sys
import time

from detail.download_unzip import download_unzip
from detail.substitute_line import substitute_line

def android_studio_build():
arch = os.getenv('ANDROID_STUDIO_ARCH')

arch_expected = 'Expected values:\n* x86_64\n* armeabi-v7a\n* arm64-v8a'

if not arch:
sys.exit('Environment variable ANDROID_STUDIO_ARCH is empty.\n{}'.format(arch_expected))

if arch != 'x86_64' and arch != 'armeabi-v7a' and arch != 'arm64-v8a':
sys.exit('Unknown ANDROID_STUDIO_ARCH value: "{}".\n{}'.format(arch, arch_expected))

is_appveyor = (os.getenv('APPVEYOR') == 'True')

cmake_dir = os.path.join(os.getcwd(), '_ci', 'cmake')
cmake_build_directory = os.path.join(
os.getcwd(),
'src',
'examples',
'facefilter',
'android-studio',
'app',
'.externalNativeBuild',
'cmake',
'debug',
arch
)

cmakelists_top = os.path.join(os.getcwd(), 'CMakeLists.txt')
if not os.path.exists(cmakelists_top):
sys.exit('File not found: "{}"'.format(cmakelists_top))

os.chdir('android-studio')

if is_appveyor:
download_unzip(
'https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-win.zip',
'_ninja'
)

ninja_path = os.path.join(os.getcwd(), '_ninja')
os.environ['PATH'] = "{};{}".format(ninja_path, os.getenv('PATH'))

download_unzip(
'https://dl.google.com/android/repository/android-ndk-r17c-windows-x86_64.zip',
'_android_ndk'
)

android_ndk = os.path.join(os.getcwd(), '_android_ndk', 'android-ndk-r17c')
android_sdk = os.path.join(os.getenv('USERPROFILE'), 'android-sdk')
licenses_dir = os.path.join(android_sdk, 'licenses')

os.makedirs(licenses_dir, exist_ok=True)

android_ndk = android_ndk.replace('\\', '/')
cmake_dir = cmake_dir.replace('\\', '/')
android_sdk = android_sdk.replace('\\', '/')

# Create 'local.properties'
f = open('local.properties', 'w')
f.write('sdk.dir={}\n'.format(android_sdk))
f.write('ndk.dir={}\n'.format(android_ndk))
f.write('cmake.dir={}\n'.format(cmake_dir))
f.close()

# https://stackoverflow.com/a/38381577
f = open(os.path.join(licenses_dir, 'android-sdk-license'), 'w')
f.write('\nd56f5187479451eabf01fb78af6dfcb131a6481e')
f.close()

# https://stackoverflow.com/a/38339046
f = open(os.path.join(os.getcwd(), 'gradle.properties'), 'w')
f.write('android.builder.sdkDownload=true')
f.close()

expected = os.path.join(os.getcwd(), 'local.properties')

if not os.path.exists(expected):
sys.exit('Path not found: {}'.format(expected))

# Let's stop Gradle build at beginning of CMakeLists.txt so we can lauch
# it explicitly by `cmake --build` (workaround for Android Studio bug, see below)
substitute_line(
cmakelists_top,
'^if\(DRISHTI_DEBUG_STOP\)$',
'if(DRISHTI_DEBUG_STOP OR TRUE)'
)

if is_appveyor:
# First Gradle lauch will hit issue:
# * https://issuetracker.google.com/issues/75268076
subprocess.call(
['gradlew.bat', 'assembleDebug', '-Parch={}'.format(arch)]
)

# Sometimes second launch failing with the same error, put a wait command
# to try to improve stability
time.sleep(15)

subprocess.check_call(
['gradlew.bat', 'assembleDebug', '-Parch={}'.format(arch)]
)

if not os.path.exists(cmake_build_directory):
sys.exit('Path not found: {}'.format(cmake_build_directory))

# Back to normal CMake configuration
substitute_line(
cmakelists_top,
'^if\(DRISHTI_DEBUG_STOP OR TRUE\)$',
'if(DRISHTI_DEBUG_STOP)'
)

# Lauch CMake build without Gradle.
subprocess.check_call(['cmake', '--build', cmake_build_directory])

# CMake part done, now we can continue with the
# rest parts of Android Studio project
subprocess.check_call(
['gradlew.bat', 'assembleDebug', '-Parch={}'.format(arch)]
)
47 changes: 47 additions & 0 deletions bin/detail/download_unzip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import os
import requests
import subprocess

# http://stackoverflow.com/a/16696317/2288008
def file_download_once(url, local_path):
print('Downloading:\n {}\n -> {}'.format(url, local_path))
r = requests.get(url, stream=True)
if not r.ok:
raise Exception('Downloading failed: {}'.format(url))
with open(local_path, 'wb') as f:
for chunk in r.iter_content(chunk_size=16*1024):
if chunk:
f.write(chunk)

def file_download(url, local_path):
max_retry = 3
for i in range(max_retry):
try:
file_download_once(url, local_path)
print('Done')
return
except Exception as exc:
print('Exception catched ({}), retry... ({} of {})'.format(exc, i+1, max_retry))
time.sleep(60)
sys.exit('Download failed')

def download_unzip(url, todir):
if not os.path.exists(todir):
os.mkdir(todir)
backdir = os.getcwd()

os.chdir(todir)

temp_local_path = os.path.join(os.getcwd(), 'temp.zip')

file_download(url, temp_local_path)

# Can't use ZipFile module because permissions will be lost, see bug:
# * https://bugs.python.org/issue15795
devnull = open(os.devnull, 'w') # subprocess.DEVNULL is not available for Python 3.2
subprocess.check_call(
['7z', 'x', '-y', temp_local_path], stdout=devnull, stderr=devnull, bufsize=0
)

os.remove(temp_local_path)
os.chdir(backdir)
50 changes: 50 additions & 0 deletions bin/detail/polly_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os
import subprocess
import sys
import time

from detail.download_unzip import download_unzip

def polly_build():
polly_script = [sys.executable]

if os.getenv('APPVEYOR') == 'True':
polly_script += [
os.path.join(os.getcwd(), '_polly', 'polly-master', 'bin', 'polly.py')
]
else:
polly_script += [subprocess.check_output(['where', 'polly.py']).decode('utf-8').rstrip()]

config = os.getenv('CONFIG')
if not config:
sys.exit('Environment variable CONFIG is empty')

toolchain = os.getenv('TOOLCHAIN')
if not toolchain:
sys.exit('Environment variable TOOLCHAIN is empty')

build_shared = os.getenv('BUILD_SHARED')
if not build_shared:
sys.exit('Environment variable BUILD_SHARED is empty')

polly_script += [
'--verbose',
'--archive',
'drishti',
'--config',
config,
'--toolchain',
toolchain,
'--test',
'--fwd',
'DRISHTI_BUILD_SHARED_SDK={}'.format(build_shared),
'DRISHTI_COPY_3RDPARTY_LICENSES=ON',
'DRISHTI_BUILD_TESTS=ON',
'DRISHTI_BUILD_EXAMPLES=ON',
'DRISHTI_HAS_GPU=OFF'
]

if os.getenv('APPVEYOR') == 'True':
polly_script += ['HUNTER_SUPPRESS_LIST_OF_FILES=ON']

subprocess.check_call(polly_script)
9 changes: 9 additions & 0 deletions bin/detail/substitute_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import io
import re

def substitute_line(filename, pattern, repl):
with io.open(filename, "r") as f:
lines = f.readlines()
with io.open(filename, "w", newline='\n') as f:
for line in lines:
f.write(re.sub(pattern, repl, line))
44 changes: 0 additions & 44 deletions bin/hunter_env.cmd

This file was deleted.

Loading

0 comments on commit 3787257

Please sign in to comment.