
Guía paso a paso para compilar kernels personalizados de Kali NetHunter para Android: obtención del código fuente, selección de la cadena de herramientas, compilación cruzada y flasheo.
El mayor obstáculo para la mayoría de las personas que quieren configurar un dispositivo Nethunter es el requisito del kernel. A menos que tu dispositivo ya tenga un kernel precompilado (y mantenido), te dirán que compiles uno tú mismo. Ya hay mucha documentación sobre este proceso, pero en mi experiencia puede ser difícil saber qué aplica en tu caso y qué no.
Este problema se ve agravado por gilipollas personas que escriben guías con títulos clickbait como “¡Compila un kernel de Nethunter para CUALQUIER dispositivo Android!” o con falsas promesas como “¡Aprende a compilar un kernel de Nethunter en diez minutos!” También es una desafortunada realidad de internet en 2025 que muchas idiotas personas piensen que ChatGPT u otros modelos de lenguaje grandes tienen respuestas autoritativas a sus preguntas, cuando todo lo que esos modelos realmente tienen es información que extrajeron de los mencionados gilipollas.
Escribo esta guía de la manera más exhaustiva y honesta que puedo. Sin embargo, no pretende ser el único documento que necesitarás leer para este proceso – seguramente tendrás preguntas que este documento no puede responder. Me gustaría animarte a buscar respuestas a estas preguntas en la documentación de software relevante, y NO en YouTube ni en ChatGPT.
Antes de comenzar CUALQUIER parte de este proceso, ya deberías tener:
apt update && apt upgrade -y (opcional: añadidos metapaquetes)Para completar este proceso, necesitarás:
cd, rm, ls, mkdir, find, diff, grep, etc.)vim para los más guays, o si no nano)build-devel en distros basadas en Arch, build-essential en las basadas en Debian) – también recomendaría instalar Perl + Python3, ya que algunos makefiles del kernel los requieren¿Esto será posible para mi dispositivo?
El kernel de Linux está licenciado bajo la GNU General Public License 2.0, que es una licencia copyleft. Esto significa que el código fuente del kernel de Linux se distribuye libremente y puedes modificar el código fuente como desees (como ha hecho cada fabricante de Android), SIN EMBARGO, tu código fuente resultante TAMBIÉN debe distribuirse libremente.
Para sorpresa de absolutamente nadie, muchas de las gigantescas corporaciones que usan código con licencia GPL hacen caso omiso de los términos de esta licencia. O se niegan a distribuir su código fuente o solo publican parte de él (generalmente roto, desactualizado y con blobs binarios incrustados). Si no hay código fuente disponible para el kernel de tu dispositivo, entonces no hay forma de crear un kernel de Nethunter para él.
Tu capacidad de desbloquear el bootloader e instalar una ROM personalizada también depende en gran medida de los caprichos del fabricante de tu dispositivo. Incluso si permiten desbloquear el bootloader y has podido rootear tu teléfono con Magisk, si no publican device trees, probablemente no haya ROMs personalizadas para tu dispositivo. En este caso, es extremadamente dudoso que el código fuente del kernel que publicaron (si lo hay) haya recibido mantenimiento desde su publicación, o que compile incluso sin modificaciones. Si no ves a nadie más manteniendo nada (kernels, ROMs, recoveries) para tu dispositivo, entonces será difícil, si no imposible, convertir ese dispositivo en un Nethunter completo.
Una Nota Sobre las Versiones del Kernel
Imaginemos que hay ROMs/kernels/recoveries personalizados actualizados y mantenidos regularmente para tu dispositivo, pero simplemente no hay kernel de Nethunter. En este caso, deberías poder completar este proceso, pero el proceso variará según la versión del kernel de Linux que use tu dispositivo.
La información en esta guía se basa en mi experiencia modificando kernels 4.14.x. Hay guías más antiguas que hablan sobre el uso de toolchains GCC (en lugar de LLVM/clang, como usaremos nosotros) que se aplican a kernels 3.x. Si tu dispositivo usa una versión 5.x/6.x del kernel de Linux, entonces la información de esta guía no será suficiente para completar este proceso. El método de compilación de Android cambia todo el tiempo, y deberías buscar una guía que cubra los kernels GKI y el uso de Bazel/Kleaf.
Una buena forma de encontrar repositorios que contengan el código fuente del kernel de tu dispositivo es usar su codename. Todo Android tiene uno, aunque algunos fabricantes (p. ej. OnePlus) se divierten un poco más con esto que otros (p. ej. Samsung). El codename de mi Xiaomi Poco X3 NFC es "surya", mientras que el codename de mi Samsung A51 es "SM-A515F". Normalmente, los repositorios de código fuente del kernel siguen la convención de nomenclatura
android_kernel_MANUFACTURER_CODENAME
donde el fabricante es la empresa matriz, es decir, android_kernel_xiaomi_surya, no android_kernel_poco_surya.
Sin embargo, también puede haber repositorios basados en el SoC (system-on-a-chip) de tu dispositivo, a veces “unificados” para incluir archivos fuente de otros dispositivos con el mismo SoC. Este es el caso del Samsung que mencioné, cuyo repositorio fuente se llama android_kernel_samsung_exynos9611. Echa un vistazo por github/gitlab y mira lo que puedes encontrar.
Para los propósitos de esta guía, usaré la última LineageOS 22.2 (compilada el 2025-08-04) en surya, por lo tanto, querré clonar el código fuente del kernel desde el repositorio de LineageOS. Pero antes de hacer eso, quiero copiar dos archivos desde mi dispositivo a la computadora que usaré para compilar el kernel: /proc/config.gz y /proc/version.
Podría copiar el primer archivo, /proc/config.gz, a /sdcard, extraerlo del dispositivo con ADB, descomprimirlo con gunzip y renombrarlo. Pero eso parece demasiados pasos, así que lo que hice en su lugar fue esto:

Luego, en el propio dispositivo, ejecuté (como root)

¿Qué está pasando aquí?
En mi laptop: nc (netcat) -l (escuchar conexiones entrantes) -p (puerto) 4545 (realmente podría ser cualquier número entre 1024-65535, pero normalmente uso 4545) > (escribir a archivo) surya-defconfig-lineageos22.2-20250804 (nombre de archivo descriptivo) < (entrada desde archivo) /dev/null (dispositivo nulo – esto asegura que si toco el teclado no enviará las pulsaciones al archivo que estoy recibiendo, lo que potencialmente lo estropearía).
En el teléfono: zcat (como el comando cat para concatenar, pero para archivos comprimidos con gzip) /proc/config.gz (la configuración del kernel con la que se compiló el kernel actualmente en ejecución) | (enviar la salida de ese proceso como entrada al siguiente proceso) nc (netcat de nuevo) 192.168.1.42 (la dirección IP local de mi laptop) 4545 (el puerto que configuré antes)
Aunque esto debería darte el archivo .config que se usó para compilar tu kernel actualmente en ejecución, no siempre es así. Algunos dispositivos más modernos/compilaciones de ROM más recientes se negarán a arrancar si la configuración guardada en /proc/config.gz no coincide con el .config que se usó para compilar el kernel de fábrica. Afortunadamente, esa es la única comprobación que tiene lugar (no algo mucho más difícil de evitar como una suma de verificación SHA256 de todo el kernel), así que algunas personas ingeniosas han ideado una forma de suplantar el archivo en /proc/config.gz para que coincida con el kernel de fábrica, a pesar de sus modificaciones. Si no estás seguro de si el archivo en tu dispositivo es real o suplantado, puedes ejecutar zcat /proc/config.gz | head y luego uname -r. Si los números de versión no coinciden, entonces el archivo en /proc fue suplantado. En ese caso, aunque todavía puedes continuar con esta guía, quizás quieras ejecutar diff para comparar la configuración extraída con algunos de los archivos que encuentres en el directorio arch/arm64/configs de tu código fuente del kernel.
En cuanto a /proc/version, quizás no sea tan necesario enviar ese archivo, ya que todo lo que realmente necesitamos es la información sobre qué versión de clang/ld.lld se usó para compilarlo. Así que podemos simplemente ejecutar cat /proc/version y echar un vistazo:

¡Vaya! Parece que quien compiló este kernel cometió un pequeño “oopsie” y su Makefile registró todos los -CFLAGS que usaron con clang, pero no la versión de Clang. Sin embargo, podemos ver que usaron una toolchain precompilada de Android, y que usaron ld.lld versión 19.0.1.
Aquí hay una imagen un poco más útil. La primera salida es de /proc/version antes de modificar, compilar e instalar un nuevo kernel en Samsung A51. La segunda salida es de /proc/version actualmente.

¿Notas algo? (No, no mi extraño nombre de usuario y hostname).
El mejor truco para elegir una toolchain es usar la toolchain EXACTA que compiló el kernel actualmente en ejecución.
En este caso, esa fue Neutron clang 18.0.0git, que fue bastante fácil de encontrar:

Y mira por dónde, los md5sums coinciden y todo.
Solo por diversión, echemos un vistazo rápido a la cadena /proc/version de un dispositivo considerablemente más antiguo, Samsung J7 (2016), codename j7xelte:

Este es un dispositivo lo suficientemente antiguo como para que todavía usara toolchains GCC para compilar el kernel.
Pero cuando busco “gcc version 4.9.x 20150123 prerelease”, encuentro dos repositorios:

Entonces, ¿cuál debo descargar?
La respuesta: ambos. GCC es diferente de Clang en que al compilar compiladores/binutils/enlazadores/etc. para compilación cruzada, requiere que se compile una toolchain separada para cada “target triple”. El target triple (supuestamente) tiene el formato
machine-vendor-operating_system
Pero como veremos, esta “regla” tiene un millón de excepciones. Pero empecemos con “machine”.
En la sección “necesitarás” de este documento, dije que necesitabas una computadora de 64 bits con un procesador Intel o AMD ejecutando GNU/Linux. Eso es porque las toolchains que usaremos están compiladas para ejecutarse en x86_64-linux-gnu.
Sin embargo, estas toolchains son cross-compilers, lo que significa que el código máquina que generan a partir de los archivos de código fuente en C no se ejecutará en esa computadora, sino en una diferente con su propio target triple.
Aarch64, también conocida como arm64, es la arquitectura que casi todos los dispositivos Android usan. Arm, sin el “64”, se refiere a las implementaciones de 32 bits de los chips ARM. La mayoría de los kernels de Android se compilan usando tanto un triple aarch64 como arm, para proporcionar compatibilidad hacia atrás con software de 32 bits.
Pasando a la siguiente parte: “Linux”. Se explica por sí mismo. Es un kernel de Linux.
Pero la última parte de estos “triples” vale la pena explicarla, al menos brevemente, porque es un lío tan enrevesado y cada compilador que usa “triples” (GCC, Rust, Go, LLVM) lo hace de forma ligeramente diferente. “Android”, el primer ejemplo, tiene sentido, pero ¿qué es “androideabi”? EABI significa “embedded application binary interface”, pero realmente no tienes que preocuparte demasiado por eso – consideremos EABI como el tercer valor “base”. También verás “gnueabi”, que ahora tiene un poco más de sentido – la implementación GNU de la EABI, ¿verdad? (Lo que esto realmente significa es la biblioteca C de GNU, glibc, que es por lo que también verás triples como arm-linux-musleabi al compilar contra una biblioteca C alternativa como musl). También puedes ver “gnueabihf”. HF significa “hard float”, y si quieres saber cómo ARM implementó una solución en el chip para operaciones de punto flotante con enteros, ve a leer un artículo de Wikipedia.
Esto es lo que necesitamos saber:
Si usamos una toolchain LLVM, declararemos nuestra intención de compilar de forma cruzada estableciendo CROSS_COMPILE=aarch64-linux-gnu- CROSS_COMPILE_32=arm-linux-gnueabi- (así, con el - al final) en la línea de comandos.
Si compilas para un dispositivo muy antiguo y por lo tanto usamos una toolchain GCC, necesitaremos dos conjuntos de archivos, prefijados con diferentes triples. Pueden ser los mismos valores que en el ejemplo de LLVM, o pueden ser diferentes, como en las toolchains para j7xelte.
Pero ¿POR QUÉ hay tantas formas de escribir lo mismo? i386, i686, 386, i32, i64, x86, x64, x86_64, amd64 -- ¡¿qué posible razón podría haber para tanta variación?!
Tira cómica relevante de xkcd:

Volviendo al ejemplo que compilaré hoy (surya), casualmente guardé la información de /proc/version de otro kernel, que decía:

Esto es más o menos como debería verse, con el enlace, checksums, versiones del compilador/enlazador, etc. Y dado que las versiones de clang y LLD aquí eran ambas 17.0.3 y el /proc/version alterado que tenemos de la LineageOS actual muestra LLD 19.0.3, creo que es razonable buscar una toolchain que tenga 19.0.3 para ambos.
Después de unos tres minutos de búsqueda, encontré un repositorio que podemos clonar como submódulo (para facilitar una compilación reproducible) aquí: https://gitlab.com/kei-space/clang/r536225/ Esa toolchain resultó tener serios problemas, así que opté por Neutron Clang 19. (Volveremos a esto).
Así que tenemos nuestro código fuente y nuestra toolchain listos para clonar, lo que nos lleva a:
Decidí crear un nuevo usuario para este tutorial, principalmente para poder usar gh auth login y hacer commits sin hacerlos accidentalmente en mi cuenta principal de github. Pero para hacer eso, tuve que crear una cuenta (en un navegador), configurar un nuevo usuario, generar claves SSH para él…

Copia .ssh/id_ed25519.pub en GitHub, luego ejecuta gh de nuevo en la terminal

Y entonces estoy listo

…casi. Todavía tengo que hacer fork del repositorio en mi navegador,

luego init/clonarlo en la terminal.

Así que una vez que todo esté listo (fuentes actualizadas, origin configurado, etc.) podemos comenzar a clonar los submódulos.

La sintaxis es git submodule add URL directory/

Recuerda, para un historial de commits muy limpio queremos ejecutar git add . y git commit -a después de cada cambio.

No voy a ejecutar git push todavía, pero cuando finalmente lo haga, actualizará todos los commits.
Aquí es donde probablemente esperas que la guía hable sobre hacer modificaciones al código fuente del kernel para añadir soporte Nethunter. Eso viene – pronto. PRIMERO, sin embargo, veamos cómo compila el código fuente sin modificar con nuestra toolchain y configuración.

Esa configuración del kernel actualmente en ejecución debe copiarse al directorio del código fuente del kernel, pero como vamos a usar out/ para nuestros binarios compilados, necesito copiarla también allí. También necesito añadir el directorio bin/ de la toolchain a mi variable PATH. Podría escribir export PATH=/home/build_user/android_kernel_xiaomi_surya/toolchain/bin:$PATH pero una forma más fácil es simplemente cd a ese directorio y luego ejecutar export PATH=$(pwd):$PATH. $() se expande al resultado del comando que contiene, y pwd listará la ruta completa del directorio de trabajo actual.
También he listado el contenido del directorio bin/ de la toolchain para que puedas ver cómo los binutils de LLVM tienen su propio prefijo. Idealmente, el Makefile contiene una instrucción donde si declaro LLVM=1, entonces automáticamente establece que AR=llvm-ar, AS=llvm-as, etc. Así que veamos qué hay en el Makefile.

¡Excelente! Puedo simplemente declarar LLVM=1 y no tener que declarar individualmente el resto… en su mayoría. También necesito usar el ensamblador de LLVM, pero eso tiene su propia declaración, LLVM_IAS:

Así que ahora todo lo que necesitaré declarar es ARCH=arm64 LLVM=1 LLVM_IAS=1 AS=llvm-as O=out CROSS_COMPILE=aarch64-linux-gnu- CROSS_COMPILE_32=arm-linux-gnueabi-. Eso puede parecer mucho, pero es mucho menos que declarar cada binutil individual.
Así que ejecutemos nuestro comando para abrir la configuración….
Espera. Parece que esta toolchain tiene algunos problemas. Así que he decidido desinicializar el submódulo y en su lugar obtener Neutron Clang 19.0.0 desde aquí, y lo descargaré con wget

Luego extraer en un directorio toolchain/ recién creado (olvidando al principio la sintaxis para extraer archivos .tar.zst)

Y luego añado este directorio al archivo .gitignore.
Ahora cuando ejecuto esto:

Funciona, abriendo el menú nconfig:

Muchos tutoriales te dirán que uses menuconfig, pero yo prefiero nconfig porque 1) se ve mejor 2) no tiene la misma tendencia que menuconfig de no cargar porque no puede encontrar las bibliotecas ncurses que ya instalaste. En cualquier caso, esto es solo un kernel de prueba, así que podemos cargar .config y guardarlo (de nuevo como .config) y por ahora terminamos.
Y ahora intentamos compilar Image.gz, y…

¡Nuestro primer error! Hurra.
Según esto, esto es porque una actualización de Arch rompió algo.
Aunque Arch quita, Arch también da, en este caso en forma del paquete AUR libxml-legacy. Así que lo instalé, ejecuté make de nuevo, y esta vez:

Felicitaciones a los mantenedores de LineageOS, porque todo el kernel se compiló con solo una advertencia:

Así que ahora en out/arch/arm64/boot/ podemos encontrar Image.gz. Pero, ¿cómo flasheamos esto en nuestro dispositivo?
Necesitamos hacer un zip AnyKernel3.
Hay dos formas de hacer esto:
Image, puede ser el Image.gz que creamos y nada más, puede ser Image.gz-dtb (una imagen combinada de device tree/kernel – estas son menos comunes hoy en día, pero si tu dispositivo espera una, tendrás que habilitar "Build a concatenated Image.gz-dtb" en la configuración de tu kernel), o puede ser Image.gz, dtbo.img y/o dtb.img.
Para los propósitos de esta guía, descargué uno de los muchos kernels que se distribuyen por Telegram con un estúpido nombre de anime y sin código fuente enlazado. Nunca instales uno de estos kernels.
Pero no haremos eso, no te preocupes, solo estamos tomando prestada su configuración de zip de AnyKernel. Así que renombro y descomprimo el archivo

Y edité el script anykernel.sh para cambiar también la cadena del nombre del kernel. Ahora sobrescribamos el Image.gz de ese zip con el nuestro nuevo

Usar zip -f (de "freshen") simplemente reemplazará el archivo interno por la nueva versión. El 0 es para compresión cero.
Veamos si puedo flashear este kernel y si arranca, pero primero:

Es mucho más fácil hacer seguimiento de los zips de kernel cuando incluyes cadenas de fecha y hora.

Sin embargo, en aras de ser exhaustivo (y de depender lo menos posible de los kernels de Telegram), te contaré cómo hacer tus propios archivos dtb.img y/o dtbo.img, ya que la documentación al respecto es dolorosamente inadecuada.
Existen dos programas de AOSP para este propósito. Uno de ellos, mkdtboimg, está escrito en Python, lo que hace que sea fácil simplemente descargar y ejecutar mkdtboimg.py desde el sitio web oficial de AOSP. Sin embargo, también puede que necesites el otro, mkdtimg, que está escrito en C y se distribuye sin Makefile. Según la documentación, los archivos Android.bp son suficientes -- solo tienes que hacer checkout de todo el código de AOSP para poder ejecutar los comandos que listan allí. Me parece una locura total, así que tomé el Makefile que alguien más había creado hace tiempo para compilar esta herramienta por sí sola, actualicé los archivos fuente con la última versión, y luego la compilé como static-PIE contra Musl. Puedes descargar este binario (que funcionará en cualquier computador Linux x86_64, como el que estás usando para compilar el kernel) desde aquí, o compilarlo tú mismo desde el código fuente.
Ahora viene la parte complicada: los archivos .dtbo que se generan durante una compilación del kernel no se podrán convertir a archivos dtb.img/dtbo.img sin un poco de esfuerzo adicional. Android necesita que la llamada a dtc incluya la bandera -a 64. Como ya estamos usando DTC_EXT=/usr/bin/dtc para forzar que el Makefile use nuestro DTC actualizado y agradable del gestor de paquetes, y no el roto que se encuentra en muchos kernels, no es tan difícil simplemente poner ese comando entre comillas simples y añadir la bandera. Puedes simplemente pasar DTC_EXT='/usr/bin/dtc -a 64'. Sin embargo, en mi caso, me gusta crear (y probar) scripts build.sh para todos los kernels que mantengo, de modo que incluso sin leer esta guía, cualquiera, sin importar lo novato que sea, pueda compilar el suyo desde el código fuente. Mientras luchaba con capas y capas de lógica bash de comillas simples y dobles, encontré una solución simple, aunque poco elegante, que asegura que DTC sea invocado con la bandera correcta: un script envoltorio.
Simplemente creé un archivo ejecutable llamado dtc en el directorio de nivel superior de mi kernel, que contenía las siguientes líneas:
#!/bin/sh
exec /usr/bin/dtc -a 64 $@
Luego apunté DTC_EXT= a ese archivo, y eso resolvió el problema.
Quizás te estés preguntando: "¿Qué archivos .dtbo? ¡Mis compilaciones de kernel nunca generan esos!" En ese caso, deberías verificar que este símbolo del kernel esté habilitado:

Entonces, ¿cómo usamos estas herramientas? Lo primero que hice fue analizar los archivos dtb.img y dtbo.img que encontré en otros zips de kernel para ver qué tipo de archivos eran. (Lo sé, lo sé, no queremos depender de los extraños kernels de la escena de ROMs personalizadas para los nuestros, pero sí vale la pena verificarlo). El comando file dtb.img devolvió:
dtb.img: Device Tree Blob version 17, size=345849, boot CPU=0, string block size=31481, DT structure block size=314312
que es (casi) exactamente el mismo resultado que obtengo cuando ejecuto file ../arch/arm64/boot/dts/qcom/sdmmagpie.dtb:
../arch/arm64/boot/dts/qcom/sdmmagpie.dtb: Device Tree Blob version 17, size=345856, boot CPU=0, string block size=31481, DT structure block size=314312
Esa pequeña diferencia me preocupó, hasta que ejecuté diff <(strings dtb.img) <(strings ../arch/arm64/boot/dts/qcom/sdmmagpie.dtb) y descubrí que contenían exactamente las mismas cosas. Así que pude asumir con seguridad que crear mi propio dtb.img era solo cuestión de copiar sdmmagpie.dtb y cambiarle el nombre.
En cuanto a dtbo.img, file no nos ayuda mucho:
dtbo.img: data
Pero aquí es donde podemos usar mkdtimg o mkdtboimg.py para analizarlo. Cuando ejecuto mkdtimg dump dtbo.img, obtengo:

Así que sé que al crear el mío, debo pasar ya sea
mkdtimg create dtbo.img --page_size=4096 ../arch/arm64/boot/dts/qcom/sdmmagpie-idp-overlay.dtbo
o
mkdtboimg create --page_size=4096 dtbo.img ../arch/arm64/boot/dts/qcom/sdmmagpie-idp-overlay.dtbo
Ambos comandos producen archivos idénticos. También puedes ejecutar mkdtimg dump dtbo.img después y comparar los valores con el otro archivo. Si necesitas incluir más de un archivo .dtbo en tu imagen, simplemente añade su ruta al final de cualquiera de los dos comandos.
Ahora volvamos al kernel de prueba que creamos. La buena noticia es que se flasheó sin problemas; la mala noticia es que voy a tener que arreglar ese Makefile que crea un /proc/version tan feo.
Pero eso puede esperar. Ahora, finalmente, hemos llegado a:
Es hora de añadir algunos submódulos. Primero, este que viene con instrucciones muy fáciles de seguir. (Nota: ahora también contiene los símbolos del kernel del subsistema CAN, ya que mi pull request que los añadía fue fusionado, aunque no lo verás en las capturas de pantalla siguientes).

Y ahora cuando ejecuto make nconfig de nuevo (el mismo comando de antes)

Tenemos esta encantadora opción nueva

Eso habilitará todas estas cosas. Selecciónala, guarda como .config – pero ten cuidado, eso lo guardará en out/.config y vamos a eliminar todo ese directorio antes de volver a compilar. Así que una vez que salgas de nconfig, copia ese archivo al directorio fuente del kernel.
Ahora es momento de parchear algunos archivos fuente, así que añadamos el repositorio de scripts de compilación de nethunter como submódulo:

Hacemos cd al nuevo directorio y ejecutamos ./build.sh, y elegimos la opción 4: Apply Nethunter kernel patches.

Si recibes algún mensaje que diga "the test run was completed with errors," NO apliques el parche. De lo contrario, adelante. En mi caso apliqué los parches 4, 5 y 8.
Ahora que hemos hecho cambios, volvamos al directorio fuente de nivel superior del kernel y hagamos commit de ellos.

En este punto podrías simplemente compilar el kernel de nuevo y estarías listo. Pero yo soy extra, y quiero incluir soporte para un montón de cosas adicionales, a saber:

Necesitaremos modificar el Kconfig y el Makefile en drivers/net/wireless/realtek para que la configuración recoja estos controladores recién añadidos, pero también:

Asegúrate de cambiar la plataforma en el Makefile de rtl8812au a ANDROID_ARM64 (y también para rtl8188eus).
También vale la pena verificar dos veces el Kconfig de los controladores recién añadidos para ver cómo se llama la opción de configuración:

Ahora sé que debo referirme a ella como 88XXAU en el Makefile un nivel más arriba.

Por suerte, el Kconfig simplemente se incluye así:

Voy a tener que editar estos archivos de nuevo después de añadir también rtl88x2bu y la rama ARM de rtl8188fu. (Y resulta que la opción de configuración de rtl88x2bu se llama RTL8822BU, que es por lo que siempre vale la pena verificarlo).
Ahora los controladores backport de MediaTek. Usando este commit como guía, he portado con éxito estos controladores a dos dispositivos diferentes con kernels 4.14.x. (¿Ves por qué es importante el historial de commits?) Pero primero necesitamos el directorio mt76 con todos sus archivos.
En lugar de tener que clonar un kernel 4.19 y copiar los archivos de allí, y luego hacer los parches necesarios a esos archivos en tu nueva copia, puedes simplemente añadir https://github.com/akabul0us/mt76.git como submódulo. Luego edita el Makefile y el Kconfig en el directorio drivers/net/wireless/mediatek:

Al añadir este repositorio con los parches del commit mencionado anteriormente ya aplicados a su código fuente, podemos saltar a las modificaciones que necesitamos hacer en otros archivos del kernel. El primero es este:

Pero resulta que nuestro código fuente del kernel ya tiene este struct:

Así que pasamos al siguiente archivo a modificar, include/linux/overflow.h. Este sí tiene algunas modificaciones, pero como son bastante claras de leer en el commit original, te ahorraré más capturas de pantalla. include/linux/skbuff.h y include/linux/scatterplot.h también tienen cambios, pero ninguno es necesario para include/net/cfg80211.h. Los cambios necesarios en include/net/mac80211.h son menores – solo insertar RX_ENC_HE como línea final dentro de enum mac80211_rx_encoding { } y añadir u8 vht_flag; a struct ieee80211_rx_status { }. El archivo net/wireless/of.c ya existe y es igual al del commit que estamos aplicando mediante cherry-pick, así que con eso terminamos. (¡Uf!)
En cuanto al soporte de Docker, bueno, gracias (una vez más) a cyberknight777 por esto, podemos simplemente copiar y pegar

¡Y ahora estamos listos para hacer nconfig de nuevo! …casi. Primero, haz commit y push de los cambios, luego rm -rf out/ (asegurándote de haber guardado tu .config fuera de allí), mkdir -p out, y ENTONCES podemos volver a la configuración.

Una nota sobre los controladores USB Realtek fuera del árbol que hemos añadido al kernel: Son un poco malos. Si intentas compilar más de uno de ellos en línea, obtendrás errores en el momento del enlazado. Una solución de larga data es compilar solo uno (1) en línea y el resto como módulos. Los controladores Mediatek, sin embargo, se pueden compilar en línea sin problemas.
Terminé habilitando un montón de otras cosas; si quieres ver el diff completo, lo puse aquí: aquí pero en fin, ¡a compilar!

Buen comienzo - siempre es agradable cuando ves un vistazo de los nuevos archivos objeto que acabas de añadir compilándose sin errores ni advertencias.

¿Esto? Menos agradable, pero fácil de arreglar. Solo tenemos que eliminar -Wno-stringop-overread del Makefile que tenga eso como bandera de advertencia. Y ya que estamos, -Werror es un poco hardcore, ¿no crees? (Esta bandera significa 'tratar todas las advertencias como errores', deteniendo la compilación ante CUALQUIER tropiezo, incluyendo una bandera -W desconocida).

Al menos este es fácil de arreglar.

Un rápido # delante de esa línea y estamos listos para ejecutar make de nuevo – y esta vez, ¡llegó hasta el final!
Pero como he configurado algunos controladores como módulos, todavía no hemos terminado. Necesitamos ejecutar make modules, o más específicamente, make -j $(nproc --all) ARCH=arm64 O=out CROSS_COMPILE=aarch64-linux-gnu- CROSS_COMPILE_32=arm-linux-gnueabi- LLVM=1 LLVM_IAS=1 AS=llvm-as modules. Y vaya, el código del controlador Realtek para rtl8188fu es un desastre:

¿Podría arreglar manualmente cada una de las líneas que causan estas advertencias? Claro. ¿Lo haré? No. Hay una razón por la que compilo estos controladores como módulos y no en línea, y animo activamente a todos a evitar los adaptadores basados en Realtek. Sin embargo:

Al menos compilaron con éxito. Volveremos a eso en un momento. Primero refresquemos nuestro zip de kernel:

(Casi lo olvido - esto ya no es un kernel de "prueba", es uno de Nethunter en condiciones).
En cuanto a los módulos, los archivos .tar son realmente el camino a seguir porque preservan todo sobre los archivos que contienen – sin embargo, también preservan las rutas. A menos que hagamos algo al respecto, al extraer nuestro tarball de módulos crearemos un montón de directorios, como drivers/net/wireless/realtek/rtl8188fu/rtl8188fu.ko por ejemplo, así que creemos un directorio (y añadámoslo a .gitignore), copiémoslos allí, y luego hagamos el archivo.

¿Puedes flashearlos como lo harías con un kernel?

Estos necesitan ser extraídos en algún lugar de tu dispositivo. Digo "en algún lugar" porque realmente no importa dónde, siempre que cuando ejecutes insmod /cualquier/ruta/a/cualquier.ko el módulo se cargue. Podrías hacerlo en /sdcard, eso estaría bien, pero recuerda, yo soy extra, así que los extraeré en el lugar "apropiado" para este dispositivo, /vendor/lib/modules. Por supuesto, /vendor está montado de solo lectura, así que primero necesitaré abrir un shell root (NO en la terminal de Nethunter – eso es un chroot – aunque puedes usar la aplicación de terminal de Nethunter si seleccionas "New Session → Root Shell") y ejecutar mount -o rw,remount /vendor antes de poder hacer cualquier cosa en esa partición. Luego cd /vendor/lib/modules; tar xzvf /sdcard/o/donde/sea/que/guardaste/el/tarball.tgz; mount -o ro,remount /vendor y listo con los módulos.
Si recibes un error sobre falta de espacio en esa partición, también puedes usar un enlace simbólico – guarda el archivo en, por ejemplo, /sdcard/modules, y luego crea un enlace usando la ruta absoluta. Así que si hiciéramos esto con 88x2bu.ko, ejecutaríamos ln -s /storage/emulated/0/modules/88x2bu.ko /vendor/lib/modules/88x2bu.ko.

Haz un último push a tu repositorio y, si quieres, guarda el .config que usaste como un nuevo defconfig para nethunter. (Esto realmente ayuda a la gente que compila desde el código fuente).
¿Funciona? Se flashea bien, claro, pero ¿funciona?
Bueno, ya es bastante tarde aquí, así que no voy a probar absolutamente cada función ahora mismo, pero vayamos con la crucial: modo monitor/inyección de paquetes en los controladores que añadí al kernel. Empecemos con rtl88x2bu:

Nada mal, para un controlador Realtek.
Y ahora, el evento principal: mt76x2u:

¡Eso sí es un dispositivo de pentesting!
El paso final es subir tu .zip y .tar.gz a github como release. Luego ve a publicarlo en xdaforums, Telegram, Twitter, donde sea que creas que otros usuarios del mismo dispositivo/ROM lo encontrarán y se beneficiarán de él.
Y cuando algún idiota ingrato con el trasero sin lavar responda a tu publicación con "¿¿AHORA HACES KARNEL PARA DISPOSITIVO BUTTPHONE 34AC PRO EDITION?!", pásales el enlace a esta guía y diles que se pongan las pilas.
Buenas noches a todos.
--Akabul0us