mkfs.erofs is a user-space tool to create erofs filesystem images.

erofs是华为为了增强安卓性能提出的自研文件系统,其内核文档提到用户态工具:

The following git tree provides the file system user-space
tools under development (ex, formatting tool mkfs.erofs):
>> git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git

ok, 先down下来:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git

查看所有分支:

tj@qemu:~/erofs-utils$ git branch -a
remotes/origin/experimental
remotes/origin/experimental-dip
remotes/origin/mkfs-dev

切到mkfs-dev,其他2个还有问题:

tj@qemu:~/erofs-utils$ git checkout -b mkfs-dev origin/mkfs-dev
Branch mkfs-dev set up to track remote branch mkfs-dev from origin.
Switched to a new branch 'mkfs-dev'

ok, ls能看到东西了,看下编译介绍:

Note that mkfs.erofs can only be linked statically with lz4 library
due to the dependency of experimental lz4hc apis which were added in
lz4 1.8.0. Anyway, it’s a good start to begin with building the latest
lz4 library statically first. :)

Dependencies
lz4-1.8.0 or above

How to build with lz4 static library
./configure –with-lz4=
\eg. if lz4 lib has been installed into fold of /usr/local/lib
./configure –with-lz4=/usr/local/lib && make
On Fedora, static lz4 can be installed using:
yum install lz4-static.x86_64
To build you should run this first:
$ ./autogen.sh
$ ./configure
$ make

build lz4

环境:Ubuntu14.04,下一份lz4 code,要1z4-1.8.0 or above,我down了个1.8.2。

交叉工具用了aarch64-linux-android-4.9,安卓版本里也有,如果编译lz4 for x86会提示不兼容错误:

840 /home/tj/crosstools/aarch64-linux-android-4.9/bin/../lib/gcc/aarch64-linux-android/4.9.x-google/../../../../aarch64-linux-android/bin/ld: skipping incompatible /usr/local/lib/liblz4.so when searching for -llz4
841 /home/tj/crosstools/aarch64-linux-android-4.9/bin/../lib/gcc/aarch64-linux-android/4.9.x-google/../../../../aarch64-linux-android/bin/ld: skipping incompatible /usr/local/lib/liblz4.a when searching for -llz4
843 collect2: error: ld returned 1 exit status

编译工具参数CC指定为aarch64-linux-android就好,记得把工具链都include到PATH环境变量中。

export CC=aarch64-linux-android

另外还需要个包,如我的N平台:

prebuilts/ndk/current/platforms/android-21/arch-arm64

编译时要指定--sysroot,不然编译会报找不到头文件错误:

export CFLAGS="--sysroot=/home/tj/sysroot/arch-arm64/"

then make,then sudo make install会默认装到了/usr/local/下:

tj@qemu:~/lz4-1.8.2$ ls -l /usr/local/lib/liblz4.
liblz4.a liblz4.so liblz4.so.1 liblz4.so.1.8.2
tj@qemu:~/lz4-1.8.2$ ls -l /usr/local/include/lz4
lz4frame.h lz4frame_static.h lz4.h lz4hc.h

configurate mkfs.erofs

运行autogen.sh没有问题,如何交叉编译找了半天,以为是定义CC,i’m wrong,--help发现:

System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]

ok, run below:

./configure --host aarch64-linux-android

会报错:

checking lz4.h presence... yes
configure: WARNING: lz4.h: present but cannot be compiled
configure: WARNING: lz4.h: check for missing prerequisite headers?
configure: WARNING: lz4.h: see the Autoconf documentation
configure: WARNING: lz4.h: section "Present But Cannot Be Compiled"
configure: WARNING: lz4.h: proceeding with the compiler's result
configure: WARNING: ## --------------------------------------- ##
configure: WARNING: ## Report this to bluce.liguifu@huawei.com ##
configure: WARNING: ## --------------------------------------- ##
checking for lz4.h... no
checking for LZ4_versionNumber in -llz4... no
configure: error: Cannot build without lz4

找不到lz4.h? 试着按如下文档配置:

\eg. if lz4 lib has been installed into fold of /usr/local/lib
./configure –with-lz4=/usr/local/lib && make

运行如下命令:

./configure --with-lz4=/usr/local/lib --host aarch64-linux-android

一样的错误,查了下:

tj@qemu:~/test/erofs-utils$ grep -rn LZ4_VERSION_NUMBER ~/lz4-1.8.2-arm64/
/home/tj/lz4-1.8.2-arm64/lib/lz4.h:98:#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
/home/tj/lz4-1.8.2-arm64/lib/lz4.c:493:int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }

都有的啊,路径不对? 再看看--with-lz4说明:

--with-lz4-include=DIR  LZ4 include directory
--with-lz4-lib=DIR LZ4 lib directory
--with-lz4=DIR LZ4 install directory, e.g. /usr/local or /usr

很明显README有错误嘛,多了个/lib,试试:

./configure --with-lz4=/usr/local --host aarch64-linux-android

aha… working…

checking lz4.h usability... yes
checking lz4.h presence... yes
checking for lz4.h... yes
checking for LZ4_versionNumber in -llz4... yes
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating mkfs/Makefile
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands

前面提到的sysroot如果不加,还会出现如下错误:

configure:3411: checking whether the C compiler works
82 configure:3433: aarch64-linux-android-gcc conftest.c >&5
83 /home/tj/crosstools/aarch64-linux-android-4.9/bin/../lib/gcc/aarch64-linux-android/4.9.x-google/../../../../aarch64-linux-android/bin/ld: cannot find crtbegin_dynamic.o: No such file or directory
84 /home/tj/crosstools/aarch64-linux-android-4.9/bin/../lib/gcc/aarch64-linux-android/4.9.x-google/../../../../aarch64-linux-android/bin/ld: cannot find -lc
85 /home/tj/crosstools/aarch64-linux-android-4.9/bin/../lib/gcc/aarch64-linux-android/4.9.x-google/../../../../aarch64-linux-android/bin/ld: cannot find -ldl
86 /home/tj/crosstools/aarch64-linux-android-4.9/bin/../lib/gcc/aarch64-linux-android/4.9.x-google/../../../../aarch64-linux-android/bin/ld: cannot find crtend_android.o: No such file or directory
87 collect2: error: ld returned 1 exit status

build mkfs.erofs

有个错误:

mkfs_file.c: In function 'erofs_compress_file':
mkfs_file.c:600:2: error: implicit declaration of function 'rpl_malloc' [-Werror=implicit-function-declaration]
inode->i_inline_data = malloc(EROFS_BLKSIZE);
^
mkfs_file.c:600:23: error: assignment makes pointer from integer without a cast [-Werror]
inode->i_inline_data = malloc(EROFS_BLKSIZE);
^
mkfs_file.c: In function 'erofs_init_compress_context':
mkfs_file.c:874:17: error: assignment makes pointer from integer without a cast [-Werror]
ctx->cc_srcbuf = malloc(erofs_cfg.c_compr_maxsz);
^
mkfs_file.c:875:17: error: assignment makes pointer from integer without a cast [-Werror]
ctx->cc_dstbuf = malloc(erofs_cfg.c_compr_maxsz * 2);
^
cc1: all warnings being treated as errors
make[2]: *** [mkfs_erofs-mkfs_file.o] Error 1

把configure.ac里的AC_FUNC_MALLOC去掉就ok了(见参考文档):

# Checks for library functions.
#AC_FUNC_MALLOC
tj@qemu:~/erofs-utils/mkfs$ ls
erofs_cache.c erofs_config.c erofs_io.c Makefile mkfs_erofs-erofs_cache.o mkfs_erofs-erofs_lz4hc.o mkfs_erofs-mkfs_main.o mkfs_inode.h
erofs_cache.h erofs_config.h erofs_io.h Makefile.am mkfs_erofs-erofs_compressor.o mkfs_erofs.h mkfs_file.c mkfs_main.c
erofs_compressor.c erofs_debug.h erofs_lz4hc.c Makefile.in mkfs_erofs-erofs_config.o mkfs_erofs-mkfs_file.o mkfs_file.h
erofs_compressor.h erofs_error.h erofs_lz4hc.h mkfs.erofs mkfs_erofs-erofs_io.o mkfs_erofs-mkfs_inode.o mkfs_inode.c
tj@qemu:~/erofs-utils/mkfs$
tj@qemu:~/erofs-utils/mkfs$ file mkfs.erofs
mkfs.erofs: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

好像还有个PAGE_SIZE重定义的,just remove.

run mkfs.erofs

push到设备中,提示有错误:

xxx:/ # /data/mkfs.erofs
"/data/mkfs.erofs": error: Android 5.0 and later only support position-independe
nt executables (-fPIE).

查了下要加入-fPIE -pie,也就是:

export CFLAGS="--sysroot=/home/tj/sysroot/arch-arm64/ -fPIE -pie"

重新编下运行:

xxx:/data # ./mkfs.erofs
mkfs.erofs 0.1 May 30 2019 02:32:33

Usage:
[-z <compr_algri>] [-d <dbglvl>]
[target path] [source directory]

参考文档

Done.