Misc Formatting

* PEP8 and linting
* empty exceptions
This commit is contained in:
Aidan Holland 2019-02-11 03:18:15 -05:00 committed by John Wu
parent 49640ce03a
commit 65ebb0d2f8
2 changed files with 371 additions and 319 deletions

View File

@ -1,15 +1,19 @@
# Magisk
[Downloads](https://github.com/topjohnwu/Magisk/releases) | [Documentation](https://topjohnwu.github.io/Magisk/) | [XDA Thread](https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445)
[Downloads](https://github.com/topjohnwu/Magisk/releases) \| [Documentation](https://topjohnwu.github.io/Magisk/) \| [XDA Thread](https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445)
## Introduction
Magisk is a suite of open source tools for customizing Android, supporting devices higher than Android 4.2 (API 17). It covers the fundamental parts for Android customization: root, boot scripts, SELinux patches, AVB2.0 / dm-verity / forceencrypt removals etc.
Furthermore, Magisk provides a **Systemless Interface** to alter the system (or vendor) arbitrarily while the actual partitions stay completely intact. With its systemless nature along with several other hacks, Magisk can hide modifications from nearly any system integrity verifications used in banking apps, corporation monitoring apps, game cheat detections, and most importantly [Google's SafetyNet API](https://developer.android.com/training/safetynet/index.html).
## Bug Reports
**Make sure to install the latest [Canary Build](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337) before reporting any bugs!** **DO NOT** report bugs that is already fixed upstream. Follow the instructions in the [Canary Channel XDA Thread](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337), and report a bug either by opening an issue on GitHub or directly in the thread.
## Building Environment Requirements
1. Python 3: run `build.py` script
2. Java Development Kit (JDK) 8: Compile Magisk Manager and sign zips
3. Latest Android SDK: set `ANDROID_HOME` environment variable to the path to Android SDK
@ -17,6 +21,7 @@ Furthermore, Magisk provides a **Systemless Interface** to alter the system (or
5. (Windows Only) Python package Colorama: Install with `pip install colorama`, used for ANSI color codes
## Building Notes and Instructions
1. Clone sources with submodules: `git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git`
2. Building is supported on macOS, Linux, and Windows. Official releases are built and tested with [FrankeNDK](https://github.com/topjohnwu/FrankeNDK); point `ANDROID_NDK_HOME` to FrankeNDK if you want to use it for compiling.
3. Set configurations in `config.prop`. A sample file `config.prop.sample` is provided as an example.
@ -25,7 +30,6 @@ Furthermore, Magisk provides a **Systemless Interface** to alter the system (or
## License
```
Magisk, including all git submodules are free software:
you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
@ -38,4 +42,3 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
```

129
build.py
View File

@ -7,17 +7,21 @@ if os.name == 'nt':
import colorama
colorama.init()
def error(str):
print('\n' + '\033[41m' + str + '\033[0m' + '\n')
sys.exit(1)
def header(str):
print('\n' + '\033[44m' + str + '\033[0m' + '\n')
def vprint(str):
if args.verbose:
print(str)
# Environment checks
if not sys.version_info >= (3, 6):
error('Requires Python 3.6+')
@ -26,7 +30,8 @@ if 'ANDROID_HOME' not in os.environ:
error('Please add Android SDK path to ANDROID_HOME environment variable!')
try:
subprocess.run(['java', '-version'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.run(['java', '-version'],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except FileNotFoundError:
error('Please install JDK and make sure \'java\' is available in PATH')
@ -37,13 +42,13 @@ import datetime
import errno
import shutil
import lzma
import base64
import tempfile
if 'ANDROID_NDK_HOME' in os.environ:
ndk_build = os.path.join(os.environ['ANDROID_NDK_HOME'], 'ndk-build')
else:
ndk_build = os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build')
ndk_build = os.path.join(
os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build')
cpu_count = multiprocessing.cpu_count()
gradlew = os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')
@ -51,19 +56,22 @@ archs = ['armeabi-v7a', 'x86']
keystore = 'release-key.jks'
config = {}
def mv(source, target):
try:
shutil.move(source, target)
except:
except shutil.Error:
pass
def cp(source, target):
try:
shutil.copyfile(source, target)
vprint(f'cp: {source} -> {target}')
except:
except shutil.Error:
pass
def rm(file):
try:
os.remove(file)
@ -71,21 +79,25 @@ def rm(file):
if e.errno != errno.ENOENT:
raise
def mkdir(path, mode=0o777):
try:
os.mkdir(path, mode)
except:
except OSError:
pass
def mkdir_p(path, mode=0o777):
os.makedirs(path, mode, exist_ok=True)
def zip_with_msg(zipfile, source, target):
def zip_with_msg(zip_file, source, target):
if not os.path.exists(source):
error(f'{source} does not exist! Try build \'binary\' and \'apk\' before zipping!')
zipfile.write(source, target)
zip_file.write(source, target)
vprint(f'zip: {source} -> {target}')
def collect_binary():
for arch in archs:
mkdir_p(os.path.join('native', 'out', arch))
@ -94,15 +106,19 @@ def collect_binary():
target = os.path.join('native', 'out', arch, bin)
mv(source, target)
def execv(cmd, redirect=None):
return subprocess.run(cmd, stdout=redirect if redirect != None else STDOUT)
def system(cmd, redirect=None):
return subprocess.run(cmd, shell=True, stdout=redirect if redirect != None else STDOUT)
def xz(data):
return lzma.compress(data, preset=9, check=lzma.CHECK_NONE)
def sign_zip(unsigned, output, release):
signer_name = 'zipsigner-3.0.jar'
zipsigner = os.path.join('signing', 'build', 'libs', signer_name)
@ -116,13 +132,15 @@ def sign_zip(unsigned, output, release):
header('* Signing Zip')
if release:
proc = execv(['java', '-jar', zipsigner, keystore, config['keyStorePass'], config['keyAlias'], config['keyPass'], unsigned, output])
proc = execv(['java', '-jar', zipsigner, keystore, config['keyStorePass'],
config['keyAlias'], config['keyPass'], unsigned, output])
else:
proc = execv(['java', '-jar', zipsigner, unsigned, output])
if proc.returncode != 0:
error('Signing zip failed!')
def binary_dump(src, out, var_name):
out.write(f'const static unsigned char {var_name}[] = {{')
for i, c in enumerate(xz(src.read())):
@ -132,6 +150,7 @@ def binary_dump(src, out, var_name):
out.write('\n};\n')
out.flush()
def gen_update_binary():
bs = 1024
update_bin = bytearray(bs)
@ -154,15 +173,17 @@ def gen_update_binary():
update_bin.extend(arm_bb)
return update_bin
def build_binary(args):
support_targets = {'magisk', 'magiskinit', 'magiskboot', 'busybox'}
if len(args.target) == 0:
if args.target:
args.target = set(args.target) & support_targets
else:
# If nothing specified, build everything
args.target = support_targets
else:
args.target = set(args.target) & support_targets
if len(args.target) == 0:
# Unsure why this is separate
if not args.target:
return
header('* Building binaries: ' + ' '.join(args.target))
@ -215,44 +236,51 @@ def build_binary(args):
error('Build binaries failed!')
collect_binary()
def build_apk(args, flavor):
header('* Building {} Magisk Manager'.format(flavor))
buildType = 'Release' if args.release else 'Debug'
build_type = 'Release' if args.release else 'Debug'
proc = execv([gradlew, f'app:assemble{flavor}{buildType}', '-PconfigPath=' + os.path.abspath(args.config)])
proc = execv([gradlew, f'app:assemble{flavor}{build_type}', '-PconfigPath=' + os.path.abspath(args.config)])
if proc.returncode != 0:
error('Build Magisk Manager failed!')
flavor = flavor.lower()
buildType = buildType.lower()
apk = f'app-{flavor}-{buildType}.apk'
build_type = build_type.lower()
apk = f'app-{flavor}-{build_type}.apk'
source = os.path.join('app', 'build', 'outputs', 'apk', flavor, buildType, apk)
source = os.path.join('app', 'build', 'outputs',
'apk', flavor, build_type, apk)
target = os.path.join(config['outdir'], apk)
mv(source, target)
header('Output: ' + target)
return target
def build_app(args):
source = os.path.join('scripts', 'util_functions.sh')
target = os.path.join('app-core', 'src', 'main', 'res', 'raw', 'util_functions.sh')
target = os.path.join('app-core', 'src', 'main',
'res', 'raw', 'util_functions.sh')
cp(source, target)
build_apk(args, 'Full')
def build_stub(args):
stub = build_apk(args, 'Stub')
# Dump the stub APK to header
mkdir(os.path.join('native', 'out'))
with open(os.path.join('native', 'out', 'binaries.h'), 'w') as out:
with open(stub, 'rb') as src:
binary_dump(src, out, 'manager_xz');
binary_dump(src, out, 'manager_xz')
def build_snet(args):
proc = execv([gradlew, 'snet:assembleRelease'])
if proc.returncode != 0:
error('Build snet extention failed!')
source = os.path.join('snet', 'build', 'outputs', 'apk', 'release', 'snet-release-unsigned.apk')
source = os.path.join('snet', 'build', 'outputs', 'apk',
'release', 'snet-release-unsigned.apk')
target = os.path.join(config['outdir'], 'snet.apk')
# Re-compress the whole APK for smaller size
with zipfile.ZipFile(target, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zout:
@ -262,6 +290,7 @@ def build_snet(args):
rm(source)
header('Output: ' + target)
def zip_main(args):
header('* Packing Flashable Zip')
@ -270,12 +299,14 @@ def zip_main(args):
with zipfile.ZipFile(unsigned, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf:
# META-INF
# update-binary
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
target = os.path.join('META-INF', 'com', 'google',
'android', 'update-binary')
vprint('zip: ' + target)
zipf.writestr(target, gen_update_binary())
# updater-script
source = os.path.join('scripts', 'flash_script.sh')
target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script')
target = os.path.join('META-INF', 'com', 'google',
'android', 'updater-script')
zip_with_msg(zipf, source, target)
# Binaries
@ -286,7 +317,8 @@ def zip_main(args):
zip_with_msg(zipf, source, target)
# APK
source = os.path.join(config['outdir'], 'app-full-release.apk' if args.release else 'app-full-debug.apk')
source = os.path.join(
config['outdir'], 'app-full-release.apk' if args.release else 'app-full-debug.apk')
target = os.path.join('common', 'magisk.apk')
zip_with_msg(zipf, source, target)
@ -321,6 +353,7 @@ def zip_main(args):
sign_zip(unsigned, output, args.release)
header('Output: ' + output)
def zip_uninstaller(args):
header('* Packing Uninstaller Zip')
@ -329,12 +362,14 @@ def zip_uninstaller(args):
with zipfile.ZipFile(unsigned, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf:
# META-INF
# update-binary
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
target = os.path.join('META-INF', 'com', 'google',
'android', 'update-binary')
vprint('zip: ' + target)
zipf.writestr(target, gen_update_binary())
# updater-script
source = os.path.join('scripts', 'magisk_uninstaller.sh')
target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script')
target = os.path.join('META-INF', 'com', 'google',
'android', 'updater-script')
zip_with_msg(zipf, source, target)
# Binaries
@ -364,13 +399,14 @@ def zip_uninstaller(args):
sign_zip(unsigned, output, args.release)
header('Output: ' + output)
def cleanup(args):
support_targets = {'native', 'java'}
if len(args.target) == 0:
if args.target:
args.target = set(args.target) & support_targets
else:
# If nothing specified, clean everything
args.target = support_targets
else:
args.target = set(args.target) & support_targets
if 'native' in args.target:
header('* Cleaning native')
@ -379,7 +415,9 @@ def cleanup(args):
if 'java' in args.target:
header('* Cleaning java')
execv([gradlew, 'app:clean', 'app-core:clean', 'snet:clean', 'signing:clean'])
execv([gradlew, 'app:clean', 'app-core:clean',
'snet:clean', 'signing:clean'])
def build_all(args):
vars(args)['target'] = []
@ -390,36 +428,47 @@ def build_all(args):
zip_uninstaller(args)
build_snet(args)
parser = argparse.ArgumentParser(description='Magisk build script')
parser.add_argument('-r', '--release', action='store_true', help='compile Magisk for release')
parser.add_argument('-v', '--verbose', action='store_true', help='verbose output')
parser.add_argument('-c', '--config', default='config.prop', help='config file location')
parser.add_argument('-r', '--release', action='store_true',
help='compile Magisk for release')
parser.add_argument('-v', '--verbose', action='store_true',
help='verbose output')
parser.add_argument('-c', '--config', default='config.prop',
help='config file location')
subparsers = parser.add_subparsers(title='actions')
all_parser = subparsers.add_parser('all', help='build everything (binaries/apks/zips)')
all_parser = subparsers.add_parser(
'all', help='build everything (binaries/apks/zips)')
all_parser.set_defaults(func=build_all)
binary_parser = subparsers.add_parser('binary', help='build binaries')
binary_parser.add_argument('target', nargs='*', help='Support: magisk, magiskinit, magiskboot, busybox. Leave empty to build all.')
binary_parser.add_argument(
'target', nargs='*', help='Support: magisk, magiskinit, magiskboot, busybox. Leave empty to build all.')
binary_parser.set_defaults(func=build_binary)
apk_parser = subparsers.add_parser('apk', help='build Magisk Manager APK')
apk_parser.set_defaults(func=build_app)
stub_parser = subparsers.add_parser('stub', help='build stub Magisk Manager APK')
stub_parser = subparsers.add_parser(
'stub', help='build stub Magisk Manager APK')
stub_parser.set_defaults(func=build_stub)
snet_parser = subparsers.add_parser('snet', help='build snet extention for Magisk Manager')
snet_parser = subparsers.add_parser(
'snet', help='build snet extention for Magisk Manager')
snet_parser.set_defaults(func=build_snet)
zip_parser = subparsers.add_parser('zip', help='zip Magisk into a flashable zip')
zip_parser = subparsers.add_parser(
'zip', help='zip Magisk into a flashable zip')
zip_parser.set_defaults(func=zip_main)
un_parser = subparsers.add_parser('uninstaller', help='create flashable uninstaller')
un_parser = subparsers.add_parser(
'uninstaller', help='create flashable uninstaller')
un_parser.set_defaults(func=zip_uninstaller)
clean_parser = subparsers.add_parser('clean', help='cleanup.')
clean_parser.add_argument('target', nargs='*', help='Support: native, java. Leave empty to clean all.')
clean_parser.add_argument(
'target', nargs='*', help='Support: native, java. Leave empty to clean all.')
clean_parser.set_defaults(func=cleanup)
if len(sys.argv) == 1: