本文在ubuntu20.04上对qemu进行交叉编译
注意:NDK编译器工具API级别要在30以后,最好用33
因为只有30以后的版本支持函数memfd_create,详情请看http://t.csdn.cn/465cy
1.下载并安装Android NDK
NDK 下载 | Android NDK | Android Developershttps://developer.android.google.cn/ndk/downloadsNDK下载网址下载linux版本安装包:android-ndk-r25-linux.zip
vi ~/.bashrc
export API=21
export NDK=/home/dubu/android-ndk-r25
export NDK_CROSS=${NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin
export SYSROOT=${NDK}/toolchains/llvm/prebuilt/linux-x86_64/sysroot
export PKG_CONFIG_PATH=${SYSROOT}/python3/lib/pkgconfig
export PKG_CONFIG_LIBDIR=${NDK_CROSS}
export PATH=${PATH}:${NDK}:${NDK_CROSS}
source .bashrc
2.安装glib库
下载glib
git clone https://github.com/GNOME/glib.git
cd glib
cat HACKING /*查看HACKING文件*/
HACKING文件内容如下:
If you want to hack on the GLib project, you'll need to have the
following packages installed:
- Meson 0.48.0
- GNU gettext 0.10.40
- pkg-config 0.16
- gtk-doc
- libffi 3.0.0
To compile a Git version of glib on your system, you will need to take
several steps to setup the tree for compilation. You can do all these
steps at once by running:
checkout/glib# meson _build
For information about submitting patches see the CONTRIBUTING.md file. For
information about major design decisions, see the docs/README.rationale file.
想要编译glib库,需要如下几个组件:
- Meson 0.48.0
- GNU gettext 0.10.40
- pkg-config 0.16
- gtk-doc
- libffi 3.0.0
(1)安装MMeson 0.48.0或以上版本
注意:meson安装前必须确认是否已经安装python3.5及以上版本;因为meson依赖于python3和ninja
sudo apt-get install python3 python3-pip ninja-build
sudo pip3 install --user meson
测试meson是否安装成功,此步骤可以忽略:
创建1.c与meson.build两个文件
vim 1.c
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
vim meson.build
project('tutorial', 'c')
executable('demo', '1.c')
meson builid
cd build
ninja
./demo
在执行./demo的时候会打印出hello world.
(2)安装GNU gettext 0.10.40或以上版本
官网地址:https://www.gnu.org/software/gettext/
wget https://ftp.gnu.org/pub/gnu/gettext/gettext-0.21.tar.gz
tar -zxvf gettext-0.21.tar.gz
cd gettext-0.21
sudo ./configure
sudo make
sudo make install
(3)安装pkg-config 0.16及以上版本
方法一:
sudo apt-get install pkg-config
方法二:
Linux上,到pkg-config官网https://www.freedesktop.org/wiki/Software/pkg-config/,下载最新安装包
tar -zxvf pkg-config-0.29.2.tar.gz
cd pkg-config-0.29.2/
./configure
make
make check
sudo make install
pkg-config --version
(4)安装gtk-doc
参考网址:
(5)安装libffi 3.0.0及以上版本
sudo apt-get install libffi-dev
此前的内容当作废话,真正的交叉编译从这里开始。因为写的太好不想删除。
3.安装libiconv库
下载地址:https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.17.tar.gz
ln -sf ${NDK_CROSS}/aarch64-linux-android21-clang ${NDK_CROSS}/aarch64-linux-android21-gcc
ln -sf ${NDK_CROSS}/aarch64-linux-android21-clang++ ${NDK_CROSS}/aarch64-linux-android21-g++
tar -zxvf libiconv-1.17.tar.gz
cd libiconv-1.17
mkdir build && cd build
CC="aarch64-linux-android21-gcc" CFLAGS="-I${SYSROOT}/usr/include --sysroot $SYSROOT" ../configure --prefix="${SYSROOT}/usr" --host=arm-linux-android21 --enable-shared=yes --enable-static=no
make && make install
4.安装gettext库
官网地址:
Index of /pub/gnu/gettexthttps://ftp.gnu.org/pub/gnu/gettext/?C=M;O=A下载安装包:gettext-0.21.tar.gz
tar -zxvf gettext-0.21.tar.gz
cd gettext-0.21 && mkdir build && cd build
CC="aarch64-linux-android21-clang" CPP="aarch64-linux-android21-clang -E" CPPFLAGS="-I${SYSROOT}/usr/include" CXX="aarch64-linux-android21-clang++" CXXCPP="aarch64-linux-android21-clang++ -E" ../configure --prefix="${SYSROOT}/usr" --host=arm-linux-android21 CFLAGS="-fPIC" --with-libiconv-prefix=${SYSROOT}/usr --with-sysroot=${SYSROOT}
make
make install
http://t.csdn.cn/NZ7Gfhttp://t.csdn.cn/NZ7Gf若是make install出现问题,可以查看上面的连接进行解决。
5.安装libffi
官网地址:libffihttps://sourceware.org/libffi/
下载安装包:libffi-3.4.2.tar.gz
tar -zxvf libffi-3.4.2.tar.gz
cd libffi-3.4.2 && mkdir build && cd build
../configure --prefix="${SYSROOT}/usr" --host=aarch64-linux-android21 --with-sysroot=${SYSROOT} CC=${NDK_CROSS}/aarch64-linux-android21-gcc CFLAGS="-march=armv8-a -DANDROID" CXX=${NDK_CROSS}/aarch64-linux-android21-g++ CXXFLAGS="-march=armv8-a -DANDROID" CPPFLAGS="-I${SYSROOT}/usr/include" LDFLAGS="-L${SYSROOT}/usr/lib" --disable-multi-os-directory --target=aarch64-linux-android21
make
make install
可以查看如下网址,对gcc 的-march,-mtune,-mcpu作大概了解。
6.安装pcre
官网地址:http://pcre.org/
下载安装包:pcre2-10.40.zip
unzip pcre2-10.40.zip
cd pcre2-10.40 && mkdir build && cd build
CC="aarch64-linux-android21-gcc" LDFLAGS="-L${SYSROOT}/usr/lib" CPPFLAGS="-I${SYSROOT}/usr/include" ../configure --prefix=${SYSROOT}/usr --host=aarch64-linux-android21 --with-sysroot=${SYSROOT}/usr
make
make install
7.安装pixman-0.34
8.安装glib
9.编译qemu
编译命令如下:
下面的编译命令只做参考:
PKG_CONFIG_PATH="$SYSROOT/usr/lib/pkgconfig" ../configure --prefix=/home/dubu/installtest --target-list=x86_64-softmmu --cpu=aarch64 --cross-prefix=aarch64-linux-android33- --cc=aarch64-linux-android33-clang --cxx=aarch64-linux-android33-clang++ --host-cc=aarch64-linux-android33-gcc --enable-gettext --enable-iconv --enable-kvm --enable-pie --enable-gio --enable-qcow1 --enable-vhost-user
上面的配置命令只做参考,用下面的配置命令配置:
PKG_CONFIG_PATH="$SYSROOT/usr/lib/pkgconfig" ../configure --prefix=/home/dubu/installtest --target-list=x86_64-softmmu --cpu=aarch64 --cross-prefix=aarch64-linux-android33- --python=$NDK_PYTHON --extra-cflags=" --sysroot=$SYSROOT" --extra-cxxflags=" --sysroot=$SYSROOT" --enable-pie
为什么要加上--enable-pie和--extra-cflags=" --sysroot=$SYSROOT" --extra-cxxflags=" --sysroot=$SYSROOT" 看如下链接:
只交叉编译出可以运行win10的运行程序即可。
PKG_CONFIG_PATH="$SYSROOT/usr/lib/pkgconfig",这个是指定交叉编译好的依赖包的位置。
--cross-prefix=aarch64-linux-android33- 这个是指定的交叉编译前缀,这个选项用于表明是交叉编译,详情可以去看官网qemu的交叉编译的介绍。
其中会报找不到aarch64-linux-android33-pkg-config
ln -s /usr/bin/pkg-config aarch64-linux-android33-pkg-config
make报错:
aarch64-linux-android29-clang -o subprojects/libvhost-user/link-test subprojects/libvhost-user/link-test.p/link-test.c.o -Wl,--as-needed -Wl,--no-undefined -pie -Wl,--whole-archive -Wl,--start-group subprojects/libvhost-user/libvhost-user.a -Wl,--end-group -Wl,--no-whole-archive -Wl,-z,relro -Wl,-z,now -fstack-protector-strong -pthread
ld: error: undefined symbol: memfd_create
>>> referenced by libvhost-user.c:1670 (../subprojects/libvhost-user/libvhost-user.c:1670)
>>> libvhost-user.a.p/libvhost-user.c.o:(vu_dispatch) in archive subprojects/libvhost-user/libvhost-user.a
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)
可查看如下网址解决:
make 报错:
[69/2776] Linking target subprojects/libvhost-user/link-test
FAILED: subprojects/libvhost-user/link-test
aarch64-linux-android33-clang -o subprojects/libvhost-user/link-test subprojects/libvhost-user/link-test.p/link-test.c.o -Wl,--as-needed -Wl,--no-undefined -pie -Wl,--whole-archive -Wl,--start-group subprojects/libvhost-user/libvhost-user.a -Wl,--end-group -Wl,--no-whole-archive -Wl,-z,relro -Wl,-z,now -fstack-protector-strong -pthread
ld: error: undefined symbol: vring_need_event
>>> referenced by libvhost-user.c:2399 (../subprojects/libvhost-user/libvhost-user.c:2399)
>>> libvhost-user.a.p/libvhost-user.c.o:(_vu_queue_notify) in archive subprojects/libvhost-user/libvhost-user.a
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
make: *** [Makefile:163:run-ninja] 错误 1
其实这里的函数vring_need_event在/usr/include/linux/virtio_ring.h和~/qemu-7.0.0/include/standard-headers/linux/virtio_ring.h中都有定义,而正常编译的时候用的/usr/include/linux/virtio_ring.h文件,而不是~/qemu-7.0.0/include/standard-headers/linux/virtio_ring.h这个文件里面的定义,因为这两文件的开头是都
#ifndef _LINUX_VIRTIO_RING_H
#define _LINUX_VIRTIO_RING_H,所以包含了其中一个就不会包含另外一个。
这里的解决办法是把/usr/include/linux/virtio_ring.h文件里面定义的函数vring_init,vring_size,vring_need_event添加到${SYSROOT}/usr/include/linux/virtio_ring.h文件里面。
并且把~/qemu-7.0.0/include/standard-headers/linux/virtio_ring.h文件里面的_LINUX_VIRTIO_RING_H改成“_UAPI_LINUX_VIRTIO_RING_H”,因为交叉编译用到的是${SYSROOT}/usr/include/linux/virtio_ring.h这个文件。可以参考如下链接:
出现qemu:tests/qtest/libqos/libqos.fa.p/pci.c.o报错,查看http://t.csdn.cn/gS8js
出现shm_open和shm_unlink这两个函数未定义的报错,直接在build.ninja里面删除这个目标(在all里面的目标里面删除)就可以了,为什么,因为是在contrib目录下的目标用到了这来两个函数,而且删除这个目录下面的内容对于运行虚拟机没有什么影响,所以就删除了。
具体做法:打开build.ninja文件
在编译目标build all,build build.ninja,以及最后一个build里面,删除带有contrib/的所有目标,并且删除tests/qtest/ivshmem-test目标。这些目标的生成规则可以不用管。
至此编译就可以成功了,如果遇到新问题,欢迎留言。
make install 会报错aarch64-linux-android33-strip文件未找到
ln -sf llvm-strip aarch64-linux-android33-strip即可。
注意:我这边只是说编译成功,没有说可以在android上面运行win10。