stm32 cube に作成してもらった makefile を使用して c++ のプログラムをコンパイルできるようにする ( memo )

こんにちは。

最近毎日外に出ると蒸し風呂かって言いたくなるくらいの暑さですが、皆様いかがお過ごしでしょうか?

体調管理はしっかり気を付けてやっていきましょう。(自戒)

 

最近、マイクロマウスの迷路のソフトをc++で少し書いていたので、マイコンでもc++が動くようにしたいというところからこの話はスタートしました。

今回の記事では私がnone-eabi-g++,makefile を使用してすべての.c,.cppファイルをコンパイルするまでのやり方を書き残しておこうと思い書くものになります。

所々抜けている点や間違えている点があるかもしれません。ご愛顧でお願いします。また、ご指摘していただけるばと思います。

さて、まずはstm32cube からコードをはいてもらいましょう!

 

そしたら makefile を開いてください。

今回はすべてのファイルを一括でg++でコンパイルをしてしまうということなので

#######################################
# binaries
#######################################
BINPATH =
PREFIX = arm-none-eabi-
CC = $(PREFIX)g++
AS = $(PREFIX)g++ -x assembler-with-cpp
CP = $(PREFIX)objcopy
AR = $(PREFIX)ar
SZ = $(PREFIX)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S

のようにしてgccのところをg++に変えてしまいます。

その後、ソース管理のところに

CPP_SOURCES = \

というものを作成してcppソース置き場を作りましょう。

そしたら次にコンパイルオプションの追加を行います。

CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall
-fdata-sections -ffunction-sections -std=c++11

std=c++11でコンパイルをしたかったためこのようにしました。必要なもののオプションを通せば大丈夫だと思います。

続いてobjectに追加して

# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o)))
vpath %.cpp $(sort $(dir $(CPP_SOURCES)))
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
 
$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
  $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.cpp=.lst)) $< -o $@

また、c言語と同じように、コンパイルをするときのルール?も決めましょう。

 

ここまでやったらcpp_sourseのところにc++のソースファイルを置いてあげればコンパイルをすることが可能になりました。

以上でmakefileの操作は終了になります。

 

ここから先はまった点になります。

一つ目 printf が使えなくなった。

先日の記事で記載した方法でそのまま使用をしようとしたところ使うことができずになぜかと考えたり調べたりしたところ、

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
void __io_putchar(uint8_t ch) {
HAL_UART_Transmit(&huart1, &ch, 1, 1);
}
 

はだめじゃん、__GNUC__はgccに定義されているものじゃんということになり、

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
void __io_putchar(uint8_t ch) {
HAL_UART_Transmit(&huart1, &ch, 1, 1);
}
#ifdef __cplusplus
}
#endif

のようにc言語としてコンパイルしろというマクロを使うことで使用可能にしました。

 

次にerror_handler()のwarningがたくさんおきました。

それはchar*型の関数の引数は関数内で値の変更ができるから推奨しないよということでした。これにはすべてのhファイル,関数の引数を const char*とすることで解決します。

また、main.hも上記に挙げたマクロが使用されていないため自分で書いておくと安全かもしれないです。

 

最後に

 なにか質問等ございましたらコメントに書いていただければわかる内容であれば答えます。間違いなどがあれば教えていただければ幸いです。