mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-15 06:07:26 +00:00
Compare commits
13 Commits
canary-270
...
canary-270
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0495468d02 | ||
![]() |
300a2a242c | ||
![]() |
33aebb5976 | ||
![]() |
b3d6809c0b | ||
![]() |
461f7e9f89 | ||
![]() |
9cc50b20d8 | ||
![]() |
f488e9df8f | ||
![]() |
0dc596e206 | ||
![]() |
c3bf03190b | ||
![]() |
021ae891a9 | ||
![]() |
9c03514eb1 | ||
![]() |
eb74b266e1 | ||
![]() |
80eb6ff25a |
@@ -22,8 +22,7 @@ Click the icon below to download Magisk apk.
|
|||||||
|
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
||||||
[](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-release.apk)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-27006)
|
||||||
[](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-debug.apk)
|
|
||||||
|
|
||||||
## Useful Links
|
## Useful Links
|
||||||
|
|
||||||
@@ -31,8 +30,6 @@ Click the icon below to download Magisk apk.
|
|||||||
- [Building and Development](https://topjohnwu.github.io/Magisk/build.html)
|
- [Building and Development](https://topjohnwu.github.io/Magisk/build.html)
|
||||||
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
|
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
|
||||||
- [Zygisk module sample](https://github.com/topjohnwu/zygisk-module-sample)
|
- [Zygisk module sample](https://github.com/topjohnwu/zygisk-module-sample)
|
||||||
- [Canary channel changelog](https://github.com/topjohnwu/magisk-files/blob/canary/notes.md)
|
|
||||||
|
|
||||||
|
|
||||||
## Bug Reports
|
## Bug Reports
|
||||||
|
|
||||||
|
@@ -59,8 +59,8 @@ dependencies {
|
|||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
implementation("androidx.recyclerview:recyclerview:1.3.2")
|
implementation("androidx.recyclerview:recyclerview:1.3.2")
|
||||||
implementation("androidx.transition:transition:1.5.0")
|
implementation("androidx.transition:transition:1.5.1")
|
||||||
implementation("androidx.fragment:fragment-ktx:1.8.1")
|
implementation("androidx.fragment:fragment-ktx:1.8.2")
|
||||||
implementation("androidx.appcompat:appcompat:1.7.0")
|
implementation("androidx.appcompat:appcompat:1.7.0")
|
||||||
implementation("com.google.android.material:material:1.12.0")
|
implementation("com.google.android.material:material:1.12.0")
|
||||||
|
|
||||||
|
5
app/build.gradle.kts
Normal file
5
app/build.gradle.kts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
tasks.register("clean") {
|
||||||
|
subprojects.forEach {
|
||||||
|
dependsOn(":app:${it.name}:clean")
|
||||||
|
}
|
||||||
|
}
|
@@ -61,8 +61,8 @@ dependencies {
|
|||||||
|
|
||||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||||
implementation("androidx.core:core-ktx:1.13.1")
|
implementation("androidx.core:core-ktx:1.13.1")
|
||||||
implementation("androidx.activity:activity:1.9.0")
|
implementation("androidx.activity:activity:1.9.1")
|
||||||
implementation("androidx.collection:collection-ktx:1.4.1")
|
implementation("androidx.collection:collection-ktx:1.4.2")
|
||||||
implementation("androidx.profileinstaller:profileinstaller:1.3.1")
|
implementation("androidx.profileinstaller:profileinstaller:1.3.1")
|
||||||
implementation("androidx.lifecycle:lifecycle-process:2.8.3")
|
implementation("androidx.lifecycle:lifecycle-process:2.8.4")
|
||||||
}
|
}
|
||||||
|
@@ -176,6 +176,8 @@
|
|||||||
<string name="setting_add_shortcut_summary">在隐藏后难以识别名称和图标的情况下,添加快捷方式到桌面</string>
|
<string name="setting_add_shortcut_summary">在隐藏后难以识别名称和图标的情况下,添加快捷方式到桌面</string>
|
||||||
<string name="settings_doh_title">安全 DNS(DoH)</string>
|
<string name="settings_doh_title">安全 DNS(DoH)</string>
|
||||||
<string name="settings_doh_description">解决某些地区的 DNS 污染问题</string>
|
<string name="settings_doh_description">解决某些地区的 DNS 污染问题</string>
|
||||||
|
<string name="settings_random_name_title">随机文件名</string>
|
||||||
|
<string name="settings_random_name_description">随机修补镜像和 tar 文件的文件名以防止检测</string>
|
||||||
|
|
||||||
<string name="multiuser_mode">多用户模式</string>
|
<string name="multiuser_mode">多用户模式</string>
|
||||||
<string name="settings_owner_only">仅设备所有者</string>
|
<string name="settings_owner_only">仅设备所有者</string>
|
||||||
|
@@ -6,7 +6,7 @@ plugins {
|
|||||||
lsparanoid {
|
lsparanoid {
|
||||||
seed = if (RAND_SEED != 0) RAND_SEED else null
|
seed = if (RAND_SEED != 0) RAND_SEED else null
|
||||||
includeDependencies = true
|
includeDependencies = true
|
||||||
global = true
|
classFilter = { true }
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
215
build.py
215
build.py
@@ -81,9 +81,9 @@ triples = [
|
|||||||
"x86_64-linux-android",
|
"x86_64-linux-android",
|
||||||
"riscv64-linux-android",
|
"riscv64-linux-android",
|
||||||
]
|
]
|
||||||
default_targets = ["magisk", "magiskinit", "magiskboot", "magiskpolicy"]
|
default_targets = {"magisk", "magiskinit", "magiskboot", "magiskpolicy"}
|
||||||
support_targets = default_targets + ["resetprop"]
|
support_targets = default_targets | {"resetprop"}
|
||||||
rust_targets = ["magisk", "magiskinit", "magiskboot", "magiskpolicy"]
|
rust_targets = {"magisk", "magiskinit", "magiskboot", "magiskpolicy"}
|
||||||
|
|
||||||
ndk_root = sdk_path / "ndk"
|
ndk_root = sdk_path / "ndk"
|
||||||
ndk_path = ndk_root / "magisk"
|
ndk_path = ndk_root / "magisk"
|
||||||
@@ -243,13 +243,54 @@ def run_ndk_build(args, flags):
|
|||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error("Build binary failed!")
|
error("Build binary failed!")
|
||||||
os.chdir("..")
|
os.chdir("..")
|
||||||
|
|
||||||
for arch in archs:
|
for arch in archs:
|
||||||
for tgt in support_targets + ["libinit-ld.so"]:
|
arch_dir = Path("native", "libs", arch)
|
||||||
source = Path("native", "libs", arch, tgt)
|
out_dir = Path("native", "out", arch)
|
||||||
target = Path("native", "out", arch, tgt)
|
for source in arch_dir.iterdir():
|
||||||
|
target = out_dir / source.name
|
||||||
mv(source, target)
|
mv(source, target)
|
||||||
|
|
||||||
|
|
||||||
|
def build_cpp_src(args, targets: set):
|
||||||
|
dump_flag_header()
|
||||||
|
|
||||||
|
flags = ""
|
||||||
|
clean = False
|
||||||
|
|
||||||
|
if "magisk" in targets:
|
||||||
|
flags += " B_MAGISK=1"
|
||||||
|
clean = True
|
||||||
|
|
||||||
|
if "magiskpolicy" in targets:
|
||||||
|
flags += " B_POLICY=1"
|
||||||
|
clean = True
|
||||||
|
|
||||||
|
if "magiskinit" in targets:
|
||||||
|
flags += " B_PRELOAD=1"
|
||||||
|
|
||||||
|
if "resetprop" in targets:
|
||||||
|
flags += " B_PROP=1"
|
||||||
|
|
||||||
|
if flags:
|
||||||
|
run_ndk_build(args, flags)
|
||||||
|
|
||||||
|
flags = ""
|
||||||
|
|
||||||
|
if "magiskinit" in targets:
|
||||||
|
flags += " B_INIT=1"
|
||||||
|
|
||||||
|
if "magiskboot" in targets:
|
||||||
|
flags += " B_BOOT=1"
|
||||||
|
|
||||||
|
if flags:
|
||||||
|
flags += " B_CRT0=1"
|
||||||
|
run_ndk_build(args, flags)
|
||||||
|
|
||||||
|
if clean:
|
||||||
|
clean_elf()
|
||||||
|
|
||||||
|
|
||||||
def run_cargo(cmds):
|
def run_cargo(cmds):
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env["PATH"] = f'{rust_bin}{os.pathsep}{env["PATH"]}'
|
env["PATH"] = f'{rust_bin}{os.pathsep}{env["PATH"]}'
|
||||||
@@ -258,17 +299,19 @@ def run_cargo(cmds):
|
|||||||
return execv([cargo, *cmds], env)
|
return execv([cargo, *cmds], env)
|
||||||
|
|
||||||
|
|
||||||
def run_cargo_build(args):
|
def build_rust_src(args, targets: set):
|
||||||
|
targets = targets.copy()
|
||||||
|
if "resetprop" in targets:
|
||||||
|
targets.add("magisk")
|
||||||
|
targets = targets & rust_targets
|
||||||
|
if not targets:
|
||||||
|
return
|
||||||
|
|
||||||
|
os.chdir(Path("native", "src"))
|
||||||
|
|
||||||
native_out = Path("..", "out")
|
native_out = Path("..", "out")
|
||||||
native_out.mkdir(mode=0o755, exist_ok=True)
|
native_out.mkdir(mode=0o755, exist_ok=True)
|
||||||
|
|
||||||
targets = set(args.target) & set(rust_targets)
|
|
||||||
if "resetprop" in args.target:
|
|
||||||
targets.add("magisk")
|
|
||||||
|
|
||||||
if len(targets) == 0:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Start building the actual build commands
|
# Start building the actual build commands
|
||||||
cmds = ["build", "-p", ""]
|
cmds = ["build", "-p", ""]
|
||||||
rust_out = "debug"
|
rust_out = "debug"
|
||||||
@@ -289,8 +332,8 @@ def run_cargo_build(args):
|
|||||||
)
|
)
|
||||||
cmds[-1] = rust_triple
|
cmds[-1] = rust_triple
|
||||||
|
|
||||||
for target in targets:
|
for tgt in targets:
|
||||||
cmds[2] = target
|
cmds[2] = tgt
|
||||||
proc = run_cargo(cmds)
|
proc = run_cargo(cmds)
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error("Build binary failed!")
|
error("Build binary failed!")
|
||||||
@@ -302,6 +345,8 @@ def run_cargo_build(args):
|
|||||||
target = arch_out / f"lib{tgt}-rs.a"
|
target = arch_out / f"lib{tgt}-rs.a"
|
||||||
mv(source, target)
|
mv(source, target)
|
||||||
|
|
||||||
|
os.chdir(Path("..", ".."))
|
||||||
|
|
||||||
|
|
||||||
def run_cargo_cmd(args):
|
def run_cargo_cmd(args):
|
||||||
global STDOUT
|
global STDOUT
|
||||||
@@ -324,25 +369,6 @@ def write_if_diff(file_name: Path, text: str):
|
|||||||
f.write(text)
|
f.write(text)
|
||||||
|
|
||||||
|
|
||||||
def binary_dump(src, var_name, compressor=xz):
|
|
||||||
out_str = f"constexpr unsigned char {var_name}[] = {{"
|
|
||||||
for i, c in enumerate(compressor(src.read())):
|
|
||||||
if i % 16 == 0:
|
|
||||||
out_str += "\n"
|
|
||||||
out_str += f"0x{c:02X},"
|
|
||||||
out_str += "\n};\n"
|
|
||||||
return out_str
|
|
||||||
|
|
||||||
|
|
||||||
def dump_bin_header(args):
|
|
||||||
native_gen_path.mkdir(mode=0o755, parents=True, exist_ok=True)
|
|
||||||
for arch in archs:
|
|
||||||
preload = Path("native", "out", arch, "libinit-ld.so")
|
|
||||||
with open(preload, "rb") as src:
|
|
||||||
text = binary_dump(src, "init_ld_xz")
|
|
||||||
write_if_diff(Path(native_gen_path, f"{arch}_binaries.h"), text)
|
|
||||||
|
|
||||||
|
|
||||||
def dump_flag_header():
|
def dump_flag_header():
|
||||||
flag_txt = textwrap.dedent(
|
flag_txt = textwrap.dedent(
|
||||||
"""\
|
"""\
|
||||||
@@ -369,65 +395,17 @@ def build_binary(args):
|
|||||||
except:
|
except:
|
||||||
error('Unmatched NDK. Please install/upgrade NDK with "build.py ndk"')
|
error('Unmatched NDK. Please install/upgrade NDK with "build.py ndk"')
|
||||||
|
|
||||||
if "target" not in vars(args):
|
if "targets" not in vars(args) or not args.targets:
|
||||||
vars(args)["target"] = []
|
targets = default_targets
|
||||||
|
|
||||||
if args.target:
|
|
||||||
args.target = set(args.target) & set(support_targets)
|
|
||||||
if not args.target:
|
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
args.target = default_targets
|
targets = set(args.targets) & support_targets
|
||||||
|
if not targets:
|
||||||
|
return
|
||||||
|
|
||||||
header("* Building binaries: " + " ".join(args.target))
|
header("* Building binaries: " + " ".join(targets))
|
||||||
|
|
||||||
os.chdir(Path("native", "src"))
|
build_rust_src(args, targets)
|
||||||
run_cargo_build(args)
|
build_cpp_src(args, targets)
|
||||||
os.chdir(Path("..", ".."))
|
|
||||||
|
|
||||||
dump_flag_header()
|
|
||||||
|
|
||||||
flag = ""
|
|
||||||
clean = False
|
|
||||||
|
|
||||||
if "magisk" in args.target:
|
|
||||||
flag += " B_MAGISK=1"
|
|
||||||
clean = True
|
|
||||||
|
|
||||||
if "magiskpolicy" in args.target:
|
|
||||||
flag += " B_POLICY=1"
|
|
||||||
clean = True
|
|
||||||
|
|
||||||
if "magiskinit" in args.target:
|
|
||||||
flag += " B_PRELOAD=1"
|
|
||||||
|
|
||||||
if "resetprop" in args.target:
|
|
||||||
flag += " B_PROP=1"
|
|
||||||
|
|
||||||
if flag:
|
|
||||||
run_ndk_build(args, flag)
|
|
||||||
|
|
||||||
flag = ""
|
|
||||||
|
|
||||||
if "magiskinit" in args.target:
|
|
||||||
# magiskinit embeds preload.so
|
|
||||||
dump_bin_header(args)
|
|
||||||
flag += " B_INIT=1"
|
|
||||||
|
|
||||||
if "magiskboot" in args.target:
|
|
||||||
flag += " B_BOOT=1"
|
|
||||||
|
|
||||||
if flag:
|
|
||||||
flag += " B_CRT0=1"
|
|
||||||
run_ndk_build(args, flag)
|
|
||||||
|
|
||||||
if clean:
|
|
||||||
clean_elf()
|
|
||||||
|
|
||||||
# BusyBox is built with different API level
|
|
||||||
|
|
||||||
if "busybox" in args.target:
|
|
||||||
run_ndk_build(args, "B_BB=1")
|
|
||||||
|
|
||||||
|
|
||||||
def find_jdk():
|
def find_jdk():
|
||||||
@@ -513,21 +491,21 @@ def build_stub(args):
|
|||||||
|
|
||||||
def cleanup(args):
|
def cleanup(args):
|
||||||
support_targets = {"native", "cpp", "rust", "java"}
|
support_targets = {"native", "cpp", "rust", "java"}
|
||||||
if args.target:
|
if args.targets:
|
||||||
args.target = set(args.target) & support_targets
|
targets = set(args.targets) & support_targets
|
||||||
if "native" in args.target:
|
if "native" in targets:
|
||||||
args.target.add("cpp")
|
targets.add("cpp")
|
||||||
args.target.add("rust")
|
targets.add("rust")
|
||||||
else:
|
else:
|
||||||
args.target = support_targets
|
targets = support_targets
|
||||||
|
|
||||||
if "cpp" in args.target:
|
if "cpp" in targets:
|
||||||
header("* Cleaning C++")
|
header("* Cleaning C++")
|
||||||
rm_rf(Path("native", "libs"))
|
rm_rf(Path("native", "libs"))
|
||||||
rm_rf(Path("native", "obj"))
|
rm_rf(Path("native", "obj"))
|
||||||
rm_rf(Path("native", "out"))
|
rm_rf(Path("native", "out"))
|
||||||
|
|
||||||
if "rust" in args.target:
|
if "rust" in targets:
|
||||||
header("* Cleaning Rust")
|
header("* Cleaning Rust")
|
||||||
rm_rf(Path("native", "src", "target"))
|
rm_rf(Path("native", "src", "target"))
|
||||||
rm(Path("native", "src", "boot", "proto", "mod.rs"))
|
rm(Path("native", "src", "boot", "proto", "mod.rs"))
|
||||||
@@ -535,18 +513,9 @@ def cleanup(args):
|
|||||||
for rs_gen in glob.glob("native/**/*-rs.*pp", recursive=True):
|
for rs_gen in glob.glob("native/**/*-rs.*pp", recursive=True):
|
||||||
rm(rs_gen)
|
rm(rs_gen)
|
||||||
|
|
||||||
if "java" in args.target:
|
if "java" in targets:
|
||||||
header("* Cleaning java")
|
header("* Cleaning java")
|
||||||
execv(
|
execv([gradlew, ":app:clean"], env=find_jdk())
|
||||||
[
|
|
||||||
gradlew,
|
|
||||||
":app:apk:clean",
|
|
||||||
":app:core:clean",
|
|
||||||
":app:shared:clean",
|
|
||||||
":app:stub:clean",
|
|
||||||
],
|
|
||||||
env=find_jdk(),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_ndk(args):
|
def setup_ndk(args):
|
||||||
@@ -611,22 +580,22 @@ def setup_avd(args):
|
|||||||
|
|
||||||
def patch_avd_file(args):
|
def patch_avd_file(args):
|
||||||
if not args.skip:
|
if not args.skip:
|
||||||
args.release = False
|
|
||||||
build_all(args)
|
build_all(args)
|
||||||
|
|
||||||
args.target = Path(args.target)
|
input = Path(args.image)
|
||||||
src_file = f"/data/local/tmp/{args.target.name}"
|
|
||||||
out_file = f"{src_file}.magisk"
|
|
||||||
if args.output:
|
if args.output:
|
||||||
args.output = Path(args.output)
|
output = Path(args.output)
|
||||||
else:
|
else:
|
||||||
args.output = args.target.parent / f"{args.target.name}.magisk"
|
output = input.parent / f"{input.name}.magisk"
|
||||||
|
|
||||||
header(f"* Patching {args.target.name}")
|
src_file = f"/data/local/tmp/{input.name}"
|
||||||
|
out_file = f"{src_file}.magisk"
|
||||||
|
|
||||||
|
header(f"* Patching {input.name}")
|
||||||
|
|
||||||
push_files(args, Path("scripts", "avd_patch.sh"))
|
push_files(args, Path("scripts", "avd_patch.sh"))
|
||||||
|
|
||||||
proc = execv([adb_path, "push", args.target, "/data/local/tmp"])
|
proc = execv([adb_path, "push", input, "/data/local/tmp"])
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error("adb push failed!")
|
error("adb push failed!")
|
||||||
|
|
||||||
@@ -634,11 +603,11 @@ def patch_avd_file(args):
|
|||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error("avd_patch.sh failed!")
|
error("avd_patch.sh failed!")
|
||||||
|
|
||||||
proc = execv([adb_path, "pull", out_file, args.output])
|
proc = execv([adb_path, "pull", out_file, output])
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error("adb pull failed!")
|
error("adb pull failed!")
|
||||||
|
|
||||||
header(f"Output: {args.output}")
|
header(f"Output: {output}")
|
||||||
|
|
||||||
|
|
||||||
def build_all(args):
|
def build_all(args):
|
||||||
@@ -693,7 +662,7 @@ all_parser.set_defaults(func=build_all)
|
|||||||
|
|
||||||
binary_parser = subparsers.add_parser("binary", help="build binaries")
|
binary_parser = subparsers.add_parser("binary", help="build binaries")
|
||||||
binary_parser.add_argument(
|
binary_parser.add_argument(
|
||||||
"target",
|
"targets",
|
||||||
nargs="*",
|
nargs="*",
|
||||||
help=f"{', '.join(support_targets)}, \
|
help=f"{', '.join(support_targets)}, \
|
||||||
or empty for defaults ({', '.join(default_targets)})",
|
or empty for defaults ({', '.join(default_targets)})",
|
||||||
@@ -723,7 +692,7 @@ avd_parser.set_defaults(func=setup_avd)
|
|||||||
avd_patch_parser = subparsers.add_parser(
|
avd_patch_parser = subparsers.add_parser(
|
||||||
"avd_patch", help="patch AVD ramdisk.img or init_boot.img"
|
"avd_patch", help="patch AVD ramdisk.img or init_boot.img"
|
||||||
)
|
)
|
||||||
avd_patch_parser.add_argument("target", help="path to ramdisk.img or init_boot.img")
|
avd_patch_parser.add_argument("image", help="path to ramdisk.img or init_boot.img")
|
||||||
avd_patch_parser.add_argument("output", help="optional output file name", nargs="?")
|
avd_patch_parser.add_argument("output", help="optional output file name", nargs="?")
|
||||||
avd_patch_parser.add_argument(
|
avd_patch_parser.add_argument(
|
||||||
"-s", "--skip", action="store_true", help="skip building binaries and the app"
|
"-s", "--skip", action="store_true", help="skip building binaries and the app"
|
||||||
@@ -732,7 +701,7 @@ avd_patch_parser.set_defaults(func=patch_avd_file)
|
|||||||
|
|
||||||
clean_parser = subparsers.add_parser("clean", help="cleanup")
|
clean_parser = subparsers.add_parser("clean", help="cleanup")
|
||||||
clean_parser.add_argument(
|
clean_parser.add_argument(
|
||||||
"target", nargs="*", help="native, cpp, rust, java, or empty to clean all"
|
"targets", nargs="*", help="native, cpp, rust, java, or empty to clean all"
|
||||||
)
|
)
|
||||||
clean_parser.set_defaults(func=cleanup)
|
clean_parser.set_defaults(func=cleanup)
|
||||||
|
|
||||||
|
@@ -29,6 +29,6 @@ dependencies {
|
|||||||
implementation("com.android.tools.build:gradle:8.5.1")
|
implementation("com.android.tools.build:gradle:8.5.1")
|
||||||
implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.0.0-1.0.23")
|
implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.0.0-1.0.23")
|
||||||
implementation("androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7")
|
implementation("androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7")
|
||||||
implementation("org.lsposed.lsparanoid:gradle-plugin:0.5.2")
|
implementation("org.lsposed.lsparanoid:gradle-plugin:0.6.0")
|
||||||
implementation("org.eclipse.jgit:org.eclipse.jgit:6.10.0.202406032230-r")
|
implementation("org.eclipse.jgit:org.eclipse.jgit:6.10.0.202406032230-r")
|
||||||
}
|
}
|
||||||
|
@@ -126,13 +126,13 @@ fun Project.setupCoreLib() {
|
|||||||
for (abi in arrayOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64", "riscv64")) {
|
for (abi in arrayOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64", "riscv64")) {
|
||||||
into(abi) {
|
into(abi) {
|
||||||
from(rootProject.file("native/out/$abi")) {
|
from(rootProject.file("native/out/$abi")) {
|
||||||
include("magiskboot", "magiskinit", "magiskpolicy", "magisk")
|
include("magiskboot", "magiskinit", "magiskpolicy", "magisk", "libinit-ld.so")
|
||||||
rename { "lib$it.so" }
|
rename { if (it.endsWith(".so")) it else "lib$it.so" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onlyIf {
|
onlyIf {
|
||||||
if (inputs.sourceFiles.files.size != 20)
|
if (inputs.sourceFiles.files.size != 25)
|
||||||
throw StopExecutionException("Please build binaries first! (./build.py binary)")
|
throw StopExecutionException("Please build binaries first! (./build.py binary)")
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,9 @@ org.gradle.parallel=true
|
|||||||
# Enable build cache
|
# Enable build cache
|
||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
|
|
||||||
|
# Use K2 in kapt
|
||||||
|
kapt.use.k2=true
|
||||||
|
|
||||||
# Android
|
# Android
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.injected.testOnly=false
|
android.injected.testOnly=false
|
||||||
@@ -27,5 +30,5 @@ android.nonFinalResIds=false
|
|||||||
|
|
||||||
# Magisk
|
# Magisk
|
||||||
magisk.stubVersion=40
|
magisk.stubVersion=40
|
||||||
magisk.versionCode=27005
|
magisk.versionCode=27006
|
||||||
magisk.ondkVersion=r27.2
|
magisk.ondkVersion=r27.2
|
||||||
|
@@ -7,7 +7,7 @@ LOCAL_MODULE := libbase
|
|||||||
LOCAL_C_INCLUDES := \
|
LOCAL_C_INCLUDES := \
|
||||||
src/include \
|
src/include \
|
||||||
$(LOCAL_PATH)/include \
|
$(LOCAL_PATH)/include \
|
||||||
$(LOCAL_PATH)/../external/cxx-rs/include \
|
src/external/cxx-rs/include \
|
||||||
out/generated
|
out/generated
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
||||||
LOCAL_EXPORT_STATIC_LIBRARIES := libcxx
|
LOCAL_EXPORT_STATIC_LIBRARIES := libcxx
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
#if defined(__arm__)
|
|
||||||
#include <armeabi-v7a_binaries.h>
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
#include <arm64-v8a_binaries.h>
|
|
||||||
#elif defined(__i386__)
|
|
||||||
#include <x86_binaries.h>
|
|
||||||
#elif defined(__x86_64__)
|
|
||||||
#include <x86_64_binaries.h>
|
|
||||||
#elif defined(__riscv)
|
|
||||||
#include <riscv64_binaries.h>
|
|
||||||
#else
|
|
||||||
#error Unsupported ABI
|
|
||||||
#endif
|
|
@@ -201,12 +201,16 @@ pub fn find_preinit_device() -> String {
|
|||||||
let (_, preinit_info, _) = matched_info.select_nth_unstable_by(
|
let (_, preinit_info, _) = matched_info.select_nth_unstable_by(
|
||||||
0,
|
0,
|
||||||
|(ap, MountInfo { fs_type: at, .. }), (bp, MountInfo { fs_type: bt, .. })| match (
|
|(ap, MountInfo { fs_type: at, .. }), (bp, MountInfo { fs_type: bt, .. })| match (
|
||||||
|
ap,
|
||||||
|
bp,
|
||||||
at.as_str() == "ext4",
|
at.as_str() == "ext4",
|
||||||
bt.as_str() == "ext4",
|
bt.as_str() == "ext4",
|
||||||
) {
|
) {
|
||||||
// take ext4 over others (f2fs) because f2fs has a kernel bug that causes kernel panic
|
// metadata is not affected by f2fs kernel bug
|
||||||
(true, false) => Less,
|
(PartId::Metadata, _, _, true) | (_, PartId::Metadata, true, _) => ap.cmp(bp),
|
||||||
(false, true) => Greater,
|
// otherwise, take ext4 f2fs because f2fs has a kernel bug that causes kernel panic
|
||||||
|
(_, _, true, false) => Less,
|
||||||
|
(_, _, false, true) => Greater,
|
||||||
// if both has the same fs type, compare the mount point
|
// if both has the same fs type, compare the mount point
|
||||||
_ => ap.cmp(bp),
|
_ => ap.cmp(bp),
|
||||||
},
|
},
|
||||||
|
@@ -6,7 +6,6 @@
|
|||||||
#include <xz.h>
|
#include <xz.h>
|
||||||
|
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
#include <embed.hpp>
|
|
||||||
|
|
||||||
#include "init.hpp"
|
#include "init.hpp"
|
||||||
|
|
||||||
|
@@ -189,6 +189,7 @@ static void magic_mount(const string &sdir, const string &ddir = "") {
|
|||||||
static void extract_files(bool sbin) {
|
static void extract_files(bool sbin) {
|
||||||
const char *magisk_xz = sbin ? "/sbin/magisk.xz" : "magisk.xz";
|
const char *magisk_xz = sbin ? "/sbin/magisk.xz" : "magisk.xz";
|
||||||
const char *stub_xz = sbin ? "/sbin/stub.xz" : "stub.xz";
|
const char *stub_xz = sbin ? "/sbin/stub.xz" : "stub.xz";
|
||||||
|
const char *init_ld_xz = sbin ? "/sbin/init-ld.xz" : "init-ld.xz";
|
||||||
|
|
||||||
if (access(magisk_xz, F_OK) == 0) {
|
if (access(magisk_xz, F_OK) == 0) {
|
||||||
mmap_data magisk(magisk_xz);
|
mmap_data magisk(magisk_xz);
|
||||||
@@ -206,6 +207,14 @@ static void extract_files(bool sbin) {
|
|||||||
unxz(ch, stub);
|
unxz(ch, stub);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
if (access(init_ld_xz, F_OK) == 0) {
|
||||||
|
mmap_data init_ld(init_ld_xz);
|
||||||
|
unlink(init_ld_xz);
|
||||||
|
int fd = xopen("init-ld", O_WRONLY | O_CREAT, 0);
|
||||||
|
fd_stream ch(fd);
|
||||||
|
unxz(ch, init_ld);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskInit::parse_config_file() {
|
void MagiskInit::parse_config_file() {
|
||||||
@@ -279,16 +288,19 @@ void MagiskInit::patch_ro_root() {
|
|||||||
patch_rc_scripts("/", tmp_dir.data(), false);
|
patch_rc_scripts("/", tmp_dir.data(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract magisk
|
// Extract overlay archives
|
||||||
extract_files(false);
|
extract_files(false);
|
||||||
|
|
||||||
// Oculus Go will use a special sepolicy if unlocked
|
// Oculus Go will use a special sepolicy if unlocked
|
||||||
if (access("/sepolicy.unlocked", F_OK) == 0) {
|
if (access("/sepolicy.unlocked", F_OK) == 0) {
|
||||||
patch_sepolicy("/sepolicy.unlocked", ROOTOVL "/sepolicy.unlocked");
|
patch_sepolicy("/sepolicy.unlocked", ROOTOVL "/sepolicy.unlocked");
|
||||||
} else if ((access(SPLIT_PLAT_CIL, F_OK) != 0 && access("/sepolicy", F_OK) == 0) ||
|
} else {
|
||||||
!hijack_sepolicy()) {
|
bool patch = access(SPLIT_PLAT_CIL, F_OK) != 0 && access("/sepolicy", F_OK) == 0;
|
||||||
|
if (patch || !hijack_sepolicy()) {
|
||||||
patch_sepolicy("/sepolicy", ROOTOVL "/sepolicy");
|
patch_sepolicy("/sepolicy", ROOTOVL "/sepolicy");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
unlink("init-ld");
|
||||||
|
|
||||||
// Mount rootdir
|
// Mount rootdir
|
||||||
magic_mount(ROOTOVL);
|
magic_mount(ROOTOVL);
|
||||||
@@ -338,12 +350,14 @@ void MagiskInit::patch_rw_root() {
|
|||||||
setup_tmp(PRE_TMPDIR);
|
setup_tmp(PRE_TMPDIR);
|
||||||
chdir(PRE_TMPDIR);
|
chdir(PRE_TMPDIR);
|
||||||
|
|
||||||
// Extract magisk
|
// Extract overlay archives
|
||||||
extract_files(true);
|
extract_files(true);
|
||||||
|
|
||||||
if ((!treble && access("/sepolicy", F_OK) == 0) || !hijack_sepolicy()) {
|
bool patch = !treble && access("/sepolicy", F_OK) == 0;
|
||||||
|
if (patch || !hijack_sepolicy()) {
|
||||||
patch_sepolicy("/sepolicy", "/sepolicy");
|
patch_sepolicy("/sepolicy", "/sepolicy");
|
||||||
}
|
}
|
||||||
|
unlink("init-ld");
|
||||||
|
|
||||||
chdir("/");
|
chdir("/");
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <consts.hpp>
|
#include <consts.hpp>
|
||||||
#include <sepolicy.hpp>
|
#include <sepolicy.hpp>
|
||||||
#include <embed.hpp>
|
|
||||||
|
|
||||||
#include "init.hpp"
|
#include "init.hpp"
|
||||||
|
|
||||||
@@ -31,16 +30,6 @@ void MagiskInit::patch_sepolicy(const char *in, const char *out) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_preload() {
|
|
||||||
int fd = xopen("/dev/preload.so", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
|
|
||||||
if (fd < 0)
|
|
||||||
return;
|
|
||||||
fd_stream ch(fd);
|
|
||||||
if (!unxz(ch, byte_view(init_ld_xz, sizeof(init_ld_xz))))
|
|
||||||
return;
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MOCK_COMPAT SELINUXMOCK "/compatible"
|
#define MOCK_COMPAT SELINUXMOCK "/compatible"
|
||||||
#define MOCK_LOAD SELINUXMOCK "/load"
|
#define MOCK_LOAD SELINUXMOCK "/load"
|
||||||
#define MOCK_ENFORCE SELINUXMOCK "/enforce"
|
#define MOCK_ENFORCE SELINUXMOCK "/enforce"
|
||||||
@@ -53,7 +42,7 @@ bool MagiskInit::hijack_sepolicy() {
|
|||||||
// This meant that instead of going through convoluted methods trying to alter
|
// This meant that instead of going through convoluted methods trying to alter
|
||||||
// and block init's control flow, we can just LD_PRELOAD and replace the
|
// and block init's control flow, we can just LD_PRELOAD and replace the
|
||||||
// security_load_policy function with our own implementation.
|
// security_load_policy function with our own implementation.
|
||||||
dump_preload();
|
cp_afc("init-ld", "/dev/preload.so");
|
||||||
setenv("LD_PRELOAD", "/dev/preload.so", 1);
|
setenv("LD_PRELOAD", "/dev/preload.so", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,18 +89,10 @@ bool MagiskInit::hijack_sepolicy() {
|
|||||||
|
|
||||||
// Read all custom rules into memory
|
// Read all custom rules into memory
|
||||||
string rules;
|
string rules;
|
||||||
if (auto dir = xopen_dir("/data/" PREINITMIRR)) {
|
auto rule = "/data/" PREINITMIRR "/sepolicy.rule";
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
if (xaccess(rule, R_OK) == 0) {
|
||||||
auto name = "/data/" PREINITMIRR "/"s + entry->d_name;
|
LOGD("Loading custom sepolicy patch: [%s]\n", rule);
|
||||||
auto rule_file = name + "/sepolicy.rule";
|
rules = full_read(rule);
|
||||||
if (xaccess(rule_file.data(), R_OK) == 0 &&
|
|
||||||
access((name + "/disable").data(), F_OK) != 0 &&
|
|
||||||
access((name + "/remove").data(), F_OK) != 0) {
|
|
||||||
LOGD("Load custom sepolicy patch: [%s]\n", rule_file.data());
|
|
||||||
full_read(rule_file.data(), rules);
|
|
||||||
rules += '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Create a new process waiting for init operations
|
// Create a new process waiting for init operations
|
||||||
if (xfork()) {
|
if (xfork()) {
|
||||||
|
@@ -118,10 +118,6 @@ impl SepolicyExt for sepolicy {
|
|||||||
|
|
||||||
fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) {
|
fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) {
|
||||||
reader.foreach_lines(|line| {
|
reader.foreach_lines(|line| {
|
||||||
let line = line.trim();
|
|
||||||
if line.is_empty() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
parse_statement(self.as_mut(), line);
|
parse_statement(self.as_mut(), line);
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
@@ -3,7 +3,6 @@ use std::io::stderr;
|
|||||||
use std::{iter::Peekable, pin::Pin, vec::IntoIter};
|
use std::{iter::Peekable, pin::Pin, vec::IntoIter};
|
||||||
|
|
||||||
use base::{error, warn, FmtAdaptor};
|
use base::{error, warn, FmtAdaptor};
|
||||||
|
|
||||||
use crate::ffi::Xperm;
|
use crate::ffi::Xperm;
|
||||||
use crate::sepolicy;
|
use crate::sepolicy;
|
||||||
|
|
||||||
@@ -436,15 +435,16 @@ fn extract_token<'a>(s: &'a str, tokens: &mut Vec<Token<'a>>) {
|
|||||||
fn tokenize_statement(statement: &str) -> Vec<Token> {
|
fn tokenize_statement(statement: &str) -> Vec<Token> {
|
||||||
let mut tokens = Vec::new();
|
let mut tokens = Vec::new();
|
||||||
for s in statement.split_whitespace() {
|
for s in statement.split_whitespace() {
|
||||||
if s.starts_with('#') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
extract_token(s, &mut tokens);
|
extract_token(s, &mut tokens);
|
||||||
}
|
}
|
||||||
tokens
|
tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_statement(sepolicy: Pin<&mut sepolicy>, statement: &str) {
|
pub fn parse_statement(sepolicy: Pin<&mut sepolicy>, statement: &str) {
|
||||||
|
let statement = statement.trim();
|
||||||
|
if statement.is_empty() || statement.starts_with('#') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let mut tokens = tokenize_statement(statement).into_iter().peekable();
|
let mut tokens = tokenize_statement(statement).into_iter().peekable();
|
||||||
let result = exec_statement(sepolicy, &mut tokens);
|
let result = exec_statement(sepolicy, &mut tokens);
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
|
@@ -71,13 +71,14 @@ export KEEPFORCEENCRYPT=true
|
|||||||
echo "KEEPVERITY=$KEEPVERITY" > config
|
echo "KEEPVERITY=$KEEPVERITY" > config
|
||||||
echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config
|
echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config
|
||||||
echo "PREINITDEVICE=$(./magisk --preinit-device)" >> config
|
echo "PREINITDEVICE=$(./magisk --preinit-device)" >> config
|
||||||
# For API 28, we also patch advancedFeatures.ini to disable SAR
|
# For API 28, we also manually disable SystemAsRoot
|
||||||
# Manually override skip_initramfs by setting RECOVERYMODE=true
|
# Explicitly override skip_initramfs by setting RECOVERYMODE=true
|
||||||
[ $API = "28" ] && echo 'RECOVERYMODE=true' >> config
|
[ $API = "28" ] && echo 'RECOVERYMODE=true' >> config
|
||||||
cat config
|
cat config
|
||||||
|
|
||||||
./magiskboot compress=xz magisk magisk.xz
|
./magiskboot compress=xz magisk magisk.xz
|
||||||
./magiskboot compress=xz stub.apk stub.xz
|
./magiskboot compress=xz stub.apk stub.xz
|
||||||
|
./magiskboot compress=xz init-ld init-ld.xz
|
||||||
|
|
||||||
./magiskboot cpio ramdisk.cpio \
|
./magiskboot cpio ramdisk.cpio \
|
||||||
"add 0750 init magiskinit" \
|
"add 0750 init magiskinit" \
|
||||||
@@ -85,12 +86,13 @@ cat config
|
|||||||
"mkdir 0750 overlay.d/sbin" \
|
"mkdir 0750 overlay.d/sbin" \
|
||||||
"add 0644 overlay.d/sbin/magisk.xz magisk.xz" \
|
"add 0644 overlay.d/sbin/magisk.xz magisk.xz" \
|
||||||
"add 0644 overlay.d/sbin/stub.xz stub.xz" \
|
"add 0644 overlay.d/sbin/stub.xz stub.xz" \
|
||||||
|
"add 0644 overlay.d/sbin/init-ld.xz init-ld.xz" \
|
||||||
"patch" \
|
"patch" \
|
||||||
"backup ramdisk.cpio.orig" \
|
"backup ramdisk.cpio.orig" \
|
||||||
"mkdir 000 .backup" \
|
"mkdir 000 .backup" \
|
||||||
"add 000 .backup/.magisk config"
|
"add 000 .backup/.magisk config"
|
||||||
|
|
||||||
rm -f ramdisk.cpio.orig config magisk*.xz stub.xz
|
rm -f ramdisk.cpio.orig config *.xz
|
||||||
if $IS_RAMDISK; then
|
if $IS_RAMDISK; then
|
||||||
./magiskboot compress=gzip ramdisk.cpio "$OUTPUT_FILE"
|
./magiskboot compress=gzip ramdisk.cpio "$OUTPUT_FILE"
|
||||||
else
|
else
|
||||||
|
@@ -221,7 +221,7 @@ else
|
|||||||
# Android 15 Beta
|
# Android 15 Beta
|
||||||
run_test 35 google_apis
|
run_test 35 google_apis
|
||||||
# Run 16k page tests
|
# Run 16k page tests
|
||||||
run_test VanillaIceCream google_apis_ps16k
|
run_test 35 google_apis_ps16k
|
||||||
fi
|
fi
|
||||||
|
|
||||||
"$avd" delete avd -n test
|
"$avd" delete avd -n test
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
# magiskinit binary The binary to replace /init.
|
# magiskinit binary The binary to replace /init.
|
||||||
# magisk binary The magisk binary.
|
# magisk binary The magisk binary.
|
||||||
# magiskboot binary A tool to manipulate boot images.
|
# magiskboot binary A tool to manipulate boot images.
|
||||||
|
# init-ld binary The library that will be LD_PRELOAD of /init
|
||||||
# stub.apk binary The stub Magisk app to embed into ramdisk.
|
# stub.apk binary The stub Magisk app to embed into ramdisk.
|
||||||
# chromeos folder This folder includes the utility and keys to sign
|
# chromeos folder This folder includes the utility and keys to sign
|
||||||
# (optional) chromeos boot images. Only used for Pixel C.
|
# (optional) chromeos boot images. Only used for Pixel C.
|
||||||
@@ -161,6 +162,7 @@ $BOOTMODE && [ -z "$PREINITDEVICE" ] && PREINITDEVICE=$(./magisk --preinit-devic
|
|||||||
# Compress to save precious ramdisk space
|
# Compress to save precious ramdisk space
|
||||||
./magiskboot compress=xz magisk magisk.xz
|
./magiskboot compress=xz magisk magisk.xz
|
||||||
./magiskboot compress=xz stub.apk stub.xz
|
./magiskboot compress=xz stub.apk stub.xz
|
||||||
|
./magiskboot compress=xz init-ld init-ld.xz
|
||||||
|
|
||||||
echo "KEEPVERITY=$KEEPVERITY" > config
|
echo "KEEPVERITY=$KEEPVERITY" > config
|
||||||
echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config
|
echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config
|
||||||
@@ -177,13 +179,14 @@ fi
|
|||||||
"mkdir 0750 overlay.d/sbin" \
|
"mkdir 0750 overlay.d/sbin" \
|
||||||
"add 0644 overlay.d/sbin/magisk.xz magisk.xz" \
|
"add 0644 overlay.d/sbin/magisk.xz magisk.xz" \
|
||||||
"add 0644 overlay.d/sbin/stub.xz stub.xz" \
|
"add 0644 overlay.d/sbin/stub.xz stub.xz" \
|
||||||
|
"add 0644 overlay.d/sbin/init-ld.xz init-ld.xz" \
|
||||||
"patch" \
|
"patch" \
|
||||||
"$SKIP_BACKUP backup ramdisk.cpio.orig" \
|
"$SKIP_BACKUP backup ramdisk.cpio.orig" \
|
||||||
"mkdir 000 .backup" \
|
"mkdir 000 .backup" \
|
||||||
"add 000 .backup/.magisk config" \
|
"add 000 .backup/.magisk config" \
|
||||||
|| abort "! Unable to patch ramdisk"
|
|| abort "! Unable to patch ramdisk"
|
||||||
|
|
||||||
rm -f ramdisk.cpio.orig config magisk*.xz stub.xz
|
rm -f ramdisk.cpio.orig config *.xz
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Binary Patches
|
# Binary Patches
|
||||||
|
248
scripts/release.sh
Executable file
248
scripts/release.sh
Executable file
@@ -0,0 +1,248 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# On macOS, gsed is required (brew install gnu-sed)
|
||||||
|
# Required tools: jq, gh
|
||||||
|
# The GitHub cli (gh) has to be properly authenticated
|
||||||
|
|
||||||
|
# These variables can be modified as needed
|
||||||
|
MAGISK_FILES=../magisk-files
|
||||||
|
CONFIG=config.prop
|
||||||
|
NOTES=notes.md
|
||||||
|
|
||||||
|
# These are constants, do not modify
|
||||||
|
GCONFIG=gradle.properties
|
||||||
|
README=README.MD
|
||||||
|
BUILDCMD="./build.py -c $CONFIG"
|
||||||
|
CWD=$(pwd)
|
||||||
|
|
||||||
|
grep_prop() {
|
||||||
|
local REGEX="s/^$1=//p"
|
||||||
|
shift
|
||||||
|
local FILES=$@
|
||||||
|
sed -n "$REGEX" $FILES | head -n 1
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_version_config() {
|
||||||
|
# Make sure version is not commented out and exists
|
||||||
|
sed -i "s:^# version=:version=:g" $CONFIG
|
||||||
|
if ! grep -qE '^version=' $CONFIG; then
|
||||||
|
echo 'version=' >> $CONFIG
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_version_config() {
|
||||||
|
# Comment out version config
|
||||||
|
sed -i "s:^version=:# version=:g" $CONFIG
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = tag
|
||||||
|
update_readme_stable() {
|
||||||
|
sed -i "s:badge/Magisk-v.*:badge/Magisk-${1}-blue)](https\://github.com/topjohnwu/Magisk/releases/tag/$1):g" $README
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = tag
|
||||||
|
update_readme_beta() {
|
||||||
|
sed -i "s:badge/Magisk%20Beta.*:badge/Magisk%20Beta-${1}-blue)](https\://github.com/topjohnwu/Magisk/releases/tag/$1):g" $README
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = tag
|
||||||
|
update_readme_canary() {
|
||||||
|
sed -i "s:badge/Magisk-Canary.*:badge/Magisk-Canary-red)](https\://github.com/topjohnwu/Magisk/releases/tag/$1):g" $README
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_link() {
|
||||||
|
echo "https://github.com/topjohnwu/Magisk/releases/download/$1/$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_canary_json() {
|
||||||
|
local ver=$(grep_prop version $CONFIG)
|
||||||
|
local code=$(grep_prop magisk.versionCode $GCONFIG)
|
||||||
|
local tag="canary-$code"
|
||||||
|
local json
|
||||||
|
|
||||||
|
json=$MAGISK_FILES/canary.json
|
||||||
|
jq ".magisk.version=\"$ver\"|.magisk.versionCode=\"$code\"|
|
||||||
|
.magisk.link=\"$(gen_link $tag app-release.apk)\"|
|
||||||
|
.magisk.note=\"$(gen_link $tag notes.md)\"" $json > ${json}.tmp
|
||||||
|
mv ${json}.tmp $json
|
||||||
|
|
||||||
|
json=$MAGISK_FILES/debug.json
|
||||||
|
jq ".magisk.version=\"$ver\"|.magisk.versionCode=\"$code\"|
|
||||||
|
.magisk.link=\"$(gen_link $tag app-debug.apk)\"|
|
||||||
|
.magisk.note=\"$(gen_link $tag notes.md)\"" $json > ${json}.tmp
|
||||||
|
mv ${json}.tmp $json
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = json path
|
||||||
|
update_release_json() {
|
||||||
|
local json=$1
|
||||||
|
local ver=$(grep_prop version $CONFIG)
|
||||||
|
local code=$(grep_prop magisk.versionCode $GCONFIG)
|
||||||
|
|
||||||
|
jq ".magisk.version=\"$ver\"|.magisk.versionCode=\"$code\"|
|
||||||
|
.magisk.link=\"$(gen_link v${ver} Magisk-v${ver}.apk)\"|
|
||||||
|
.magisk.note=\"https://topjohnwu.github.io/Magisk/releases/${code}.md\"" $json > ${json}.tmp
|
||||||
|
mv ${json}.tmp $json
|
||||||
|
}
|
||||||
|
|
||||||
|
build_canary() {
|
||||||
|
enable_version_config
|
||||||
|
|
||||||
|
# Update version code
|
||||||
|
local code=$(grep_prop magisk.versionCode $GCONFIG)
|
||||||
|
code=$((code + 1))
|
||||||
|
local tag="canary-$code"
|
||||||
|
sed -i "s:versionCode=.*:versionCode=${code}:g" $GCONFIG
|
||||||
|
update_readme_canary $tag
|
||||||
|
|
||||||
|
# Commit version code changes
|
||||||
|
git add -u .
|
||||||
|
git status
|
||||||
|
git commit -m "Release new canary build"
|
||||||
|
git tag $tag
|
||||||
|
|
||||||
|
# Update version name
|
||||||
|
local ver=$(git rev-parse --short=8 HEAD)
|
||||||
|
sed -i "s:version=.*:version=${ver}:g" $CONFIG
|
||||||
|
sed -i "s:## Magisk (.*:## Magisk (${ver}) (${code}):g" $NOTES
|
||||||
|
|
||||||
|
# Update and commit JSON
|
||||||
|
update_canary_json
|
||||||
|
cd $MAGISK_FILES
|
||||||
|
git add -u .
|
||||||
|
git status
|
||||||
|
git commit -m "Update Canary Channel: Upstream to $ver"
|
||||||
|
cd $CWD
|
||||||
|
|
||||||
|
# Build
|
||||||
|
$BUILDCMD clean
|
||||||
|
$BUILDCMD all
|
||||||
|
$BUILDCMD -r all
|
||||||
|
|
||||||
|
disable_version_config
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = ver, $2 = stable?
|
||||||
|
build_release() {
|
||||||
|
enable_version_config
|
||||||
|
|
||||||
|
# Update version configs
|
||||||
|
local ver=$1
|
||||||
|
local stable=$2
|
||||||
|
local code=$(echo - | awk "{ print $ver * 1000 }")
|
||||||
|
local tag="v$ver"
|
||||||
|
sed -i "s:versionCode=.*:versionCode=${code}:g" $GCONFIG
|
||||||
|
sed -i "s:version=.*:version=${ver}:g" $CONFIG
|
||||||
|
|
||||||
|
# Update and commit JSON
|
||||||
|
if $stable; then
|
||||||
|
update_readme_stable $tag
|
||||||
|
update_readme_beta $tag
|
||||||
|
update_release_json $MAGISK_FILES/stable.json
|
||||||
|
cp -vf $MAGISK_FILES/stable.json $MAGISK_FILES/beta.json
|
||||||
|
else
|
||||||
|
update_readme_beta $tag
|
||||||
|
update_release_json $MAGISK_FILES/beta.json
|
||||||
|
fi
|
||||||
|
cd $MAGISK_FILES
|
||||||
|
git add -u .
|
||||||
|
git status
|
||||||
|
git commit -m "Release Magisk v$ver"
|
||||||
|
cd $CWD
|
||||||
|
|
||||||
|
# Commit version code changes
|
||||||
|
git add -u .
|
||||||
|
git status
|
||||||
|
git commit -m "Release Magisk v$ver"
|
||||||
|
git tag $tag
|
||||||
|
|
||||||
|
# Build
|
||||||
|
$BUILDCMD clean
|
||||||
|
$BUILDCMD -r all
|
||||||
|
|
||||||
|
disable_version_config
|
||||||
|
}
|
||||||
|
|
||||||
|
stable() {
|
||||||
|
[ -z $1 ] && exit 1
|
||||||
|
local ver=$1
|
||||||
|
build_release $ver true
|
||||||
|
}
|
||||||
|
|
||||||
|
beta() {
|
||||||
|
[ -z $1 ] && exit 1
|
||||||
|
local ver=$1
|
||||||
|
build_release $ver false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub() {
|
||||||
|
gh auth status
|
||||||
|
|
||||||
|
local latest_tag=$(git describe --abbrev=0 --tags)
|
||||||
|
local ver=$(grep_prop version $CONFIG)
|
||||||
|
local code=$(grep_prop magisk.versionCode $GCONFIG)
|
||||||
|
local out=$(grep_prop outdir $CONFIG)
|
||||||
|
local tag title
|
||||||
|
|
||||||
|
if [ -z $out ]; then
|
||||||
|
out=out
|
||||||
|
fi
|
||||||
|
|
||||||
|
git push origin master
|
||||||
|
git push --tags
|
||||||
|
|
||||||
|
if [ $(($code % 100)) -ne 0 ]; then
|
||||||
|
tag="canary-$code"
|
||||||
|
title="Magisk ($ver) ($code)"
|
||||||
|
|
||||||
|
# Assert tag format
|
||||||
|
[ $latest_tag = $tag ]
|
||||||
|
|
||||||
|
# Publish release
|
||||||
|
tail -n +3 $NOTES > release.md
|
||||||
|
gh release create --verify-tag $tag -p -t "$title" -F release.md $out/app-release.apk $out/app-debug.apk $NOTES
|
||||||
|
else
|
||||||
|
tag="v$ver"
|
||||||
|
title="Magisk v$ver"
|
||||||
|
|
||||||
|
# Assert tag format
|
||||||
|
[ $latest_tag = $tag ]
|
||||||
|
|
||||||
|
# Publish release
|
||||||
|
tail -n +3 docs/releases/$code.md > release.md
|
||||||
|
gh release create --verify-tag $tag -t "$title" -F release.md "$out/app-release.apk#Magisk-v${ver}.apk"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f release.md
|
||||||
|
cd $MAGISK_FILES
|
||||||
|
git push origin master
|
||||||
|
cd $CWD
|
||||||
|
}
|
||||||
|
|
||||||
|
revert() {
|
||||||
|
local latest_tag=$(git describe --abbrev=0 --tags)
|
||||||
|
|
||||||
|
git tag -d $latest_tag
|
||||||
|
git reset --hard HEAD~
|
||||||
|
cd $MAGISK_FILES
|
||||||
|
git reset --hard HEAD~
|
||||||
|
cd $CWD
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use GNU sed on macOS
|
||||||
|
if command -v gsed >/dev/null; then
|
||||||
|
function sed() { gsed "$@"; }
|
||||||
|
export -f sed
|
||||||
|
fi
|
||||||
|
|
||||||
|
git pull
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
"canary" ) build_canary ;;
|
||||||
|
"stable" ) stable $2 ;;
|
||||||
|
"beta" ) beta $2 ;;
|
||||||
|
"pub" ) pub ;;
|
||||||
|
"revert" ) revert ;;
|
||||||
|
* ) exit 1 ;;
|
||||||
|
esac
|
Reference in New Issue
Block a user