[英]CMake: handle linking of shared library with static libraries
对于我的项目,我希望能够将核心c ++库构建为静态库,但是将主JNI(Java glue)编译为共享库(需要在运行时由JVM加载)。 在伪代码中,这将是:
project(foo CXX)
add_library(foo1 foo1.cxx)
add_library(foo2 foo2.cxx)
add_library(foojni SHARED foojni.cxx)
target_link_libraries(foojni LINK_PRIVATE foo1 foo2)
现在在x86_64上,它失败并显示以下错误消息:
relocation R_X86_64_32 against `.rodata' cannot be used when making a shared object; recompile with -fPIC
显然,简单的解决方法是:
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
但是,对于我的用户,我更喜欢一种侵入性较小的解决方案,我想:
if(BUILD_JNI)
if(NOT BUILD_SHARED_LIBS)
if(CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_ARCHITECTURE STREQUAL "x86_64") # FIXME !!
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
endif()
endif()
endif()
当然,以下行不起作用(没有CMAKE_ARCHITECTURE
这样的东西)。
if(CMAKE_ARCHITECTURE STREQUAL "x86_64") # FIXME !!
由于检测架构看起来很难( 参见参考资料),即使我能够这样做,我也不知道ppc64el,mips或m68k的要求是什么(在这里插入任何奇特的系统)。 所以我想知道是否有一种简单的方法来查询cmake:
我知道:
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
但正如上面的链接所解释的,这不适用于交叉编译。
更新:问题显然不是如何设置-fPIC
(或等效)编译器标志,但何时需要设置它。
您可以将与位置无关的代码设置为与全局相对的库的属性
project(foo CXX)
add_library(foo1 foo1.cxx)
set_property(TARGET foo1 PROPERTY POSITION_INDEPENDENT_CODE ON)
add_library(foo2 foo2.cxx)
set_property(TARGET foo2 PROPERTY POSITION_INDEPENDENT_CODE ON)
add_library(foojni SHARED foojni.cxx)
target_link_libraries(foojni LINK_PRIVATE foo1 foo2)
所以我终于继续前进,只是这样实现:
# Expose a way to pass -fPIC to static libs of gdcm core, while still build wrapped language as shared lib:
if(NOT DEFINED GDCM_USE_PIC_FOR_STATIC_LIBS)
if(GDCM_WRAP_JAVA)
if(NOT BUILD_SHARED_LIBS)
if(CMAKE_COMPILER_IS_GNUCXX)
set(GDCM_USE_PIC_FOR_STATIC_LIBS ON)
endif()
endif()
endif()
endif()
if(GDCM_USE_PIC_FOR_STATIC_LIBS)
if(BUILD_SHARED_LIBS)
message(FATAL_ERROR "Invalid configuration for static/shared lib")
else()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
endif()
这解决了:
最后,作为用户仍然覆盖默认行为(在x86_64
和x86
上验证)的一种方式,我在顶层添加了:
if(NOT DEFINED GDCM_USE_PIC_FOR_STATIC_LIBS)
所以仍然可以编译:
$ cmake -DGDCM_USE_PIC_FOR_STATIC_LIBS:BOOL=OFF ...
这应该处理未经测试的疯狂系统( powerpc
, sparc64
...)
正如nktiwari所说,您可以(并且应该)使用库属性:
set_property(TARGET my_lib PROPERTY POSITION_INDEPENDENT_CODE ON)
然后,要检测64位编译,只需使用以下(惯用)CMake测试:
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
# ...
endif()
这给出了类似的东西:
if(BUILD_JNI AND (NOT BUILD_SHARED_LIBS) AND CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set_property(TARGET my_lib PROPERTY POSITION_INDEPENDENT_CODE ON)
endif()
endif()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.