diff --git a/buildSrc/src/main/kotlin/HmppConfigure.kt b/buildSrc/src/main/kotlin/HmppConfigure.kt
index 35c2903c7..3f723732c 100644
--- a/buildSrc/src/main/kotlin/HmppConfigure.kt
+++ b/buildSrc/src/main/kotlin/HmppConfigure.kt
@@ -27,7 +27,7 @@ private val miraiPlatform = Attribute.of(
 )
 
 
-fun Project.configureHMPPJvm() {
+fun Project.configureHMPP() {
     extensions.getByType(KotlinMultiplatformExtension::class.java).apply {
 //        jvm("jvmBase") {
 //            compilations.all {
@@ -128,38 +128,76 @@ fun Project.configureHMPPJvm() {
     }
 }
 
+private fun Project.linkerDirs(): List<String> {
+    return listOf(
+        ":mirai-core",
+        ":mirai-core-api",
+        ":mirai-core-utils",
+    ).map {
+        rootProject.project(it).projectDir.resolve("src/nativeMainInterop/target/debug/").absolutePath
+    }
+}
+
+private fun Project.includeDirs(): List<String> {
+    return listOf(
+        ":mirai-core",
+        ":mirai-core-api",
+        ":mirai-core-utils",
+    ).map {
+        rootProject.project(it).projectDir.resolve("src/nativeMainInterop/").absolutePath
+    }
+}
+
 private fun Project.configureNativeInterop(
     compilationName: String,
     nativeInteropDir: File,
     nativeTargets: MutableList<KotlinNativeTarget>
 ) {
+    val crateName = project.name.replace("-", "_") + "_i"
+
+    configure(nativeTargets) {
+        binaries {
+            for (buildType in NativeBuildType.values()) {
+                findTest(buildType)?.apply {
+                    linkerOpts("-v")
+                    linkerOpts(*linkerDirs().map { "-L$it" }.toTypedArray())
+                    linkerOpts("-undefined", "dynamic_lookup") // resolve symbol in runtime
+                }
+            }
+        }
+    }
     if (nativeInteropDir.exists() && nativeInteropDir.isDirectory && nativeInteropDir.resolve("build.rs").exists()) {
-        val crateName = project.name.replace("-", "_") + "_i"
         val kotlinDylibName = project.name.replace("-", "_")
 
         val headerName = "$crateName.h"
         val rustLibDir = nativeInteropDir.resolve("target/debug/")
 
+        var interopTaskName = ""
+
         configure(nativeTargets) {
-            compilations.getByName(compilationName).cinterops.create(compilationName) {
+            interopTaskName = compilations.getByName(compilationName).cinterops.create(compilationName) {
+                defFile(nativeInteropDir.resolve("interop.def"))
                 val headerFile = nativeInteropDir.resolve(headerName)
                 if (headerFile.exists()) headers(headerFile)
-                defFile(nativeInteropDir.resolve("interop.def"))
-            }
+            }.interopProcessingTaskName
 
             binaries {
                 sharedLib {
                     linkerOpts("-v")
-                    linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}")
-//                    linkerOpts("-lmirai_core_utils_i")
-                    linkerOpts("-undefined", "dynamic_lookup")
+                    linkerOpts(*linkerDirs().map { "-L$it" }.toTypedArray())
+//                    linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}")
+                    linkerOpts("-undefined", "dynamic_lookup") // resolve symbol in runtime
                     baseName = project.name
                 }
-                getTest(NativeBuildType.DEBUG).apply {
-                    linkerOpts("-v")
-                    linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}")
-                    linkerOpts("-lmirai_core_utils_i")
-//                    linkerOpts("-undefined", "dynamic_lookup")
+
+                configure(nativeTargets) {
+                    binaries {
+                        for (buildType in NativeBuildType.values()) {
+                            findTest(buildType)?.apply {
+                                linkerOpts("-l$crateName") // test strongly links
+                            }
+                        }
+                    }
                 }
             }
         }
@@ -185,14 +223,16 @@ private fun Project.configureNativeInterop(
             }
         }
 
-        val cinteropTask = tasks.getByName("cinterop${compilationName.titlecase()}Native")
-        cinteropTask.mustRunAfter(cbindgen)
-
         val generateRustBindings = tasks.register("generateRustBindings${compilationName.titlecase()}") {
             group = "mirai"
             description = "Generates Rust bindings for Kotlin"
             dependsOn(cbindgen)
-            dependsOn(cinteropTask)
+        }
+
+        afterEvaluate {
+            val cinteropTask = tasks.getByName(interopTaskName)
+            cinteropTask.mustRunAfter(cbindgen)
+            generateRustBindings.get().dependsOn(cinteropTask)
         }
 
         val bindgen = tasks.register("bindgen${compilationName.titlecase()}") {
diff --git a/buildSrc/src/main/kotlin/ProjectConfigure.kt b/buildSrc/src/main/kotlin/ProjectConfigure.kt
index 9568617b7..7827c1b4d 100644
--- a/buildSrc/src/main/kotlin/ProjectConfigure.kt
+++ b/buildSrc/src/main/kotlin/ProjectConfigure.kt
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
 import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
 import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
 import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
+import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
 
 
 fun Project.useIr() {
@@ -41,7 +42,6 @@ fun Project.preConfigureJvmTarget() {
     val defaultVer = jvmVersion()
 
     tasks.withType(KotlinJvmCompile::class.java) {
-        kotlinOptions.languageVersion = "1.6"
         kotlinOptions.jvmTarget = defaultVer.toString()
         kotlinOptions.freeCompilerArgs += "-Xjvm-default=all"
 
diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt
index 2b5def5e5..26103dd55 100644
--- a/buildSrc/src/main/kotlin/Versions.kt
+++ b/buildSrc/src/main/kotlin/Versions.kt
@@ -24,9 +24,9 @@ object Versions {
 
     const val kotlinCompiler = "1.7.0-RC"
     const val kotlinStdlib = kotlinCompiler
-    const val dokka = "1.6.20"
+    const val dokka = "1.6.21"
 
-    const val kotlinCompilerForIdeaPlugin = "1.6.20"
+    const val kotlinCompilerForIdeaPlugin = "1.7.0-RC"
 
     const val coroutines = "1.6.1"
     const val atomicFU = "0.17.2"
@@ -38,8 +38,8 @@ object Versions {
     const val io = "0.1.16"
     const val coroutinesIo = "0.1.16"
 
-    const val blockingBridge = "2.1.0-162.1"
-    const val dynamicDelegation = "0.3.0-162.4"
+    const val blockingBridge = "2.1.0-170.1"
+    const val dynamicDelegation = "0.3.0-170.1"
 
     const val androidGradlePlugin = "4.1.1"
     const val android = "4.1.1.4"
diff --git a/mirai-console/tools/compiler-annotations/build.gradle.kts b/mirai-console/tools/compiler-annotations/build.gradle.kts
index 538ab056f..059a1ec0f 100644
--- a/mirai-console/tools/compiler-annotations/build.gradle.kts
+++ b/mirai-console/tools/compiler-annotations/build.gradle.kts
@@ -20,7 +20,7 @@ description = "Mirai Console compiler annotations"
 kotlin {
     explicitApi()
 
-    configureHMPPJvm()
+    configureHMPP()
 }
 
 configureMppPublishing()
\ No newline at end of file
diff --git a/mirai-core-api/build.gradle.kts b/mirai-core-api/build.gradle.kts
index 4f7c42565..342e886aa 100644
--- a/mirai-core-api/build.gradle.kts
+++ b/mirai-core-api/build.gradle.kts
@@ -26,7 +26,7 @@ description = "Mirai API module"
 
 kotlin {
     explicitApi()
-    configureHMPPJvm()
+    configureHMPP()
 
 
     sourceSets {
diff --git a/mirai-core-api/src/nativeMain/kotlin/spi/SPIServiceLoader.kt b/mirai-core-api/src/nativeMain/kotlin/spi/SPIServiceLoader.kt
index 0f6b5c2df..856713847 100644
--- a/mirai-core-api/src/nativeMain/kotlin/spi/SPIServiceLoader.kt
+++ b/mirai-core-api/src/nativeMain/kotlin/spi/SPIServiceLoader.kt
@@ -10,6 +10,7 @@
 package net.mamoe.mirai.spi
 
 import net.mamoe.mirai.utils.MiraiLogger
+import net.mamoe.mirai.utils.loadService
 import kotlin.reflect.KClass
 
 internal actual class SPIServiceLoader<T : BaseService> actual constructor(
@@ -19,7 +20,7 @@ internal actual class SPIServiceLoader<T : BaseService> actual constructor(
     actual var service: T = defaultService
 
     actual fun reload() {
-        TODO("native")
+        service = loadService(serviceType) { service }
     }
 
     init {
diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/BotConfiguration.kt b/mirai-core-api/src/nativeMain/kotlin/utils/BotConfiguration.kt
index c6850065c..009ae9dca 100644
--- a/mirai-core-api/src/nativeMain/kotlin/utils/BotConfiguration.kt
+++ b/mirai-core-api/src/nativeMain/kotlin/utils/BotConfiguration.kt
@@ -7,6 +7,8 @@
  * https://github.com/mamoe/mirai/blob/dev/LICENSE
  */
 
+@file:Suppress("RedundantVisibilityModifier")
+
 package net.mamoe.mirai.utils
 
 import io.ktor.utils.io.core.*
diff --git a/mirai-core-utils/build.gradle.kts b/mirai-core-utils/build.gradle.kts
index 89cdef48e..0d2848c86 100644
--- a/mirai-core-utils/build.gradle.kts
+++ b/mirai-core-utils/build.gradle.kts
@@ -23,7 +23,7 @@ description = "mirai-core utilities"
 kotlin {
     explicitApi()
 
-    configureHMPPJvm()
+    configureHMPP()
 
     sourceSets {
         val commonMain by getting {
diff --git a/mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt b/mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt
index 0282bd04b..372bdd4e9 100644
--- a/mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt
+++ b/mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt
@@ -19,18 +19,20 @@ import platform.posix.uint8_tVar
 
 public actual val DEFAULT_BUFFER_SIZE: Int get() = 8192
 
-public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray = callImpl(::mirai_crypto_md5, offset, length)
-public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray = callImpl(::mirai_crypto_sha1, offset, length)
+public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray = callImpl(::mirai_hash_md5, offset, length)
+public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray = callImpl(::mirai_hash_sh1, offset, length)
+
+public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray =
+    callImpl(::mirai_compression_gzip, offset, length)
 
-public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray = callImpl(::mirai_crypto_gzip, offset, length)
 public actual fun ByteArray.ungzip(offset: Int, length: Int): ByteArray =
-    callImpl(::mirai_crypto_ungzip, offset, length)
+    callImpl(::mirai_compression_ungzip, offset, length)
 
 public actual fun ByteArray.deflate(offset: Int, length: Int): ByteArray =
-    callImpl(::mirai_crypto_deflate, offset, length)
+    callImpl(::mirai_compression_deflate, offset, length)
 
 public actual fun ByteArray.inflate(offset: Int, length: Int): ByteArray =
-    callImpl(::mirai_crypto_inflate, offset, length)
+    callImpl(::mirai_compression_infalte, offset, length)
 
 
 private fun ByteArray.callImpl(
diff --git a/mirai-core-utils/src/nativeMainInterop/src/crypto.rs b/mirai-core-utils/src/nativeMainInterop/src/cipher.rs
similarity index 83%
rename from mirai-core-utils/src/nativeMainInterop/src/crypto.rs
rename to mirai-core-utils/src/nativeMainInterop/src/cipher.rs
index 6efd52b6e..e4845ea3d 100644
--- a/mirai-core-utils/src/nativeMainInterop/src/crypto.rs
+++ b/mirai-core-utils/src/nativeMainInterop/src/cipher.rs
@@ -24,7 +24,7 @@ pub struct SizedByteArray {
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn mirai_crypto_md5(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
+pub unsafe extern "C" fn mirai_hash_md5(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
     let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
     let result = md5::compute(data);
     let size = 16;
@@ -37,7 +37,7 @@ pub unsafe extern "C" fn mirai_crypto_md5(data: *const u8, len: u32, ret: &mut S
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn mirai_crypto_sha1(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
+pub unsafe extern "C" fn mirai_hash_sh1(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
     let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
     let mut hasher = Sha1::new();
     hasher.update(data);
@@ -53,7 +53,7 @@ pub unsafe extern "C" fn mirai_crypto_sha1(data: *const u8, len: u32, ret: &mut
 
 
 #[no_mangle]
-pub unsafe extern "C" fn mirai_crypto_gzip(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
+pub unsafe extern "C" fn mirai_compression_gzip(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
     let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
     let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
 
@@ -71,7 +71,7 @@ pub unsafe extern "C" fn mirai_crypto_gzip(data: *const u8, len: u32, ret: &mut
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn mirai_crypto_ungzip(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
+pub unsafe extern "C" fn mirai_compression_ungzip(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
     let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
     let mut encoder = GzDecoder::new(Vec::new());
 
@@ -89,7 +89,7 @@ pub unsafe extern "C" fn mirai_crypto_ungzip(data: *const u8, len: u32, ret: &mu
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn mirai_crypto_deflate(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
+pub unsafe extern "C" fn mirai_compression_deflate(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
     let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
     let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
 
@@ -107,7 +107,7 @@ pub unsafe extern "C" fn mirai_crypto_deflate(data: *const u8, len: u32, ret: &m
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn mirai_crypto_inflate(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
+pub unsafe extern "C" fn mirai_compression_infalte(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
     let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
     let mut encoder = ZlibDecoder::new(Vec::new());
 
diff --git a/mirai-core-utils/src/nativeMainInterop/src/lib.rs b/mirai-core-utils/src/nativeMainInterop/src/lib.rs
index 592b7953c..bb8a0cb90 100644
--- a/mirai-core-utils/src/nativeMainInterop/src/lib.rs
+++ b/mirai-core-utils/src/nativeMainInterop/src/lib.rs
@@ -15,6 +15,6 @@ extern crate sha1;
 
 /// cbindgen:ignore
 mod bindings;
-mod crypto;
+mod cipher;
 mod chmap;
 
diff --git a/mirai-core/build.gradle.kts b/mirai-core/build.gradle.kts
index f4054499c..08cfc5a49 100644
--- a/mirai-core/build.gradle.kts
+++ b/mirai-core/build.gradle.kts
@@ -25,7 +25,7 @@ description = "Mirai Protocol implementation for QQ Android"
 kotlin {
     explicitApi()
 
-    configureHMPPJvm()
+    configureHMPP()
 
     sourceSets.apply {
 
diff --git a/mirai-core/src/nativeMainInterop/Cargo.toml b/mirai-core/src/nativeMainInterop/Cargo.toml
index 6864969ca..f3dad07b1 100644
--- a/mirai-core/src/nativeMainInterop/Cargo.toml
+++ b/mirai-core/src/nativeMainInterop/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
-name = "mirai_core"
+name = "mirai_core_i"
 version = "0.1.0"
 
 [dependencies]
 
 [lib]
-name = "mirai_core"
+name = "mirai_core_i"
 crate-type = ["cdylib"]      # Creates dynamic lib
 # crate-type = ["staticlib"] # Creates static lib