开发中常见的编译器技巧

引言

编译器是我们开发人员与机器指令之间的翻译,现在编译器越来越优化,而且基于一些开源的编译器项目(gcc,clang)等,相继出现不同platform下的编译器。
此外,各种芯片、开发板层出不穷,各个商业公司都针对自己出产的开发板定制特定的编译链条。例如华为hisi系列的himix100中提供的编译链中,包括编译器,链接器,打包器之外,还提供了nm,gdb,gcov,gprof等等开发工具。
这篇文章将主要将开发工作中与编译器(这篇文章中不作特殊说明,指的是gnu gcc编译器)相关的一些options和配置参数进行总结,方便在后面的项目遇到相似的问题进行查阅与借鉴。

编译常见问题

包含静态库中所有符号的option

编译器编译动态库或者运行程序的时候,会对依赖的静态库中进行基于.o的选择,但是有的时候我们希望我们编译的动态库能够包含所有的函数实现给用户使用。gcc中的链接控制选项-Wl,--whole-archive xxxxx_lib -Wl,--no-whole-archive就可以实现类似功能。

target_link_libraries(xxxx_export 
            PRIVATE "-Wl,--whole-archive" $<TARGET_FILE:xxxxx_lib>
                    "-Wl,--no-whole-archive -Wl,--exclude-libs,ALL")

其他可能问题

--exclude-libs does not work for static libraries affected by the --whole-archive option.

  • --exclude-libs creates a list of static library paths and does library lookups in this list.
  • --whole-archive splits the static libraries that follow it into separate objects. As a result, lld no longer sees static libraries among linked files and does no --exclude-libs lookups.

Solution

The proposed solution is to make --exclude-libs consider object files too. When lld finds an object file it checks whether this file originates from an archive and, if so, looks the archive up in the --exclude-libs list.

Reference: https://reviews.llvm.org/D39353

编译运行查找头文件和库的顺序

gcc 在编译时如何去寻找所需要的头文件:

  • 所以header file的搜寻会从-I开始
  • 然后找gcc的环境变量 C_INCLUDE_PATHCPLUS_INCLUDE_PATHOBJC_INCLUDE_PATH
  • 再找内定目录
    • /usr/include
    • /usr/local/include

gcc的一系列自带目录
CPLUS_INCLUDE_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.9.4/include:/usr/include/c++/4.9.4

库文件

编译的时候:

  • gcc会去找-L
  • 再找gcc的环境变量LIBRARY_PATH
  • 再找内定目录
    • /lib/lib64
    • /usr/lib/usr/lib64
    • /usr/local/lib/usr/local/lib64

这是当初compile gcc时写在程序内的

运行时动态库的搜索路径

动态库的搜索路径搜索的先后顺序是:

  1. 编译目标代码时指定的动态库搜索路径;
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径;
  4. 默认的动态库搜索路径/lib
  5. 默认的动态库搜索路径/usr/lib

动态库中的static变量

In all cases, static global variables (or functions) are never visible from outside a module (dll/so or executable). The C++ standard requires that these have internal linkage, meaning that they are not visible outside the translation unit (which becomes an object file) in which they are defined.

windows编译

在windows常用的编译器是VS里面的cl编译器。我们要实现上述
cmake使用cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=TRUE

Enable this boolean property to automatically create a module definition (.def) file with all global symbols found in the input .obj files for a SHARED library on Windows. The module definition file will be passed to the linker causing all symbols to be exported from the .dll. For global data symbols, __declspec(dllimport) must still be used when compiling against the code in the .dll. All other function symbols will be automatically exported and imported by callers. This simplifies porting projects to Windows by reducing the need for explicit dllexport markup, even in C++ classes.

This property is initialized by the value of the CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS variable if it is set when a target is created.

Reference: WINDOWS_EXPORT_ALL_SYMBOLS

windows下路径长度不能太长

error MSB3491: Could n ot write lines to file

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值