Allow Linux users to build Android even if Python 2 is their default Python
After this commit, users who have the `python` executable as Python 2 can do simply:
cd android/
./build-all.py
./build.py
Previously, the following would fail:
python3 build-all.py
since build-all.py did subcalls to `python build.py`.
Remove install-all.py as it is redundant with `build-all.py -deploy`,
instead of fixing it as well.
Introduce argparse since we are separating argument parsing out of
the `main()` function.
Tested in Ubuntu 16.04, behaviour should be unchanged for Windows.
This commit is contained in:
parent
542be437da
commit
848310ffdb
6 changed files with 142 additions and 139 deletions
|
|
@ -39,7 +39,7 @@ This will build all apks and puts them into the **bin** folder.
|
||||||
#### Build and deploy
|
#### Build and deploy
|
||||||
|
|
||||||
```
|
```
|
||||||
install-all.py
|
build-all.py -deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
This will build all apks and deploys them to the currently attached android device.
|
This will build all apks and deploys them to the currently attached android device.
|
||||||
|
|
|
||||||
19
android/build-all.py
Normal file → Executable file
19
android/build-all.py
Normal file → Executable file
|
|
@ -1,8 +1,11 @@
|
||||||
# Build all examples
|
#!/usr/bin/env python3
|
||||||
# Pass -deploy to also install on connected device
|
|
||||||
|
import argparse
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import build
|
||||||
|
|
||||||
EXAMPLES = [
|
EXAMPLES = [
|
||||||
"bloom",
|
"bloom",
|
||||||
"computecullandlod",
|
"computecullandlod",
|
||||||
|
|
@ -64,18 +67,16 @@ COLOR_END = '\033[0m'
|
||||||
|
|
||||||
CURR_INDEX = 0
|
CURR_INDEX = 0
|
||||||
|
|
||||||
BUILD_ARGUMENTS = ""
|
parser = argparse.ArgumentParser()
|
||||||
for arg in sys.argv[1:]:
|
parser.add_argument('-deploy', default=False, action='store_true', help="install examples on device")
|
||||||
if arg == "-deploy":
|
parser.add_argument('-validation', default=False, action='store_true')
|
||||||
BUILD_ARGUMENTS += "-deploy"
|
args = parser.parse_args()
|
||||||
if arg == "-validation":
|
|
||||||
BUILD_ARGUMENTS += "-validation"
|
|
||||||
|
|
||||||
print("Building all examples...")
|
print("Building all examples...")
|
||||||
|
|
||||||
for example in EXAMPLES:
|
for example in EXAMPLES:
|
||||||
print(COLOR_GREEN + "Building %s (%d/%d)" % (example, CURR_INDEX, len(EXAMPLES)) + COLOR_END)
|
print(COLOR_GREEN + "Building %s (%d/%d)" % (example, CURR_INDEX, len(EXAMPLES)) + COLOR_END)
|
||||||
if subprocess.call(("python build.py %s %s" % (example, BUILD_ARGUMENTS)).split(' ')) != 0:
|
if not build.main(example, args.deploy, args.validation):
|
||||||
print("Error during build process for %s" % example)
|
print("Error during build process for %s" % example)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
CURR_INDEX += 1
|
CURR_INDEX += 1
|
||||||
|
|
|
||||||
239
android/build.py
Normal file → Executable file
239
android/build.py
Normal file → Executable file
|
|
@ -1,142 +1,153 @@
|
||||||
# Single example build and deploy script
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
import glob
|
import glob
|
||||||
import json
|
import json
|
||||||
|
import argparse
|
||||||
|
|
||||||
# Android SDK version used
|
def main(project_folder, deploy=False, validation=False):
|
||||||
SDK_VERSION = "android-23"
|
|
||||||
|
|
||||||
PROJECT_FOLDER = ""
|
# Android SDK version used
|
||||||
|
SDK_VERSION = "android-23"
|
||||||
|
|
||||||
# Check if python 3, python 2 not supported
|
# Check if python 3, python 2 not supported
|
||||||
if sys.version_info <= (3, 0):
|
if sys.version_info <= (3, 0):
|
||||||
print("Sorry, requires Python 3.x, not Python 2.x")
|
print("Sorry, requires Python 3.x, not Python 2.x")
|
||||||
sys.exit(-1)
|
return False
|
||||||
|
|
||||||
# Name/folder of the project to build
|
# Definitions (apk name, folders, etc.) will be taken from a json definition
|
||||||
if len(sys.argv) > 1:
|
if not os.path.isfile(os.path.join(project_folder, "example.json")):
|
||||||
PROJECT_FOLDER = sys.argv[1]
|
print("Could not find json definition for example %s" % project_folder)
|
||||||
if not os.path.exists(PROJECT_FOLDER):
|
return False
|
||||||
print("Please specify a valid project folder to build!")
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
# Definitions (apk name, folders, etc.) will be taken from a json definition
|
# Check if a build file is present, if not create one using the android SDK version specified
|
||||||
if not os.path.isfile(os.path.join(PROJECT_FOLDER, "example.json")):
|
if not os.path.isfile(os.path.join(project_folder, "build.xml")):
|
||||||
print("Could not find json definition for example %s" % PROJECT_FOLDER)
|
print("Build.xml not present, generating with %s " % SDK_VERSION)
|
||||||
sys.exit(-1)
|
ANDROID_CMD = "android"
|
||||||
|
if os.name == 'nt':
|
||||||
|
ANDROID_CMD += ".bat"
|
||||||
|
if subprocess.call(("%s update project -p ./%s -t %s" % (ANDROID_CMD, project_folder, SDK_VERSION)).split(' ')) != 0:
|
||||||
|
print("Error: Project update failed!")
|
||||||
|
return False
|
||||||
|
|
||||||
# Check if a build file is present, if not create one using the android SDK version specified
|
# Load example definition from json file
|
||||||
if not os.path.isfile(os.path.join(PROJECT_FOLDER, "build.xml")):
|
with open(os.path.join(project_folder, "example.json")) as json_file:
|
||||||
print("Build.xml not present, generating with %s " % SDK_VERSION)
|
EXAMPLE_JSON = json.load(json_file)
|
||||||
ANDROID_CMD = "android"
|
|
||||||
if os.name == 'nt':
|
|
||||||
ANDROID_CMD += ".bat"
|
|
||||||
if subprocess.call(("%s update project -p ./%s -t %s" % (ANDROID_CMD, PROJECT_FOLDER, SDK_VERSION)).split(' ')) != 0:
|
|
||||||
print("Error: Project update failed!")
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
# Load example definition from json file
|
APK_NAME = EXAMPLE_JSON["apkname"]
|
||||||
with open(os.path.join(PROJECT_FOLDER, "example.json")) as json_file:
|
SHADER_DIR = EXAMPLE_JSON["directories"]["shaders"]
|
||||||
EXAMPLE_JSON = json.load(json_file)
|
|
||||||
|
|
||||||
APK_NAME = EXAMPLE_JSON["apkname"]
|
# Additional
|
||||||
SHADER_DIR = EXAMPLE_JSON["directories"]["shaders"]
|
ADDITIONAL_DIRS = []
|
||||||
|
ADDITIONAL_FILES = []
|
||||||
|
if "assets" in EXAMPLE_JSON and "additional" in EXAMPLE_JSON["assets"]:
|
||||||
|
ADDITIONAL = EXAMPLE_JSON["assets"]["additional"]
|
||||||
|
if "directories" in ADDITIONAL:
|
||||||
|
ADDITIONAL_DIRS = ADDITIONAL["directories"]
|
||||||
|
if "files" in ADDITIONAL:
|
||||||
|
ADDITIONAL_FILES = ADDITIONAL["files"]
|
||||||
|
|
||||||
# Additional
|
# Get assets to be copied
|
||||||
ADDITIONAL_DIRS = []
|
ASSETS_MODELS = []
|
||||||
ADDITIONAL_FILES = []
|
ASSETS_TEXTURES = []
|
||||||
if "assets" in EXAMPLE_JSON and "additional" in EXAMPLE_JSON["assets"]:
|
if "assets" in EXAMPLE_JSON:
|
||||||
ADDITIONAL = EXAMPLE_JSON["assets"]["additional"]
|
ASSETS = EXAMPLE_JSON["assets"]
|
||||||
if "directories" in ADDITIONAL:
|
if "models" in ASSETS:
|
||||||
ADDITIONAL_DIRS = ADDITIONAL["directories"]
|
ASSETS_MODELS = EXAMPLE_JSON["assets"]["models"]
|
||||||
if "files" in ADDITIONAL:
|
if "textures" in ASSETS:
|
||||||
ADDITIONAL_FILES = ADDITIONAL["files"]
|
ASSETS_TEXTURES = EXAMPLE_JSON["assets"]["textures"]
|
||||||
|
|
||||||
# Get assets to be copied
|
# Enable validation
|
||||||
ASSETS_MODELS = []
|
BUILD_ARGS = ""
|
||||||
ASSETS_TEXTURES = []
|
|
||||||
if "assets" in EXAMPLE_JSON:
|
|
||||||
ASSETS = EXAMPLE_JSON["assets"]
|
|
||||||
if "models" in ASSETS:
|
|
||||||
ASSETS_MODELS = EXAMPLE_JSON["assets"]["models"]
|
|
||||||
if "textures" in ASSETS:
|
|
||||||
ASSETS_TEXTURES = EXAMPLE_JSON["assets"]["textures"]
|
|
||||||
|
|
||||||
# Enable validation
|
if validation:
|
||||||
VALIDATION = False
|
|
||||||
BUILD_ARGS = ""
|
|
||||||
|
|
||||||
for arg in sys.argv[1:]:
|
|
||||||
if arg == "-validation":
|
|
||||||
VALIDATION = True
|
|
||||||
# Use a define to force validation in code
|
# Use a define to force validation in code
|
||||||
BUILD_ARGS = "APP_CFLAGS=-D_VALIDATION"
|
BUILD_ARGS = "APP_CFLAGS=-D_VALIDATION"
|
||||||
break
|
|
||||||
|
|
||||||
# Verify submodules are loaded in external folder
|
# Verify submodules are loaded in external folder
|
||||||
if not os.listdir("../external/glm/") or not os.listdir("../external/gli/"):
|
if not os.listdir("../external/glm/") or not os.listdir("../external/gli/"):
|
||||||
print("External submodules not loaded. Clone them using:")
|
print("External submodules not loaded. Clone them using:")
|
||||||
print("\tgit submodule init\n\tgit submodule update")
|
print("\tgit submodule init\n\tgit submodule update")
|
||||||
sys.exit(-1)
|
return False
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
os.chdir(PROJECT_FOLDER)
|
old_cwd = os.getcwd()
|
||||||
|
os.chdir(project_folder)
|
||||||
|
|
||||||
if subprocess.call("ndk-build %s" %BUILD_ARGS, shell=True) == 0:
|
if subprocess.call("ndk-build %s" %BUILD_ARGS, shell=True) == 0:
|
||||||
print("Build successful")
|
print("Build successful")
|
||||||
|
|
||||||
if VALIDATION:
|
if validation:
|
||||||
# Copy validation layers
|
# Copy validation layers
|
||||||
# todo: Currently only arm v7
|
# todo: Currently only arm v7
|
||||||
print("Validation enabled, copying validation layers...")
|
print("Validation enabled, copying validation layers...")
|
||||||
os.makedirs("./libs/armeabi-v7a", exist_ok=True)
|
os.makedirs("./libs/armeabi-v7a", exist_ok=True)
|
||||||
for file in glob.glob("../layers/armeabi-v7a/*.so"):
|
for file in glob.glob("../layers/armeabi-v7a/*.so"):
|
||||||
print("\t" + file)
|
print("\t" + file)
|
||||||
shutil.copy(file, "./libs/armeabi-v7a")
|
shutil.copy(file, "./libs/armeabi-v7a")
|
||||||
|
|
||||||
# Create folders
|
# Create folders
|
||||||
os.makedirs("./assets/shaders/base", exist_ok=True)
|
os.makedirs("./assets/shaders/base", exist_ok=True)
|
||||||
os.makedirs("./assets/shaders/%s" % SHADER_DIR, exist_ok=True)
|
os.makedirs("./assets/shaders/%s" % SHADER_DIR, exist_ok=True)
|
||||||
os.makedirs("./assets/models", exist_ok=True)
|
os.makedirs("./assets/models", exist_ok=True)
|
||||||
os.makedirs("./assets/textures", exist_ok=True)
|
os.makedirs("./assets/textures", exist_ok=True)
|
||||||
for directory in ADDITIONAL_DIRS:
|
for directory in ADDITIONAL_DIRS:
|
||||||
os.makedirs("./assets/%s" % directory, exist_ok=True)
|
os.makedirs("./assets/%s" % directory, exist_ok=True)
|
||||||
os.makedirs("./res/drawable", exist_ok=True)
|
os.makedirs("./res/drawable", exist_ok=True)
|
||||||
|
|
||||||
for filename in glob.glob("../../data/shaders/base/*.spv"):
|
for filename in glob.glob("../../data/shaders/base/*.spv"):
|
||||||
shutil.copy(filename, "./assets/shaders/base")
|
shutil.copy(filename, "./assets/shaders/base")
|
||||||
for filename in glob.glob("../../data/shaders/%s/*.spv" %SHADER_DIR):
|
for filename in glob.glob("../../data/shaders/%s/*.spv" %SHADER_DIR):
|
||||||
shutil.copy(filename, "./assets/shaders/%s" % SHADER_DIR)
|
shutil.copy(filename, "./assets/shaders/%s" % SHADER_DIR)
|
||||||
for filename in ASSETS_MODELS:
|
for filename in ASSETS_MODELS:
|
||||||
shutil.copy("../../data/models/%s" % filename, "./assets/models")
|
shutil.copy("../../data/models/%s" % filename, "./assets/models")
|
||||||
for filename in ASSETS_TEXTURES:
|
for filename in ASSETS_TEXTURES:
|
||||||
shutil.copy("../../data/textures/%s" % filename, "./assets/textures")
|
shutil.copy("../../data/textures/%s" % filename, "./assets/textures")
|
||||||
for filename in ADDITIONAL_FILES:
|
for filename in ADDITIONAL_FILES:
|
||||||
if "*." in filename:
|
if "*." in filename:
|
||||||
for fname in glob.glob("../../data/%s" % filename):
|
for fname in glob.glob("../../data/%s" % filename):
|
||||||
locfname = fname.replace("../../data/", "")
|
locfname = fname.replace("../../data/", "")
|
||||||
shutil.copy(fname, "./assets/%s" % locfname)
|
shutil.copy(fname, "./assets/%s" % locfname)
|
||||||
|
else:
|
||||||
|
shutil.copy("../../data/%s" % filename, "./assets/%s" % filename)
|
||||||
|
|
||||||
|
shutil.copy("../../android/images/icon.png", "./res/drawable")
|
||||||
|
|
||||||
|
if subprocess.call("ant debug -Dout.final.file=%s.apk" % APK_NAME, shell=True) == 0:
|
||||||
|
if deploy and subprocess.call("adb install -r %s.apk" % APK_NAME, shell=True) != 0:
|
||||||
|
print("Could not deploy to device!")
|
||||||
else:
|
else:
|
||||||
shutil.copy("../../data/%s" % filename, "./assets/%s" % filename)
|
print("Error during build process!")
|
||||||
|
return False
|
||||||
shutil.copy("../../android/images/icon.png", "./res/drawable")
|
|
||||||
|
|
||||||
if subprocess.call("ant debug -Dout.final.file=%s.apk" % APK_NAME, shell=True) == 0:
|
|
||||||
# Deploy to device
|
|
||||||
for arg in sys.argv[1:]:
|
|
||||||
if arg == "-deploy":
|
|
||||||
if subprocess.call("adb install -r %s.apk" % APK_NAME, shell=True) != 0:
|
|
||||||
print("Could not deploy to device!")
|
|
||||||
else:
|
else:
|
||||||
print("Error during build process!")
|
print("Error building project!")
|
||||||
sys.exit(-1)
|
return False
|
||||||
else:
|
|
||||||
print("Error building project!")
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
# Copy apk to bin folder
|
# Copy apk to bin folder
|
||||||
os.makedirs("../bin", exist_ok=True)
|
os.makedirs("../bin", exist_ok=True)
|
||||||
shutil.move('%s.apk' % APK_NAME, "../bin/%s.apk" % APK_NAME)
|
shutil.move('%s.apk' % APK_NAME, "../bin/%s.apk" % APK_NAME)
|
||||||
|
os.chdir(old_cwd)
|
||||||
|
return True
|
||||||
|
|
||||||
|
class ReadableDir(argparse.Action):
|
||||||
|
def __call__(self, parser, namespace, values, option_string=None):
|
||||||
|
if not os.path.isdir(values):
|
||||||
|
raise argparse.ArgumentTypeError("{0} is not a valid path".format(values))
|
||||||
|
if not os.access(values, os.R_OK):
|
||||||
|
raise argparse.ArgumentTypeError("{0} is not a readable dir".format(values))
|
||||||
|
setattr(namespace, self.dest,values)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser(description="Build and deploy a single example")
|
||||||
|
parser.add_argument('-deploy', default=False, action='store_true', help="install example on device")
|
||||||
|
parser.add_argument('-validation', default=False, action='store_true')
|
||||||
|
parser.add_argument('project_folder', action=ReadableDir)
|
||||||
|
try:
|
||||||
|
args = parser.parse_args()
|
||||||
|
except SystemExit:
|
||||||
|
sys.exit(1)
|
||||||
|
ok = main(args.project_folder, args.deploy, args.validation)
|
||||||
|
sys.exit(0 if ok else 1)
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# Install all examples to connected device(s)
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
|
|
||||||
answer = input("Install all vulkan examples to attached device, this may take some time! (Y/N)").lower() == 'y'
|
|
||||||
if answer:
|
|
||||||
BUILD_ARGUMENTS = ""
|
|
||||||
for arg in sys.argv[1:]:
|
|
||||||
if arg == "-validation":
|
|
||||||
BUILD_ARGUMENTS += "-validation"
|
|
||||||
if subprocess.call(("python build-all.py -deploy %s" % BUILD_ARGUMENTS).split(' ')) != 0:
|
|
||||||
print("Error: Not all examples may have been installed!")
|
|
||||||
sys.exit(-1)
|
|
||||||
2
android/uninstall-all.py
Normal file → Executable file
2
android/uninstall-all.py
Normal file → Executable file
|
|
@ -1,3 +1,5 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# Remove all examples from connected device(s)
|
# Remove all examples from connected device(s)
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
|
||||||
2
download_assets.py
Normal file → Executable file
2
download_assets.py
Normal file → Executable file
|
|
@ -1,3 +1,5 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from urllib.request import urlretrieve
|
from urllib.request import urlretrieve
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue