准备工作

用mac自带的磁盘工具新建一个区分大小写的硬盘分区,后续的操作建议都在此分区进行,不然会出现文件找不到等错误。运行脚本需要gnu-sed,不是OSX上自带的sed,所以需要先下载一个,修改PATH变量,并用ln建立链接sed指向gsed

brew install gnu-sed
export PATH=/usr/local/Cellar/gnu-sed/4.7/bin:$PATH

其他一些前提依赖项

ulimit -n 8192
brew install gawk wget autoconf gettext

运行脚本

根据herehere,前者是arm平台,主要根据后者,结合自己需要,修改了gcc版本和一些环境参数

vars.sh

#! /bin/bash
INSTALL_PATH=/Volumes/Develop/cross_compile/x86_64
TARGET=x86_64-linux
USE_NEWLIB=0
LINUX_ARCH=x86_64
CONFIGURATION_OPTIONS="--disable-multilib --disable-nls --disable-werror" # --disable-threads --disable-shared
PARALLEL_MAKE=
BINUTILS_VERSION=binutils-2.25
GCC_VERSION=gcc-4.8.5
LINUX_KERNEL_VERSION=linux-3.17.2
GLIBC_VERSION=glibc-2.20
MPFR_VERSION=mpfr-3.1.2
GMP_VERSION=gmp-6.0.0a
MPC_VERSION=mpc-1.0.2
ISL_VERSION=isl-0.12.2
CLOOG_VERSION=cloog-0.18.1
export PATH=$INSTALL_PATH/bin:$PATH

build.sh

#! /bin/bash
set -e
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
trap 'echo FAILED COMMAND: $previous_command' EXIT

#-------------------------------------------------------------------------------------------
# This script will download packages for a GCC cross-compiler.
# Customize the variables (INSTALL_PATH, TARGET, etc.) in vars.sh to your liking before running.
#
# See: http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler
#-------------------------------------------------------------------------------------------

source ./vars.sh

# Download packages
export http_proxy=$HTTP_PROXY https_proxy=$HTTP_PROXY ftp_proxy=$HTTP_PROXY
wget -nc https://ftp.gnu.org/gnu/binutils/$BINUTILS_VERSION.tar.gz
wget -nc https://ftp.gnu.org/gnu/gcc/$GCC_VERSION/$GCC_VERSION.tar.gz
if [ $USE_NEWLIB -ne 0 ]; then
    wget -nc -O newlib-master.zip https://github.com/bminor/newlib/archive/master.zip || true
    unzip -qo newlib-master.zip
else
    wget -nc https://www.kernel.org/pub/linux/kernel/v3.x/$LINUX_KERNEL_VERSION.tar.xz
    wget -nc https://ftp.gnu.org/gnu/glibc/$GLIBC_VERSION.tar.xz
fi
wget -nc https://ftp.gnu.org/gnu/mpfr/$MPFR_VERSION.tar.xz
wget -nc https://ftp.gnu.org/gnu/gmp/$GMP_VERSION.tar.xz
wget -nc https://ftp.gnu.org/gnu/mpc/$MPC_VERSION.tar.gz
wget -nc ftp://gcc.gnu.org/pub/gcc/infrastructure/$ISL_VERSION.tar.bz2
wget -nc ftp://gcc.gnu.org/pub/gcc/infrastructure/$CLOOG_VERSION.tar.gz

# Extract everything
for f in *.tar*; do tar xfk $f; done

# Make symbolic links
cd $GCC_VERSION
ln -sf `ls -1d ../mpfr-*/` mpfr
ln -sf `ls -1d ../gmp-*/` gmp
ln -sf `ls -1d ../mpc-*/` mpc
ln -sf `ls -1d ../isl-*/` isl
ln -sf `ls -1d ../cloog-*/` cloog
cd ..

trap - EXIT
echo 'Success!'

download.sh

#! /bin/bash
set -e
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
trap 'echo FAILED COMMAND: $previous_command' EXIT

#-------------------------------------------------------------------------------------------
# This script will configure, build and install a GCC cross-compiler.
# It assumes that all packages have been downloaded using download.sh before this file is run.
# Customize the variables (INSTALL_PATH, TARGET, etc.) in vars.sh to your liking before running.
# If you get an error and need to resume the script from some point in the middle,
# just delete/comment the preceding lines before running it again.
#
# See: http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler
#
# This script requires gnu-sed, not the normal sed that comes with OSX.  If you don't want to
# mess with the normal sed, perhaps add to the front of PATH the path to gnu-sed before you
# run this script?  e.g. export PATH=/path/to/gnu-sed-directory/bin:$PATH
#
# This script should be run in a case-sensitive partition which you can make using OSX's disk 
# utility.
#-------------------------------------------------------------------------------------------

source ./vars.sh

# extra flags and env variables are needed to get this to compile on OSX
export BUILD_ALL_BASE_DIR=`pwd`
export HOST_EXTRACFLAGS="-I$BUILD_ALL_BASE_DIR/endian"

# these are needed for gettext and assuming that it was installed using brew
export BUILD_CPPFLAGS='-I/usr/local/Cellar/gettext/0.20.1/include'
export BUILD_LDFLAGS='-L/usr/local/Cellar/gettext/0.20.1/lib -lintl'

# Step 1. Binutils
echo -e "\nStep 1 - building binutils...\n" && sleep 2
mkdir -p build-binutils
cd build-binutils
../$BINUTILS_VERSION/configure --prefix=$INSTALL_PATH --target=$TARGET $CONFIGURATION_OPTIONS
make $PARALLEL_MAKE
make install
cd ..

# Step 2. Linux Kernel Headers
echo -e "\nStep 2 - Linux kernel headers...\n" && sleep 2
if [ $USE_NEWLIB -eq 0 ]; then
    cd $LINUX_KERNEL_VERSION
    make V=1 ARCH=$LINUX_ARCH INSTALL_HDR_PATH=$INSTALL_PATH/$TARGET headers_install
    cd ..
fi

# Step 3. C/C++ Compilers
echo -e "\nStep 3 - C/C++ compilers...\n" && sleep 2
mkdir -p build-gcc
cd build-gcc
if [ $USE_NEWLIB -ne 0 ]; then
    NEWLIB_OPTION=--with-newlib
fi
../$GCC_VERSION/configure --prefix=$INSTALL_PATH --target=$TARGET --enable-languages=c,c++ $CONFIGURATION_OPTIONS $NEWLIB_OPTION
make $PARALLEL_MAKE gcc_cv_libc_provides_ssp=yes all-gcc
make install-gcc
cd ..

if [ $USE_NEWLIB -ne 0 ]; then
    # Steps 4-6: Newlib
    echo -e "\nSteps 4-6 - newlib...\n" && sleep 2
    mkdir -p build-newlib
    cd build-newlib
    ../newlib-master/configure --prefix=$INSTALL_PATH --target=$TARGET $CONFIGURATION_OPTIONS
    make $PARALLEL_MAKE
    make install
    cd ..
else
    # Step 4. Standard C Library Headers and Startup Files
    echo -e "\nStep 4 - standard lib headers...\n" && sleep 2
    mkdir -p build-glibc
    cd build-glibc
    ../$GLIBC_VERSION/configure --prefix=$INSTALL_PATH/$TARGET --build=$MACHTYPE --host=$TARGET --target=$TARGET --with-headers=$INSTALL_PATH/$TARGET/include $CONFIGURATION_OPTIONS libc_cv_forced_unwind=yes
    make install-bootstrap-headers=yes install-headers
    make $PARALLEL_MAKE csu/subdir_lib
    install csu/crt1.o csu/crti.o csu/crtn.o $INSTALL_PATH/$TARGET/lib
    $TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $INSTALL_PATH/$TARGET/lib/libc.so
    touch $INSTALL_PATH/$TARGET/include/gnu/stubs.h
    cd ..

    # Step 5. Compiler Support Library
    echo -e "\nStep 5 - building libgcc...\n" && sleep 2
    cd build-gcc
    make $PARALLEL_MAKE all-target-libgcc
    make install-target-libgcc
    cd ..

    # Step 6. Standard C Library & the rest of Glibc
    echo -e "\nStep 6 - standard C library and the rest of glibc...\n" && sleep 2
    cd build-glibc
    make $PARALLEL_MAKE
    make install
    cd ..
fi

# Step 7. Standard C++ Library & the rest of GCC
echo -e "\nStep 7 - building C++ library and rest of gcc\n"  && sleep 2
cd build-gcc
make $PARALLEL_MAKE all
make install
cd ..

trap - EXIT
echo 'Success!'

依次执行download.sh和build.sh即可

编译开源代码遇到的一些问题

ffmpeg

./config.h:17:19: error: expected identifier or '(' before 'void'
 #define getenv(x) NULL
                   ^
./config.h:17:19: error: expected ')' before numeric constant
 #define getenv(x) NULL
                   ^

在config.h中注释掉:

//#define getenv(x) NULL
In file included from libavformat/asfdec_o.c:30:0:
./libavutil/time_internal.h:26:26: error: static declaration of 'gmtime_r' follows non-static declaration
 static inline struct tm *gmtime_r(const time_t* clock, struct tm *result)
                          ^
In file included from ./libavutil/time_internal.h:22:0,
                 from libavformat/asfdec_o.c:30:
/Volumes/Develop/cross_compile/x86_64/x86_64-linux/include/time.h:249:19: note: previous declaration of 'gmtime_r' was here
 extern struct tm *gmtime_r (const time_t *__restrict __timer,
                   ^
In file included from libavformat/asfdec_o.c:30:0:
./libavutil/time_internal.h:37:26: error: static declaration of 'localtime_r' follows non-static declaration
 static inline struct tm *localtime_r(const time_t* clock, struct tm *result)
                          ^
In file included from ./libavutil/time_internal.h:22:0,
                 from libavformat/asfdec_o.c:30:
/Volumes/Develop/cross_compile/x86_64/x86_64-linux/include/time.h:254:19: note: previous declaration of 'localtime_r' was here
 extern struct tm *localtime_r (const time_t *__restrict __timer,
                   ^

参照here将下列定义从0改为1

#define HAVE_LLRINT 1
#define HAVE_LLRINTF 1
#define HAVE_LRINT 1
#define HAVE_LRINTF 1
#define HAVE_ROUND 1
#define HAVE_ROUNDF 1
#define HAVE_CBRT 1
#define HAVE_CBRTF 1
#define HAVE_COPYSIGN 1
#define HAVE_TRUNC 1
#define HAVE_TRUNCF 1
#define HAVE_RINT 1
#define HAVE_HYPOT 1
#define HAVE_ERF 1

或者

sed -i -e 's/#define HAVE_LLRINT 0/#define HAVE_LLRINT 1/g' config.h
sed -i -e 's/#define HAVE_LLRINTF 0/#define HAVE_LLRINTF 1/g' config.h
sed -i -e 's/#define HAVE_LRINT 0/#define HAVE_LRINT 1/g' config.h
sed -i -e 's/#define HAVE_LRINTF 0/#define HAVE_LRINTF 1/g' config.h
sed -i -e 's/#define HAVE_ROUND 0/#define HAVE_ROUND 1/g' config.h
sed -i -e 's/#define HAVE_ROUNDF 0/#define HAVE_ROUNDF 1/g' config.h
sed -i -e 's/#define HAVE_CBRT 0/#define HAVE_CBRT 1/g' config.h
sed -i -e 's/#define HAVE_CBRTF 0/#define HAVE_CBRTF 1/g' config.h
sed -i -e 's/#define HAVE_COPYSIGN 0/#define HAVE_COPYSIGN 1/g' config.h
sed -i -e 's/#define HAVE_TRUNC 0/#define HAVE_TRUNC 1/g' config.h
sed -i -e 's/#define HAVE_TRUNCF 0/#define HAVE_TRUNCF 1/g' config.h
sed -i -e 's/#define HAVE_RINT 0/#define HAVE_RINT 1/g' config.h
sed -i -e 's/#define HAVE_HYPOT 0/#define HAVE_HYPOT 1/g' config.h
sed -i -e 's/#define HAVE_ERF 0/#define HAVE_ERF 1/g' config.h
sed -i -e 's/#define HAVE_GMTIME_R 0/#define HAVE_GMTIME_R 1/g' config.h
sed -i -e 's/#define HAVE_LOCALTIME_R 0/#define HAVE_LOCALTIME_R 1/g' config.h
sed -i -e 's/#define HAVE_INET_ATON 0/#define HAVE_INET_ATON 1/g' config.h
CC	libavdevice/alldevices.o
In file included from ./libavutil/common.h:36:0,
                 from ./libavutil/avutil.h:289,
                 from ./libavutil/log.h:25,
                 from libavdevice/avdevice.h:46,
                 from libavdevice/alldevices.c:22:
./libavutil/libm.h:86:38: error: expected identifier or '(' before 'sizeof'
 static av_always_inline av_const int isinf(float x)
                                      ^
./libavutil/libm.h:96:38: error: expected identifier or '(' before 'sizeof'
 static av_always_inline av_const int isnan(float x)
                                      ^
make: *** [libavdevice/alldevices.o] Error 1
michaels-MBP:ffmpeg michael$ make clean;make
CC	libavdevice/alldevices.o
In file included from ./libavutil/common.h:36:0,
                 from ./libavutil/avutil.h:289,
                 from ./libavutil/log.h:25,
                 from libavdevice/avdevice.h:46,
                 from libavdevice/alldevices.c:22:
./libavutil/libm.h:96:38: error: expected identifier or '(' before 'sizeof'
 static av_always_inline av_const int isnan(float x)
                                      ^
make: *** [libavdevice/alldevices.o] Error 1

修改

#define HAVE_ISINF 1
#define HAVE_ISNAN 1
../ffmpeg/libavutil/libavutil.a(file.o): In function `av_tempfile':
file.c:(.text+0x15d): warning: the use of `tempnam' is dangerous, better use `mkstemp'

修改

#define HAVE_MKSTEMP 1

编译过程坑比较多,小心谨慎

Logo

更多推荐