关于静态编译(一)

一般C/C++语言的编译,我还是喜欢使用automake,虽然它缺少通配符的支持,但其支持Makefile的原生语法以及一旦生成了Makefile,在任意有Makefile的目录修改Makefile.am之后都可以直接make;且结合libtool之后,动态库和静态库可以随心编译;这个是cmake不能比的,但cmake也有其优点,比如通配等。

这里不是比较automake和cmake,但在工作当中,当一个三方库(sse_pb)既有动态库,又有静态库时,我们使用-lsse_pb连接时,系统会默认使用动态库,但我们需要优先使用静态库链接时, automake方式比较简单,但对于cmake,这里提供3种办法:

1.使用GCC编译参数

我们可以使用GCC的编译参数-Wl,-Bstatic-Wl,-Bdynamic来实现指定优先静态编译:

find_package(PkgConfig)
pkg_check_modules(brpc REQUIRED IMPORTED_TARGET brpc)
pkg_search_module(sse_pb REQUIRED sse_pb)
add_library(basic_search SHARED)
target_link_libraries(basic_search
  PRIVATE
  basic_search_common
  basic_search_util

...

  PUBLIC
  PkgConfig::brpc
  -Wl,-Bstatic
   ${sse_pb_LIBRARIES}
  -Wl,-Bdynamic
   )

值得注意的是 pkg_check_modules 会将 pc 文件内的链接 -lsse_pb 预先生成 /usr/lib64/libsse_pb.so 形式,导致即使添加GCC参数也不会生效。所以正确的方式是使用 pkg_search_module 来生成cmake的宏变量,一般存在两组值:

  • 用于普通情况, pkg-config 在使用--libs 选项调用时提供的信息,如<XXX> = <prefix>

  • 用于 pkg-config 在额外添加--static 选项调用时提供的信息 (<XXX> = <prefix>_STATIC)

对应的宏变量有下列这些:

<XXX>_FOUND:如果模块存在,则设置为 1
<XXX>_LIBRARIES:只有库 (没有 "-l")
<XXX>_LINK_LIBRARIES:库及其绝对路径
<XXX>_LIBRARY_DIRS:库的路径 (没有 "-L")
<XXX>_LDFLAGS:所有必需的链接器标志
<XXX>_LDFLAGS_OTHER:所有其他链接器标志
<XXX>_INCLUDE_DIRS:预处理器标记'-I'(没有'-I')
<XXX>_CFLAGS:所有必需的 cflags
<XXX>_CFLAGS_OTHER:其他编译器标志
<YYY>_VERSION:模块版本
<YYY>_PREFIX:模块的前缀目录
<YYY>_INCLUDEDIR:包含模块的目录
<YYY>_LIBDIR:模块的 Lib 目录

如上述 ${sse_pb_LIBRARIES} 的设置,就是将 sse_pb 库以静态优先的方式链接起来。

2.使用CMAKE_FIND_LIBRARY_SUFFIXES

我们还可以使用 find_library ,通过改变查找 .a 文件的顺序来获得静态文件优先规则,如下所示:

if (WIN32 OR MSVC)
   set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
elseif (UNIX)
   # 仅查找静态库,强制后缀为 .a
   set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")

   # 如果只是优先查找静态库,保证 .a 后缀在前面即可,把默认的后缀加上
   # set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
endif()

find_library(sse_pb_lib sse_pb)
target_link_libraries(basic_search
   ${sse_pb_lib}
)

3.写死路径

在这种 set_property 方式下,主要依赖路径:

add_library(sse_pb STATIC IMPORTED)
set_property(TARGET sse_pb PROPERTY IMPORTED_LOCATION /path/to/libsse_pb.a)
target_link_libraries(basic_search sse_pb)

其中 /path/to/libsse_pb.a 就可以随意发挥了。

从上可以看出,最灵活也是最优雅的还是第一种方式,可以依赖pkg-config建立很好的环境变量,从而进行静态编译。

Monthly Archives

Pages

Powered by Movable Type 7.9.4

About this Entry

This page contains a single entry by Cnangel published on March 7, 2023 4:39 PM.

在rhel安装高版本nodejs was the previous entry in this blog.

关于静态编译(二) is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.