大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是MCUXpresso IDE下添加C++源文件進SDK工程編譯的方法。
最近有客戶反映在MCUXpresso IDE下的SDK工程里添加一些.cpp后綴的源文件,該.cpp源文件里的函數無法被工程正常編譯鏈接,只能把工程抽離出來然后利用MCUXpresso工具鏈配合makefile手動編譯才行。
痞子衡在MCUXpresso IDE下快速試了這個問題,確實如客戶反映那樣,無法直接編譯.cpp文件,這跟痞子衡在IAR/Keil MDK工程下經驗不一致,在IAR/Keil MDK工程里添加.cpp源文件和.c源文件流程是一樣的,IDE角度不需要什么特殊設置。
MCUXpresso IDE功能其實是非常強大的,痞子衡不相信它無法直接編譯.cpp文件,因此折騰了一番,終於能正常編譯.cpp文件了,特此將經驗分享給大家。
一、准備實驗環境
首先需要准備好測試環境,包含必要的軟件,痞子衡的環境如下:
二、查看工程Build信息
用MCUXpresso IDE打開經典的 \SDK_2.8.2_EVK-MIMXRT1010\boards\evkmimxrt1010\demo_apps\hello_world 例程,嘗試Build一次,可以在Console窗口看到全部的Build信息:
其實掃一眼Console窗口里的信息對於理解MCUXpresso IDE工程流程很有幫助,其實總結下來就是如下三步分離的命令,只不過IDE自動按序執行了這些分離的命令:
**** Build of configuration Debug for project evkmimxrt1010_hello_world ****
make -r -j4 all
// 步驟一:激活C編譯器按序編譯工程內所有源文件(.c)生成對應重定向文件(.o)
Invoking: MCU C Compiler
arm-none-eabi-gcc -std=gnu99 -D__REDLIB__ // 略去一些工程宏、文件路徑
Building file: ../source/hello_world.c
...
Finished building: ../source/hello_world.c
// 步驟二:激活鏈接器鏈接所有重定向文件(.o)生成可執行文件(.axf)
Building target: evkmimxrt1010_hello_world.axf
Invoking: MCU Linker
arm-none-eabi-gcc -nostdlib -Xlinker // 略去一些參數 -T evkmimxrt1010_hello_world_Debug.ld -o "evkmimxrt1010_hello_world.axf" // 略去所有.o文件
Finished building target: evkmimxrt1010_hello_world.axf
// 步驟三:執行post build將可執行文件(.axf)轉成鏡像文件(.bin)
make --no-print-directory post-build
Performing post-build steps
arm-none-eabi-size "evkmimxrt1010_hello_world.axf"; # arm-none-eabi-objcopy -v -O binary "evkmimxrt1010_hello_world.axf" "evkmimxrt1010_hello_world.bin" ;
Build Finished. 0 errors, 0 warnings. (took 15s.851ms)
三、添加c++源文件編譯報錯
為了測試方便,痞子衡直接寫了個簡單的sw_delay()軟延時函數,放到如下sw_delay.cpp/h源文件中,這兩個新增源文件被放在了\MCUXpressoIDE_11.2.0_4120\workspace\evkmimxrt1010_hello_world\source 目錄下,然后在工程hello_world.c文件里增加一句sw_delay()的調用代碼。
////////////////sw_delay.cpp////////////////
#include "sw_delay.h"
void sw_delay(uint32_t n)
{
while (n != 0U)
{
n--;
}
}
////////////////sw_delay.h////////////////
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
void sw_delay(uint32_t n);
#if defined(__cplusplus)
}
#endif
現在開始重新Build加了sw_delay.cpp文件的工程,得到如下錯誤,這個錯誤就是找不到sw_delay()函數定義,因為sw_delay()函數代碼被放在.cpp文件中(如果是放在.c文件中,編譯一切正常),翻看全部編譯log,並沒有找到關於sw_delay.cpp文件的編譯信息,看起來就像是.cpp文件被自動忽略了。
四、讓MCUXpresso IDE正確編譯C++文件
4.1 激活C++編譯器
在第二節里我們分析過Build信息,對於.c文件的編譯都是通過激活MCU C Compiler來實現的,現在.cpp文件被自動忽略了,估計是沒有使能C++編譯器,那我們來開啟一下C++編譯器,在.project文件中增加一句代碼即可,具體如下:
那句開啟C++編譯器的代碼是立刻生效的,不需要關掉重開IDE工程。現在讓我們再次Build工程,此時編譯log里已經有了sw_delay.cpp的身影,似乎大功告成了。
4.2 為C++鏈接器指明鏈接文件
事情沒有那么簡單,雖然.cpp文件能夠編譯了,但工程最終Build發生了更多錯誤,log里信息上來看是鏈接階段找不到代碼里調用的一些c標准庫函數以及鏈接文件里定義的一些段名和stack名等,看起來是鏈接文件有問題。
打開工程屬性設置,在C/C++ Build的Settings下面可以看到激活C++編譯器后,新增了MCU C++ Compiler選項,並且MCU C Linker選項升級成了MCU C++ Linker選項,但是MCU C++ Linker選項里沒有指明Linker Script(本來MCU C Linker選項里有鏈接文件),這時候我們只要勾選Manage linker script,便可以設好鏈接文件。
Apply屬性設置之后,再次重編工程,終於看到0 errors, 0 warnings了,為了確保萬一,可以在map文件里查看是否有sw_delay()函數,存在即說明.cpp文件確實被正常編譯鏈接了。
4.3 為C++編譯器設置引用路徑和宏(可選)
最后還需要提醒一下,如果cpp文件也依賴一些路徑和宏,需要把這些路徑和宏填到MCU C++ Compiler選項對應設置里,默認路徑和宏定義都是空的。
至此,MCUXpresso IDE下添加C++源文件進SDK工程編譯的方法痞子衡便介紹完畢了,掌聲在哪里~~~
歡迎訂閱
文章會同時發布到我的 博客園主頁、CSDN主頁、知乎主頁、微信公眾號 平台上。
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。