我想以用户身份在CentOS上编译带有SDK 23.0.3的Android应用程序。不幸的是,每次运行build-tools/23.0.3/aapt
时,都会返回
bash: build-tools/23.0.3/aapt: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
问题似乎是需要安装32位库。如果我有sudo权限(在Ubuntu上),我可以运行sudo apt install libc6-i386 lib32stdc++6 lib32gcc1
(就像在CentOS 64位糟糕的ELF解释器中描述的那样),但不幸的是,我想编译的机器上没有sudo。
我假设我可以获得使用过的库(如中所述https://www.cs.virginia.edu/~dww4s/articles/ld_linux.html),然后通过设置LD_LIBRARY_PATH
(如中所述http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html)。我通过提取了图书馆
ldd ../androidsdk/build-tools/23.0.3/aapt |
grep "i386" | awk '{print $3}' |
while read file
do cp $file .
done
并将它们复制到CCD_ 4。然后我运行了export LD_LIBRARY_PATH=/home/test
,但aapt
返回了相同的错误。
我尝试的另一件事是获取和提取库(在Ubuntu上):
apt-get download libc6-i386 lib32stdc++6 lib32gcc1
for file in *.deb
do dpkg -x $file .
done
并向后将LD_LIBRY_PATH设置为/home/test/lib:/home/test/lib32
,这也不起作用。
这可以通过docker容器来复制:运行docker run -it ubuntu bash
,然后运行
apt update && apt install git unzip wget openjdk-8-jdk
cd home/
wget https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
unzip sdk-tools-linux-4333796.zip
cd tools/
yes | bin/sdkmanager --install "build-tools;23.0.3"
cd ..
用于设置。然后,build-tools/23.0.3/aapt
返回
bash: build-tools/23.0.3/aapt: No such file or directory
这与在CentOS中的问题相同(无法运行android/sdk/build-tools/23.0.2/aapt):缺少一个32位库。
有人能告诉我添加库的正确方法是什么吗?
EDIT由于解释器,通常/lib/ld-linux.so.2
开始解释文件,因此需要更换它。如果我像上面描述的那样手动提取所有.so文件,请将它们放在lib/
中并运行
LD_LIBRARY_PATH=$(pwd)/libs libs/ld-linux.so.2 build-tools/23.0.3/aapt
aapt命令执行正确。不幸的是,这还不足以构建:
LD_LIBRARY_PATH=/nfs/user/do820mize/workspaces/dissworkspace/androidsdk/libs /nfs/user/do820mize/workspaces/dissworkspace/androidsdk/libs/ld-linux.so.2 ./gradlew --init-script ../init.gradle assemble
再次返回ELF错误,因为gradle包装器(以及Java等)是64位二进制文件。
glibc.i686
可从基本存储库获得:
$ yum whatprovides ld-linux.so.2
glibc-2.17-260.el7.i686 : The GNU libc libraries
Repo : base
Matched from:
Provides : ld-linux.so.2
如果不能提供基本的依赖关系,那么集群就没有用了。当然,它需要安装在所有节点上;在glibc
库的x86_64
版本具有相同版本号的情况下,它破坏某些内容的可能性相当小。
问题是,elf文件的标头(例如aapt)包含指向解释器的链接(例如/lib/ld-linux.2.so)。执行时需要替换此链接,但仅适用于32位elf二进制文件。Gradle和Java仍然需要使用它们的常规64位解释器来执行。由于被调用的进程(例如aapt)是子进程,因此不可能直接调用另一个解释器。
一种可能的解决方案是使用patchelf(https://nixos.org/patchelf.html)。首先,它需要编译(即使他们说,有一个二进制,我没有找到它):
wget https://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.bz2
tar -xvf patchelf-0.9.tar.bz2
cd patchelf-0.9/
./configure && make
之后,您将在src/中找到一个patchelf
可执行文件(这对我来说是一个相当令人惊讶的位置)。
只需通过PATH=$(pwd)/src:$PATH
将其添加到路径中,从系统中获取ld-linux.so.2
,将其保存到$MY_PLACE/libs/ld-linux.so.2
,cd保存到Android SDK并执行
patchelf --set-interpreter $MY_PLACE/libs/ld-linux.so.2 build-tools/23.0.1/aapt
patchelf --set-interpreter $MY_PLACE/libs/ld-linux.so.2 build-tools/23.0.1/aidl
patchelf --set-interpreter $MY_PLACE/libs/ld-linux.so.2 build-tools/23.0.1/zipalign
然后,您需要设置库路径,例如通过export LD_LIBRARY_PATH=$MY_PLACE/libs/
。之后./gradlew assemble
运行良好(对于这个构建工具版本)。
虽然此解决方案有效,但您需要手动编辑每个二进制文件(稍后可能需要)。我认为在多体系结构系统中有一些魔力,可以决定使用哪种解释器,32位或64位的解释器(ldd
将根据文件为解释器返回不同的路径)。为了在没有root的情况下运行32位可执行文件,利用这种魔力将是一个更好的解决方案。因此,我将接受一种解决方案,该解决方案可以通过只更改环境变量而不篡改可执行文件来运行构建。