CMake交叉编译:如何为静态库中间目标添加符号?
问题背景
我正在进行交叉编译,通过CMake将多个汇编文件打包为静态库libtop.a,CMake配置如下:
add_library(top STATIC /path/to/one.S /path/to/two.S ... /path/to/ten.S )
CMake会将每个汇编文件单独编译为中间目标文件(路径类似<build_dir>/path/to/top.dir/.../one.S.obj),再用ar打包成最终的静态库。
现在需要为其中部分中间文件(比如ten.S.obj)添加额外符号,期望执行类似以下的objcopy命令:
add_custom_command( TARGET <???ten.S.obj???> POST_BUILD COMMAND "${CMAKE_OBJCOPY}" ARGS "--add-symbol" "ten=.text:__ten_aarch64,function,global" "$<TARGET_FILE:<???ten.S???>>" )
但无法找到对应的中间目标名称,直接使用make help查到的名称也无效(提示No TARGET)。
直接对libtop.a执行objcopy会导致大量重复定义错误,因为objcopy会修改库中所有符号表。我曾尝试将ten.S单独拆分为OBJECT库再加入静态库,但CMake不允许为OBJECT库添加PRE_BUILD/PRE_LINK/POST_BUILD命令,报错如下:
CMake Error at ./path/to/CMakeLists.txt:46 (add_custom_command): Target "ten" is an OBJECT library that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.
解决方案1:生成修改后的目标文件再纳入静态库
直接通过add_custom_command控制单个汇编文件的编译与修改流程,生成带额外符号的目标文件后,再将其加入静态库:
# 指定源文件路径 set(TEN_SRC "/path/to/ten.S") # 定义修改后的目标文件输出路径 set(TEN_OBJ_MODIFIED "${CMAKE_CURRENT_BINARY_DIR}/ten_modified.obj") # 自定义命令:先编译源文件为临时目标,再用objcopy添加符号,最后清理临时文件 add_custom_command( OUTPUT ${TEN_OBJ_MODIFIED} COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} ${CMAKE_ASM_FLAGS} -c ${TEN_SRC} -o ${TEN_OBJ_MODIFIED}.tmp COMMAND ${CMAKE_OBJCOPY} --add-symbol "ten=.text:__ten_aarch64,function,global" ${TEN_OBJ_MODIFIED}.tmp ${TEN_OBJ_MODIFIED} COMMAND ${CMAKE_COMMAND} -E remove ${TEN_OBJ_MODIFIED}.tmp DEPENDS ${TEN_SRC} VERBATIM ) # 构建静态库时,替换原ten.S为修改后的目标文件 add_library(top STATIC /path/to/one.S /path/to/two.S ... ${TEN_OBJ_MODIFIED} )
解决方案2:利用PRE_LINK钩子修改静态库中的目标文件
先正常编译所有源文件生成中间目标,在静态库打包前修改指定的中间文件:
add_library(top STATIC /path/to/one.S /path/to/two.S ... /path/to/ten.S ) # 获取ten.S对应的中间目标文件路径 get_property(TEN_SRC_FILE TARGET top PROPERTY SOURCES) list(FILTER TEN_SRC_FILE INCLUDE REGEX "ten\\.S$") get_source_file_property(TEN_OBJ_PATH ${TEN_SRC_FILE} OBJECT_OUTPUTS) # 在静态库打包前执行objcopy修改目标文件 add_custom_command( TARGET top PRE_LINK COMMAND ${CMAKE_OBJCOPY} --add-symbol "ten=.text:__ten_aarch64,function,global" ${TEN_OBJ_PATH} VERBATIM )
说明:该方法依赖CMake的
OBJECT_OUTPUTS属性来获取中间文件路径,不同CMake版本可能需要适配路径匹配逻辑。
内容的提问来源于stack exchange,提问作者Lance E.T. Compte
相关产品推荐
相关产品推荐

