引言
编译器是我们开发人员与机器指令之间的翻译,现在编译器越来越优化,而且基于一些开源的编译器项目(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_PATH
,CPLUS_INCLUDE_PATH
,OBJC_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时写在程序内的
运行时动态库的搜索路径
动态库的搜索路径搜索的先后顺序是:
- 编译目标代码时指定的动态库搜索路径;
- 环境变量
LD_LIBRARY_PATH
指定的动态库搜索路径; - 配置文件
/etc/ld.so.conf
中指定的动态库搜索路径; - 默认的动态库搜索路径
/lib
; - 默认的动态库搜索路径
/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