背景
我们采用arm公司的芯片,arm会提供官方支持的编译 toolchain,访问地址:ARM 官网
源码编译的好处,可以客制化一些features,features都是通过宏开关控制,比如arm 的gcc中 针对freertos 砍去了posix,所以需要手动打开posix 开关
gcc-arm-none-eabi 源码编译
下载 解压源码
把gcc-arm-none-eabi-6-2019-q3-update-linux.tar.bz2解压出来
How-to-build-toolchain.pdf
ARM 公司已经给了编译的参考文档,最主要的就是搭建可以跑起来的编译gcc的环境
以下,在文档中都有介绍,按照步骤操作
- ubuntu的编译环境
最好是ubuntu14.04 以上的版本,也可以是win10 linux 子系统18.04(本人实践环境)
- 环境搭建
$ sudo su
$ apt-get install software-properties-common
$ add-apt-repository universe
编辑文本 /etc/apt/sources.list.d/xenial.list
deb http://archive.ubuntu.com/ubuntu xenial main universe
deb-src http://archive.ubuntu.com/ubuntu xenial main universe
deb http://security.ubuntu.com/ubuntu xenial-security main
用来支持支持32bit的包
dpkg --add-architecture i386
更新所有的包
apt-get update
安装生成windows 环境的包
apt-get install -y -t xenial \
gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686
安装所有的工具包
apt-get -f install -y \
build-essential \
autoconf \
autogen \
bison \
dejagnu \
flex \
flip \
gawk \
git \
gperf \
gzip \
nsis \
openssh-client \
p7zip-full \
perl \
python-dev \
libisl-dev \
scons \
tcl \
texinfo \
tofrodos \
wget \
zip \
texlive \
texlive-extra-utils \
libncurses5-dev
# 退出sudo 权限
exit
进入解压目录下图 1
- 编译步骤
正常OK的步骤如下
./install-sources.sh
./build-prerequisites.sh
./build-toolchain.sh
注意事项
- 整个编译过程十分耗时,所以建议每一步都十分仔细,整个过程最长6.5小时
- 官方文档建议体跳过mingw32 的环境包,加快速度,建议跳过
- 在win10 的linux 子系统下,必须将源码放置在 ~ 主目录下面自己创建一个toolchain目录下,放在e盘或者d盘其他盘,会导致找不到头文件(猜测,微软linux子系统和windows 本身的文件系统兼容性做的不好)
- 编译的时候按照我的步骤加快编译和避开编译其他错误
# 下载 和 解压 依赖包
./install-sources.sh --skip_steps=mingw32
# 下载包的时候,可能会出现 缺少包
# 检查 build-common.sh文件所有安装包的链接和对应版本,缺少的话手动下载放在src目录下
# build-common.sh 中需要下载的依赖包的链接
https://gmplib.org/download/gmp/gmp-6.1.0.tar.bz2
http://www.mpfr.org/mpfr-3.1.4/mpfr-3.1.4.tar.bz2
ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3
http://isl.gforge.inria.fr/isl-0.18
https://downloads.sourceforge.net/project/expat/expat/expat-2.1.1/expat-2.1.1.tar.bz2
https://fossies.org/linux/misc/old/libelf-0.8.13.tar.gz
https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
http://www.zlib.net/fossils/zlib-1.2.8.tar.gz
http://nsis.sourceforge.net/mediawiki/images/a/ad/EnvVarUpdate.7z
https://www.python.org/ftp/python/python-2.7.13.msi
# 再次执行
./install-sources.sh --skip_steps=mingw32
./build-prerequisites.sh --skip_steps=mingw32
# 生成 linux版本 免安装 toolchain
执行命令
./build-toolchain.sh \
--skip_steps=mingw32,manual,gdb-with-python,mi
ngw32-gdb-with-python
–skip_steps 就是 所有源码安装依赖包 configure 步骤中配置的参数
mingw32 是跳过 生成32位系统 免安装toolchain
manual 不生成 pdf 和html等说明文档
-gdb- 相关参数跳过所有的gdb调试工具生成
整个过程3小时15分钟
基本上一个源码编译生成的免安装gcc toolchain 可以进行玩耍了
记得盯着编译过程,就知道为什么编译时间这么长了
win10 linux 子系统会打包失败,如图2:
增加posix gcc编译
因为想拥有支持多线程posix的 gcc,那么上面的gcc 工具features中并没有支持posix,编译报错是合理的
查看编译器支持features 图3
那么需要在支持posix 配置的依赖库的源码中,在./configure 增加参数–enable-threads=posix (默认是 --enable-threads=single 即 --disable-threads)
所以 需要build-toolchain.sh 中将所有 的–disable-threads 替换为 --enable-threads=posix ,让编译器支持 posix threads,修改后再次编译
但是编译后,出现编译报错 图4
编译出错,说明我们的编译器不支持posix,所以需要看具体错误
图4 的错误,指出 在mutls.c 中引用了gthr.h 包含头文件中的gthr-default.h 中的pthread 但是不识别
找到源码:在gcc 源码包中找到gthr.h 注释说明了如何手动修改支持 posix
/* If this file is compiled with threads support, it must
#define __GTHREADS 1
to indicate that threads support is present. Also it has define
function
int __gthread_active_p ()
that returns 1 if thread system is active, 0 if not.
The threads interface must define the following types:
__gthread_key_t
__gthread_once_t
__gthread_mutex_t
__gthread_recursive_mutex_t
The threads interface must define the following macros:
__GTHREAD_ONCE_INIT
to initialize __gthread_once_t
__GTHREAD_MUTEX_INIT
to initialize __gthread_mutex_t to get a fast
non-recursive mutex.
__GTHREAD_MUTEX_INIT_FUNCTION
to initialize __gthread_mutex_t to get a fast
non-recursive mutex.
Define this to a function which looks like this:
void __GTHREAD_MUTEX_INIT_FUNCTION (__gthread_mutex_t *)
Some systems can't initialize a mutex without a
function call. Don't define __GTHREAD_MUTEX_INIT in this case.
__GTHREAD_RECURSIVE_MUTEX_INIT
__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
as above, but for a recursive mutex.
The threads interface must define the following static functions:
int __gthread_once (__gthread_once_t *once, void (*func) ())
int __gthread_key_create (__gthread_key_t *keyp, void (*dtor) (void *))
int __gthread_key_delete (__gthread_key_t key)
void *__gthread_getspecific (__gthread_key_t key)
int __gthread_setspecific (__gthread_key_t key, const void *ptr)
int __gthread_mutex_destroy (__gthread_mutex_t *mutex);
int __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex);
int __gthread_mutex_lock (__gthread_mutex_t *mutex);
int __gthread_mutex_trylock (__gthread_mutex_t *mutex);
int __gthread_mutex_unlock (__gthread_mutex_t *mutex);
int __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex);
int __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex);
int __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex);
The following are supported in POSIX threads only. They are required to
fix a deadlock in static initialization inside libsupc++. The header file
gthr-posix.h defines a symbol __GTHREAD_HAS_COND to signify that these extra
features are supported.
Types:
__gthread_cond_t
Macros:
__GTHREAD_COND_INIT
__GTHREAD_COND_INIT_FUNCTION
Interface:
int __gthread_cond_broadcast (__gthread_cond_t *cond);
int __gthread_cond_wait (__gthread_cond_t *cond, __gthread_mutex_t *mutex);
int __gthread_cond_wait_recursive (__gthread_cond_t *cond,
__gthread_recursive_mutex_t *mutex);
All functions returning int should return zero on success or the error
number. If the operation is not supported, -1 is returned.
If the following are also defined, you should
#define __GTHREADS_CXX0X 1
to enable the c++0x thread library.
Types:
__gthread_t
__gthread_time_t
Interface:
int __gthread_create (__gthread_t *thread, void *(*func) (void*),
void *args);
int __gthread_join (__gthread_t thread, void **value_ptr);
int __gthread_detach (__gthread_t thread);
int __gthread_equal (__gthread_t t1, __gthread_t t2);
__gthread_t __gthread_self (void);
int __gthread_yield (void);
int __gthread_mutex_timedlock (__gthread_mutex_t *m,
const __gthread_time_t *abs_timeout);
int __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *m,
const __gthread_time_t *abs_time);
int __gthread_cond_signal (__gthread_cond_t *cond);
int __gthread_cond_timedwait (__gthread_cond_t *cond,
__gthread_mutex_t *mutex,
const __gthread_time_t *abs_timeout);
*/