diff --git a/.cargo/config.toml b/.cargo/config.toml
index 4b1b35d413d5d17cf970c8cd087906b188d0f1ae..3a85f90dbb31dad18bfa7a439520412e40b9ae33 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -4,7 +4,7 @@ build-std = ["core", "alloc"]
 build-std-features = ["compiler-builtins-mem"]
 
 [build]
-target = "x86_64-unknown-none-hermitkernel"
+target = "targets/x86_64-unknown-none-hermitkernel.json"
 rustflags = [
   "-Zmutable-noalias=no"
 ]
diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml
index be636965787d963d981f51e125ebea90f09f5351..a562065dbe5931c7a3c763ce86fbc917e44d5508 100644
--- a/.github/workflows/aarch64.yml
+++ b/.github/workflows/aarch64.yml
@@ -41,7 +41,7 @@ jobs:
         run: rustup show
       - name: Build minimal kernel
         working-directory: libhermit-rs
-        run: cargo build --no-default-features --target aarch64-unknown-none-hermitkernel -Z build-std=core,alloc
+        run: cargo build --no-default-features --target targets/aarch64-unknown-none-hermitkernel.json -Z build-std=core,alloc
       - name: Build dev profile
         run: cargo build --target aarch64-unknown-hermit -p hello_world
       - name: Build loader
diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml
index e387d1421afd2434798617e60a310fee92b2c874..f91b40e4c94f0fe7cbde6496fdad252c818b06bb 100644
--- a/.github/workflows/doc.yml
+++ b/.github/workflows/doc.yml
@@ -27,5 +27,5 @@ jobs:
         env:
           RUSTDOCFLAGS: -D warnings
         run: |
-          cargo doc --no-deps --document-private-items --target x86_64-unknown-none-hermitkernel
-          cargo doc --no-deps --document-private-items --target aarch64-unknown-none-hermitkernel
+          cargo doc --no-deps --document-private-items --target targets/x86_64-unknown-none-hermitkernel.json
+          cargo doc --no-deps --document-private-items --target targets/aarch64-unknown-none-hermitkernel.json
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 333dfb55e312d38872a16113b3795a1010c5cd49..fc9367d8311df4bf44a05f65db8aa67e0cd2f4cf 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -59,10 +59,10 @@ test:integration:
     - python3 --version
     - HERMIT_LOG_LEVEL_FILTER=Debug cargo test --test '*' --no-fail-fast -Z build-std=core,alloc 
         -Z build-std-features=compiler-builtins-mem --no-default-features --features=pci,acpi 
-        --target x86_64-unknown-none-hermitkernel -- --veryverbose
+        --target targets/x86_64-unknown-none-hermitkernel.json -- --veryverbose
     - HERMIT_LOG_LEVEL_FILTER=Debug cargo test --test '*' --no-fail-fast -Z build-std=core,alloc 
         -Z build-std-features=compiler-builtins-mem --no-default-features --features=pci,acpi 
-        --target x86_64-unknown-none-hermitkernel -- --num_cores 2
+        --target targets/x86_64-unknown-none-hermitkernel.json -- --num_cores 2
         --veryverbose
   tags:
     - privileged
diff --git a/Cargo.toml b/Cargo.toml
index 0e753ecd37fb557d704c99581b395b8588778bdb..4f66b1f43e59948ab0cf59733e1c5135cdcd805c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,12 +31,6 @@ exclude = [
 	".gitignore",
 ]
 
-[package.metadata.docs.rs]
-targets = [
-	"x86_64-unknown-none-hermitkernel",
-	"aarch64-unknown-none-hermitkernel",
-]
-
 [lib]
 crate-type = ["staticlib", "lib"]  # "lib" required for integration tests
 name = "hermit"
diff --git a/README.md b/README.md
index 1af84caff8c822f7158973e9baf7b16a5b325aaa..8649280118e9bfd48fa478dcf69fb305ae413f7f 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ rustup component add rust-src llvm-tools-preview
 You can then build `libhermit-rs` with the following command
 
 ```sh
-cargo build -Z build-std=core,alloc,panic_abort --target x86_64-unknown-none-hermitkernel
+cargo build -Z build-std=core,alloc,panic_abort --target targets/x86_64-unknown-none-hermitkernel.json
 ```
 
 The resulting library then can be found in `target/x86_64-unknown-none-hermitkernel/debug/libhermit.a`
@@ -44,7 +44,7 @@ You can change it by setting it at compile time to a string matching the name of
 If the variable is not set, or the name doesn't match, then `LevelFilter::Info` is used by default.
 
 ```sh
-$ HERMIT_LOG_LEVEL_FILTER=Debug cargo build -Z build-std=core,alloc,panic_abort --target x86_64-unknown-none-hermitkernel
+$ HERMIT_LOG_LEVEL_FILTER=Debug cargo build -Z build-std=core,alloc,panic_abort --target targets/x86_64-unknown-none-hermitkernel.json
 ```
 
 ## Credits
diff --git a/targets/aarch64-unknown-none-hermitkernel.json b/targets/aarch64-unknown-none-hermitkernel.json
new file mode 100644
index 0000000000000000000000000000000000000000..5728ac222f2e534b6479483d3d36946a660cc3b3
--- /dev/null
+++ b/targets/aarch64-unknown-none-hermitkernel.json
@@ -0,0 +1,23 @@
+{
+    "abi": "softfloat",
+    "arch": "aarch64",
+    "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
+    "disable-redzone": true,
+    "executables": true,
+    "features": "+strict-align,-neon,-fp-armv8",
+    "linker": "rust-lld",
+    "linker-flavor": "ld.lld",
+    "llvm-target": "aarch64-unknown-hermit",
+    "max-atomic-width": 128,
+    "panic-strategy": "abort",
+    "position-independent-executables": true,
+    "pre-link-args": {
+        "ld.lld": [
+            "--build-id",
+            "--hash-style=gnu",
+            "--Bstatic"
+        ]
+    },
+    "static-position-independent-executables": true,
+    "target-pointer-width": "64"
+}
\ No newline at end of file
diff --git a/targets/x86_64-unknown-none-hermitkernel.json b/targets/x86_64-unknown-none-hermitkernel.json
new file mode 100644
index 0000000000000000000000000000000000000000..e441048ef91803c3b5cae8f702859b0d53532613
--- /dev/null
+++ b/targets/x86_64-unknown-none-hermitkernel.json
@@ -0,0 +1,26 @@
+{
+    "arch": "x86_64",
+    "cpu": "x86-64",
+    "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
+    "disable-redzone": true,
+    "executables": true,
+    "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
+    "linker": "rust-lld",
+    "linker-flavor": "ld.lld",
+    "llvm-target": "x86_64-unknown-hermit",
+    "max-atomic-width": 64,
+    "panic-strategy": "abort",
+    "position-independent-executables": true,
+    "pre-link-args": {
+        "ld.lld": [
+            "--build-id",
+            "--hash-style=gnu",
+            "--Bstatic"
+        ]
+    },
+    "stack-probes": {
+        "kind": "call"
+    },
+    "static-position-independent-executables": true,
+    "target-pointer-width": "64"
+}
\ No newline at end of file