对于我的项目,我希望能够将核心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 !!
由于检测架构似乎很难(see),即使我能够这样做,我也不知道对ppc64el,mips或m68k有什么要求(在这里插入任何奇特的系统)。所以我想知道是否有一种简单的方法来查询cmake:
我知道:
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
但正如上面的链接所解释的那样,这不适用于交叉编译。
更新:问题显然不是如何来设置-fPIC
(或等效的)编译器标志,但何时我需要设置它。
答案 0 :(得分:2)
您可以将与位置无关的代码设置为与全局
对立的库的属性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)
请参阅What is the idiomatic way in CMAKE to add the -fPIC compiler option?
答案 1 :(得分:2)
所以我终于继续前进,只是这样实现:
# 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
...)
答案 2 :(得分:0)
正如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()