At Sentio, we reach to the point that we have to support our hardware, that is we update firmware from our app. All the native code was compiled with gradle successfully on my machine until I pushed. A question popped up, how it would work on CI since local.properties
is ignored from git.
With that being said, the first error message appeared on CI
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':firmware'.
> NDK not configured.
After having googled, CirleCI 2.0 currently doesn’t have pre-built NDK which means it’s required to download NDK or use a custom docker image
with an NDK image.
1. Download NDK
circleCiEnvironmentSetup.sh
function getAndroidNDK { ANDROID_HOME="/opt/android/sdk"
ANDROID_NDK="$ANDROID_HOME/android-ndk-r16b"
echo 'export ANDROID_NDK=$ANDROID_HOME/android-ndk-r16b' >> $BASH_ENV
echo 'export ANDROID_NDK_HOME=$ANDROID_HOME/ndk-bundle/' >> $BASH_ENV
if [ ! -e ANDROID_NDK ]; then
cd $ANDROID_HOME
echo "Downloading NDK..."
sudo curl -L -o ndk.zip https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip
unzip -o -q ndk.zip
mv android-ndk-r16b ndk-bundle
echo "Installed Android NDK at $ANDROID_NDK"
sudo rm ndk.zip
fi
}
Since the SDK is location in a restricted directory, it is obligatory to add sudo
for some operations. The idea of the script is to download the NDK, unzip as ndk-bundle
. The most important point to note is the NDK must be located in the SDK. An example on my local machine
ndk.dir=/Users/***/Library/Android/sdk/ndk-bundle
sdk.dir=/Users/***/Library/Android/sdk
Otherwise, you may see a message
NDK is missing a "platforms" directory.
If you are using NDK, verify the ndk.dir is set to a valid NDK directory. It is currently set to /opt/android/sdk/android-ndk-r16b.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.
Googling in this case does not help me. Some answers are Android Studio 2.3 bug. The others are guide to set up NDK by GUI.
Last but not least, an environment variable must be named ANDROID_NDK_HOME
containing the NDK path.
Next step
config.yml
- run:
name: Install Android NDK
command: source ./script/circleCiEnvironmentSetup.sh && getAndroidNDK
2. Docker
If you are familiar with Docker or just want to play with it. Your docker file must support both SDK and NDK. It is because I tried to compose
with a NDK image
docker:
- image: circleci/android:api-27-alpha
- image: circleci/openjdk:8-jdk
- image: bitriseio/android-ndk:latest
but ended up
If you have your custom image, your config.yml
should be
docker:
- image: path // your path on docker hub
circleci/android:api-27-alpha
is removed as well.
An dockerfile example
FROM openjdk:8-jdk
RUN mkdir -p /opt/android-sdk-linux && mkdir -p ~/.android && touch ~/.android/repositories.cfg
WORKDIR /opt
ENV ANDROID_HOME /opt/android-sdk-linux
ENV PATH ${PATH}:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools:${PATH}:${ANDROID_HOME}/tools
ENV ANDROID_NDK /opt/android-ndk-linux
ENV ANDROID_NDK_HOME /opt/android-ndk-linux
RUN apt-get update && apt-get install -y --no-install-recommends \
unzip \
wget
RUN cd /opt/android-sdk-linux && \
wget -q --output-document=sdk-tools.zip https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip && \
unzip sdk-tools.zip && \
rm -f sdk-tools.zip && \
echo y | sdkmanager "build-tools;27.0.3" "platforms;android-27" && \
echo y | sdkmanager "extras;android;m2repository" "extras;google;m2repository" "extras;google;google_play_services" && \
sdkmanager "cmake;3.6.4111459"
RUN wget -q --output-document=android-ndk.zip https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip && \
unzip android-ndk.zip && \
rm -f android-ndk.zip && \
mv android-ndk-r16b android-ndk-linux
Conclusion
After having spent a few hours fixing CircleCI with frustration, even though devOps does not sounds interesting, it was a great experience for me to learn new things. Happy Android coding 🎉🎉🎉🎉🎉 .