在 安卓手机 arm 上运行一些linux程序 tree busybox

最简单的办法是(在github上)寻找静态编译构建好的arm aarch64二进制文件

https://github.com/therealsaumil/static-arm-bins

https://github.com/Azathothas/Static-Binaries

尝试从apt yum包里提取

https://blog.csdn.net/proware/article/details/126068071

发现不行,这些包都是动态链接的

 

交叉静态编译tree

在windows上虚拟机开Ubuntu

参考

https://unix.stackexchange.com/questions/320033/static-linking-util-linux-cross-compiling-produces-dynamically-linked-files-i

https://www.cnblogs.com/chen2ha/p/14787699.html

https://stackoverflow.com/questions/34739525/how-can-i-rebuild-core-utils-for-arm-android

http://mama.indstate.edu/users/ice/tree/

https://gitlab.com/OldManProgrammer/unix-tree我是在这里浏览器下的源码压缩包

https://blog.csdn.net/hhd1988/article/details/123443004

https://www.cnblogs.com/jiftle/p/16426858.html

https://subscription.packtpub.com/book/iot-and-hardware/9781783289851/1/ch01lvl1sec09/compiling-busybox-simple

https://stackoverflow.com/questions/12591785/how-to-specify-static-linking-in-makefile

https://stackoverflow.com/questions/983515/how-to-statically-link-a-complex-program

 

 

说一下相较于正常编译tree修改的地方

首先得安个交叉编译工具链

sudo apt-cache search aarch64 搜索一下

我这里选的

sudo apt-get install gcc-5-aarch64-linux-gnu

gcc-aarch64-linux-gnu不带5应该也可以

安装好之后

:~$ aarch64-linux-gnu-gcc-5 -v
Using built-in specs.
COLLECT_GCC=aarch64-linux-gnu-gcc-5
COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/aarch64-linux-gnu/5/lto-wrapper
Target: aarch64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 5.5.0-12ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libquadmath --enable-plugin --enable-default-pie --with-system-zlib --enable-multiarch --enable-fix-cortex-a53-843419 --disable-werror --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=aarch64-linux-gnu --program-prefix=aarch64-linux-gnu- --includedir=/usr/aarch64-linux-gnu/include
Thread model: posix
gcc version 5.5.0 20171010 (Ubuntu/Linaro 5.5.0-12ubuntu1) 

 

然后就是改Makefile了

经过我测试,只需要

make CC=aarch64-linux-gnu-gcc-5 LDFLAGS="--static"

因为我是交叉编译,就不执行install了

就可以,可以覆盖Makefile里的CC设置,LDFLAGS在Makefile默认没设置

不知道为什么

CFLAGS+=-ggdb -std=c11 -pedantic -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -static这里的static可以不加,加和不加编译出来的tree文件是一样的

编译的很快,就几秒钟就好了

有个问题就是,会有俩警告,这俩函数不能用

warning: Using '' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

但是经过我在高通cpu 安卓10 手机上的测试,没什么影响,就是组名、用户名可能显示不出来

(确实是这俩函数不能用的原因,显示不出来用户名和组名,我后来用ndk编译了一版,就正常了)

getgrgid 函数:该函数通过用户组的组ID(GID)来获取用户组的相关信息。

getpwuid 函数:该函数通过用户的用户ID(UID)来获取用户的相关信息。

statically linked解决办法是

1是用android NDK

2是用musl

对tree没啥影响,就没再研究

https://www.reddit.com/r/haskell/comments/vqqq7x/trying_to_build_a_statically_linked_binary/

https://www.cnblogs.com/zackary/p/13940504.html

https://stackoverflow.com/questions/15165306/compile-a-static-binary-which-code-there-a-function-gethostbyname

https://stackoverflow.com/questions/15118408/compile-c-with-function-gethostbyname-to-static-linked-error

 

有说推荐使用android NDK(Bionic LIBC)动态编译的

https://developer.android.com/ndk/guides/other_build_systems?hl=zh-cn

但是我看了看配置没太看懂,没有用

折腾了一下,成功用ndk编译了

 

https://wiki.musl-libc.org/getting-started.html

https://musl.cc/

 

 

 

util-linux 静态编译链接

https://github.com/util-linux/util-linux/blob/master/Documentation/howto-compilation.txt

Static linking

当你想使用静态链接的程序时,使用——enable-static-programs[=LIST] configure选项。

注意,mount(8)使用get{pw,gr}nam()和getpwuid()函数将用户名和组名转换为UID和GID。这些函数可以通过动态加载独立模块(NSS)在libc中实现(例如glibc)。这些模块不是静态链接到mount(8)和mount。静态仍然像动态链接版本一样使用dlopen()。

(dlopen() 是一个 POSIX 标准的函数,用于在运行时动态加载共享库(即动态链接库,.so 文件)并获取对其的句柄,从而使程序能够在运行时调用库中的函数和访问库中的变量。dlopen() 在动态链接库中查找符号(函数或变量),并返回一个指向该库的句柄,程序可以使用该句柄调用库中的符号。

在动态链接的程序中,dlopen() 可以用来加载其他共享库,以便在运行时扩展程序的功能或实现插件系统。在静态链接的程序中,由于所有的代码和库都在编译时就已经链接在一起,因此不需要使用 dlopen()。

在你提到的情况中,即使使用静态链接(static),程序仍然在某种程度上使用 dlopen() 的功能。这可能是因为程序在运行时仍然需要加载一些动态链接库,或者在静态链接时使用了类似 dlopen() 的机制来实现某些功能。)

 

makefile

all目标通常是 makefile 中的第一个目标,因为如果您只在命令行中编写make,而不指定目标,它将构建第一个目标。而你期望这就是全部

 

当您执行“make all”之类的操作时,make 程序会从当前目录中名为“Makefile”的文件中执行名为“all”的规则。这个规则通常会调用编译器将一些源代码编译成二进制文件。

当您执行“make install”时,make 程序会获取上一步中的二进制文件并将它们复制到一些适当的位置,以便可以访问它们。与 Windows 不同,安装只需要复制一些库和可执行文件,并且没有注册表要求。简而言之,“make install”只是将编译的文件复制到适当的位置。

 

all:  tree #命令只执行make,就是构建这个第一个目标

tree: $(OBJS)
  $(CC) $(LDFLAGS) -o $(TREE_DEST) $(OBJS)

$(OBJS): %.o: %.c tree.h
  $(CC) $(CFLAGS) -c -o $@ $<

clean:
  rm -f $(TREE_DEST) *.o *~

install: tree #命令执行make install,就是既构建tree,又把它移到定义的DESTDIR位置,像我这种交叉编译就不需要make install,只make (all)就行
  $(INSTALL) -d $(DESTDIR)
  $(INSTALL) -d $(MANDIR)/man1
  $(INSTALL) $(TREE_DEST) $(DESTDIR)/$(TREE_DEST); \
  $(INSTALL) -m 644 doc/$(MAN) $(MANDIR)/man1/$(MAN)

distclean:
  rm -f *.o *~

dist: distclean
  tar zcf ../tree-$(VERSION).tgz -C .. `cat .tarball`

 

posted @ 2024-02-19 23:50  hrdom  阅读(6)  评论(0编辑  收藏  举报