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=<lz4 install path>

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

怎么是x86,安卓大部分都是跑在ARM/ARM64上,ok,我的环境是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

nm,一样的错误,查了下:

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.