簡體   English   中英

從gcc切換到g ++進行交叉編譯時,CMake鏈接器“未定義的引用”

[英]CMake linker “undefined reference” when switching from gcc to g++ for cross compilation

我有一個C項目,可以成功編譯。 現在,我想在同一項目中使用C ++代碼,因此我將main.c重命名為main.cpp 該項目是針對嵌入式微控制器的,因此我正在使用arm-none-eabi工具鏈進行交叉編譯。

將主文件重命名為.cpp后,出現以下錯誤:

Linking CXX executable discovery_simple_test.elf
/usr/lib/gcc/arm-none-eabi/<long_path>/fpu/libg.a(lib_a-abort.o): In function `abort':
/build/<long_path>/newlib/libc/stdlib/abort.c:63: undefined reference to `_exit'

這是因為某些標准庫不適用於此“裸機”目標。 (請參閱https://stackoverflow.com/a/13237079/507369

這可以通過我的鏈接描述文件解決:

/* Remove information from the standard libraries */
/DISCARD/ :
{
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
}

鏈接器腳本由我的CMake工具鏈文件添加:

INCLUDE(CMakeForceCompiler)

SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_VERSION 1)

# specify the cross compiler
CMAKE_FORCE_C_COMPILER(arm-none-eabi-gcc GNU)
CMAKE_FORCE_CXX_COMPILER(arm-none-eabi-g++ GNU)

SET(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/STM32F407VGTx_FLASH.ld)
SET(COMMON_FLAGS "-mcpu=cortex-m4 -mthumb -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffunction-sections -fdata-sections -g -fno-common -fmessage-length=0")
UNSET(CMAKE_CXX_FLAGS CACHE)
UNSET(CMAKE_C_FLAGS CACHE)
UNSET(CMAKE_EXE_LINKER_FLAGS CACHE)
SET(CMAKE_CXX_FLAGS "${COMMON_FLAGS} -std=c++11" CACHE STRING "" FORCE)
SET(CMAKE_C_FLAGS "${COMMON_FLAGS} -std=gnu99" CACHE STRING "" FORCE)
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections -Wl,-T ${LINKER_SCRIPT}" CACHE STRING "" FORCE)

我的CMakeLists.txt看起來像:

project(discovery_simple_test CXX C ASM)
add_definitions(-DSTM32F407xx)

file(GLOB_RECURSE USER_SOURCES "Src/*.c" "Src/*.cpp")
include_directories(Inc)
add_executable(${PROJECT_NAME}.elf ${USER_SOURCES}  ${LINKER_SCRIPT})

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.map")

當鏈接為C可執行文件時,這可行。 當鏈接為C ++可執行文件時,出現undefined reference錯誤。

更新資料

我看了由CMake組成的確切鏈接器命令,這些命令是:

對於GCC(成功):

/usr/bin/arm-none-eabi-gcc  -mcpu=cortex-m4 -mthumb -mthumb-interwork 
-mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffunction-sections -fdata-sections 
-g -fno-common -fmessage-length=0 -std=gnu99  -Wl,-gc-sections 
-T /path/STM32F407VGTx_FLASH.ld -Wl,
-Map=/path/build/discovery_simple_test.map 
CMakeFiles/discovery_simple_test.elf.dir/Src/main.c.obj 
<list of obj files>  
-o discovery_simple_test.elf libCMSIS.a

對於G ++(錯誤):

/usr/bin/arm-none-eabi-g++   -mcpu=cortex-m4 -mthumb -mthumb-interwork 
-mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffunction-sections -fdata-sections 
-g -fno-common -fmessage-length=0 -std=c++11  -Wl,-gc-sections 
-T /home/niels/Dev/stm32/discovery_simple_test/STM32F407VGTx_FLASH.ld 
-Wl
-Map=/path/discovery_simple_test/build/discovery_simple_test.map 
CMakeFiles/discovery_simple_test.elf.dir/Src/stm32f4xx_hal_msp.c.obj 
CMakeFiles/discovery_simple_test.elf.dir/Src/stm32f4xx_it.c.obj   
CMakeFiles/discovery_simple_test.elf.dir/Src/main.cpp.obj 
<List of obj files>
-o discovery_simple_test.elf libCMSIS.a 

因此,至少傳遞給g ++的參數是我期望的。 我嘗試刪除--gc-sections並添加-nostartfiles,但這沒有幫助。

我不確定是否有更多的CMakeish方法來執行此操作,但是嘗試像這樣添加-specs=nosys.specs您的CMake工具鏈文件:

SET(CMAKE_EXE_LINKER_FLAGS "-specs=nosys.specs, -Wl,--gc-sections -Wl,-T ${LINKER_SCRIPT}" CACHE STRING "" FORCE)

“ nosys”是准系統的通用實現。

https://launchpadlibrarian.net/170926122/readme.txt

鏈接CXX可執行文件Discovery_simple_test.elf /usr/lib/gcc/arm-none-eabi//fpu/libg.a(lib_a-abort.o):在函數abort': /build/<long_path>/newlib/libc/stdlib/abort.c:63: undefined reference to _exit的abort': /build/<long_path>/newlib/libc/stdlib/abort.c:63: undefined reference to

_exit函數是newlib的一部分(請檢查newlib/_exit.c )。 嘗試將以下標志添加到CMAKE_EXE_LINKER_FLAGS :-- --specs=nano.specs

當您在獨立系統上時,將-ffreestanding添加到C和C ++編譯器標志也很有意義。

缺少的功能必須提供newlib與硬件或OS之間的接口,這些被稱為system calls

可以通過添加用戶Cinder Biscuits所述的--specs=nosys.specs命令行選項來解決鏈接問題。 此選項主要提供系統調用的非功能性實現。

但這僅解決了鏈接問題,如果實際上需要newlib的功能,則需要提供系統調用的實現。

此處可以找到開發系統調用的指南。

對於STM32微控制器,ST提供了一個文件syscalls.c作為其STM32CubeF4軟件包的一部分。 可以在Projects/STM32F4-Discovery/Examples/BSP/SW4STM32/的包中找到該文件。 通過將此文件添加到項目中,可以提供所有syscall的實現,並且可以使用newlib。

對於像STM32這樣的小型微控制器,應使用newlib nano,因為它要小得多。 這可以通過添加--specs=nano.specs命令行參數來實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM