背景
我们采用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 123
编辑文本 /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 123
用来支持支持32bit的包
dpkg --add-architecture i386 1
更新所有的包
apt-get update 1
安装生成windows 环境的包
apt-get install -y -t xenial \ gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 12
安装所有的工具包
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 1234567891011121314151617181920212223242526272829
进入解压目录下图 1
-
编译步骤 正常OK的步骤如下
./install-sources.sh ./build-prerequisites.sh ./build-toolchain.sh 123
注意事项
-
整个编译过程十分耗时,所以建议每一步都十分仔细,整个过程最长6.5小时
-
官方文档建议体跳过mingw32 的环境包,加快速度,建议跳过
-
在win10 的linux 子系统下,必须将源码放置在 ~ 主目录下面自己创建一个toolchain目录下,放在e盘或者d盘其他盘,会导致找不到头文件(猜测,微软linux子系统和windows 本身的文件系统兼容性做的不好)
-
编译的时候按照我的步骤加快编译和避开编译其他错误
# 下载 和 解压 依赖包 ./install-sources.sh --skip_steps=mingw32 12 # 下载包的时候,可能会出现 缺少包 # 检查 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 1234567891011121314 # 再次执行 ./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 12345678
–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); */