欢迎来到皮皮网网首页

【筹码高度秘籍源码】【内核qos源码】【侠义Online源码】glibc gcc 源码

来源:任性摇钱树源码 时间:2024-12-24 04:19:26

1.为什么GCC、源码GLIBC、源码libstdc++ not found?
2.如何为嵌入式开发建立交叉编译环境
3.Linux下的交叉编译环境设置
4.如何制作arm-linux-gcc编译工具
5.升级 GLIBC 后想回退,源码遇到 __resolv_context_ 相关符号报错
6.Linux 调试秘籍深入探索 C++运行时获取堆栈信息和源代码行数的源码终极指南

glibc gcc 源码

为什么GCC、GLIBC、源码libstdc++ not found?

       GLIBCXX not found

       相关报错处理方式:

       1. 需要确认所使用的源码筹码高度秘籍源码库文件是否存在于系统中,通常通过运行 `ldd` 命令查看程序依赖的源码动态库。如果出现类似`/usr/lib/libstdc++.so.6: version 'GLIBCXX_3.4.' not found (required by ./xxx)`的源码错误信息,说明缺少特定版本的源码GLIBCXX库。

       处理方法如下:

       2. **源码编译更新gcc

**

       3. **下载官方包复制

**

       4. **手动编译复制

**

       GLIBC not found

       相关错误信息示例:

       若报错信息为`/lib/libc.so.6: version 'GLIBC_2.' not found (required by /lib/libstdc++.so.6)`,源码则表明缺少特定版本的源码GLIBC库。

       处理方法有以下几种:

       2. **源码编译更新gcc

**

       3. **下载官方包复制

**

       4. **手动编译复制

**

       gcc

       gcc 是源码 GNU Compiler Collection 的简称,用于将c/c++源代码编译为不同操作系统平台的源码汇编代码和可执行程序。

       gcc 是源码一组编译工具的集合,主要负责预处理和编译任务,源码自动调用汇编器和链接器,提供与编译器紧密相关的运行库支持。

       glibc

       glibc 是 GNU 实现的标准 C 库,提供操作系统级的底层函数和核心API,如I/O设备操作。内核qos源码

       glibc 包含多个头文件,每个文件定义一组相关设施。

       libstdc++

       libstdc++ 类似于 glibc,但针对 C++ 标准库。

       提供与标准 C 库相同的核心定义和底层功能,以及 C++ 标准库的实现,用于实现 C++ 程序中的库内容,如线程、流、文件、输入/输出等。

       大多数 Linux 发行版默认使用 libstdc++。

       ABI

       标准库的一个关键方面是 Application Binary Interface (ABI),它确保了编写的 C 程序能在不同版本的 glibc 上运行。

       为了改进而不破坏兼容性,glibc 使用符号版本控制,每个函数与特定版本关联,允许新版本的程序使用新符号,而旧版本的侠义Online源码程序仍能使用旧但兼容的符号。

       binutils 是将汇编语言翻译为目标代码的程序,与标准库之间存在密切关系。

       GNU C 函数库为开发者提供了便利,便于使用 C 语言开发基于 Linux 操作系统的程序。

       glibc 是 Linux 下的 C 标准库实现,是 GNU C Library 的一部分,已成为 Linux 的主要 C 库之一。

       相关命令

       使用 `ldd` 命令查看程序依赖的动态库。

       通过 `strings /lib/libc.so.6 | grep GLIBC_` 查看系统 GLIBC 支持的版本。

       通过 `strings /usr/lib/libstdc++.so.6 | grep GLIBCXX` 查看系统 GLIBCXX 支持的版本。

       使用 `readelf` 命令可以检查应用程序或库所需的 GLIBC 或 GLIBCXX 版本。

如何为嵌入式开发建立交叉编译环境

       ã€€ã€€ä¸‹é¢æˆ‘们将以建立针对arm的交叉编译开发环境为例来解说整个过程,其他的体系结构与这个相类似,只要作一些对应的改动。我的开发环境是,宿主机 i-redhat-7.2,目标机 arm。

       ã€€ã€€è¿™ä¸ªè¿‡ç¨‹å¦‚下

       ã€€ã€€1. 下载源文件、补丁和建立编译的目录

       ã€€ã€€2. 建立内核头文件

       ã€€ã€€3. 建立二进制工具(binutils)

       ã€€ã€€4. 建立初始编译器(bootstrap gcc)

       ã€€ã€€5. 建立c库(glibc)

       ã€€ã€€6. 建立全套编译器(full gcc)

       ã€€ã€€ä¸‹è½½æºæ–‡ä»¶ã€è¡¥ä¸å’Œå»ºç«‹ç¼–译的目录

       ã€€ã€€1. 选定软件版本号

       ã€€ã€€é€‰æ‹©è½¯ä»¶ç‰ˆæœ¬å·æ—¶ï¼Œå…ˆçœ‹çœ‹glibc源代码中的INSTALL文件。那里列举了该版本的glibc编译时所需的binutils 和gcc的版本号。例如在 glibc-2.2.3/INSTALL 文件中推荐 gcc 用 2.以上,binutils 用 2..1 以上版本。

       ã€€ã€€æˆ‘选的各个软件的版本是:

       ã€€ã€€linux-2.4.+rmk2

       ã€€ã€€binutils-2..1

       ã€€ã€€gcc-2..3

       ã€€ã€€glibc-2.2.3

       ã€€ã€€glibc-linuxthreads-2.2.3

       ã€€ã€€å¦‚果你选的glibc的版本号低于2.2,你还要下载一个叫glibc-crypt的文件,例如glibc-crypt-2.1.tar.gz。 Linux 内核你可以从www.kernel.org 或它的镜像下载。

       ã€€ã€€Binutils、gcc和glibc你可以从FSF的FTP站点ftp://ftp.gun.org/gnu/ 或它的镜像去下载。 在编译glibc时,要用到 Linux 内核中的 include 目录的内核头文件。如果你发现有变量没有定义而导致编译失败,你就改变你的内核版本号。例如我开始用linux-2.4.+vrs2,编译glibc-2.2.3 时报 BUS_ISA 没定义,后来发现在 2.4. 开始它的名字被改为 CTL_BUS_ISA。如果你没有完全的把握保证你改的内核改完全了,就不要动内核,而是把你的 Linux 内核的版本号降低或升高,来适应 glibc。

       ã€€ã€€Gcc 的版本号,推荐用 gcc-2. 以上的。太老的版本编译可能会出问题。Gcc-2..3 是一个比较稳定的版本,也是内核开发人员推荐用的一个 gcc 版本。

       ã€€ã€€å¦‚果你发现无法编译过去,有可能是你选用的软件中有的加入了一些新的特性而其他所选软件不支持的原因,就相应降低该软件的版本号。例如我开始用 gcc-3.3.2,发现编译不过,报 as、ld 等版本太老,我就把 gcc 降为 2..3。 太新的版本大多没经过大量的测试,建议不要选用。

       ã€€ã€€å›žé¡µé¦–

       ã€€ã€€2. 建立工作目录

       ã€€ã€€é¦–先,我们建立几个用来工作的目录:

       ã€€ã€€åœ¨ä½ çš„用户目录,我用的是用户liang,因此用户目录为 /home/liang,先建立一个项目目录embedded。

       ã€€ã€€$pwd

       ã€€ã€€/home/liang

       ã€€ã€€$mkdir embedded

       ã€€ã€€å†åœ¨è¿™ä¸ªé¡¹ç›®ç›®å½• embedded 下建立三个目录 build-tools、kernel 和 tools。

       ã€€ã€€build-tools-用来存放你下载的 binutils、gcc 和 glibc 的源代码和用来编译这些源代码的目录。

       ã€€ã€€kernel-用来存放你的内核源代码和内核补丁。

       ã€€ã€€tools-用来存放编译好的交叉编译工具和库文件。

       ã€€ã€€$cd embedded

       ã€€ã€€$mkdir build-tools kernel tools

       ã€€ã€€æ‰§è¡Œå®ŒåŽç›®å½•ç»“构如下:

       ã€€ã€€$ls embedded

       ã€€ã€€build-tools kernel tools

       ã€€ã€€3. 输出和环境变量

       ã€€ã€€æˆ‘们输出如下的环境变量方便我们编译。

       ã€€ã€€$export PRJROOT=/home/liang/embedded

       ã€€ã€€$export TARGET=arm-linux

       ã€€ã€€$export PREFIX=$PRJROOT/tools

       ã€€ã€€$export TARGET_PREFIX=$PREFIX/$TARGET

       ã€€ã€€$export PATH=$PREFIX/bin:$PATH

       ã€€ã€€å¦‚果你不惯用环境变量的,你可以直接用绝对或相对路径。我如果不用环境变量,一般都用绝对路径,相对路径有时会失败。环境变量也可以定义在.bashrc文件中,这样当你logout或换了控制台时,就不用老是export这些变量了。

       ã€€ã€€ä½“系结构和你的TAEGET变量的对应如下表

       ã€€ã€€ä½ å¯ä»¥åœ¨é€šè¿‡glibc下的config.sub脚本来知道,你的TARGET变量是否被支持,例如:

       ã€€ã€€$./config.sub arm-linux

       ã€€ã€€arm-unknown-linux-gnu

       ã€€ã€€åœ¨æˆ‘的环境中,config.sub 在 glibc-2.2.3/scripts 目录下。

       ã€€ã€€ç½‘上还有一些 HOWTO 可以参考,ARM 体系结构的《The GNU Toolchain for ARM Target HOWTO》,PowerPC 体系结构的《Linux for PowerPC Embedded Systems HOWTO》等。对TARGET的选取可能有帮助。

       ã€€ã€€4. 建立编译目录

       ã€€ã€€ä¸ºäº†æŠŠæºç å’Œç¼–译时生成的文件分开,一般的编译工作不在的源码目录中,要另建一个目录来专门用于编译。用以下的命令来建立编译你下载的binutils、gcc和glibc的源代码的目录。

       ã€€ã€€$cd $PRJROOT/build-tools

       ã€€ã€€$mkdir build-binutils build-boot-gcc build-gcc build-glibc gcc-patch

       ã€€ã€€build-binutils-编译binutils的目录

       ã€€ã€€build-boot-gcc-编译gcc 启动部分的目录

       ã€€ã€€build-glibc-编译glibc的目录

       ã€€ã€€build-gcc-编译gcc 全部的目录

       ã€€ã€€gcc-patch-放gcc的补丁的目录

       ã€€ã€€gcc-2..3 的补丁有 gcc-2..3-2.patch、gcc-2..3-no-fixinc.patch 和gcc-2..3-returntype-fix.patch,可以从 http://www.linuxfromscratch.org/ 下载到这些补丁。

       ã€€ã€€å†å°†ä½ ä¸‹è½½çš„ binutils-2..1、gcc-2..3、glibc-2.2.3 和 glibc-linuxthreads-2.2.3 的源代码放入 build-tools 目录中

       ã€€ã€€çœ‹ä¸€ä¸‹ä½ çš„ build-tools 目录,有以下内容:

       ã€€ã€€$ls

       ã€€ã€€binutils-2..1.tar.bz2 build-gcc gcc-patch

       ã€€ã€€build-binutls build-glibc glibc-2.2.3.tar.gz

       ã€€ã€€build-boot-gcc gcc-2..3.tar.gz glibc-linuxthreads-2.2.3.tar.gz

       ã€€ã€€å›žé¡µé¦–

       ã€€ã€€å»ºç«‹å†…核头文件

       ã€€ã€€æŠŠä½ ä»Ž www.kernel.org 下载的内核源代码放入 $PRJROOT /kernel 目录

       ã€€ã€€è¿›å…¥ä½ çš„ kernel 目录:

       ã€€ã€€$cd $PRJROOT /kernel

       ã€€ã€€è§£å¼€å†…核源代码

       ã€€ã€€$tar -xzvf linux-2.4..tar.gz

       ã€€ã€€æˆ–

       ã€€ã€€$tar -xjvf linux-2.4..tar.bz2

       ã€€ã€€å°äºŽ 2.4. 的内核版本解开会生成一个 linux 目录,没带版本号,就将其改名。

       ã€€ã€€$mv linux linux-2.4.x

       ã€€ã€€ç»™ Linux 内核打上你的补丁

       ã€€ã€€$cd linux-2.4.

       ã€€ã€€$patch -p1 < ../patch-2.4.-rmk2

       ã€€ã€€ç¼–译内核生成头文件

       ã€€ã€€$make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig

       ã€€ã€€ä½ ä¹Ÿå¯ä»¥ç”¨ config 和 xconfig 来代替 menuconfig,但这样用可能会没有设置某些配置文件选项和没有生成下面编译所需的头文件。推荐大家用 make menuconfig,这也是内核开发人员用的最多的配置方法。配置完退出并保存,检查一下的内核目录中的 include/linux/version.h 和 include/linux/autoconf.h 文件是不是生成了,这是编译 glibc 是要用到的,version.h 和 autoconf.h 文件的存在,也说明了你生成了正确的头文件。

       ã€€ã€€è¿˜è¦å»ºç«‹å‡ ä¸ªæ­£ç¡®çš„链接

       ã€€ã€€$cd include

       ã€€ã€€$ln -s asm-arm asm

       ã€€ã€€$cd asm

       ã€€ã€€$ln -s arch-epxa arch

       ã€€ã€€$ln -s proc-armv proc

       ã€€ã€€æŽ¥ä¸‹æ¥ä¸ºä½ çš„交叉编译环境建立你的内核头文件的链接

       ã€€ã€€$mkdir -p $TARGET_PREFIX/include

       ã€€ã€€$ln -s $PRJROOT/kernel/linux-2.4./include/linux $TARGET_PREFIX/include/linux

       ã€€ã€€$in -s $PRJROOT/kernel/linux-2.4./include/asm-arm $TARGET_PREFIX/include/asm

       ã€€ã€€ä¹Ÿå¯ä»¥æŠŠ Linux 内核头文件拷贝过来用

       ã€€ã€€$mkdir -p $TARGET_PREFIX/include

       ã€€ã€€$cp -r $PRJROOT/kernel/linux-2.4./include/linux $TARGET_PREFIX/include

       ã€€ã€€$cp -r $PRJROOT/kernel/linux-2.4./include/asm-arm $TARGET_PREFIX/include

       ã€€ã€€å›žé¡µé¦–

       ã€€ã€€å»ºç«‹äºŒè¿›åˆ¶å·¥å…·ï¼ˆbinutils)

       ã€€ã€€binutils是一些二进制工具的集合,其中包含了我们常用到的as和ld。

       ã€€ã€€é¦–先,我们解压我们下载的binutils源文件。

       ã€€ã€€$cd $PRJROOT/build-tools

       ã€€ã€€$tar -xvjf binutils-2..1.tar.bz2

       ã€€ã€€ç„¶åŽè¿›å…¥build-binutils目录配置和编译binutils。

       ã€€ã€€$cd build-binutils

       ã€€ã€€$../binutils-2..1/configure --target=$TARGET --prefix=$PREFIX

       ã€€ã€€--target 选项是指出我们生成的是 arm-linux 的工具,--prefix 是指出我们可执行文件安装的位置。

       ã€€ã€€ä¼šå‡ºçŽ°å¾ˆå¤š check,最后产生 Makefile 文件。

       ã€€ã€€æœ‰äº† Makefile 后,我们来编译并安装 binutils,命令很简单。

       ã€€ã€€$make

       ã€€ã€€$make install

       ã€€ã€€çœ‹ä¸€ä¸‹æˆ‘们 $PREFIX/bin 下的生成的文件

       ã€€ã€€$ls $PREFIX/bin

       ã€€ã€€arm-linux-addr2line arm-linux-gasp arm-linux-objdump arm-linux-strings

       ã€€ã€€arm-linux-ar arm-linux-ld arm-linux-ranlib arm-linux-strip

       ã€€ã€€arm-linux-as arm-linux-nm arm-linux-readelf

       ã€€ã€€arm-linux-c++filt arm-linux-objcopy arm-linux-size

       ã€€ã€€æˆ‘们来解释一下上面生成的可执行文件都是用来干什么的

       ã€€ã€€add2line - 将你要找的地址转成文件和行号,它要使用 debug 信息。

       ã€€ã€€Ar-产生、修改和解开一个存档文件

       ã€€ã€€As-gnu 的汇编器

       ã€€ã€€C++filt-C++ 和 java 中有一种重载函数,所用的重载函数最后会被编译转化成汇编的标号,c++filt 就是实现这种反向的转化,根据标号得到函数名。

       ã€€ã€€Gasp-gnu 汇编器预编译器。

       ã€€ã€€Ld-gnu 的连接器

       ã€€ã€€Nm-列出目标文件的符号和对应的地址

       ã€€ã€€Objcopy-将某种格式的目标文件转化成另外格式的目标文件

       ã€€ã€€Objdump-显示目标文件的信息

       ã€€ã€€Ranlib-为一个存档文件产生一个索引,并将这个索引存入存档文件中

       ã€€ã€€Readelf-显示 elf 格式的目标文件的信息

       ã€€ã€€Size-显示目标文件各个节的大小和目标文件的大小

       ã€€ã€€Strings-打印出目标文件中可以打印的字符串,有个默认的长度,为4

       ã€€ã€€Strip-剥掉目标文件的所有的符号信息

       ã€€ã€€å›žé¡µé¦–

       ã€€ã€€å»ºç«‹åˆå§‹ç¼–译器(bootstrap gcc)

       ã€€ã€€é¦–先进入 build-tools 目录,将下载 gcc 源代码解压

       ã€€ã€€$cd $PRJROOT/build-tools

       ã€€ã€€$tar -xvzf gcc-2..3.tar.gz

       ã€€ã€€ç„¶åŽè¿›å…¥ gcc-2..3 目录给 gcc 打上补丁

       ã€€ã€€$cd gcc-2..3

       ã€€ã€€$patch -p1< ../gcc-patch/gcc-2..3.-2.patch

       ã€€ã€€$patch -p1< ../gcc-patch/gcc-2..3.-no-fixinc.patch

       ã€€ã€€$patch -p1< ../gcc-patch/gcc-2..3-returntype-fix.patch

       ã€€ã€€echo timestamp > gcc/cstamp-h.in

       ã€€ã€€åœ¨æˆ‘们编译并安装 gcc 前,我们先要改一个文件 $PRJROOT/gcc/config/arm/t-linux,把

       ã€€ã€€TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC

       ã€€ã€€è¿™ä¸€è¡Œæ”¹ä¸º

       ã€€ã€€TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h

       ã€€ã€€ä½ å¦‚果没定义 -Dinhibit,编译时将会报如下的错误

       ã€€ã€€../../gcc-2..3/gcc/libgcc2.c:: stdlib.h: No such file or directory

       ã€€ã€€../../gcc-2..3/gcc/libgcc2.c:: unistd.h: No such file or directory

       ã€€ã€€make[3]: *** [libgcc2.a] Error 1

       ã€€ã€€make[2]: *** [stmp-multilib-sub] Error 2

       ã€€ã€€make[1]: *** [stmp-multilib] Error 1

       ã€€ã€€make: *** [all-gcc] Error 2

       ã€€ã€€å¦‚果没有定义 -D__gthr_posix_h,编译时会报如下的错误

       ã€€ã€€In file included from gthr-default.h:1,

       ã€€ã€€from ../../gcc-2..3/gcc/gthr.h:,

       ã€€ã€€from ../../gcc-2..3/gcc/libgcc2.c::

       ã€€ã€€../../gcc-2..3/gcc/gthr-posix.h:: pthread.h: No such file or directory

       ã€€ã€€make[3]: *** [libgcc2.a] Error 1

       ã€€ã€€make[2]: *** [stmp-multilib-sub] Error 2

       ã€€ã€€make[1]: *** [stmp-multilib] Error 1

       ã€€ã€€make: *** [all-gcc] Error 2

       ã€€ã€€è¿˜æœ‰ä¸€ç§ä¸Ž-Dinhibit同等效果的方法,那就是在你配置configure时多加一个参数-with-newlib,这个选项不会迫使我们必须使用newlib。我们编译了bootstrap-gcc后,仍然可以选择任何c库。

       ã€€ã€€æŽ¥ç€å°±æ˜¯é…ç½®boostrap gcc, 后面要用bootstrap gcc 来编译 glibc 库。

       ã€€ã€€$cd ..; cd build-boot-gcc

       ã€€ã€€$../gcc-2..3/configure --target=$TARGET --prefix=$PREFIX \

       ã€€ã€€>--without-headers --enable-languages=c --disable-threads

       ã€€ã€€è¿™æ¡å‘½ä»¤ä¸­çš„ -target、--prefix 和配置 binutils 的含义是相同的,--without-headers 就是指不需要头文件,因为是交叉编译工具,不需要本机上的头文件。-enable-languages=c是指我们的 boot-gcc 只支持 c 语言。--disable-threads 是去掉 thread 功能,这个功能需要 glibc 的支持。

       ã€€ã€€æŽ¥ç€æˆ‘们编译并安装 boot-gcc

       ã€€ã€€$make all-gcc

       ã€€ã€€$make install-gcc

       ã€€ã€€æˆ‘们来看看 $PREFIX/bin 里面多了哪些东西

       ã€€ã€€$ls $PREFIX/bin

       ã€€ã€€ä½ ä¼šå‘现多了 arm-linux-gcc 、arm-linux-unprotoize、cpp 和 gcov 几个文件。

       ã€€ã€€Gcc-gnu 的 C 语言编译器

       ã€€ã€€Unprotoize-将 ANSI C 的源码转化为 K&R C 的形式,去掉函数原型中的参数类型。

       ã€€ã€€Cpp-gnu的 C 的预编译器

       ã€€ã€€Gcov-gcc 的辅助测试工具,可以用它来分析和优程序。

       ã€€ã€€ä½¿ç”¨ gcc3.2 以及 gcc3.2 以上版本时,配置 boot-gcc 不能使用 --without-headers 选项,而需要使用 glibc 的头文件。

       ã€€ã€€å›žé¡µé¦–

       ã€€ã€€å»ºç«‹ c 库(glibc)

       ã€€ã€€é¦–先解压 glibc-2.2.3.tar.gz 和 glibc-linuxthreads-2.2.3.tar.gz 源代码

       ã€€ã€€$cd $PRJROOT/build-tools

       ã€€ã€€$tar -xvzf glibc-2.2.3.tar.gz

       ã€€ã€€$tar -xzvf glibc-linuxthreads-2.2.3.tar.gz --directory=glibc-2.2.3

       ã€€ã€€ç„¶åŽè¿›å…¥ build-glibc 目录配置 glibc

       ã€€ã€€$cd build-glibc

       ã€€ã€€$CC=arm-linux-gcc ../glibc-2.2.3/configure --host=$TARGET --prefix="/usr"

       ã€€ã€€--enable-add-ons --with-headers=$TARGET_PREFIX/include

       ã€€ã€€CC=arm-linux-gcc 是把 CC 变量设成你刚编译完的boostrap gcc,用它来编译你的glibc。--enable-add-ons是告诉glibc用 linuxthreads 包,在上面我们已经将它放入了 glibc 源码目录中,这个选项等价于 -enable-add-ons=linuxthreads。--with-headers 告诉 glibc 我们的linux 内核头文件的目录位置。

       ã€€ã€€é…ç½®å®ŒåŽå°±å¯ä»¥ç¼–译和安装 glibc

       ã€€ã€€$make

       ã€€ã€€$make install_root=$TARGET_PREFIX prefix="" install

       ã€€ã€€ç„¶åŽä½ è¿˜è¦ä¿®æ”¹ libc.so 文件

       ã€€ã€€å°†

       ã€€ã€€GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a)

       ã€€ã€€æ”¹ä¸º

       ã€€ã€€GROUP ( libc.so.6 libc_nonshared.a)

       ã€€ã€€è¿™æ ·è¿žæŽ¥ç¨‹åº ld 就会在 libc.so 所在的目录查找它需要的库,因为你的机子的/lib目录可能已经装了一个相同名字的库,一个为编译可以在你的宿主机上运行的程序的库,而不是用于交叉编译的。

       ã€€ã€€å›žé¡µé¦–

       ã€€ã€€å»ºç«‹å…¨å¥—编译器(full gcc)

       ã€€ã€€åœ¨å»ºç«‹boot-gcc 的时候,我们只支持了C。到这里,我们就要建立全套编译器,来支持C和C++。

       ã€€ã€€$cd $PRJROOT/build-tools/build-gcc

       ã€€ã€€$../gcc-2..3/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++

       ã€€ã€€--enable-languages=c,c++ 告诉 full gcc 支持 c 和 c++ 语言。

       ã€€ã€€ç„¶åŽç¼–译和安装你的 full gcc

       ã€€ã€€$make all

       ã€€ã€€$make install

       ã€€ã€€æˆ‘们再来看看 $PREFIX/bin 里面多了哪些东西

       ã€€ã€€$ls $PREFIX/bin

       ã€€ã€€ä½ ä¼šå‘现多了 arm-linux-g++ 、arm-linux-protoize 和 arm-linux-c++ 几个文件。

       ã€€ã€€G++-gnu的 c++ 编译器。

       ã€€ã€€Protoize-与Unprotoize相反,将K&R C的源码转化为ANSI C的形式,函数原型中加入参数类型。

       ã€€ã€€C++-gnu 的 c++ 编译器。

       ã€€ã€€åˆ°è¿™é‡Œä½ çš„交叉编译工具就算做完了,简单验证一下你的交叉编译工具。

       ã€€ã€€ç”¨å®ƒæ¥ç¼–译一个很简单的程序 helloworld.c

       ã€€ã€€#include <stdio.h>

       ã€€ã€€int main(void)

       ã€€ã€€{

       ã€€ã€€printf("hello world\n");

       ã€€ã€€return 0;

       ã€€ã€€}

       ã€€ã€€$arm-linux-gcc helloworld.c -o helloworld

       ã€€ã€€$file helloworld

       ã€€ã€€helloworld: ELF -bit LSB executable, ARM, version 1,

       ã€€ã€€dynamically linked (uses shared libs), not stripped

       ã€€ã€€ä¸Šé¢çš„输出说明你编译了一个能在 arm 体系结构下运行的 helloworld,证明你的编译工具做成功了。

       è½¬è½½ä»…供参考,版权属于原作者

Linux下的交叉编译环境设置

       é‡‡ç”¨äº¤å‰ç¼–译的主要原因在于,多数嵌入式目标系统不能提供足够的资源供编译过程使用,因而只好将编译工程转移到高性能的主机中进行。

       linux下的交叉编译环境重要包括以下几个部分:

       1.对目标系统的编译器gcc

       2.对目标系统的二进制工具binutils

       3.目标系统的标准c库glibc

       4.目标系统的linux内核头文件

       äº¤å‰ç¼–译环境的建立步骤

       ä¸€ã€ä¸‹è½½æºä»£ç  下载包括binutils、gcc、glibc及linux内核的源代码(需要注意的是,glibc和内核源代码的版本必须与目标机上实际使用的版本保持一致),并设定shell变量PREFIX指定可执行程序的安装路径。

       äºŒã€ç¼–译binutils 首先运行configure文件,并使用--prefix=$PREFIX参数指定安装路径,使用--target=arm-linux参数指定目标机类型,然后执行make install。

       ä¸‰ã€é…ç½®linux内核头文件

       é¦–先执行make mrproper进行清理工作,然后执行make config ARCH=arm(或make menuconfig/xconfig ARCH=arm)进行配置(注意,一定要在命令行中使用ARCH=arm指定cpu架构,因为缺省架构为主机的cpu架构),这一步需要根据目标机的实际情况进行详细的配置,笔者进行的实验中目标机为HP的ipaq-hp PDA,因而设置system type为SAX0,SAX0 Implementations中选择Compaq iPAQ H/H。

       é…ç½®å®Œæˆä¹‹åŽï¼Œéœ€è¦å°†å†…核头文件拷贝到安装目录: cp -dR include/asm-arm $PREFIX/arm-linux/include/asm cp -dR include/linux $PREFIX/arm-linux/include/linux

       å››ã€ç¬¬ä¸€æ¬¡ç¼–译gcc

       é¦–先运行configure文件,使用--prefix=$PREFIX参数指定安装路径,使用--target=arm-linux参数指定目标机类型,并使用--disable-threads、--disable-shared、--enable-languages=c参数,然后执行make install。这一步将生成一个最简的gcc。由于编译整个gcc是需要目标机的glibc库的,它现在还不存在,因此需要首先生成一个最简的gcc,它只需要具备编译目标机glibc库的能力即可。

       äº”、交叉编译glibc

       è¿™ä¸€æ­¥éª¤ç”Ÿæˆçš„代码是针对目标机cpu的,因此它属于一个交叉编译过程。该过程要用到linux内核头文件,默认路径为$PREFIX/arm-linux/sys-linux,因而需要在$PREFIX/arm-linux中建立一个名为sys-linux的软连接,使其内核头文件所在的include目录;或者,也可以在接下来要执行的configure命令中使用--with-headers参数指定linux内核头文件的实际路径。

       configure的运行参数设置如下(因为是交叉编译,所以要将编译器变量CC设为arm-linux-gcc): CC=arm-linux-gcc ./configure --prefix=$PREFIX/arm-linux --host=arm-linux --enable-add-ons 最后,按以上配置执行configure和make install,glibc的交叉编译过程就算完成了,这里需要指出的是,glibc的安装路径设置为$PREFIXARCH=arm/arm-linux,如果此处设置不当,第二次编译gcc时可能找不到glibc的头文件和库。

       å…­ã€ç¬¬äºŒæ¬¡ç¼–译gcc

       è¿è¡Œconfigure,参数设置为--prefix=$PREFIX --target=arm-linux --enable-languages=c,c++。

       è¿è¡Œmake install。

       åˆ°æ­¤ä¸ºæ­¢æ•´ä¸ªäº¤å‰ç¼–译环境就完全生成了。

       å‡ ç‚¹æ³¨æ„äº‹é¡¹

       ç¬¬ä¸€ç‚¹ã€åœ¨ç¬¬ä¸€æ¬¡ç¼–译gcc的时候可能会出现找不到stdio.h的错误,解决办法是修改gcc/config/arm/t-linux文件,在TARGET_LIBGCC2_CFLAGS变量的设定中增加-Dinhibit_libc和-D__gthr_posix_h。

如何制作arm-linux-gcc编译工具

       ä¸€ã€ä¸‹è½½æºæ–‡ä»¶

       æºä»£ç æ–‡ä»¶åŠå…¶ç‰ˆæœ¬ï¼š

       binutils-2..tar.bz2, gcc-core-4.4.4.tar.bz2 gcc-g++-4.4.4.tar.bz2 Glibc-2.7.tar.bz2 Glibc-ports-2.7.tar.bz2 Gmp-4.2.tar.bz2 mpfr-2.4.0.tar.bz2mpc-1.0.1.tar.gz Linux-2.6..tar.bz2 (由于我在编译出错的过程中,根据出错的信息修改了相关的C代码,故而没有下载相应的补丁)

       ä¸€èˆ¬ä¸€ä¸ªå®Œæ•´çš„交叉编译器涉及到多个软件,主要包括bilinguals、cc、glibc等。其中,binutils主要生成一些辅助工具;gcc是用来生成交叉编译器,主要生成arm-linux-gcc交叉编译工具,而glibc主要提供用户程序所需要的一些基本函数库。

       äºŒã€å»ºç«‹å·¥ä½œç›®å½•

       ç¼–译所用主机型号 fc.i,虚拟机选的是VM7.0,Linux发行版选的是Fedora9,

       ç¬¬ä¸€æ¬¡ç¼–译时用的是root用户(第二次用一般用户yyz), 所有的工作目录都在/home/yyz/cross下面建立完成,首先在/home/yyz目录下建立cross目录,然后进入工作目录,查看当前目录。命令如下:

       åˆ›å»ºå·¥å…·é“¾æ–‡ä»¶å¤¹ï¼š

       [root@localhost cross]# mkdir embedded-toolchains

       ä¸‹é¢åœ¨æ­¤æ–‡ä»¶å¤¹ä¸‹å»ºç«‹å¦‚下几个目录:

       setup-dir:存放下载的压缩包;

       src-dir:存放binutils、gcc、glibc解压之后的源文件;

       Kernel:存放内核文件,对内核的配置和编译工作也在此完成;

       build-dir :编译src-dir下面的源文件,这是GNU推荐的源文件目录与编译目录分离的做法;

       tool-chain:交叉编译工具链的安装位;

       program:存放编写程序;

       doc:说明文档和脚本文件;

       ä¸‹é¢å»ºç«‹ç›®å½•ï¼Œå¹¶æ‹·è´æºæ–‡ä»¶ã€‚

       [root@localhost cross] #cd embedded- toolchains

       [root@localhost embedded- toolchains] #mkdir setup-dir src-dir kernel build-dir tool-chain program doc

       [root@localhost embedded- toolchains] #ls

       build-dir doc kernel program setup-dir src-dir tool-chain

       [root@localhost embedded- toolchains] #cd setup-dir

       æ‹·è´æºæ–‡ä»¶ï¼š

       è¿™é‡Œæˆ‘们采用直接拷贝源文件的方法,首先应该修改setup-dir的权限

       [root@localhost embedded- toolchains] #chmod setup-dir

       ç„¶åŽç›´æŽ¥æ‹·è´/home/yyz目录下的源文件到setup-dir目录中,如下图:

       å»ºç«‹ç¼–译目录:

       [root@localhost setup-dir] #cd ../build-dir

       [root@localhost build -dir] #mkdir build-binutils build-gcc build-glibc

       ä¸‰ã€è¾“出环境变量

       è¾“出如下的环境变量方便我们编译。

       ä¸ºç®€åŒ–操作过程。下面就建立shell命令脚本environment-variables:

       [root@localhost build -dir] #cd ../doc

       [root@localhost doc] #mkdir scripts

       [root@localhost doc] #cd scripts

       ç”¨ç¼–辑器vi编辑环境变量脚本envionment-variables:[root@localhost scripts]

       #vi envionment-variables

       export PRJROOT=/home/yyz/cross/embedded-toolchains

       export TARGET=arm-linux

       export PREFIX=$PRJROOT/tool-chain

       export TARGET_PREFIX=$PREFIX/$TARGET

       export PATH=$PREFIX/bin:$PATH

       æˆªå›¾å¦‚下:

       æ‰§è¡Œå¦‚下语句使环境变量生效:

       [root@localhost scripts]# source ./environment-variables

       å››ã€å»ºç«‹äºŒè¿›åˆ¶å·¥å…·ï¼ˆbinutils)

       ä¸‹é¢å°†åˆ†æ­¥ä»‹ç»å®‰è£…binutils-2..1的过程。

       [root@localhost script] # cd $PRJROOT/src-dir

       [root@localhost src-dir] # tar jxvf ../setup-dir/binutils-2..1.tar.bz2

       [root@localhost src-dir] # cd $PRJROOT/build-dir/build-binutils

       åˆ›å»ºMakefile:

       [root@localhost build-binutils] #../../src-dir/binutils-2..1/configure --target=$TARGET --prefix=$PREFIX

       åœ¨build-binutils目录下面生成Makefile文件,然后执行make,make install,此过程比较缓慢,大约需要一个分钟左右。完成后可以在$PREFIX/bin下面看到我们的新的binutil。

       è¾“入如下命令

       [root@localhost build-binutils]#ls $PREFIX/bin

升级 GLIBC 后想回退,遇到 __resolv_context_ 相关符号报错

       在处理GLIBC升级后回退问题时,遇到了与__resolv_context_相关符号的链接错误。本文将详细分析这一现象及其解决方案。

       首先,升级GLIBC后,若用户希望回退到原有版本,却发现编译出的源码实现sizeof可执行文件和依赖的动态库在链接时遇到错误。这是由于新版GLIBC的libc.so干扰了链接过程。在Ubuntu .服务器上,GLIBC版本为2.,但用户为了运行Open3D,安装了GLIBC 2.。

       当使用新版GLIBC后,GCC在链接时会寻找libc.so,而在PATH环境变量中指定了新的目录,使得GCC在链接时使用了新的libc.so文件。为解决此问题,可以临时使用export命令修改PATH,排除/usr/local/bin。

       链接错误通常与libc.so的加载有关。GCC在链接可执行文件时,会查找依赖的动态库,如OpenCV的libopencv_videoio.a静态库和ffmpeg的动态库。在/etc/ld.so.conf.d/libc.so中,配置了将/usr/local/lib目录作为默认查找目录。使用ldconfig -p验证了这一配置,keepalive源码vue并显示了在旧版本GLIBC中找到的三个库。

       错误符号__resolv_context_get与libresolv.so.2库关联,但实际上这是与符号解析有关的问题。在GLIBC代码中找到了这些符号的描述。为解决此问题,可以修改/usr/local/lib目录为/usr/local/lib-old,并验证先前链接器报告的未找到符号现在位于GLIBC 2.中。

       若希望在回退GLIBC版本时保持可执行文件和动态链接阶段的libc.so不变,需要确保当前GCC使用的是预期的GLIBC版本。正确的卸载和安装GLIBC方式是关键。一种策略是在外部目录构建并安装GLIBC,避免直接修改系统的默认配置。

       在处理已经安装到/usr/local的GLIBC问题时,应谨慎处理,避免影响其他文件或系统稳定。正确的做法是使用与安装配套的卸载工具,或通过目录改名等方法进行回退。本文建议在执行卸载操作时,使用外部目录构建的GLIBC版本,以避免直接在glibc源码目录下执行构建带来的风险。

       总之,升级GLIBC后遇到回退问题时,关键在于理解链接过程中的依赖关系和环境变量的影响,以及采取适当的策略来管理和修改这些依赖,以确保系统稳定性和兼容性。

Linux 调试秘籍深入探索 C++运行时获取堆栈信息和源代码行数的终极指南

       在软件开发的世界里,特别是在C++领域,运行时错误和异常是常见的挑战。这些错误和异常往往需要开发者深入探索、分析和解决。在这个过程中,获取运行时的堆栈信息和代码行数成为了一项至关重要的任务。正如《代码大全》(Code Complete) 中所说:“好的代码是自我解释的。” 但在现实世界中,当面临复杂的、多层次的代码结构时,我们需要更多的上下文信息来理解和解决问题。

       在C++中,获取运行时的堆栈信息和代码行数并不像看上去那么简单。我们常常需要依赖外部工具和库来帮助我们完成这项任务。但是,这并不意味着我们无法在代码内部实现这一功能。通过深入探索和学习,我们可以找到合适的方法和技术来实现这一目标。

       在本文中,我们将探讨如何使用backtrace, dladdr, 和 libbfd 的组合来获取运行时的堆栈信息和代码行数。我们将从底层原理出发,深入分析每个函数和库的工作原理和使用方法。我们将通过实例代码,展示如何整合这些技术来实现我们的目标。

       正如《C++编程思想》(The C++ Programming Language) 中所说:“C++的设计目标是表达直观的设计。” 我们的目标也是通过直观、清晰的代码和解释,帮助读者理解这一复杂但有趣的主题。

       在GCC的源码中,我们可以找到backtrace 和 dladdr 函数的具体实现。这些函数位于 libgcc 和 glibc 中,通过深入分析这些源码,我们可以更好地理解它们的工作原理和限制。

       通过阅读本文,读者将能够了解如何使用backtrace 函数获取当前的堆栈地址,并使用 backtrace_symbols 函数将这些地址转换为人类可读的字符串形式。这些字符串通常包含函数名、偏移量和地址。我们还将讨论如何使用 dladdr 函数解析堆栈地址,获取函数名和所在的动态链接库信息。libbfd 库将用于获取源代码的行数信息。通过详细的代码示例、图表和解释,我们将帮助读者逐步理解和掌握这些技术。

       正如《深入理解计算机系统》中所说:“堆栈跟踪是程序运行时的快照,它展示了函数调用的层次结构和执行路径。” 获取堆栈信息对于调试和优化代码至关重要。

       接下来,我们将深入探讨如何使用backtrace 函数获取堆栈信息。backtrace 是一个强大的工具,它能帮助我们在程序运行时捕获当前的堆栈跟踪信息。

       在获取堆栈信息后,我们将讨论如何解析这些信息,以获取更具体的信息,例如函数名和源代码行数。我们将深入分析 dladdr 函数的工作原理,以及如何使用它解析堆栈地址。此外,我们还将探讨 libbfd 库如何帮助我们从堆栈地址中获取源代码的文件名和行号。

       为了提供一个完整的解决方案,我们将整合所有步骤,展示如何从获取堆栈信息到解析堆栈地址,再到获取源代码行数,形成一个完整的、自动化的解决方案。

       在解决可能出现的问题方面,我们将详细探讨符号缺失、动态链接库的影响、编译器和平台差异以及复杂或模糊的堆栈信息等问题,并提供相应的解决方案。我们的目标是确保实现既准确又完整,能够在各种情况下可靠地工作。

       总结而言,通过综合应用backtrace, dladdr, 和 libbfd 等技术,我们不仅解决了运行时获取堆栈信息和源代码行数的复杂问题,还为读者展示了这些技术的实际应用和深层次原理。在这个过程中,我们不仅学习了技术,更深入探讨了技术背后的原理和思维。