Skip to content

Commit

Permalink
have a shell script that packages things; still annoyingly needs a pa…
Browse files Browse the repository at this point in the history
…ssword for the keystore; maybe can use a non-java key management structure next time.
  • Loading branch information
ixchow committed Nov 13, 2023
1 parent 2212a57 commit 799bb6d
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 122 deletions.
131 changes: 97 additions & 34 deletions Maekfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,44 +182,69 @@ const android_options = {
};


maek.CPP('main.cpp', android_options);

const android_game_objs = game_sources.map((x) => maek.CPP(x, undefined, android_options));
const android_common_objs = common_sources.map((x) => maek.CPP(x, undefined, android_options));

const android_game_so = maek.LINK([...android_game_objs, ...android_common_objs], 'dist-android/apk/lib/arm64-v8a/libgame.so', android_options);
const android_game_so = maek.LINK([...android_game_objs, ...android_common_objs], 'objs/android/apk/lib/arm64-v8a/libgame.so', android_options);

//quick generic "RULE" for running commands with maek:
// [outFiles] = maek.RULE([outFile0, outFile1, ...], [inFile0, inFile1, ...], command, [desc])
maek.RULE = (outFiles, inFiles, command, desc = "run") => {
const task = async () => {
for (const outFile of outFiles) {
await fsPromises.mkdir(path.dirname(outFile), { recursive: true });
}
await run(command, `${task.label}: ${desc} [${idx} of ${commands.length+1}]`,
async () => {
return {
read:[...inFiles],
written:[...outFiles]
};
}
);
};
const ovr_openxr_loader_so = maek.COPY('../ovr-openxr-sdk/OpenXR/Libs/Android/arm64-v8a/Release/libopenxr_loader.so', 'objs/android/apk/lib/arm64-v8a/libopenxr_loader.so');

task.depends = [...inFiles];
task.label = `RULE {${inFiles.join(", ")}}`;

for (outFile of outFiles) {
if (outFile in maek.tasks) {
throw new Error(`Task ${task.label} purports to create ${outFile}, but ${maek.tasks[outFile].label} already creates that file.`);
const AAPT2 = `../android-sdk/build-tools/30.0.3/aapt2`;

const apkFile = `android/game.apk`;

const android_icons = [ ];
for (const dpi of ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi', 'xxxhdpi']) {
const inFile = `android/res/mipmap-${dpi}/gp-icon.png`;
const outFile = `objs/android/apk/mipmap-${dpi}_gp-icon.png.flat`;
const command = [AAPT2, 'compile', '-o', 'objs/android/apk', '-v', inFile];
android_icons.push( ...maek.RULE( [outFile], [inFile], command, "aapt compile" ) );
}

//basically just the shell script, transcribed:

const package_apk_task = async () => {

const proc = child_process.spawnSync(
[AAPT2,
);
//make object file:
await fsPromises.mkdir(path.dirname(objFile), { recursive: true });
await fsPromises.mkdir(path.dirname(depsFile), { recursive: true });
await run(command, `${task.label}: compile + prerequisites`,
async () => {
return {
read:[...await loadDeps()],
written:[objFile, depsFile]
};
}
maek.tasks[outFile] = task;
}
return outFiles;
);
};
package_apk_task.depends = [android_game_so, ovr_openxr_loader_so, android_icons];
package_apk_task.label = `PACKAGE ${apkFile}`;
maek.tasks[apkFile] = task;


maek.TARGETS = [android_game_so]; //DEBUG


const android_apk = maek.RULE(
[`dist-android/game.apk`],
[android_game_so, ...android_icons, 'android/AndroidManifest.xml'],
['../../../' + AAPT2, 'link',
'-o', 'dist-android/game.apk',
'-I', `../android-sdk/platforms/android-29/android.jar`,
...android_icons,
android_game_so,
'--manifest', 'android/AndroidManifest.xml',
//'-A', 'objs/android/apk',
'-v'
],
{label:"aapt link", cwd:'objs/android/apk'}
);


maek.TARGETS = [android_apk]; //DEBUG


//======================================================================
Expand Down Expand Up @@ -350,6 +375,42 @@ function init_maek() {
return dstFile;
};

//RULE adds a generic task:
// outFiles is an array of output files
// inFiles is an array of input files
// command is a command (as an array of [program, arg1, arg2, ...]
// options:
// label: printed during rule execution
// cwd: working directory for command (if not this directory)
//returns a copy of outFiles
// [outFiles] = maek.RULE([outFile0, outFile1, ...], [inFile0, inFile1, ...], command, [desc])
maek.RULE = (outFiles, inFiles, command, {label='run', cwd=''}) => {
const task = async () => {
for (const outFile of outFiles) {
await fsPromises.mkdir(path.dirname(outFile), { recursive: true });
}
await run(command, `${task.label}: ${label}`,
async () => {
return {
read:[...inFiles],
written:[...outFiles]
};
},
cwd
);
};

task.depends = [...inFiles];
task.label = `RULE {${outFiles.join(", ")}}`;
for (outFile of outFiles) {
if (outFile in maek.tasks) {
throw new Error(`Task ${task.label} purports to create ${outFile}, but ${maek.tasks[outFile].label} already creates that file.`);
}
maek.tasks[outFile] = task;
}
return outFiles;
};


//maek.CPP makes an object from a c++ source file:
// cppFile is the source file name
Expand Down Expand Up @@ -526,13 +587,14 @@ function init_maek() {
//runs a shell command (presented as an array)
// 'message' will be displayed above the command
// 'cacheInfoFn', if provided, will be called after function is run to determine which files to hash when caching the result
async function run(command, message, cacheInfoFn) {
// 'cwd' is the working directory for the command
async function run(command, message, cacheInfoFn, cwd='.') {

//cache key for the command -- encoded command name:
const cacheKey = JSON.stringify(command);
const cacheKey = JSON.stringify([cwd, ...command]);

//executable for the command:
const exe = await findExe(command);
const exe = await findExe(command, cwd);

//if no cache info function, remove any existing cache entry:
if (!cacheInfoFn) {
Expand Down Expand Up @@ -577,7 +639,8 @@ function init_maek() {
await new Promise((resolve, reject) => {
const proc = child_process.spawn(command[0], command.slice(1), {
shell: false,
stdio: ['ignore', 'inherit', 'inherit']
stdio: ['ignore', 'inherit', 'inherit'],
cwd: cwd
});
proc.on('exit', (code, signal) => {
if (code !== 0) {
Expand Down Expand Up @@ -665,13 +728,13 @@ function init_maek() {

//find an executable in the system path
// (used by run to figure out what to hash)
async function findExe(command) {
async function findExe(command, cwd='.') {
const osPath = require('path');

let PATH;
//any command with a path separator is looked up directly:
if (command[0].includes(osPath.sep)) {
PATH = [''];
PATH = [cwd];
} else {
if (maek.OS === 'windows') {
PATH = process.env.PATH.split(';');
Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,12 @@ $ ./platform-tools/adb devices
# shows "unauthorized" and causes the "allow debugging" dialog to pop on the headset
# if dialog accepted, says "device" next to the device (maybe that's the device name?)
$ ./platform-tools/adb devices
# if you like to explore a bit, get a shell on your device:
$ ./platform-tools/adb shell
# interesting things include `top` (see what's running), `cat /proc/cpuinfo` (learn more about the cpu)
#(ctrl-d to exit)
```

## Building
Expand All @@ -109,6 +111,34 @@ $ ./platform-tools/adb shell

## OpenXR Notes

## Installing on Android


Basic install + run workflow:
```
#from this folder, after building and packaging:
#install the app:
$ ../android-sdk/platform-tools/adb install -r dist-android/game.apk
#start the app:
$ ../android-sdk/platform-tools/adb shell am start --activity-clear-top -n "com.tchow.game/android.app.NativeActivity"
```

For checking things are okay:
```
#print system log: (note -- can filter)
$ ../android-sdk/platform-tools/adb logcat
#version with some filtering:
$ ../android-sdk/platform-tools/adb logcat *:E OpenXR:I
#see what's installed:
$ ../android-sdk/platform-tools/adb shell pm list packages
#uninstall the app:
$ ../android-sdk/platform-tools/adb uninstall com.tchow.com
```



## EXTRA NOTES
Expand Down
2 changes: 1 addition & 1 deletion android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
android:allowBackup="true"
android:hasCode="false"
android:icon="@mipmap/gp-icon"
android:label="@string/app_name"
android:label="gp23 openxr example"
android:roundIcon="@mipmap/gp-icon">

<!-- The activity is the built-in NativeActivity framework class. -->
Expand Down
48 changes: 48 additions & 0 deletions android/build-apk.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/sh

#based on https://stackoverflow.com/questions/59504840/create-jni-ndk-apk-only-command-line-without-gradle-ant-or-cmake

ANDROID_SDK=../../android-sdk
AAPT2=$ANDROID_SDK/build-tools/30.0.3/aapt2
AAPT=$ANDROID_SDK/build-tools/30.0.3/aapt
ZIPALIGN=$ANDROID_SDK/build-tools/30.0.3/zipalign
APKSIGNER=$ANDROID_SDK/build-tools/30.0.3/apksigner

mkdir -p ../objs/android/apk

"$AAPT2" compile -o ../objs/android/apk -v res/mipmap-mdpi/gp-icon.png
"$AAPT2" compile -o ../objs/android/apk -v res/mipmap-hdpi/gp-icon.png
"$AAPT2" compile -o ../objs/android/apk -v res/mipmap-xhdpi/gp-icon.png
"$AAPT2" compile -o ../objs/android/apk -v res/mipmap-xxhdpi/gp-icon.png
"$AAPT2" compile -o ../objs/android/apk -v res/mipmap-xxxhdpi/gp-icon.png

rm -f ../objs/android/unsigned.apk
rm -f ../objs/android/aligned.apk
rm -f ../dist-android/game.apk

"$AAPT2" link \
-o ../objs/android/unsigned.apk \
-I $ANDROID_SDK/platforms/android-29/android.jar \
../objs/android/apk/mipmap-mdpi_gp-icon.png.flat \
../objs/android/apk/mipmap-hdpi_gp-icon.png.flat \
../objs/android/apk/mipmap-xhdpi_gp-icon.png.flat \
../objs/android/apk/mipmap-xxhdpi_gp-icon.png.flat \
../objs/android/apk/mipmap-xxxhdpi_gp-icon.png.flat \
--manifest AndroidManifest.xml \
-v

cp ../../ovr-openxr-sdk/OpenXR/Libs/Android/arm64-v8a/Release/libopenxr_loader.so ../objs/android/apk/lib/arm64-v8a/

cd ../objs/android/apk
"../../../android/$AAPT" add ../unsigned.apk lib/arm64-v8a/libgame.so
"../../../android/$AAPT" add ../unsigned.apk lib/arm64-v8a/libopenxr_loader.so
cd ../../../android

"$ZIPALIGN" -f -p 4 "../objs/android/unsigned.apk" "../objs/android/aligned.apk"

#keytool -genkeypair -keystore "../objs/android/keystore.jks" -alias androidkey -validity 10000 -keyalg RSA -keysize 2048 -storepass 'android'


mkdir -p ../dist-android

"$APKSIGNER" sign --ks ../objs/android/keystore.jks --ks-key-alias androidkey --out ../dist-android/game.apk ../objs/android/aligned.apk
12 changes: 6 additions & 6 deletions android/export-icons.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
INKSCAPE=inkscape
BASENAME=gp-icon

mkdir -p mipmap-mdpi mipmap-hdpi mipmap-xhdpi mipmap-xxhdpi mipmap-xxxhdpi
mkdir -p res/mipmap-mdpi res/mipmap-hdpi res/mipmap-xhdpi res/mipmap-xxhdpi res/mipmap-xxxhdpi

"$INKSCAPE" "$BASENAME.svg" -o "mipmap-mdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=48 --export-height=48 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "mipmap-hdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=72 --export-height=72 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "mipmap-xhdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=96 --export-height=96 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "mipmap-xxhdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=144 --export-height=144 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "mipmap-xxxhdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=192 --export-height=192 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "res/mipmap-mdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=48 --export-height=48 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "res/mipmap-hdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=72 --export-height=72 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "res/mipmap-xhdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=96 --export-height=96 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "res/mipmap-xxhdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=144 --export-height=144 --export-background='#000000' --export-background-opacity=0.0
"$INKSCAPE" "$BASENAME.svg" -o "res/mipmap-xxxhdpi/$BASENAME.png" --export-type=png --export-area-page --export-width=192 --export-height=192 --export-background='#000000' --export-background-opacity=0.0
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
81 changes: 0 additions & 81 deletions dist-android/AndroidManifest.xml

This file was deleted.

0 comments on commit 799bb6d

Please sign in to comment.