在 C 语言中使用 Rust 代码和 CMake 时出现链接错误

Linking error when using Rust code in C with CMake

提问人:p3zhy 提问时间:5/20/2023 更新时间:5/20/2023 访问量:128

问:

在 C 中使用 Rust 代码和 CMake 时出现链接问题。

我正在尝试使用 CMake 将一些 Rust 代码合并到我的 C 项目中。我已经成功编译了 Rust 代码,生成为 Rust 静态库。我在 CMake 配置中将此库传递给链接器。但是,当我尝试编译 C 项目时,遇到以下错误:librust_lib.a

未定义对rust_function

以下是我的项目结构和配置的摘要:

toolchain-gcc.cmake:

这是 CMake 用于设置 GCC 工具链的配置文件。它设置与交叉编译环境相关的各种选项和变量。

# Configures CMake for using GCC

set(CMAKE_SYSTEM_NAME           Generic)
find_program(CMAKE_C_COMPILER   ${CROSS_COMPILE}gcc)
find_program(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++)
find_program(CMAKE_READELF      ${CROSS_COMPILE}readelf)

set(CMAKE_EXECUTABLE_SUFFIX_ASM .elf)
set(CMAKE_EXECUTABLE_SUFFIX_C .elf)
set(CMAKE_EXECUTABLE_SUFFIX_CXX .elf)

execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE gcc_version OUTPUT_STRIP_TRAILING_WHITESPACE)

    set(abi_options -mcpu=cortex-a5 -mtune=generic-armv7-a -mthumb -mfpu=neon-vfpv4
        -mfloat-abi=hard -mno-unaligned-access)
    set(partial_link_options)
    set(libc_file_name ${CMAKE_CURRENT_SOURCE_DIR}/components/newlib/armca5/libc.a)
    set(libm_file_name ${CMAKE_CURRENT_SOURCE_DIR}/components/newlib/armca5/libm.a)

    # specify the location of the Rust library file rust_lib.a
    set(rust_lib ${CMAKE_CURRENT_SOURCE_DIR}/rust_lib.a)

if(CONFIG_ENABLE_GCC_LTO)
    set(lto_compile_option -flto -ffat-lto-objects)
    set(lto_link_option -flto)
endif()

add_compile_options(${abi_options} -g -Os ${lto_compile_option}
    -Wall
    -fno-strict-aliasing
    -ffunction-sections -fdata-sections
)
add_link_options(${abi_options} -Os ${lto_link_option})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-exceptions -fno-rtti -fno-threadsafe-statics")

# GNU ar will alreay create index
set(CMAKE_C_ARCHIVE_FINISH "")
set(CMAKE_CXX_ARCHIVE_FINISH "")

if(WITH_WERROR)
    add_compile_options(-Werror)
endif()

if(WITH_LINK_CREF)
    set(link_cref_option -Wl,-cref)
endif()

set(multilib_opions ${abi_options})
if((${gcc_version} VERSION_GREATER 8) AND (CONFIG_CPU_ARM_CA5))
    set(multilib_opions -march=armv7-a+neon-vfpv4 -mthumb -mfloat-abi=hard)
endif()
execute_process(COMMAND ${CMAKE_C_COMPILER} ${multilib_opions} --print-file-name libgcc.a
    OUTPUT_VARIABLE libgcc_file_name
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

CMakeLists.txt:

这是项目的主要 CMake 配置文件。它包括 toolchain-gcc.cmake 文件并设置项目构建过程。

include(toolchain-gcc.cmake)
cmake_minimum_required(VERSION 3.13)

# Use a global property to collect all application libraries
define_property(GLOBAL PROPERTY app_libraries
    BRIEF_DOCS "app libraries"
    FULL_DOCS "app libraries"
)

# Other configuration options...

# "all_libs" is a target to link all app libraries
set(target all_libs)
set(all_libs_out ${out_lib_dir}/all_libs.a)
get_property(app_libraries GLOBAL PROPERTY app_libraries)

# Append the rust library to the list of application libraries
# to ensure it is linked during the build process
list(APPEND app_libraries ${libc_file_name} ${libm_file_name} ${libgcc_file_name} ${QL_LIBS_PATH} ${rust_lib})
add_custom_command(OUTPUT ${all_libs_out}
    COMMAND python3 ${groupgen_py} --base ${BINARY_TOP_DIR} ${all_libs_out} ${app_libraries}
    DEPENDS ${groupgen_py} ${app_libraries}
    WORKING_DIRECTORY ${BINARY_TOP_DIR}
)
add_custom_target(build_${target} DEPENDS ${all_libs_out})
add_library(${target} STATIC IMPORTED GLOBAL)
set_target_properties(${target} PROPERTIES IMPORTED_LOCATION ${all_libs_out})
add_dependencies(${target} build_${target})

rust_lib/lib.rs:

这是包含 .rust_function()

#[no_mangle]
pub extern "C" fn rust_function() {
    // Rust function implementation...
}

rust_lib/Cargo.toml:

这是 Rust 库的 Cargo 清单文件。

[lib]
name = "rust_lib"
crate-type = ["staticlib"]

# Other Rust configuration options...

main.h:

这是 main.c 的头文件,它声明了rust_function()

void rust_function();

main.c:

这是调用 .rust_function()

#include "main.h"

int main() {
    // Other code...

    rust_function();

    // Other code...

    return 0;
}

尽管成功编译了 Rust 代码并将库传递给我的 CMake 配置中的链接器,但我在编译 C 项目时遇到了以下错误:librust_lib.a

未定义对rust_function

为了进一步研究,我使用该命令来验证 Rust 对象文件 () 中存在的符号,并且它确实包含rust_function符号。nm -gClibrust_lib.a

我不确定为什么链接器找不到对rust_function的引用。我是否遗漏了任何其他配置?

c gcc rust cmake linker-错误

评论

0赞 Tsyvarev 5/20/2023
include(toolchain-gcc.cmake)- 这是在 CMake 中包含工具链文件的错误方法。正确的方法是将工具链文件的路径分配给变量:cmake.org/cmake/help/latest/manual/...CMAKE_TOOLCHAIN_FILE。工具链将在第一次调用时激活。project()
1赞 Finomnis 5/20/2023
如果使用环境变量集进行编译,则实际的链接器调用是什么?库会链接吗?VERBOSE=1
0赞 p3zhy 5/20/2023
谢谢你的评论。感谢您的反馈。在尝试该选项时,我观察到实际的链接器调用不包括库。VERBOSE=1librust_lib.a

答: 暂无答案