mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-08 06:32:35 +02:00
Merge pull request #14521 from jherico/feature/build/gradle-wrapper
20197: Containerized Android builds
This commit is contained in:
commit
c401f3c8bd
18 changed files with 1148 additions and 265 deletions
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -17,10 +17,11 @@ Makefile
|
|||
local.properties
|
||||
android/gradle*
|
||||
android/.gradle
|
||||
android/app/src/main/jniLibs
|
||||
android/app/libs
|
||||
android/app/src/main/res/values/libs.xml
|
||||
android/app/src/main/assets/bundled
|
||||
android/**/src/main/jniLibs
|
||||
android/**/libs
|
||||
android/**/src/main/res/values/libs.xml
|
||||
android/**/src/main/assets
|
||||
android/**/gradle*
|
||||
|
||||
# VSCode
|
||||
# List taken from Github Global Ignores master@435c4d92
|
||||
|
@ -83,9 +84,6 @@ npm-debug.log
|
|||
# Android studio files
|
||||
*___jb_old___
|
||||
|
||||
# Generated assets for Android
|
||||
android/app/src/main/assets
|
||||
|
||||
# Resource binary file
|
||||
interface/compiledResources
|
||||
|
||||
|
@ -95,6 +93,9 @@ interface/resources/GPUCache/*
|
|||
# package lock file for JSDoc tool
|
||||
tools/jsdoc/package-lock.json
|
||||
|
||||
# Python compile artifacts
|
||||
**/__pycache__
|
||||
|
||||
# ignore unneeded unity project files for avatar exporter
|
||||
tools/unity-avatar-exporter/Library
|
||||
tools/unity-avatar-exporter/Packages
|
||||
|
|
|
@ -6,13 +6,8 @@ Building is currently supported on OSX, Windows and Linux platforms, but develop
|
|||
|
||||
You will need the following tools to build Android targets.
|
||||
|
||||
* [Gradle](https://gradle.org/install/)
|
||||
* [Android Studio](https://developer.android.com/studio/index.html)
|
||||
|
||||
### Gradle
|
||||
|
||||
Install gradle version 4.1 or higher. Following the instructions to install via [SDKMAN!](http://sdkman.io/install.html) is recommended.
|
||||
|
||||
### Android Studio
|
||||
|
||||
Download the Android Studio installer and run it. Once installed, at the welcome screen, click configure in the lower right corner and select SDK manager
|
||||
|
@ -29,6 +24,8 @@ From the SDK Tools tab select the following
|
|||
* Android SDK Tools
|
||||
* NDK (even if you have the NDK installed separately)
|
||||
|
||||
Make sure the NDK installed version is 18 (or higher)
|
||||
|
||||
# Environment
|
||||
|
||||
Setting up the environment for android builds requires some additional steps
|
||||
|
@ -51,17 +48,17 @@ Enter the repository `android` directory
|
|||
|
||||
`cd hifi/android`
|
||||
|
||||
Execute a gradle pre-build setup. This step should only need to be done once
|
||||
Execute two gradle pre-build steps. This steps should only need to be done once, unless you're working on the Android dependencies
|
||||
|
||||
`gradle setupDependencies`
|
||||
`./gradlew extractDependencies`
|
||||
|
||||
`./gradlew setupDependencies`
|
||||
|
||||
# Building & Running
|
||||
|
||||
* Open Android Studio
|
||||
* Choose _Open Existing Android Studio Project_
|
||||
* Navigate to the `hifi` repository and choose the `android` folder and select _OK_
|
||||
* If Android Studio asks you if you want to use the Gradle wrapper, select cancel and tell it where your local gradle installation is. If you used SDKMAN to install gradle it will be located in `$HOME/.sdkman/candidates/gradle/current/`
|
||||
* From the _Build_ menu select _Make Project_
|
||||
* Once the build completes, from the _Run_ menu select _Run App_
|
||||
|
||||
|
|
|
@ -139,23 +139,23 @@ dependencies {
|
|||
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
implementation 'com.android.support:design:26.1.0'
|
||||
compile 'com.android.support:support-v4:26.1.0'
|
||||
compile 'com.android.support:appcompat-v7:26.1.0'
|
||||
compile 'com.android.support:support-vector-drawable:26.1.0'
|
||||
api 'com.android.support:support-v4:26.1.0'
|
||||
api 'com.android.support:appcompat-v7:26.1.0'
|
||||
api 'com.android.support:support-vector-drawable:26.1.0'
|
||||
|
||||
implementation 'com.android.support:appcompat-v7:26.1.0'
|
||||
compile 'com.android.support:recyclerview-v7:26.1.0'
|
||||
compile 'com.android.support:cardview-v7:26.1.0'
|
||||
api 'com.android.support:recyclerview-v7:26.1.0'
|
||||
api 'com.android.support:cardview-v7:26.1.0'
|
||||
|
||||
compile 'com.squareup.retrofit2:retrofit:2.4.0'
|
||||
compile 'com.squareup.retrofit2:converter-gson:2.4.0'
|
||||
api 'com.squareup.retrofit2:retrofit:2.4.0'
|
||||
api 'com.squareup.retrofit2:converter-gson:2.4.0'
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
|
||||
compile 'com.squareup.retrofit2:retrofit:2.4.0'
|
||||
compile 'com.squareup.retrofit2:converter-gson:2.4.0'
|
||||
api 'com.squareup.retrofit2:retrofit:2.4.0'
|
||||
api 'com.squareup.retrofit2:converter-gson:2.4.0'
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
|
||||
compile 'com.sothree.slidinguppanel:library:3.4.0'
|
||||
api 'com.sothree.slidinguppanel:library:3.4.0'
|
||||
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.highfidelity.hifiinterface">
|
||||
|
||||
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="26" />
|
||||
<uses-feature android:glEsVersion="0x00030002" android:required="true" />
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
|
|
@ -14,7 +14,7 @@ buildscript {
|
|||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,7 +392,7 @@ task extractDependencies(dependsOn: verifyDependencyDownloads) {
|
|||
}
|
||||
|
||||
// Copies the non Qt dependencies. Qt dependencies (primary libraries and plugins) are handled by the qtBundle task
|
||||
task copyDependencies(dependsOn: [ extractDependencies ]) {
|
||||
task copyDependencies() {
|
||||
doLast {
|
||||
packages.each { entry ->
|
||||
def packageName = entry.key
|
||||
|
@ -414,7 +414,7 @@ task copyDependencies(dependsOn: [ extractDependencies ]) {
|
|||
}
|
||||
}
|
||||
|
||||
task extractGvrBinaries(dependsOn: extractDependencies) {
|
||||
task extractGvrBinaries() {
|
||||
doLast {
|
||||
def gvrLibFolder = new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries');
|
||||
zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-audio-1.101.0.aar')).visit { element ->
|
||||
|
|
4
android/build_android.sh
Executable file
4
android/build_android.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
set -xeuo pipefail
|
||||
./gradlew -PHIFI_ANDROID_PRECOMPILED=${HIFI_ANDROID_PRECOMPILED} -PRELEASE_NUMBER=${RELEASE_NUMBER} -PRELEASE_TYPE=${RELEASE_TYPE} setupDependencies
|
||||
./gradlew -PHIFI_ANDROID_PRECOMPILED=${HIFI_ANDROID_PRECOMPILED} -PRELEASE_NUMBER=${RELEASE_NUMBER} -PRELEASE_TYPE=${RELEASE_TYPE} app:${ANDROID_BUILD_TARGET}
|
22
android/containerized_build.sh
Executable file
22
android/containerized_build.sh
Executable file
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
set -xeuo pipefail
|
||||
|
||||
DOCKER_IMAGE_NAME="hifi_androidbuild"
|
||||
|
||||
docker build --build-arg BUILD_UID=`id -u` -t "${DOCKER_IMAGE_NAME}" -f docker/Dockerfile docker
|
||||
|
||||
docker run \
|
||||
--rm \
|
||||
--security-opt seccomp:unconfined \
|
||||
-v "${WORKSPACE}":/home/jenkins/hifi \
|
||||
-e "RELEASE_NUMBER=${RELEASE_NUMBER}" \
|
||||
-e "RELEASE_TYPE=${RELEASE_TYPE}" \
|
||||
-e "ANDROID_BUILD_TARGET=assembleDebug" \
|
||||
-e "CMAKE_BACKTRACE_URL=${CMAKE_BACKTRACE_URL}" \
|
||||
-e "CMAKE_BACKTRACE_TOKEN=${CMAKE_BACKTRACE_TOKEN}" \
|
||||
-e "CMAKE_BACKTRACE_SYMBOLS_TOKEN=${CMAKE_BACKTRACE_SYMBOLS_TOKEN}" \
|
||||
-e "GA_TRACKING_ID=${GA_TRACKING_ID}" \
|
||||
-e "GIT_PR_COMMIT=${GIT_PR_COMMIT}" \
|
||||
-e "VERSION_CODE=${VERSION_CODE}" \
|
||||
"${DOCKER_IMAGE_NAME}" \
|
||||
sh -c "./build_android.sh"
|
92
android/docker/Dockerfile
Normal file
92
android/docker/Dockerfile
Normal file
|
@ -0,0 +1,92 @@
|
|||
FROM openjdk:8
|
||||
|
||||
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||
|
||||
RUN apt-get update && apt-get -y install \
|
||||
curl \
|
||||
gnupg \
|
||||
software-properties-common \
|
||||
unzip \
|
||||
-
|
||||
|
||||
# --- Versions and Download paths
|
||||
ENV ANDROID_HOME="/usr/local/android-sdk" \
|
||||
ANDROID_NDK_HOME="/usr/local/android-ndk" \
|
||||
ANDROID_SDK_HOME="/usr/local/android-sdk-home" \
|
||||
ANDROID_VERSION=26 \
|
||||
ANDROID_BUILD_TOOLS_VERSION=28.0.3 \
|
||||
ANDROID_NDK_VERSION=r18
|
||||
|
||||
ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip" \
|
||||
NDK_URL="https://dl.google.com/android/repository/android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip"
|
||||
|
||||
# --- Android SDK
|
||||
RUN mkdir -p "$ANDROID_HOME" "$ANDROID_SDK_HOME" && \
|
||||
cd "$ANDROID_HOME" && \
|
||||
curl -s -S -o sdk.zip -L "${SDK_URL}" && \
|
||||
unzip sdk.zip && \
|
||||
rm sdk.zip && \
|
||||
yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses
|
||||
|
||||
# Install Android Build Tool and Libraries
|
||||
RUN $ANDROID_HOME/tools/bin/sdkmanager --update
|
||||
RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
|
||||
"platforms;android-${ANDROID_VERSION}" \
|
||||
"platform-tools"
|
||||
|
||||
RUN chmod -R a+w "${ANDROID_HOME}"
|
||||
RUN chmod -R a+w "${ANDROID_SDK_HOME}"
|
||||
|
||||
# --- Android NDK
|
||||
# download
|
||||
RUN mkdir /usr/local/android-ndk-tmp && \
|
||||
cd /usr/local/android-ndk-tmp && \
|
||||
curl -s -S -o ndk.zip -L "${NDK_URL}" && \
|
||||
unzip -q ndk.zip && \
|
||||
mv ./android-ndk-${ANDROID_NDK_VERSION} ${ANDROID_NDK_HOME} && \
|
||||
cd ${ANDROID_NDK_HOME} && \
|
||||
rm -rf /usr/local/android-ndk-tmp
|
||||
|
||||
ENV PATH ${PATH}:${ANDROID_NDK_HOME}
|
||||
|
||||
RUN apt-get -y install \
|
||||
g++ \
|
||||
gcc \
|
||||
-
|
||||
|
||||
# --- Gradle
|
||||
ARG BUILD_UID=1001
|
||||
RUN useradd -ms /bin/bash -u $BUILD_UID jenkins
|
||||
USER jenkins
|
||||
WORKDIR /home/jenkins
|
||||
|
||||
# Hifi dependencies
|
||||
ENV HIFI_BASE="/home/jenkins/hifi_android"
|
||||
ENV HIFI_ANDROID_PRECOMPILED="$HIFI_BASE/dependencies"
|
||||
ENV HIFI_VCPKG_BASE="$HIFI_BASE/vcpkg"
|
||||
|
||||
RUN mkdir "$HIFI_BASE" && \
|
||||
mkdir "$HIFI_VCPKG_BASE" && \
|
||||
mkdir "$HIFI_ANDROID_PRECOMPILED"
|
||||
|
||||
RUN git clone https://github.com/jherico/hifi.git && \
|
||||
cd ~/hifi && \
|
||||
git checkout feature/build/gradle-wrapper
|
||||
|
||||
|
||||
WORKDIR /home/jenkins/hifi
|
||||
|
||||
RUN touch .test4 && \
|
||||
git fetch && git reset origin/feature/build/gradle-wrapper --hard
|
||||
|
||||
RUN mkdir build
|
||||
|
||||
# Pre-cache the vcpkg managed dependencies
|
||||
WORKDIR /home/jenkins/hifi/build
|
||||
RUN python3 ../prebuild.py --build-root `pwd` --android
|
||||
|
||||
# Pre-cache the gradle dependencies
|
||||
WORKDIR /home/jenkins/hifi/android
|
||||
RUN ./gradlew -m tasks -PHIFI_ANDROID_PRECOMPILED=$HIFI_ANDROID_PRECOMPILED
|
||||
RUN ./gradlew extractDependencies -PHIFI_ANDROID_PRECOMPILED=$HIFI_ANDROID_PRECOMPILED
|
||||
|
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
#Sat Dec 01 08:32:47 PST 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
172
android/gradlew
vendored
Executable file
172
android/gradlew
vendored
Executable file
|
@ -0,0 +1,172 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
84
android/gradlew.bat
vendored
Executable file
84
android/gradlew.bat
vendored
Executable file
|
@ -0,0 +1,84 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
286
hifi_android.py
Normal file
286
hifi_android.py
Normal file
|
@ -0,0 +1,286 @@
|
|||
import hifi_utils
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import xml.etree.ElementTree as ET
|
||||
import functools
|
||||
|
||||
print = functools.partial(print, flush=True)
|
||||
|
||||
ANDROID_PACKAGE_URL = 'https://hifi-public.s3.amazonaws.com/dependencies/android/'
|
||||
|
||||
ANDROID_PACKAGES = {
|
||||
'qt' : {
|
||||
'file': 'qt-5.11.1_linux_armv8-libcpp_openssl_patched.tgz',
|
||||
'versionId': '3S97HBM5G5Xw9EfE52sikmgdN3t6C2MN',
|
||||
'checksum': 'aa449d4bfa963f3bc9a9dfe558ba29df',
|
||||
},
|
||||
'bullet': {
|
||||
'file': 'bullet-2.88_armv8-libcpp.tgz',
|
||||
'versionId': 'S8YaoED0Cl8sSb8fSV7Q2G1lQJSNDxqg',
|
||||
'checksum': '81642779ccb110f8c7338e8739ac38a0',
|
||||
},
|
||||
'draco': {
|
||||
'file': 'draco_armv8-libcpp.tgz',
|
||||
'versionId': '3.B.uBj31kWlgND3_R2xwQzT_TP6Dz_8',
|
||||
'checksum': '617a80d213a5ec69fbfa21a1f2f738cd',
|
||||
},
|
||||
'glad': {
|
||||
'file': 'glad_armv8-libcpp.zip',
|
||||
'versionId': 'r5Zran.JSCtvrrB6Q4KaqfIoALPw3lYY',
|
||||
'checksum': 'a8ee8584cf1ccd34766c7ddd9d5e5449',
|
||||
},
|
||||
'gvr': {
|
||||
'file': 'gvrsdk_v1.101.0.tgz',
|
||||
'versionId': 'nqBV_j81Uc31rC7bKIrlya_Hah4v3y5r',
|
||||
'checksum': '57fd02baa069176ba18597a29b6b4fc7',
|
||||
},
|
||||
'nvtt': {
|
||||
'file': 'nvtt_armv8-libcpp.zip',
|
||||
'versionId': 'lmkBVR5t4UF1UUwMwEirnk9H_8Nt90IO',
|
||||
'checksum': 'eb46d0b683e66987190ed124aabf8910',
|
||||
'sharedLibFolder': 'lib',
|
||||
'includeLibs': ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so']
|
||||
},
|
||||
'oculus': {
|
||||
'file': 'ovr_sdk_mobile_1.19.0.zip',
|
||||
'versionId': 's_RN1vlEvUi3pnT7WPxUC4pQ0RJBs27y',
|
||||
'checksum': '98f0afb62861f1f02dd8110b31ed30eb',
|
||||
'sharedLibFolder': 'VrApi/Libs/Android/arm64-v8a/Release',
|
||||
'includeLibs': ['libvrapi.so']
|
||||
},
|
||||
'openssl': {
|
||||
'file': 'openssl-1.1.0g_armv8.tgz',
|
||||
'versionId': 'AiiPjmgUZTgNj7YV1EEx2lL47aDvvvAW',
|
||||
'checksum': 'cabb681fbccd79594f65fcc266e02f32'
|
||||
},
|
||||
'polyvox': {
|
||||
'file': 'polyvox_armv8-libcpp.tgz',
|
||||
'versionId': 'A2kbKiNhpIenGq23bKRRzg7IMAI5BI92',
|
||||
'checksum': 'dba88b3a098747af4bb169e9eb9af57e',
|
||||
'sharedLibFolder': 'lib',
|
||||
'includeLibs': ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so'],
|
||||
},
|
||||
'tbb': {
|
||||
'file': 'tbb-2018_U1_armv8_libcpp.tgz',
|
||||
'versionId': 'mrRbWnv4O4evcM1quRH43RJqimlRtaKB',
|
||||
'checksum': '20768f298f53b195e71b414b0ae240c4',
|
||||
'sharedLibFolder': 'lib/release',
|
||||
'includeLibs': ['libtbb.so', 'libtbbmalloc.so'],
|
||||
},
|
||||
'hifiAC': {
|
||||
'baseUrl': 'http://s3.amazonaws.com/hifi-public/dependencies/',
|
||||
'file': 'codecSDK-android_armv8-2.0.zip',
|
||||
'checksum': '1cbef929675818fc64c4101b72f84a6a'
|
||||
},
|
||||
'etc2comp': {
|
||||
'file': 'etc2comp-patched-armv8-libcpp.tgz',
|
||||
'versionId': 'bHhGECRAQR1vkpshBcK6ByNc1BQIM8gU',
|
||||
'checksum': '14b02795d774457a33bbc60e00a786bc'
|
||||
},
|
||||
'breakpad': {
|
||||
'file': 'breakpad.tgz',
|
||||
'versionId': '8VrYXz7oyc.QBxNia0BVJOUBvrFO61jI',
|
||||
'checksum': 'ddcb23df336b08017042ba4786db1d9e',
|
||||
'sharedLibFolder': 'lib',
|
||||
'includeLibs': {'libbreakpad_client.a'}
|
||||
}
|
||||
}
|
||||
|
||||
ANDROID_PLATFORM_PACKAGES = {
|
||||
'Darwin' : {
|
||||
'qt': {
|
||||
'file': 'qt-5.11.1_osx_armv8-libcpp_openssl_patched.tgz',
|
||||
'versionId': 'OxBD7iKINv1HbyOXmAmDrBb8AF3N.Kup',
|
||||
'checksum': 'c83cc477c08a892e00c71764dca051a0'
|
||||
},
|
||||
},
|
||||
'Windows' : {
|
||||
'qt': {
|
||||
'file': 'qt-5.11.1_win_armv8-libcpp_openssl_patched.tgz',
|
||||
'versionId': 'JfWM0P_Mz5Qp0LwpzhrsRwN3fqlLSFeT',
|
||||
'checksum': '0582191cc55431aa4f660848a542883e'
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
QT5_DEPS = [
|
||||
'Qt5Concurrent',
|
||||
'Qt5Core',
|
||||
'Qt5Gui',
|
||||
'Qt5Multimedia',
|
||||
'Qt5Network',
|
||||
'Qt5OpenGL',
|
||||
'Qt5Qml',
|
||||
'Qt5Quick',
|
||||
'Qt5QuickControls2',
|
||||
'Qt5QuickTemplates2',
|
||||
'Qt5Script',
|
||||
'Qt5ScriptTools',
|
||||
'Qt5Svg',
|
||||
'Qt5WebChannel',
|
||||
'Qt5WebSockets',
|
||||
'Qt5Widgets',
|
||||
'Qt5XmlPatterns',
|
||||
# Android specific
|
||||
'Qt5AndroidExtras',
|
||||
'Qt5WebView',
|
||||
]
|
||||
|
||||
def getPlatformPackages():
|
||||
result = ANDROID_PACKAGES.copy()
|
||||
system = platform.system()
|
||||
if system in ANDROID_PLATFORM_PACKAGES:
|
||||
platformPackages = ANDROID_PLATFORM_PACKAGES[system]
|
||||
result = { **result, **platformPackages }
|
||||
return result
|
||||
|
||||
def getPackageUrl(package):
|
||||
url = ANDROID_PACKAGE_URL
|
||||
if 'baseUrl' in package:
|
||||
url = package['baseUrl']
|
||||
url += package['file']
|
||||
if 'versionId' in package:
|
||||
url += '?versionId=' + package['versionId']
|
||||
return url
|
||||
|
||||
def copyAndroidLibs(packagePath, appPath):
|
||||
androidPackages = getPlatformPackages()
|
||||
jniPath = os.path.join(appPath, 'src/main/jniLibs/arm64-v8a')
|
||||
if not os.path.isdir(jniPath):
|
||||
os.makedirs(jniPath)
|
||||
for packageName in androidPackages:
|
||||
package = androidPackages[packageName]
|
||||
if 'sharedLibFolder' in package:
|
||||
sharedLibFolder = os.path.join(packagePath, packageName, package['sharedLibFolder'])
|
||||
if 'includeLibs' in package:
|
||||
for lib in package['includeLibs']:
|
||||
sourceFile = os.path.join(sharedLibFolder, lib)
|
||||
destFile = os.path.join(jniPath, os.path.split(lib)[1])
|
||||
if not os.path.isfile(destFile):
|
||||
print("Copying {}".format(lib))
|
||||
shutil.copy(sourceFile, destFile)
|
||||
|
||||
class QtPackager:
|
||||
def __init__(self, appPath, qtRootPath):
|
||||
self.appPath = appPath
|
||||
self.qtRootPath = qtRootPath
|
||||
self.jniPath = os.path.join(self.appPath, 'src/main/jniLibs/arm64-v8a')
|
||||
self.assetPath = os.path.join(self.appPath, 'src/main/assets')
|
||||
self.qtAssetPath = os.path.join(self.assetPath, '--Added-by-androiddeployqt--')
|
||||
# Jars go into the qt library
|
||||
self.jarPath = os.path.realpath(os.path.join(self.appPath, '../../libraries/qt/libs'))
|
||||
self.xmlFile = os.path.join(self.appPath, 'src/main/res/values/libs.xml')
|
||||
self.files = []
|
||||
self.features = []
|
||||
self.permissions = []
|
||||
|
||||
def copyQtDeps(self):
|
||||
for lib in QT5_DEPS:
|
||||
libfile = os.path.join(self.qtRootPath, "lib/lib{}.so".format(lib))
|
||||
if not os.path.exists(libfile):
|
||||
continue
|
||||
self.files.append(libfile)
|
||||
androidDeps = os.path.join(self.qtRootPath, "lib/{}-android-dependencies.xml".format(lib))
|
||||
if not os.path.exists(androidDeps):
|
||||
continue
|
||||
|
||||
tree = ET.parse(androidDeps)
|
||||
root = tree.getroot()
|
||||
for item in root.findall('./dependencies/lib/depends/*'):
|
||||
if (item.tag == 'lib') or (item.tag == 'bundled'):
|
||||
relativeFilename = item.attrib['file']
|
||||
if (relativeFilename.startswith('qml')):
|
||||
continue
|
||||
filename = os.path.join(self.qtRootPath, relativeFilename)
|
||||
self.files.extend(hifi_utils.recursiveFileList(filename))
|
||||
elif item.tag == 'jar' and 'bundling' in item.attrib and item.attrib['bundling'] == "1":
|
||||
self.files.append(os.path.join(self.qtRootPath, item.attrib['file']))
|
||||
elif item.tag == 'permission':
|
||||
self.permissions.append(item.attrib['name'])
|
||||
elif item.tag == 'feature':
|
||||
self.features.append(item.attrib['name'])
|
||||
|
||||
def scanQmlImports(self):
|
||||
qmlImportCommandFile = os.path.join(self.qtRootPath, 'bin/qmlimportscanner')
|
||||
system = platform.system()
|
||||
if 'Windows' == system:
|
||||
qmlImportCommandFile += ".exe"
|
||||
if not os.path.isfile(qmlImportCommandFile):
|
||||
raise RuntimeError("Couldn't find qml import scanner")
|
||||
qmlRootPath = hifi_utils.scriptRelative('interface/resources/qml')
|
||||
qmlImportPath = os.path.join(self.qtRootPath, 'qml')
|
||||
commandResult = hifi_utils.executeSubprocessCapture([
|
||||
qmlImportCommandFile,
|
||||
'-rootPath', qmlRootPath,
|
||||
'-importPath', qmlImportPath
|
||||
])
|
||||
qmlImportResults = json.loads(commandResult)
|
||||
for item in qmlImportResults:
|
||||
if 'path' not in item:
|
||||
print("Warning: QML import could not be resolved in any of the import paths: {}".format(item['name']))
|
||||
continue
|
||||
path = os.path.realpath(item['path'])
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
basePath = path
|
||||
if os.path.isfile(basePath):
|
||||
basePath = os.path.dirname(basePath)
|
||||
basePath = os.path.normcase(basePath)
|
||||
if basePath.startswith(qmlRootPath):
|
||||
continue
|
||||
self.files.extend(hifi_utils.recursiveFileList(path))
|
||||
|
||||
def processFiles(self):
|
||||
self.files = list(set(self.files))
|
||||
self.files.sort()
|
||||
libsXmlRoot = ET.Element('resources')
|
||||
qtLibsNode = ET.SubElement(libsXmlRoot, 'array', {'name':'qt_libs'})
|
||||
bundledLibsNode = ET.SubElement(libsXmlRoot, 'array', {'name':'bundled_in_lib'})
|
||||
bundledAssetsNode = ET.SubElement(libsXmlRoot, 'array', {'name':'bundled_in_assets'})
|
||||
libPrefix = 'lib'
|
||||
for sourceFile in self.files:
|
||||
if not os.path.isfile(sourceFile):
|
||||
raise RuntimeError("Unable to find dependency file " + sourceFile)
|
||||
relativePath = os.path.relpath(sourceFile, self.qtRootPath)
|
||||
destinationFile = None
|
||||
if relativePath.endswith('.so'):
|
||||
garbledFileName = None
|
||||
if relativePath.startswith(libPrefix):
|
||||
garbledFileName = relativePath[4:]
|
||||
p = re.compile(r'lib(Qt5.*).so')
|
||||
m = p.search(garbledFileName)
|
||||
if not m:
|
||||
raise RuntimeError("Huh?")
|
||||
libName = m.group(1)
|
||||
ET.SubElement(qtLibsNode, 'item').text = libName
|
||||
else:
|
||||
garbledFileName = 'lib' + relativePath.replace('\\', '_'[0])
|
||||
value = "{}:{}".format(garbledFileName, relativePath).replace('\\', '/')
|
||||
ET.SubElement(bundledLibsNode, 'item').text = value
|
||||
destinationFile = os.path.join(self.jniPath, garbledFileName)
|
||||
elif relativePath.startswith('jar'):
|
||||
destinationFile = os.path.join(self.jarPath, relativePath[4:])
|
||||
else:
|
||||
value = "--Added-by-androiddeployqt--/{}:{}".format(relativePath,relativePath).replace('\\', '/')
|
||||
ET.SubElement(bundledAssetsNode, 'item').text = value
|
||||
destinationFile = os.path.join(self.qtAssetPath, relativePath)
|
||||
|
||||
destinationParent = os.path.realpath(os.path.dirname(destinationFile))
|
||||
if not os.path.isdir(destinationParent):
|
||||
os.makedirs(destinationParent)
|
||||
if not os.path.isfile(destinationFile):
|
||||
shutil.copy(sourceFile, destinationFile)
|
||||
|
||||
tree = ET.ElementTree(libsXmlRoot)
|
||||
tree.write(self.xmlFile, 'UTF-8', True)
|
||||
|
||||
def bundle(self):
|
||||
if not os.path.isfile(self.xmlFile) or True:
|
||||
self.copyQtDeps()
|
||||
self.scanQmlImports()
|
||||
self.processFiles()
|
||||
|
||||
|
46
hifi_singleton.py
Normal file
46
hifi_singleton.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
import os
|
||||
import platform
|
||||
import time
|
||||
|
||||
try:
|
||||
import fcntl
|
||||
except ImportError:
|
||||
fcntl = None
|
||||
|
||||
# Used to ensure only one instance of the script runs at a time
|
||||
class Singleton:
|
||||
def __init__(self, path):
|
||||
self.fh = None
|
||||
self.windows = 'Windows' == platform.system()
|
||||
self.path = path
|
||||
|
||||
def __enter__(self):
|
||||
success = False
|
||||
while not success:
|
||||
try:
|
||||
if self.windows:
|
||||
if os.path.exists(self.path):
|
||||
os.unlink(self.path)
|
||||
self.fh = os.open(self.path, os.O_CREAT | os.O_EXCL | os.O_RDWR)
|
||||
else:
|
||||
self.fh = open(self.path, 'x')
|
||||
fcntl.lockf(self.fh, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
success = True
|
||||
except EnvironmentError as err:
|
||||
if self.fh is not None:
|
||||
if self.windows:
|
||||
os.close(self.fh)
|
||||
else:
|
||||
self.fh.close()
|
||||
self.fh = None
|
||||
print("Couldn't aquire lock, retrying in 10 seconds")
|
||||
time.sleep(10)
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
if self.windows:
|
||||
os.close(self.fh)
|
||||
else:
|
||||
fcntl.lockf(self.fh, fcntl.LOCK_UN)
|
||||
self.fh.close()
|
||||
os.unlink(self.path)
|
124
hifi_utils.py
Normal file
124
hifi_utils.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
import os
|
||||
import hashlib
|
||||
import platform
|
||||
import shutil
|
||||
import ssl
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import urllib
|
||||
import urllib.request
|
||||
import zipfile
|
||||
import tempfile
|
||||
import time
|
||||
import functools
|
||||
|
||||
print = functools.partial(print, flush=True)
|
||||
|
||||
def scriptRelative(*paths):
|
||||
scriptdir = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
result = os.path.join(scriptdir, *paths)
|
||||
result = os.path.realpath(result)
|
||||
result = os.path.normcase(result)
|
||||
return result
|
||||
|
||||
|
||||
def recursiveFileList(startPath):
|
||||
result = []
|
||||
if os.path.isfile(startPath):
|
||||
result.append(startPath)
|
||||
elif os.path.isdir(startPath):
|
||||
for dirName, subdirList, fileList in os.walk(startPath):
|
||||
for fname in fileList:
|
||||
result.append(os.path.realpath(os.path.join(startPath, dirName, fname)))
|
||||
result.sort()
|
||||
return result
|
||||
|
||||
|
||||
def executeSubprocessCapture(processArgs):
|
||||
processResult = subprocess.run(processArgs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
if (0 != processResult.returncode):
|
||||
raise RuntimeError('Call to "{}" failed.\n\narguments:\n{}\n\nstdout:\n{}\n\nstderr:\n{}'.format(
|
||||
processArgs[0],
|
||||
' '.join(processArgs[1:]),
|
||||
processResult.stdout.decode('utf-8'),
|
||||
processResult.stderr.decode('utf-8')))
|
||||
return processResult.stdout.decode('utf-8')
|
||||
|
||||
def executeSubprocess(processArgs, folder=None, env=None):
|
||||
restoreDir = None
|
||||
if folder != None:
|
||||
restoreDir = os.getcwd()
|
||||
os.chdir(folder)
|
||||
|
||||
process = subprocess.Popen(
|
||||
processArgs, stdout=sys.stdout, stderr=sys.stderr, env=env)
|
||||
process.wait()
|
||||
|
||||
if (0 != process.returncode):
|
||||
raise RuntimeError('Call to "{}" failed.\n\narguments:\n{}\n'.format(
|
||||
processArgs[0],
|
||||
' '.join(processArgs[1:]),
|
||||
))
|
||||
|
||||
if restoreDir != None:
|
||||
os.chdir(restoreDir)
|
||||
|
||||
|
||||
def hashFile(file, hasher = hashlib.sha512()):
|
||||
with open(file, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
hasher.update(chunk)
|
||||
return hasher.hexdigest()
|
||||
|
||||
# Assumes input files are in deterministic order
|
||||
def hashFiles(filenames):
|
||||
hasher = hashlib.sha256()
|
||||
for filename in filenames:
|
||||
with open(filename, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
hasher.update(chunk)
|
||||
return hasher.hexdigest()
|
||||
|
||||
def hashFolder(folder):
|
||||
filenames = recursiveFileList(folder)
|
||||
return hashFiles(filenames)
|
||||
|
||||
def downloadFile(url, hash=None, hasher=hashlib.sha512(), retries=3):
|
||||
for i in range(retries):
|
||||
tempFileName = None
|
||||
# OSX Python doesn't support SSL, so we need to bypass it.
|
||||
# However, we still validate the downloaded file's sha512 hash
|
||||
if 'Darwin' == platform.system():
|
||||
tempFileDescriptor, tempFileName = tempfile.mkstemp()
|
||||
context = ssl._create_unverified_context()
|
||||
with urllib.request.urlopen(url, context=context) as response, open(tempFileDescriptor, 'wb') as tempFile:
|
||||
shutil.copyfileobj(response, tempFile)
|
||||
else:
|
||||
tempFileName, headers = urllib.request.urlretrieve(url)
|
||||
|
||||
# for some reason the hash we get back from the downloaded file is sometimes wrong if we check it right away
|
||||
# but if we examine the file later, it is correct.
|
||||
time.sleep(3)
|
||||
downloadHash = hashFile(tempFileName, hasher)
|
||||
# Verify the hash
|
||||
if hash is not None and hash != downloadHash:
|
||||
print("Try {}: Downloaded file {} hash {} does not match expected hash {} for url {}".format(i + 1, tempFileName, downloadHash, hash, url))
|
||||
os.remove(tempFileName)
|
||||
continue
|
||||
|
||||
return tempFileName
|
||||
|
||||
raise RuntimeError("Downloaded file hash {} does not match expected hash {} for\n{}".format(downloadHash, hash, url))
|
||||
|
||||
|
||||
def downloadAndExtract(url, destPath, hash=None, hasher=hashlib.sha512(), isZip=False):
|
||||
tempFileName = downloadFile(url, hash, hasher)
|
||||
if isZip:
|
||||
with zipfile.ZipFile(tempFileName) as zip:
|
||||
zip.extractall(destPath)
|
||||
else:
|
||||
# Extract the archive
|
||||
with tarfile.open(tempFileName, 'r:gz') as tgz:
|
||||
tgz.extractall(destPath)
|
||||
os.remove(tempFileName)
|
216
hifi_vcpkg.py
Normal file
216
hifi_vcpkg.py
Normal file
|
@ -0,0 +1,216 @@
|
|||
import hifi_utils
|
||||
import hifi_android
|
||||
import hashlib
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
import functools
|
||||
|
||||
print = functools.partial(print, flush=True)
|
||||
|
||||
# Encapsulates the vcpkg system
|
||||
class VcpkgRepo:
|
||||
CMAKE_TEMPLATE = """
|
||||
set(CMAKE_TOOLCHAIN_FILE "{}" CACHE FILEPATH "Toolchain file")
|
||||
set(CMAKE_TOOLCHAIN_FILE_UNCACHED "{}")
|
||||
set(VCPKG_INSTALL_ROOT "{}")
|
||||
set(VCPKG_TOOLS_DIR "{}")
|
||||
"""
|
||||
|
||||
CMAKE_TEMPLATE_NON_ANDROID = """
|
||||
# If the cached cmake toolchain path is different from the computed one, exit
|
||||
if(NOT (CMAKE_TOOLCHAIN_FILE_UNCACHED STREQUAL CMAKE_TOOLCHAIN_FILE))
|
||||
message(FATAL_ERROR "CMAKE_TOOLCHAIN_FILE has changed, please wipe the build directory and rerun cmake")
|
||||
endif()
|
||||
"""
|
||||
|
||||
def __init__(self, args):
|
||||
self.args = args
|
||||
# our custom ports, relative to the script location
|
||||
self.sourcePortsPath = args.ports_path
|
||||
self.id = hifi_utils.hashFolder(self.sourcePortsPath)[:8]
|
||||
self.configFilePath = os.path.join(args.build_root, 'vcpkg.cmake')
|
||||
|
||||
# OS dependent information
|
||||
system = platform.system()
|
||||
|
||||
if self.args.vcpkg_root is not None:
|
||||
self.path = args.vcpkg_root
|
||||
else:
|
||||
if 'Darwin' == system:
|
||||
defaultBasePath = os.path.expanduser('~/hifi/vcpkg')
|
||||
else:
|
||||
defaultBasePath = os.path.join(tempfile.gettempdir(), 'hifi', 'vcpkg')
|
||||
self.basePath = os.getenv('HIFI_VCPKG_BASE', defaultBasePath)
|
||||
if self.basePath == defaultBasePath:
|
||||
print("Warning: Environment variable HIFI_VCPKG_BASE not set, using {}".format(defaultBasePath))
|
||||
if self.args.android:
|
||||
self.basePath = os.path.join(self.basePath, 'android')
|
||||
if (not os.path.isdir(self.basePath)):
|
||||
os.makedirs(self.basePath)
|
||||
self.path = os.path.join(self.basePath, self.id)
|
||||
|
||||
print("Using vcpkg path {}".format(self.path))
|
||||
lockDir, lockName = os.path.split(self.path)
|
||||
lockName += '.lock'
|
||||
if not os.path.isdir(lockDir):
|
||||
os.makedirs(lockDir)
|
||||
|
||||
self.lockFile = os.path.join(lockDir, lockName)
|
||||
self.tagFile = os.path.join(self.path, '.id')
|
||||
# A format version attached to the tag file... increment when you want to force the build systems to rebuild
|
||||
# without the contents of the ports changing
|
||||
self.version = 1
|
||||
self.tagContents = "{}_{}".format(self.id, self.version)
|
||||
|
||||
if 'Windows' == system:
|
||||
self.exe = os.path.join(self.path, 'vcpkg.exe')
|
||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-win32.tar.gz?versionId=YZYkDejDRk7L_hrK_WVFthWvisAhbDzZ'
|
||||
self.vcpkgHash = '3e0ff829a74956491d57666109b3e6b5ce4ed0735c24093884317102387b2cb1b2cd1ff38af9ed9173501f6e32ffa05cc6fe6d470b77a71ca1ffc3e0aa46ab9e'
|
||||
self.hostTriplet = 'x64-windows'
|
||||
elif 'Darwin' == system:
|
||||
self.exe = os.path.join(self.path, 'vcpkg')
|
||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-osx.tar.gz?versionId=_fhqSxjfrtDJBvEsQ8L_ODcdUjlpX9cc'
|
||||
self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d'
|
||||
self.hostTriplet = 'x64-osx'
|
||||
else:
|
||||
self.exe = os.path.join(self.path, 'vcpkg')
|
||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-linux.tar.gz?versionId=97Nazh24etEVKWz33XwgLY0bvxEfZgMU'
|
||||
self.vcpkgHash = '6a1ce47ef6621e699a4627e8821ad32528c82fce62a6939d35b205da2d299aaa405b5f392df4a9e5343dd6a296516e341105fbb2dd8b48864781d129d7fba10d'
|
||||
self.hostTriplet = 'x64-linux'
|
||||
|
||||
if self.args.android:
|
||||
self.triplet = 'arm64-android'
|
||||
self.androidPackagePath = os.path.join(self.path, 'android')
|
||||
else:
|
||||
self.triplet = self.hostTriplet
|
||||
|
||||
def upToDate(self):
|
||||
# Prevent doing a clean if we've explcitly set a directory for vcpkg
|
||||
if self.args.vcpkg_root is not None:
|
||||
return True
|
||||
|
||||
if self.args.force_build:
|
||||
print("Force build, out of date")
|
||||
return False
|
||||
if not os.path.isfile(self.exe):
|
||||
print("Exe file {} not found, out of date".format(self.exe))
|
||||
return False
|
||||
if not os.path.isfile(self.tagFile):
|
||||
print("Tag file {} not found, out of date".format(self.tagFile))
|
||||
return False
|
||||
with open(self.tagFile, 'r') as f:
|
||||
storedTag = f.read()
|
||||
if storedTag != self.tagContents:
|
||||
print("Tag file {} contents don't match computed tag {}, out of date".format(self.tagFile, self.tagContents))
|
||||
return False
|
||||
return True
|
||||
|
||||
def clean(self):
|
||||
print("Cleaning vcpkg installation at {}".format(self.path))
|
||||
if os.path.isdir(self.path):
|
||||
print("Removing {}".format(self.path))
|
||||
shutil.rmtree(self.path, ignore_errors=True)
|
||||
|
||||
# Make sure the VCPKG prerequisites are all there.
|
||||
def bootstrap(self):
|
||||
if self.upToDate():
|
||||
return
|
||||
|
||||
self.clean()
|
||||
|
||||
downloadVcpkg = False
|
||||
if self.args.force_bootstrap:
|
||||
print("Forcing bootstrap")
|
||||
downloadVcpkg = True
|
||||
|
||||
if not downloadVcpkg and not os.path.isfile(self.exe):
|
||||
print("Missing executable, boostrapping")
|
||||
downloadVcpkg = True
|
||||
|
||||
# Make sure we have a vcpkg executable
|
||||
testFile = os.path.join(self.path, '.vcpkg-root')
|
||||
if not downloadVcpkg and not os.path.isfile(testFile):
|
||||
print("Missing {}, bootstrapping".format(testFile))
|
||||
downloadVcpkg = True
|
||||
|
||||
if downloadVcpkg:
|
||||
print("Fetching vcpkg from {} to {}".format(self.vcpkgUrl, self.path))
|
||||
hifi_utils.downloadAndExtract(self.vcpkgUrl, self.path, self.vcpkgHash)
|
||||
|
||||
print("Replacing port files")
|
||||
portsPath = os.path.join(self.path, 'ports')
|
||||
if (os.path.islink(portsPath)):
|
||||
os.unlink(portsPath)
|
||||
if (os.path.isdir(portsPath)):
|
||||
shutil.rmtree(portsPath, ignore_errors=True)
|
||||
shutil.copytree(self.sourcePortsPath, portsPath)
|
||||
|
||||
def run(self, commands):
|
||||
actualCommands = [self.exe, '--vcpkg-root', self.path]
|
||||
actualCommands.extend(commands)
|
||||
print("Running command")
|
||||
print(actualCommands)
|
||||
hifi_utils.executeSubprocess(actualCommands, folder=self.path)
|
||||
|
||||
def setupDependencies(self):
|
||||
# Special case for android, grab a bunch of binaries
|
||||
# FIXME remove special casing for android builds eventually
|
||||
if self.args.android:
|
||||
print("Installing Android binaries")
|
||||
self.setupAndroidDependencies()
|
||||
|
||||
print("Installing host tools")
|
||||
self.run(['install', '--triplet', self.hostTriplet, 'hifi-host-tools'])
|
||||
|
||||
# If not android, install the hifi-client-deps libraries
|
||||
if not self.args.android:
|
||||
print("Installing build dependencies")
|
||||
self.run(['install', '--triplet', self.triplet, 'hifi-client-deps'])
|
||||
|
||||
def cleanBuilds(self):
|
||||
# Remove temporary build artifacts
|
||||
builddir = os.path.join(self.path, 'buildtrees')
|
||||
if os.path.isdir(builddir):
|
||||
print("Wiping build trees")
|
||||
shutil.rmtree(builddir, ignore_errors=True)
|
||||
|
||||
def setupAndroidDependencies(self):
|
||||
# vcpkg prebuilt
|
||||
if not os.path.isdir(os.path.join(self.path, 'installed', 'arm64-android')):
|
||||
dest = os.path.join(self.path, 'installed')
|
||||
url = "https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-arm64-android.tar.gz"
|
||||
# FIXME I don't know why the hash check frequently fails here. If you examine the file later it has the right hash
|
||||
#hash = "832f82a4d090046bdec25d313e20f56ead45b54dd06eee3798c5c8cbdd64cce4067692b1c3f26a89afe6ff9917c10e4b601c118bea06d23f8adbfe5c0ec12bc3"
|
||||
#hifi_utils.downloadAndExtract(url, dest, hash)
|
||||
hifi_utils.downloadAndExtract(url, dest)
|
||||
|
||||
def writeTag(self):
|
||||
print("Writing tag {} to {}".format(self.tagContents, self.tagFile))
|
||||
with open(self.tagFile, 'w') as f:
|
||||
f.write(self.tagContents)
|
||||
|
||||
def writeConfig(self):
|
||||
print("Writing cmake config to {}".format(self.configFilePath))
|
||||
# Write out the configuration for use by CMake
|
||||
cmakeScript = os.path.join(self.path, 'scripts/buildsystems/vcpkg.cmake')
|
||||
installPath = os.path.join(self.path, 'installed', self.triplet)
|
||||
toolsPath = os.path.join(self.path, 'installed', self.hostTriplet, 'tools')
|
||||
cmakeTemplate = VcpkgRepo.CMAKE_TEMPLATE
|
||||
if not self.args.android:
|
||||
cmakeTemplate += VcpkgRepo.CMAKE_TEMPLATE_NON_ANDROID
|
||||
cmakeConfig = cmakeTemplate.format(cmakeScript, cmakeScript, installPath, toolsPath).replace('\\', '/')
|
||||
with open(self.configFilePath, 'w') as f:
|
||||
f.write(cmakeConfig)
|
||||
|
||||
def cleanOldBuilds(self):
|
||||
# FIXME because we have the base directory, and because a build will
|
||||
# update the tag file on every run, we can scan the base dir for sub directories containing
|
||||
# a tag file that is older than N days, and if found, delete the directory, recovering space
|
||||
print("Not implemented")
|
||||
|
||||
|
|
@ -802,7 +802,7 @@ Menu::Menu() {
|
|||
connect(action, &QAction::triggered, qApp, []() { std::thread(crash::newFault).join(); });
|
||||
|
||||
// Developer > Show Statistics
|
||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats);
|
||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats, 0, true);
|
||||
|
||||
// Developer > Show Animation Statistics
|
||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AnimStats);
|
||||
|
|
304
prebuild.py
304
prebuild.py
|
@ -1,5 +1,26 @@
|
|||
#!python
|
||||
|
||||
# The prebuild script is intended to simplify life for developers and dev-ops. It's repsonsible for acquiring
|
||||
# tools required by the build as well as dependencies on which we rely.
|
||||
#
|
||||
# By using this script, we can reduce the requirements for a developer getting started to:
|
||||
#
|
||||
# * A working C++ dev environment like visual studio, xcode, gcc, or clang
|
||||
# * Qt
|
||||
# * CMake
|
||||
# * Python 3.x
|
||||
#
|
||||
# The function of the build script is to acquire, if not already present, all the other build requirements
|
||||
# The build script should be idempotent. If you run it with the same arguments multiple times, that should
|
||||
# have no negative impact on the subsequent build times (i.e. re-running the prebuild script should not
|
||||
# trigger a header change that causes files to be rebuilt). Subsequent runs after the first run should
|
||||
# execute quickly, determining that no work is to be done
|
||||
|
||||
import hifi_singleton
|
||||
import hifi_utils
|
||||
import hifi_android
|
||||
import hifi_vcpkg
|
||||
|
||||
import argparse
|
||||
import concurrent
|
||||
import hashlib
|
||||
|
@ -9,252 +30,65 @@ import os
|
|||
import platform
|
||||
import shutil
|
||||
import ssl
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import re
|
||||
import tempfile
|
||||
import time
|
||||
import urllib.request
|
||||
import functools
|
||||
|
||||
print = functools.partial(print, flush=True)
|
||||
|
||||
def executeSubprocess(processArgs, folder=None, env=None):
|
||||
restoreDir = None
|
||||
if folder != None:
|
||||
restoreDir = os.getcwd()
|
||||
os.chdir(folder)
|
||||
|
||||
process = subprocess.Popen(
|
||||
processArgs, stdout=sys.stdout, stderr=sys.stderr, env=env)
|
||||
process.wait()
|
||||
|
||||
if (0 != process.returncode):
|
||||
raise RuntimeError('Call to "{}" failed.\n\narguments:\n{}\n'.format(
|
||||
processArgs[0],
|
||||
' '.join(processArgs[1:]),
|
||||
))
|
||||
|
||||
if restoreDir != None:
|
||||
os.chdir(restoreDir)
|
||||
|
||||
|
||||
def hashFile(file):
|
||||
hasher = hashlib.sha512()
|
||||
with open(file, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
hasher.update(chunk)
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def hashFolder(folder):
|
||||
hasher = hashlib.sha256()
|
||||
for dirName, subdirList, fileList in os.walk(folder):
|
||||
for fname in fileList:
|
||||
with open(os.path.join(folder, dirName, fname), "rb") as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
hasher.update(chunk)
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def downloadAndExtract(url, destPath, hash=None):
|
||||
tempFileDescriptor, tempFileName = tempfile.mkstemp()
|
||||
# OSX Python doesn't support SSL, so we need to bypass it.
|
||||
# However, we still validate the downloaded file's sha512 hash
|
||||
context = ssl._create_unverified_context()
|
||||
with urllib.request.urlopen(url, context=context) as response, open(tempFileDescriptor, 'wb') as tempFile:
|
||||
shutil.copyfileobj(response, tempFile)
|
||||
|
||||
# Verify the hash
|
||||
if hash and hash != hashFile(tempFileName):
|
||||
raise RuntimeError("Downloaded file does not match hash")
|
||||
|
||||
# Extract the archive
|
||||
with tarfile.open(tempFileName, 'r:gz') as tgz:
|
||||
tgz.extractall(destPath)
|
||||
os.remove(tempFileName)
|
||||
|
||||
|
||||
class VcpkgRepo:
|
||||
def __init__(self):
|
||||
global args
|
||||
scriptPath = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
# our custom ports, relative to the script location
|
||||
self.sourcePortsPath = os.path.join(scriptPath, 'cmake', 'ports')
|
||||
# FIXME Revert to ports hash before release
|
||||
self.id = hashFolder(self.sourcePortsPath)[:8]
|
||||
# OS dependent information
|
||||
system = platform.system()
|
||||
|
||||
if args.vcpkg_root is not None:
|
||||
print("override vcpkg path with " + args.vcpkg_root)
|
||||
self.path = args.vcpkg_root
|
||||
else:
|
||||
if 'Darwin' == system:
|
||||
defaultBasePath = os.path.expanduser('~/hifi/vcpkg')
|
||||
else:
|
||||
defaultBasePath = os.path.join(tempfile.gettempdir(), 'hifi', 'vcpkg')
|
||||
basePath = os.getenv('HIFI_VCPKG_BASE', defaultBasePath)
|
||||
if (not os.path.isdir(basePath)):
|
||||
os.makedirs(basePath)
|
||||
self.path = os.path.join(basePath, self.id)
|
||||
|
||||
self.tagFile = os.path.join(self.path, '.id')
|
||||
# A format version attached to the tag file... increment when you want to force the build systems to rebuild
|
||||
# without the contents of the ports changing
|
||||
self.version = 1
|
||||
self.tagContents = "{}_{}".format(self.id, self.version)
|
||||
|
||||
print("prebuild path: " + self.path)
|
||||
if 'Windows' == system:
|
||||
self.exe = os.path.join(self.path, 'vcpkg.exe')
|
||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-win32.tar.gz?versionId=YZYkDejDRk7L_hrK_WVFthWvisAhbDzZ'
|
||||
self.vcpkgHash = '3e0ff829a74956491d57666109b3e6b5ce4ed0735c24093884317102387b2cb1b2cd1ff38af9ed9173501f6e32ffa05cc6fe6d470b77a71ca1ffc3e0aa46ab9e'
|
||||
self.hostTriplet = 'x64-windows'
|
||||
elif 'Darwin' == system:
|
||||
self.exe = os.path.join(self.path, 'vcpkg')
|
||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-osx.tar.gz?versionId=_fhqSxjfrtDJBvEsQ8L_ODcdUjlpX9cc'
|
||||
self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d'
|
||||
self.hostTriplet = 'x64-osx'
|
||||
else:
|
||||
self.exe = os.path.join(self.path, 'vcpkg')
|
||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-linux.tar.gz?versionId=97Nazh24etEVKWz33XwgLY0bvxEfZgMU'
|
||||
self.vcpkgHash = '6a1ce47ef6621e699a4627e8821ad32528c82fce62a6939d35b205da2d299aaa405b5f392df4a9e5343dd6a296516e341105fbb2dd8b48864781d129d7fba10d'
|
||||
self.hostTriplet = 'x64-linux'
|
||||
|
||||
if args.android:
|
||||
self.triplet = 'arm64-android'
|
||||
else:
|
||||
self.triplet = self.hostTriplet
|
||||
|
||||
def outOfDate(self):
|
||||
global args
|
||||
# Prevent doing a clean if we've explcitly set a directory for vcpkg
|
||||
if args.vcpkg_root is not None:
|
||||
return False
|
||||
if args.force_build:
|
||||
return True
|
||||
print("Looking for tag file {}".format(self.tagFile))
|
||||
if not os.path.isfile(self.tagFile):
|
||||
return True
|
||||
with open(self.tagFile, 'r') as f:
|
||||
storedTag = f.read()
|
||||
print("Found stored tag {}".format(storedTag))
|
||||
if storedTag != self.tagContents:
|
||||
print("Doesn't match computed tag {}".format(self.tagContents))
|
||||
return True
|
||||
return False
|
||||
|
||||
def clean(self):
|
||||
cleanPath = self.path
|
||||
print("Cleaning vcpkg installation at {}".format(cleanPath))
|
||||
if os.path.isdir(self.path):
|
||||
print("Removing {}".format(cleanPath))
|
||||
shutil.rmtree(cleanPath, ignore_errors=True)
|
||||
|
||||
def bootstrap(self):
|
||||
global args
|
||||
if self.outOfDate():
|
||||
self.clean()
|
||||
|
||||
# don't download the vcpkg binaries if we're working with an explicit
|
||||
# vcpkg directory (possibly a git checkout)
|
||||
if args.vcpkg_root is None:
|
||||
downloadVcpkg = False
|
||||
if args.force_bootstrap:
|
||||
print("Forcing bootstrap")
|
||||
downloadVcpkg = True
|
||||
|
||||
if not downloadVcpkg and not os.path.isfile(self.exe):
|
||||
print("Missing executable, boostrapping")
|
||||
downloadVcpkg = True
|
||||
|
||||
# Make sure we have a vcpkg executable
|
||||
testFile = os.path.join(self.path, '.vcpkg-root')
|
||||
if not downloadVcpkg and not os.path.isfile(testFile):
|
||||
print("Missing {}, bootstrapping".format(testFile))
|
||||
downloadVcpkg = True
|
||||
|
||||
if downloadVcpkg:
|
||||
print("Fetching vcpkg from {} to {}".format(self.vcpkgUrl, self.path))
|
||||
downloadAndExtract(self.vcpkgUrl, self.path, self.vcpkgHash)
|
||||
|
||||
print("Replacing port files")
|
||||
portsPath = os.path.join(self.path, 'ports')
|
||||
if (os.path.islink(portsPath)):
|
||||
os.unlink(portsPath)
|
||||
if (os.path.isdir(portsPath)):
|
||||
shutil.rmtree(portsPath, ignore_errors=True)
|
||||
shutil.copytree(self.sourcePortsPath, portsPath)
|
||||
|
||||
def downloadAndroidDependencies(self):
|
||||
url = "https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-arm64-android.tar.gz"
|
||||
hash = "832f82a4d090046bdec25d313e20f56ead45b54dd06eee3798c5c8cbdd64cce4067692b1c3f26a89afe6ff9917c10e4b601c118bea06d23f8adbfe5c0ec12bc3"
|
||||
dest = os.path.join(self.path, 'installed')
|
||||
downloadAndExtract(url, dest, hash)
|
||||
|
||||
def run(self, commands):
|
||||
actualCommands = [self.exe, '--vcpkg-root', self.path]
|
||||
actualCommands.extend(commands)
|
||||
print("Running command")
|
||||
print(actualCommands)
|
||||
executeSubprocess(actualCommands, folder=self.path)
|
||||
|
||||
def buildDependencies(self):
|
||||
global args
|
||||
print("Installing host tools")
|
||||
self.run(['install', '--triplet', self.hostTriplet, 'hifi-host-tools'])
|
||||
# Special case for android, grab a bunch of binaries
|
||||
if args.android:
|
||||
self.downloadAndroidDependencies()
|
||||
return
|
||||
|
||||
print("Installing build dependencies")
|
||||
self.run(['install', '--triplet', self.triplet, 'hifi-client-deps'])
|
||||
# Remove temporary build artifacts
|
||||
builddir = os.path.join(self.path, 'buildtrees')
|
||||
if os.path.isdir(builddir):
|
||||
print("Wiping build trees")
|
||||
shutil.rmtree(builddir, ignore_errors=True)
|
||||
|
||||
def writeConfig(self):
|
||||
global args
|
||||
configFilePath = os.path.join(args.build_root, 'vcpkg.cmake')
|
||||
print("Writing cmake config to {}".format(configFilePath))
|
||||
# Write out the configuration for use by CMake
|
||||
cmakeScript = os.path.join(self.path, 'scripts/buildsystems/vcpkg.cmake')
|
||||
installPath = os.path.join(self.path, 'installed', self.triplet)
|
||||
toolsPath = os.path.join(self.path, 'installed', self.hostTriplet, 'tools')
|
||||
cmakeTemplate = 'set(CMAKE_TOOLCHAIN_FILE "{}" CACHE FILEPATH "Toolchain file")\n'
|
||||
cmakeTemplate += 'set(VCPKG_INSTALL_ROOT "{}" CACHE FILEPATH "vcpkg installed packages path")\n'
|
||||
cmakeTemplate += 'set(VCPKG_TOOLS_DIR "{}" CACHE FILEPATH "vcpkg installed packages path")\n'
|
||||
cmakeConfig = cmakeTemplate.format(cmakeScript, installPath, toolsPath).replace('\\', '/')
|
||||
with open(configFilePath, 'w') as f:
|
||||
f.write(cmakeConfig)
|
||||
|
||||
def writeTag(self):
|
||||
print("Writing tag {} to {}".format(self.tagContents, self.tagFile))
|
||||
with open(self.tagFile, 'w') as f:
|
||||
f.write(self.tagContents)
|
||||
def parse_args():
|
||||
# our custom ports, relative to the script location
|
||||
defaultPortsPath = hifi_utils.scriptRelative('cmake', 'ports')
|
||||
from argparse import ArgumentParser
|
||||
parser = ArgumentParser(description='Prepare build dependencies.')
|
||||
parser.add_argument('--android', action='store_true')
|
||||
#parser.add_argument('--android', type=str)
|
||||
parser.add_argument('--debug', action='store_true')
|
||||
parser.add_argument('--force-bootstrap', action='store_true')
|
||||
parser.add_argument('--force-build', action='store_true')
|
||||
parser.add_argument('--vcpkg-root', type=str, help='The location of the vcpkg distribution')
|
||||
parser.add_argument('--build-root', required=True, type=str, help='The location of the cmake build')
|
||||
parser.add_argument('--ports-path', type=str, default=defaultPortsPath)
|
||||
if True:
|
||||
args = parser.parse_args()
|
||||
else:
|
||||
args = parser.parse_args(['--android', 'questInterface', '--build-root', 'C:/git/hifi/android/apps/questInterface/.externalNativeBuild/cmake/debug/arm64-v8a'])
|
||||
return args
|
||||
|
||||
def main():
|
||||
vcpkg = VcpkgRepo()
|
||||
vcpkg.bootstrap()
|
||||
vcpkg.buildDependencies()
|
||||
vcpkg.writeConfig()
|
||||
vcpkg.writeTag()
|
||||
# Fixup env variables. Leaving `USE_CCACHE` on will cause scribe to fail to build
|
||||
# VCPKG_ROOT seems to cause confusion on Windows systems that previously used it for
|
||||
# building OpenSSL
|
||||
removeEnvVars = ['VCPKG_ROOT', 'USE_CCACHE']
|
||||
for var in removeEnvVars:
|
||||
if var in os.environ:
|
||||
del os.environ[var]
|
||||
|
||||
args = parse_args()
|
||||
# Only allow one instance of the program to run at a time
|
||||
pm = hifi_vcpkg.VcpkgRepo(args)
|
||||
with hifi_singleton.Singleton(pm.lockFile) as lock:
|
||||
if not pm.upToDate():
|
||||
pm.bootstrap()
|
||||
|
||||
# Always write the tag, even if we changed nothing. This
|
||||
# allows vcpkg to reclaim disk space by identifying directories with
|
||||
# tags that haven't been touched in a long time
|
||||
pm.writeTag()
|
||||
|
||||
from argparse import ArgumentParser
|
||||
parser = ArgumentParser(description='Prepare build dependencies.')
|
||||
parser.add_argument('--android', action='store_true')
|
||||
parser.add_argument('--debug', action='store_true')
|
||||
parser.add_argument('--force-bootstrap', action='store_true')
|
||||
parser.add_argument('--force-build', action='store_true')
|
||||
parser.add_argument('--vcpkg-root', type=str, help='The location of the vcpkg distribution')
|
||||
parser.add_argument('--build-root', required=True, type=str, help='The location of the cmake build')
|
||||
# Grab our required dependencies:
|
||||
# * build host tools, like spirv-cross and scribe
|
||||
# * build client dependencies like openssl and nvtt
|
||||
pm.setupDependencies()
|
||||
|
||||
args = parser.parse_args()
|
||||
# wipe out the build directories (after writing the tag, since failure
|
||||
# here shouldn't invalidte the vcpkg install)
|
||||
pm.cleanBuilds()
|
||||
|
||||
# Write the vcpkg config to the build directory last
|
||||
pm.writeConfig()
|
||||
|
||||
print(sys.argv)
|
||||
main()
|
||||
|
||||
|
|
Loading…
Reference in a new issue