Aria2介绍 与 Linux下编译 Window,Linux,Android 产物


简介

今年三月底的时候,收到了老大的一个任务说去研究一下p2p的下载,对于我们这种屌丝来说,当然是老大说什么就是什么了,俗话说拿人钱财替人消灾
首先我们要先去了解这个东西,什么是p2p下载,在搞这个之前,确实不了解,这个p2p技术早就已经存在了,所以关于他的内容也是非常的多
然后去github上面查找对应的开源项目,最终定位到了Aria2 这个开源项目,对于为什么要选择他,因为他是一个命令行的工具,而且好像还支持android平台,下面是官网的介绍
aria2是一款用于下载文件的工具。支持的协议是HTTP(S),FTP,SFTP,BitTorrent和Metalink。aria2可以从多种来源/协议下载文件,并尝试利用您的最大下载带宽。
它支持从HTTP(S)/ FTP / SFTP和BitTorrent同时下载文件,而从HTTP(S)/ FTP / SFTP下载的数据则上传到BitTorrent群。使用Metalink块校验和,aria2在下载文件时自动验证数据块。

Linux平台编译

编译的系统为Ubuntu16.04

为了从源码包构建aria2,您需要以下开发包(包名可能会因您使用的发行版而异):
● libgnutls-dev(需要HTTPS,BitTorrent,Checksum支持)
● nettle-dev(需要BitTorrent,支持Checksum)
● libgmp-dev(BitTorrent必需)
● libssh2-1-dev(SFTP支持必需)
● libc-ares-dev(异步DNS支持需要)
● libxml2-dev(Metalink支持必需)
● zlib1g-dev(gzip需要,HTTP解压解码支持)
● libsqlite3-dev(需要Firefox3 / Chromium cookie支持)
● pkg-config(需要检测已安装的库)
你可以使用libgcrypt-dev而不是nettle-dev和libgmp-dev:
您可以使用libssl-dev而不是libgnutls-dev,nettle-dev,libgmp-dev,libgpg-error-dev和libgcrypt-dev:
您可以使用libexpat1-dev而不是libxml2-dev:
如果您从git存储库下载源代码,则必须安装以下软件包以获取autoconf宏:
● libxml2-dev
● libcppunit-dev
● autoconf
● automake
● autotools-dev
● autopoint
● libtool

上面需要的包安装完之后,进入到下载下来的源码目录里面这里使用的是最新版Github上面的Maste分支的内容 然后运行以下命令生成构建程序所需的配置脚本和其他文件:

$ autoreconf -i

您还需要Sphinx来构建手册页。如果您正在为Mac OS X构建aria2,请查看make-release-os.mk GNU Make makefile。 构建aria2的最快方法是首先运行configure脚本:

$ ./configure

要建立静态链接的aria2,请使用ARIA2_STATIC=yes 命令行选项:

$ ./configure ARIA2_STATIC = yes

配置完成后,运行make以编译该程序:

$ make

编译完成就会在源码目录下面的src里面有一个可以执行的文件,名为aria2c
结果显示

测试可以下载
结果显示

Window产物

编译
● Aria2 需要用到 mingw-w64 的交叉编译工具链来编译出来 Windows 下的二进制,所以要首先安装一个 Linux 系统,推荐用 Ubuntu
● 新建一个 setup.sh 脚本,来执行环境的安装和相关依赖库的编译
● #! /bin/bash

改成 x86_64-w64-mingw32 来编译64位版本 这个要对应的为你在Linux上面安装的Mingw64对应的 是64还是32位系统
安装mingW64可以通过 sudo apt-get install mingw-w64-x86-64-dev 来完成安装
export HOST=x86_64-w64-mingw32

It would be better to use nearest ubuntu archive mirror for faster
downloads.
RUN sed -ie 's/archive\.ubuntu/jp.archive.ubuntu/g' /etc/apt/sources.list

安装编译环境 后面的其实就是将官网上面介绍的那样,要安装的软件包,这里只不过是讲这些要安装的软件包通过脚本文件的形势来编译,这样的好处是不用一个一个的执行,可以通过脚本文件,一下子执行完成

apt-get update && \
apt-get install -y make binutils autoconf automake autotools-dev libtool pkg-config git curl dpkg-dev gcc-mingw-w64 autopoint libcppunit-dev libxml2-dev libgcrypt11-dev lzip

# 下载依赖库
if [ ! -f "gmp-6.1.2.tar.lz" ]; then 
    curl -L -O https://gmplib.org/download/gmp/gmp-6.1.2.tar.lz 
fi

if [ ! -f "expat-2.2.0.tar.bz2" ]; then 
    curl -L -O http://downloads.sourceforge.net/project/expat/expat/2.2.0/expat-2.2.0.tar.bz2
fi

if [ ! -f "sqlite-autoconf-3160200.tar.gz" ]; then 
    curl -L -O https://www.sqlite.org/2017/sqlite-autoconf-3160200.tar.gz
fi

if [ ! -f "zlib-1.2.11.tar.gz" ]; then 
    curl -L -O http://zlib.net/zlib-1.2.11.tar.gz
fi

if [ ! -f "c-ares-1.12.0.tar.gz" ]; then 
    curl -L -O https://c-ares.haxx.se/download/c-ares-1.12.0.tar.gz
fi

if [ ! -f "libssh2-1.8.0.tar.gz" ]; then 
    curl -L -O http://libssh2.org/download/libssh2-1.8.0.tar.gz
fi

# 动态编译 gmp
tar xf gmp-6.1.2.tar.lz && \
cd gmp-6.1.2 && \
./configure --enable-shared --disable-static --prefix=/usr/local/$HOST --host=$HOST --disable-cxx --enable-fat CFLAGS="-mtune=generic -O2 -g0" && \
make install

# 动态编译 expat
cd ..
tar xf expat-2.2.0.tar.bz2 && \
cd expat-2.2.0 && \
./configure --enable-shared --disable-static --prefix=/usr/local/$HOST --host=$HOST --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` && \
make install

# 动态编译 sqlite3
cd ..
tar xf sqlite-autoconf-3160200.tar.gz && cd sqlite-autoconf-3160200 && \
./configure --enable-shared --disable-static --prefix=/usr/local/$HOST --host=$HOST --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` && \
make install

# 动态编译 zlib
cd ..
tar xf zlib-1.2.11.tar.gz && \
cd zlib-1.2.11
export BINARY_PATH=/usr/local/$HOST/bin
export INCLUDE_PATH=/usr/local/$HOST/include
export LIBRARY_PATH=/usr/local/$HOST/lib
make install -f win32/Makefile.gcc PREFIX=$HOST- SHARED_MODE=1

# 动态编译 c-ares
cd ..
tar xf c-ares-1.12.0.tar.gz && \
cd c-ares-1.12.0 && \
./configure --enable-shared --disable-static --without-random --prefix=/usr/local/$HOST --host=$HOST --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` LIBS="-lws2_32" && \
make install

# 动态编译 libssh2
cd ..
tar xf libssh2-1.8.0.tar.gz && \
cd libssh2-1.8.0 && \
./configure --enable-shared --disable-static --prefix=/usr/local/$HOST --host=$HOST --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` --without-openssl --with-wincng LIBS="-lws2_32" && \
make install

下载 Aria2 代码并解压,修改 aria2\mingw-config 文件,增加 --enable-libaria2 编译选项来生成 libaria2 库,并修改ARIA2_STATIC=no 来关闭静态编译,如果想在 windows xp 上运行,则还要将 --with-libssh2 改成 --without-libssh2,否则会出现 bcrypt.dll 缺失报错,最后的修改如下:

test -z "$HOST" && HOST=i686-w64-mingw32
test -z "$PREFIX" && PREFIX=/usr/local/$HOST
./configure \
    --host=$HOST \
    --prefix=$PREFIX \
    --without-included-gettext \
    --disable-nls \
    --with-libcares \
    --without-gnutls \
    --without-openssl \
    --with-sqlite3 \
    --without-libxml2 \
    --with-libexpat \
    --with-libz \
    --with-libgmp \
    --without-libssh2 \
    --without-libgcrypt \
    --without-libnettle \
    --with-cppunit-prefix=$PREFIX \
    --enable-libaria2 \
    ARIA2_STATIC=no \
    CPPFLAGS="-I$PREFIX/include" \
    LDFLAGS="-L$PREFIX/lib" \
    PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig"

新建一个 build.sh 来编译 Aria2 库

#! /bin/bash
# 改成 x86_64-w64-mingw32 来编译64位版本
export HOST=x86_64-w64-mingw32
cd aria2 && autoreconf -i && ./mingw-config && make install && $HOST-strip /usr/local/$HOST/bin/libaria2-0.dll

编译完成后

将两个 gcc 的运行库复制到 /usr/local/x86_64-w64-mingw32/bin 中,路径为 /usr/lib/gcc/x86_64-w64-mingw32/5.3-win32/libgcc_s_seh-1.dll 和 /usr/lib/gcc/x86_64-w64-mingw32/5.3-win32/libstdc++-6.dll

把 /usr/local/x86_64-w64-mingw32 文件夹复制到 Windows 中,这个文件夹中的文件就是 Windows 所需要的二进制,这个就是最后到Window中bin目录下的内容
结果显示

Android Arm 编译

编译的系统为Ubuntu16.04

下面是build-libraries.sh的脚本,用来保证编译android的时候,需要的库等

#!/bin/bash

if [[ $ANDROID_HOME == "" ]];then
echo "ANDROID_HOME not defined"
exit 0
fi

# 安装编译环境
apt-get update && \
apt-get install -y make binutils autoconf automake autotools-dev libtool pkg-config git curl dpkg-dev autopoint libcppunit-dev libxml2-dev libgcrypt11-dev

##LIBRARIES_DOWNLOAD_URL##
EXPAT=https://github.com/libexpat/libexpat/releases/download/R_2_2_5/expat-2.2.5.tar.bz2
OPENSSL=https://www.openssl.org/source/openssl-1.0.2o.tar.gz
C_ARES=https://c-ares.haxx.se/download/c-ares-1.12.0.tar.gz
SSH2=http://libssh2.org/download/libssh2-1.8.0.tar.gz
ZLIB=http://zlib.net/zlib-1.2.11.tar.gz

DOWNLOADER="wget -c"
TOOLCHAIN=$ANDROID_HOME/toolchain
PATH=$TOOLCHAIN/bin:$PATH
HOST=arm-linux-androideabi
PREFIX=$ANDROID_HOME/usr/local
LOCAL_DIR=$ANDROID_HOME/usr/local
TOOL_BIN_DIR=$ANDROID_HOME/toolchain/bin
PATH=${TOOL_BIN_DIR}:$PATH
CFLAGS="-march=armv7-a -mtune=cortex-a9"
DEST=$ANDROID_HOME/usr/local
CC=$HOST-gcc
CXX=$HOST-g++
LDFLAGS="-L$DEST/lib"
CPPFLAGS="-I$DEST/include"
CXXFLAGS=$CFLAGS

 cd /tmp
 # zlib library build
  $DOWNLOADER $ZLIB
  tar zxvf zlib-1.2.11.tar.gz
  cd zlib-1.2.11/
  PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig/ LD_LIBRARY_PATH=$PREFIX/lib/ CC=$HOST-gcc STRIP=$HOST-strip RANLIB=$HOST-ranlib CXX=$HOST-g++ AR=$HOST-ar LD=$HOST-ld ./configure --prefix=$PREFIX --static
  make
  make install

 # expat library build
  cd /tmp
  $DOWNLOADER $EXPAT
  tar xf expat-2.2.5.tar.bz2
  cd expat-2.2.5/
  PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig/ LD_LIBRARY_PATH=$PREFIX/lib/ CC=$HOST-gcc CXX=$HOST-g++ ./configure --host=$HOST --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` --prefix=$PREFIX --enable-static=yes --enable-shared=no
  make
  make install

 # c-ares library build
  cd /tmp
  $DOWNLOADER $C_ARES
  tar xf c-ares-1.12.0.tar.gz
  cd c-ares-1.12.0/
  PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig/ LD_LIBRARY_PATH=$PREFIX/lib/ CC=$HOST-gcc CXX=$HOST-g++ ./configure --host=$HOST --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` --prefix=$PREFIX --enable-static --disable-shared
  make
  make install

 # openssl library build
  cd /tmp
  $DOWNLOADER $OPENSSL
  tar xf openssl-1.0.2o.tar.gz
  cd openssl-1.0.2o/
  PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig/ LD_LIBRARY_PATH=$PREFIX/lib/ CC=$HOST-gcc CXX=$HOST-g++ ./Configure linux-armv4 $CFLAGS --prefix=$PREFIX shared zlib zlib-dynamic -D_GNU_SOURCE -D_BSD_SOURCE --with-zlib-lib=$LOCAL_DIR/lib --with-zlib-include=$LOCAL_DIR/include
  make 
  make install

 # libssh2 library build
  cd /tmp
  $DOWNLOADER $SSH2
  tar xf libssh2-1.8.0.tar.gz
  cd libssh2-1.8.0/
  rm -rf $PREFIX/lib/pkgconfig/libssh2.pc
  PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig/ LD_LIBRARY_PATH=$PREFIX/lib/ CC=$HOST-gcc CXX=$HOST-g++ AR=$HOST-ar RANLIB=$HOST-ranlib ./configure --host=$HOST --without-libgcrypt --with-openssl --without-wincng --prefix=$PREFIX --enable-static --disable-shared
  make
  make install

  cd /tmp
  rm -rf c-ares*
  rm -rf sqlite-autoconf*
  rm -rf zlib-*
  rm -rf expat-*
  rm -rf openssl-*
  rm -rf libssh2-*
 echo "all complete!"

下面是build-ndk-toolchain.sh的脚本,用来保证ndk的环境,主要官网介绍最好用ndk-41b以上的版本

#!/bin/bash

mkdir -p /opt/NDK
cd /opt/NDK
apt install wget
wget https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip
apt install unzip
unzip android-ndk-r14b-linux-x86_64.zip
rm android-ndk-r14b-linux-x86_64.zip

echo "export NDK=/opt/NDK/android-ndk-r14b
export ANDROID_HOME=/opt/NDK/android-ndk-r14b
export PATH=$ANDROID_HOME:$PATH" >> /etc/profile
source /etc/profile


if [[ $ANDROID_HOME == "" ]];then
 echo "ANDROID_HOME not defined"
 exit 0
 fi

$ANDROID_HOME/build/tools/make_standalone_toolchain.py \
   --arch arm --api 16 --stl=gnustl \
   --install-dir $ANDROID_HOME/toolchain


cd $ANDROID_HOME

mkdir -p usr/local/lib/pkgconfig

在root的权限下面,执行 ./build-ndk-toolchain.sh 没有错误之后 执行 ./build-libraries.sh 如果有发生了错误,要修正这些错误,比如资源包查找不到的化,自行修改。找到一个可以下载的地址,替换上去既可然后进入aria2的源码文件里面 执行./android-config 用来确定当前的配置,这个android-config文件跟源码提供的一样,没有做任何的修改。。然后执行./android-make 如果没有错误的化,就会编译完成

这里要注意下载Aria2源码的时候,要下载正确,不要选择最后面的source Code ,里面的文件不齐全,还要自己构建 configure 文件
结果显示

Android X86编译

要注意的是Aria2 也是支持X86平台的编译的,首先是构建X86下面的交叉编译链

#!/bin/sh
export NDK=/opt/android-ndk-r14b
export ANDROID_HOME=/opt/android-ndk-r14b

$ANDROID_HOME/build/tools/make_standalone_toolchain.py \
   --arch x86 --api 16  \
   --install-dir $ANDROID_HOME/toolchainX86
cd $ANDROID_HOME
mkdir -p usr/local/lib/pkgconfig

之后其他的外部库编译脚本文件稍微的改动就可以,比如 编译Care库,脚本文件就要变成这样,其他的类似

#!/bin/bash

C_ARES=https://c-ares.haxx.se/download/c-ares-1.13.0.tar.gz
DOWNLOADER="wget -c"

ANDROID_HOME=/opt/android-ndk-r14b
TOOLCHAIN=$ANDROID_HOME/toolchainX86
PATH=$TOOLCHAIN/bin:$PATH
HOST=i686-linux-android
PREFIX=$ANDROID_HOME/usr/local
LOCAL_DIR=$ANDROID_HOME/usr/local
TOOL_BIN_DIR=$ANDROID_HOME/toolchainX86/bin
PATH=${TOOL_BIN_DIR}:$PATH
DEST=$ANDROID_HOME/usr/local
CC="$HOST-gcc -march=x86"
CXX=$HOST-g++
LDFLAGS="-L$DEST/lib -march=x86"
CPPFLAGS="-I$DEST/include -march=x86 -std=gnu99"
CXXFLAGS=$CFLAGS

# c-ares library build
cd /tmp
  $DOWNLOADER $C_ARES
  tar xf c-ares-1.13.0.tar.gz
  cd c-ares-1.13.0/
  PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig/ LD_LIBRARY_PATH=$PREFIX/lib/ ./configure --host=$HOST --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` --prefix=$PREFIX --enable-static --disable-shared
  make
  make install

cd /tmp
  rm -rf c-ares*
echo "build libCars complete!"

编译OpenSSL库,脚本文件就要变成这样,注意 CROSS_COMPILE=$TOOLCHAIN/bin/i686-linux-android- 这里已经不是Arm的了,相应的要为x86

OPENSSL=https://www.openssl.org/source/openssl-1.0.2m.tar.gz
DOWNLOADER="wget -c"

ANDROID_HOME=/opt/android-ndk-r14b
TOOLCHAIN=$ANDROID_HOME/toolchainX86
PATH=$TOOLCHAIN/bin:$PATH
HOST=i686-linux-android
PREFIX=$ANDROID_HOME/usr/local
LOCAL_DIR=$ANDROID_HOME/usr/local
TOOL_BIN_DIR=$ANDROID_HOME/toolchainX86/bin
PATH=${TOOL_BIN_DIR}:$PATH
DEST=$ANDROID_HOME/usr/local
CC="$HOST-gcc -march=x86"
CXX=$HOST-g++
LDFLAGS="-L$DEST/lib -march=x86"
CPPFLAGS="-I$DEST/include -march=x86 -std=gnu99"
CXXFLAGS=$CFLAGS


# openssl library build
cd /tmp
  $DOWNLOADER $OPENSSL
  tar xf openssl-1.0.2m.tar.gz
  cd openssl-1.0.2m/
  PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig/ LD_LIBRARY_PATH=$PREFIX/lib/ export CROSS_COMPILE=$TOOLCHAIN/bin/i686-linux-android-
./Configure --prefix=$PREFIX android

  make
  make install
cd /tmp
  rm -rf openssl*
echo "build openssl complete!"

由于没有设置ANDROID_HOME 环境变量,对应的Aria2源码中的android-config文件就要变成

ANDROID_HOME=/opt/android-ndk-r14b
TOOLCHAIN=$ANDROID_HOME/toolchainX86

PREFIX=$ANDROID_HOME/usr/local
PATH=$TOOLCHAIN/bin:$PATH

./configure \
    --host=i686-linux-android \
    --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
    --disable-nls \
    --without-gnutls \
    --with-openssl \
    --without-sqlite3 \
    --without-libxml2 \
    --with-libexpat \
    --with-libcares \
    --with-libz \
    --with-libssh2 \
    CC="$TOOLCHAIN"/bin/i686-linux-android-clang \
    CXX="$TOOLCHAIN"/bin/i686-linux-android-clang++ \
    CXXFLAGS="-Os -g" \
    CFLAGS="-Os -g" \
    CPPFLAGS="-fPIE" \
    LDFLAGS="-fPIE -pie -L$PREFIX/lib" \
    PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig"

Aria2源码中的android-make文件就要变成

ANDROID_HOME=/opt/android-ndk-r14b
TOOLCHAIN=$ANDROID_HOME/toolchainX86
PATH=$TOOLCHAIN/bin:$PATH

make "$@"

编译结果验证

最后的编译产物为
结果显示

在上面可以发现我们编译出来的内容达到了70多M,而官网提供的一个zip包里面,解压缩也就4M,然来发现我们少执行了一个脚本android-release (个人认为这是官网的一个缺失,应该告知)

android-relese 里面会执行一些优化,其中最重要的就是调用了linux下面的strip工具 下面是这个工具的具体介绍:

strip工具
strip命令减少XCOFF对象文件的大小。strip命令从XCOFF对象文件中有选择地除去行号
信息、重定位信息、调试段、typchk 段、注释段、文件头以及所有或部分符号表。一旦您
使用该命令,则很难调试文件的符号;因此,通常应该只在已经调试和测试过的生成模块上
使用 strip 命令。使用 strip 命令减少对象文件所需的存储量开销。
对于每个对象模块,strip 命令除去给出的选项所指定的信息。对于每个归档文件,
strip 命令从归档中除去全局符号表。可以使用 ar -s 命令将除去的符号表恢复到归档文件
或库文件中。
没有选项的 strip 命令除去行号信息、重定位信息、符号表、调试段、typchk 段和注
释段。
-e 在对象文件的可选头中设置F_LOADONLY 标志。如果对象文件放置在归档中,则该
标志告知绑定程序(ld 命令),在与此归档链接时应忽略该对象文件中的符号。
-E 复位(关闭)对象文件的可选头中的 F_LOADONLY 位。(请参阅 -e 标志。)
-H 除去对象文件头、任何可选的头以及所有段的头部分。
注: 不除去符号表信息。
-l (小写 L)从对象文件中除去行号信息。
-r 除了外部符号和静态符号条目,将全部符号表信息除去。不除去重定位信息。同时
除去调试段和 typchk 段。这个选项产生一个对象文件,该对象文件仍可以用作输
入到链接编辑器(ld 命令)中。
-t 除去大多数符号表信息,但并不除去函数符号或行号信息。
-V 打印 strip 命令的版本号。
-x 除去符号表信息,但并不除去静态或外部符号信息。 -x 标志同时除去重定位信息,
因此将不可能链接到该文件。
-X mode 指定应检查 strip 的对象文件的类型。 mode 必须是下列之一:
32
只处理 32 位对象文件
64
只处理 64 位对象文件
32_64
既处理 32 位对象文件,又处理 64 位对象文件

在通过android-relase命令之后,就会生成一个对应版本的zip文件,
结果显示

打开这个压缩文件,查看文件的大小,下面显示就跟官网提供的是差不多的。所以这就可以证明了我们的编译android是没有任务的问题的,这个是我们继续往下研究的一个前提(重点)
结果显示

验证这个编译的产物是否可以运行(Linux 下面运行这个可执行文件)

将这个可执行的文件,通过adb shell命令传输动 android 手机上面,注意我们上面编译的是一个arm版本的,如果放到64位的上面是不能运行的,运行的时候会出现
not found/not executable:32-bit ELF file
对于有root的权限的手机,可以随便放到sdk的下面,如果没有权限的用户,可以放到 /data/local/tmp的目录下面,这是一个linux系统的临时目录,是不用权限的
验证android的 编译的是否是可以行的。在命令下面,进入到这个/data/local/tmp 目录下面,前提是你已经把aria2跟要下载的种子文件一起放到里面
然后执行命令./aria2c 1.toerrate 就会显示结果

结果显示
结果显示


文章作者: AheadSnail
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AheadSnail !
评论
  目录