gcc/g++ flags

gcc/g++ flags

-c

只编译源文件,不链接

-nostdinc, -nostdinc++

-nostdinc ignores standard C include directories
-nostdinc++ ignores standard C++ include directories

gcc -nostdinc -I/custom/include/path/goes/here
ref:

  • https://stackoverflow.com/questions/2988779/gcc-how-to-ignore-standard-include-paths

-fvisibility

-fvisibility=default|internal|hidden|protected
gcc的visibility是说,如果编译的时候用了这个属性,那么动态库的符号都是hidden的,除非强制声明。

ref:

  • http://blog.csdn.net/topasstem8/article/details/6736976

-fabi-version

-fabi-version=n是GCC编译器的一个选项,用于指定C++函数调用的ABI(应用程序二进制接口)版本。ABI定义了函数调用的细节,包括参数传递方式、返回值处理方式、异常处理等。

在不同版本的GCC中,C++函数调用的ABI可能会有变化。为了确保在不同版本的编译器和平台上都能够正确解析函数调用,可以使用-fabi-version=n选项指定ABI版本。下面是一些示例:

指定ABI版本为4:
g++ -fabi-version=4 -o test.o -c test.cpp
指定ABI版本为6:
g++ -fabi-version=6 -o test.o -c test.cpp
指定ABI版本为11:
g++ -fabi-version=11 -o test.o -c test.cpp
请注意,不同版本的GCC支持的ABI版本可能会有所不同。例如,GCC 9之前的版本只支持ABI版本2和3,而GCC 9及以后的版本支持ABI版本2、3、4、6、7、8、9、10和11。因此,在使用-fabi-version=n选项时,需要根据实际情况选择合适的ABI版本。

另外,需要注意的是,在使用-fabi-version=n选项时,需要确保所有编译器使用相同的ABI版本。如果不同编译器使用不同的ABI版本,可能会导致函数调用的错误或异常。

link flags

–whole-archive , --no-whole-archive

注:ld 参数, 需要加 -Wl
–whole-archive 可以把 在其后面出现的静态库包含的函数和变量输出到动态库
–no-whole-archive 则关掉这个特性

ref:

  • https://www.cnblogs.com/JimmyTY/p/5856217.html
  • https://stackoverflow.com/questions/805555/ld-linker-question-the-whole-archive-option

–start-group, --end-group

It is for resolving circular dependences between several libraries (listed between -( and -))

ref:

  • https://stackoverflow.com/questions/5651869/gcc-what-are-the-start-group-and-end-group-command-line-options
  • https://stackoverflow.com/questions/35966243/how-do-you-pass-the-start-group-and-end-group-flags-to-gcc-when-using-scons

-as-needed

这个选项时表明编译某个库或者可执行文件时所有用到的库都需要 “-l” 来指定,否则会报错。比如liba.so用到了libm.so, 可执行文件B用到了liba.so. 如果不加该选项,我们编译liba.so的时候,可以不指定 -lm, 而编译B的时候,同时指定-lm -la,但其实这种方式不是很合理,所以最好是谁用到的库,谁指定。编译B的时候我只知道用到了liba.so, 而可能我不知道liba.so用到了哪些库。所以,我们编译的时候最好都加上这个选项,谁用到的库谁指定

-rpath, $ORIGIN

ref:

注:
如果在rpath或runpath中使用了$ORIGIN, 若程序启动时设置了LD_LIB_PATH,将不会有用。
参考文章

For security reasons, when running an executable with elevated privileges (such as setuid, setgid, special capabilities, etc.), the search path list is different than normal: LD_LIBRARY_PATH is ignored, as well as any path in rpath or runpath that contains $ORIGIN.

-Wl,–copy-dt-needed-entries

背景问题:

libpthread.so.0: error adding symbols: DSO missing from command line

The DSO missing from command line message will be displayed when the linker does not find the required symbol with it’s normal search but the symbol is available in one of the dependencies of a directly specified dynamic library

推荐正确解法:
You should solve this problem by making sure that all libraries that are needed to satisfy the needed symbols are directly specified on the linker command line. Also keep in mind that order often matters.

参考文章:

-fvisibility

一般来说,只有需要导出的函数、变量和类才应该在动态库的接口中可见。使用-fvisibility=hidden选项可以将所有符号的可见性设置为默认不可见,只有明确指定为导出的符号才会在动态库的接口中可见,以此来减小动态库的大小和提高运行效率。使用-fvisibility=default选项可以将所有符号的可见性设置为默认可见,这是默认的可见性设置。

导出函数和变量
在动态库的头文件中,将需要导出的函数和变量用__attribute__((visibility("default")))声明为可见的符号,如下所示:

// 在头文件中声明函数和变量
extern "C" {
  __attribute__((visibility("default"))) void foo();
  __attribute__((visibility("default"))) int bar;
}

然后在编译动态库时,使用-fvisibility=hidden选项将所有符号的可见性设置为默认不可见,只有声明为可见的符号才会在动态库的接口中可见,如下所示:

gcc -shared -fPIC -fvisibility=hidden -o libmylib.so mylib.cpp

使用版本脚本可以更细粒度地控制可见性,可以将需要导出的符号显式地列出来。在编译动态库时,使用-Wl,--version-script=name.map

-Wl,–version-script=name.map

-Wl,–version-script=name.map 选项指定符号版本文件,明确指定要导出的符号。这样可以确保在不同版本的gcc上都能正确链接

  • CMake 使用示例:
    在CMakeLists.txt中添加以下代码:
# 生成动态库的版本脚本
configure_file(name.map.in name.map @ONLY)

# 编译动态库
add_library(mylib SHARED mylib.cpp)

# 链接动态库时指定版本脚本
set_target_properties(mylib PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/name.map")

在项目目录中创建一个name.map.in文件,内容如下:

{
  global:
    my_function;
  local:
    *;
};

这是一个版本脚本模板,用于指定需要导出的符号(此处的my_function是一个示例,你需要根据你的动态库的符号来修改)。
使用@ONLY标记的configure_file命令会将${CMAKE_CURRENT_BINARY_DIR}/name.map.in文件中的变量替换为具体的值,并生成${CMAKE_CURRENT_BINARY_DIR}/name.map文件。

  • SCons 使用示例:
    在SConstruct文件中添加以下代码:
# 生成动态库的版本脚本
env.Command('name.map', 'name.map.in', Copy('$TARGET', '$SOURCE'))

# 编译动态库
env.SharedLibrary('mylib', 'mylib.cpp')

# 链接动态库时指定版本脚本
env.Append(LINKFLAGS=['-Wl,--version-script=name.map'])

同样,在项目目录中创建一个name.map.in文件,内容如上述CMake示例中的name.map.in文件


references

  • https://www.cnblogs.com/dkblog/archive/2012/04/01/2428859.html
  • https://stackoverflow.com/questions/3375697/useful-gcc-flags-for-c
  • https://blog.csdn.net/langzijing/article/details/78555812
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值