当前位置:   article > 正文

buildroot external-toolchain的一次踩坑经历_fortran support is not selected but is available i

fortran support is not selected but is available in external toolchain

 buildroot external-toolchain的一次踩坑经历

## 背景介绍

一次使用buildroot进行交叉编译,toolchain选择如下:

  •  External toolchain
  •  Custom toolchain
  •  Pre-installed toolchain
  •  Toolchain Path:/mnt/xxxo/swgcc530-sw6-cross
  •  Toochain prefix : sw_64sw6-sunway-linux-gnu

buildroot会把指定路径下的交叉编译工具拷贝到buildroot的output/host目录下。配置完成后开始编译,编译到某个软件时报错:

  1. ```
  2. sw_64sw6-sunway-linux-gnu-g++:error trying to exec 'cc1plus' :execvp: No such file or directory
  3. ```


显而易见报错说的是没有命令cc1plus。在buildroot的output/host目录下搜索,果然没有cc1plus。有点奇怪,难道官方提供的交叉编译工具没有cc1plus?于是又在/mnt/xxx/swgcc530-sw6-cross路径下搜索cc1plus,结果搜索到了。难道是拷贝出了问题?于是开始进行验证。

## 问题验证

拷贝一份buildoort,进入新的buildroot目录,执行 *make clean && make* ,重新编译。当跑到“ >>> toolchain-external-custom Copying external toolchain sysroot to staging...”时,发现有如下报错:

  1. ```
  2. rsync: send_files failed to open "/usr/sw/swgcc530-sw6-cross/usr/libexec/gcc/sw_64sw6-sunway-linux-gnu/5.3.0/cc1plus" : Permission denied
  3. ```


我的工具链路径在/mnt/xxx/swgcc530-sw6-cross,buildroot应该去拷贝我指定路径下的文件,为什么会去拷贝“/usr/sw/swgcc530-sw6-cross”下的文件呢?因为文件/usr/sw/swgcc530-sw6-cross/usr/libexec/gcc/sw_64sw6-sunway-linux-gnu/5.3.0/cc1plus 的所有者是root,所以我去编译时会报Permission denied错。

## 调试

首先,查看buildroot中拷贝交叉工具的相关代码。经查询,拷贝工具的代码位于文件:toolchain/toolchain-external/pkg-toolchain-external.mk

  1. define TOOLCHAIN_EXTERNAL_INSTALL_SYSROOT_LIBS
  2.         $(Q)SYSROOT_DIR="$(call toolchain_find_sysroot,$(TOOLCHAIN_EXTERNAL_CC))" ; \
  3.         ARCH_SYSROOT_DIR="$(call toolchain_find_sysroot_test,$(TOOLCHAIN_EXTERNAL_CC) $(TOOLCHAIN_EXTERNAL_CFLAGS))" ; \
  4.         ARCH_LIB_DIR="$(call toolchain_find_libdir,$(TOOLCHAIN_EXTERNAL_CC) $(TOOLCHAIN_EXTERNAL_CFLAGS))" ; \
  5.         SUPPORT_LIB_DIR="" ; \
  6.         echo "toolchain external cc : $(TOOLCHAIN_EXTERNAL_CC)" ; \
  7.         echo "arch sysroot dir: $${ARCH_SYSROOT_DIR}" ; \
  8.         if test `find $${ARCH_SYSROOT_DIR} -name 'libstdc++.a' | wc -l` -eq 0 ; then \
  9.                 LIBSTDCPP_A_LOCATION=$$(LANG=C $(TOOLCHAIN_EXTERNAL_CC) $(TOOLCHAIN_EXTERNAL_CFLAGS) -print-file-name=libstdc++.a) ; \
  10.                 if [ -e "$${LIBSTDCPP_A_LOCATION}" ]; then \
  11.                         SUPPORT_LIB_DIR=`readlink -f $${LIBSTDCPP_A_LOCATION} | sed -r -e 's:libstdc\+\+\.a::'` ; \
  12.                 fi ; \
  13.         fi ; \
  14.         if [ "$${SYSROOT_DIR}" == "$${ARCH_SYSROOT_DIR}" ] ; then \
  15.                 ARCH_SUBDIR="" ; \
  16.         elif [ "`dirname $${ARCH_SYSROOT_DIR}`" = "`dirname $${SYSROOT_DIR}`" ] ; then \
  17.                 SYSROOT_DIR_DIRNAME=`dirname $${SYSROOT_DIR}`/ ; \
  18.                 ARCH_SUBDIR=`echo $${ARCH_SYSROOT_DIR} | sed -r -e "s:^$${SYSROOT_DIR_DIRNAME}(.*)/$$:\1:"` ; \
  19.         else \
  20.                 ARCH_SUBDIR=`echo $${ARCH_SYSROOT_DIR} | sed -r -e "s:^$${SYSROOT_DIR}(.*)/$$:\1:"` ; \
  21.         fi ; \
  22.         $(call MESSAGE,"Copying external toolchain sysroot to staging...") ; \
  23.         $(call copy_toolchain_sysroot,$${SYSROOT_DIR},$${ARCH_SYSROOT_DIR},$${ARCH_SUBDIR},$${ARCH_LIB_DIR},$${SUPPORT_LIB_DIR})
  24. endef


从代码可以看出,首先通过toolchain_find_sysroot获取交叉编译工具的路径,然后通过一些内部处理获取不同目录的路径,最后将四个路径作为参数传入函数copy_toolchain_sysroot,由函数copy_toolchain_sysroot执行拷贝操作。

经查询,函数copy_toolchain_sysroot位于文件 toolchain/helpers.mk。

  1. ```
  2. copy_toolchain_sysroot = \
  3.         SYSROOT_DIR="$(strip $1)"; \
  4.         ARCH_SYSROOT_DIR="$(strip $2)"; \
  5.         ARCH_SUBDIR="$(strip $3)"; \
  6.         ARCH_LIB_DIR="$(strip $4)" ; \
  7.         SUPPORT_LIB_DIR="$(strip $5)" ; \
  8.         for i in etc $${ARCH_LIB_DIR} sbin usr usr/$${ARCH_LIB_DIR}; do \
  9.                 if [ ! -d $${ARCH_SYSROOT_DIR}/$$i ] ; then \
  10.                         continue ; \
  11.                 fi ; \
  12.                 if [ "$$i" = "usr" ]; then \
  13.                         rsync -au --chmod=u=rwX,go=rX --exclude 'locale/' \
  14.                                 --include '/libexec*/' --exclude '/lib*/' \
  15.                                 $${ARCH_SYSROOT_DIR}/$$i/ $(STAGING_DIR)/$$i/ ; \
  16.                 else \
  17.                         rsync -au --chmod=u=rwX,go=rX --exclude 'locale/' \
  18.                                 $${ARCH_SYSROOT_DIR}/$$i/ $(STAGING_DIR)/$$i/ ; \
  19.                 fi ; \
  20.         done ; \
  21.         ........ ##后面的代码没有贴
  22. ```


从代码可以看出,cc1plus位于路径/xxx/usr/libexec 下,rsync将路径“ARCH_SYSROOT_DIR” 指定目录下的文件拷贝至路径“STAGING_DIR”相同的目录下。路径“ARCH_SYSROOT_DIR”是传入的第二个参数,路径"STAGING_DIR"通过文件package/Makefile.in可知为:

  1. ```
  2. STAGING_SUBDIR = $(GNU_TARGET_NAME)/sysroot
  3. STAGING_DIR    = $(HOST_DIR)/$(STAGING_SUBDIR)
  4. ```


即output/host/sw_64sw6-buildroot-linux-gnu/sysroot. 
这时回到文件 toolchain/toolchain-external/pkg-toolchain-external.mk,发现第二个参数的路径为:

  1. ```
  2. ARCH_SYSROOT_DIR="$(call toolchain_find_sysroot,$(TOOLCHAIN_EXTERNAL_CC)
  3. ```


该变量是将参数"TOOLCHAIN_EXTERNAL_CC"传入函数toolchain_find_sysroot,由函数toolchain_find_sysroot去获取toolchain的绝对路径。TOOLCHAIN_EXTERNAL_CC 为指定路径的external-toolchain下的gcc。

函数toolchain_find_sysroot位于相同文件下:

  1. ```
  2. define toolchain_find_sysroot
  3. $$(printf $(call toolchain_find_libc_a,$(1)) | sed -r -e 's:(usr/)?lib(32|64)?([^/]*)?/([^/]*/)?libc\.a::')
  4. endef
  5. define toolchain_find_libdir
  6. $$(printf $(call toolchain_find_libc_a,$(1)) | sed -r -e 's:.*/(usr/)?(lib(32|64)?([^/]*)?(/[^/]*)?)/libc.a:\2:')
  7. endef
  8. # Returns the location of the libc.a file for the given compiler + flags
  9. define toolchain_find_libc_a
  10. $$(readlink -f $$(LANG=C $(1) -print-file-name=libc.a))
  11. endef
  12. ```


看代码可知,路径的获取方式为:
1. 首先获取指定gcc连接时用到的库libc.a的绝对路径;
2. 获取该库指向的真实路径;
3. 通过sed过滤该路径中的"/usr/lib(32|64)/libc.a"字符,获取工具链的一级路径。

找到了路径的获取方式,手动执行命令"/mnt/xxx/swgcc530-sw6-cross/bin/sw_64sw6-sunway-linux-gnu-gcc -print-file-name=libc.a",发现输出如下:"/usr/sw/swgcc530-sw6-cross/usr/lib/libc.a" .看来找到原因了,竟然是sw-gcc的锅。sw-gcc 用到的库的路径竟然是/usr/sw/swgcc530-sw6-cross/,而不是sw-gcc所在的路径。

## 总结


在buildroot使用external-toolchain并指定toolchain的路径时,首先执行下xx-gcc -print-file-name=library,查看下gcc所查找的路径,确定和预想的路径是否一致,如果不一致,就需要改变toolchain的路径。

 


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/224437
推荐阅读
相关标签
  

闽ICP备14008679号