LPCXpresso IDEでのC++コードサイズ肥大化の対策
前回ポストしたLPCXpresso用のXBee APIモードライブラリですが、コードサイズが100KB程度にまで肥大化することが分かりました。組み込み用としてはでかすぎます。mbedで前回のサンプルと同様のコードをコンパイルするとバイナリサイズは31KBに収まります。
コードサイズが大きくなるトリガーは何となくわかりました。どうも、親にvirtual関数を持つクラスのインスタンスを生成すると、本来必要ないと思われるライブラリの関数がごっそりとリンクされるのが原因と思われます。以下の通り、実験をしてみました。
2011/10/16追記:
audinさんコメントをいただき、viurual関数を持つクラスを使った際のコードサイズ肥大の問題が解決し、サイズを21KBにまで圧縮できるようになりました。
最小構成でコンパイル
まず、以下のように14行目でXBeeクラスのインスタンスだけを生成するサンプルをコンパイルします。
#ifdef __USE_CMSIS #include "LPC17xx.h" #endif #include "Xbee.h" uint8_t atISCmd[] = {'I', 'S'}; // Forces a read of all enabled digital and analog input lines uint8_t atD1Cmd[] = {'D', '1'}; // DIO1 control uint8_t atDBCmd[] = {'D', 'B'}; // Received Signal Strength uint8_t cmdVal0[] = {0}; // Clear RSSI register uint8_t cmdVal4[] = {4}; // Digital output, low uint8_t cmdVal5[] = {5}; // Digital output, High XBee xbee(2); XBeeAddress64 remoteAddress(0x0013A200, 0x406B7111); // Specify your XBee address /*-- Create instance of Command and Response object --*/ // Remote ATIS command to read ADC value (ADC3 is enabled by X-CTU tool) //RemoteAtCommandRequest remoteSampleRequest(remoteAddress, atISCmd); int main(void) { while(1) { } return 0 ; }
Debugビルドですが、この段階でコードサイズが80KB程度になってしまいます。ここで、リンカスクリプトをいじってやるとコードサイズを削減できることを発見。LPCXpresso IDEのリンカスクリプトは通常自動生成ですが、プロパティ設定から;
MCU C++ Linker → Target → Manage Linker Scriptのチェックを外してやると、独自のスクリプトを書くことができます。自動生成される3本のスクリプトをマージし、以下のライブラリ定義部分を書き換えます。
オリジナル:
GROUP(libgcc.a libc.a libstdc++.a libm.a libcr_newlib_nohost.a crti.o crtn.o crtbegin.o crtend.o)
書き換え:
GROUP(libgcc.a libc.a libm.a libcr_newlib_nohost.a crti.o crtn.o crtbegin.o crtend.o)
要は、libstdc++.aを削除します。
再度ビルドすると、コードサイズが12,552byteにまで縮小します。mapファイルを見ると、以下の関数がリンクされていることが分かります。
.debug_frame 0x00000000 0x2884 .debug_frame 0x00000000 0xc8 ./src/Serial.o .debug_frame 0x000000c8 0xac ./src/Timer.o .debug_frame 0x00000174 0x1714 ./src/XBee.o .debug_frame 0x00001888 0x6c ./src/cr_cpp_config.o .debug_frame 0x000018f4 0x158 ./src/cr_startup_lpc176x.o .debug_frame 0x00001a4c 0x64 ./src/main.o .debug_frame 0x00001ab0 0x4c C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_pinsel.o) .debug_frame 0x00001afc 0x16c C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_timer.o) .debug_frame 0x00001c68 0x2f8 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_uart.o) .debug_frame 0x00001f60 0x38 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(system_LPC17xx.o) .debug_frame 0x00001f98 0xa0 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_clkpwr.o) .debug_frame 0x00002038 0x20 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_libcfg_default.o) .debug_frame 0x00002058 0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(bpabi.o) .debug_frame 0x000020a8 0x288 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(unwind-arm.o) .debug_frame 0x00002330 0xf4 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(pr-support.o) .debug_frame 0x00002424 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_divdi3.o) .debug_frame 0x00002460 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_udivdi3.o) .debug_frame 0x0000249c 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_udivsi3.o) .debug_frame 0x000024bc 0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-abort.o) .debug_frame 0x000024e4 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-init.o) .debug_frame 0x00002510 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-malloc.o) .debug_frame 0x00002540 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mallocr.o) .debug_frame 0x0000257c 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memcpy.o) .debug_frame 0x000025ac 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mlock.o) .debug_frame 0x000025dc 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-sbrkr.o) .debug_frame 0x00002608 0xc0 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-signal.o) .debug_frame 0x000026c8 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-signalr.o) .debug_frame 0x00002704 0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-freer.o) .debug_frame 0x00002754 0x64 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-reent.o) .debug_frame 0x000027b8 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_cr_sbrk.o) .debug_frame 0x000027e4 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_exit.o) .debug_frame 0x00002804 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(getpid.o) .debug_frame 0x00002824 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(kill.o) .debug_frame 0x00002844 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_cr_check_heap.o) .debug_frame 0x00002864 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-errno.o)
Virtual関数を親に持つクラスのインスタンスを生成してみる
サンプル20行目をコメントアウトして再度ビルドすると、以下のようにリンカーでエラーが発生します。
./src/XBee.o:(.rodata._ZTV11XBeeRequest[vtable for XBeeRequest]+0x8): undefined reference to `__cxa_pure_virtual'
./src/XBee.o:(.rodata._ZTV11XBeeRequest[vtable for XBeeRequest]+0xc): undefined reference to `__cxa_pure_virtual'
virutal関連の参照が解決しないと文句を言っているように見えます。ここで、リンカスクリプトのGROUP定義を元に戻して再度コンパイルすとエラーが解消しますが、コードサイズが一気に増大します。
text data bss dec hex filename
86876 1424 2368 90668 1622c LPC1769CppTest.axf
再度mapファイルを見ると、リンクしている関数が山のように増えています。
.debug_frame 0x00000000 0x4288 .debug_frame 0x00000000 0xc8 ./src/Serial.o .debug_frame 0x000000c8 0xac ./src/Timer.o .debug_frame 0x00000174 0x1714 ./src/XBee.o .debug_frame 0x00001888 0x6c ./src/cr_cpp_config.o .debug_frame 0x000018f4 0x158 ./src/cr_startup_lpc176x.o .debug_frame 0x00001a4c 0x64 ./src/main.o .debug_frame 0x00001ab0 0x4c C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_pinsel.o) .debug_frame 0x00001afc 0x16c C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_timer.o) .debug_frame 0x00001c68 0x2f8 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_uart.o) .debug_frame 0x00001f60 0x38 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(system_LPC17xx.o) .debug_frame 0x00001f98 0xa0 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_clkpwr.o) .debug_frame 0x00002038 0x20 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_libcfg_default.o) .debug_frame 0x00002058 0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(bpabi.o) .debug_frame 0x000020a8 0x288 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(unwind-arm.o) .debug_frame 0x00002330 0xf4 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(pr-support.o) .debug_frame 0x00002424 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_divdi3.o) .debug_frame 0x00002460 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_udivdi3.o) .debug_frame 0x0000249c 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_udivsi3.o) .debug_frame 0x000024bc 0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-abort.o) .debug_frame 0x000024e4 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-init.o) .debug_frame 0x00002510 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-malloc.o) .debug_frame 0x00002540 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mallocr.o) .debug_frame 0x0000257c 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memcpy.o) .debug_frame 0x000025ac 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mlock.o) .debug_frame 0x000025dc 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-sbrkr.o) .debug_frame 0x00002608 0xc0 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-signal.o) .debug_frame 0x000026c8 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-signalr.o) .debug_frame 0x00002704 0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-freer.o) .debug_frame 0x00002754 0x64 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-reent.o) .debug_frame 0x000027b8 0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(pure.o) .debug_frame 0x000027e0 0x90 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_terminate.o) .debug_frame 0x00002870 0x54 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_call.o) .debug_frame 0x000028c4 0xd0 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_exception.o) .debug_frame 0x00002994 0x64 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_arm.o) .debug_frame 0x000029f8 0x40 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(fundamental_type_info.o) .debug_frame 0x00002a38 0x70 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(pointer_type_info.o) .debug_frame 0x00002aa8 0x80 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_alloc.o) .debug_frame 0x00002b28 0x90 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(tinfo.o) .debug_frame 0x00002bb8 0xd0 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(class_type_info.o) .debug_frame 0x00002c88 0xb4 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_personality.o) .debug_frame 0x00002d3c 0x60 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_throw.o) .debug_frame 0x00002d9c 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_globals.o) .debug_frame 0x00002dcc 0x6c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_catch.o) .debug_frame 0x00002e38 0x40 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_aux_runtime.o) .debug_frame 0x00002e78 0xac c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(si_class_type_info.o) .debug_frame 0x00002f24 0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(bad_cast.o) .debug_frame 0x00002f74 0x78 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(pbase_type_info.o) .debug_frame 0x00002fec 0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(bad_typeid.o) .debug_frame 0x0000303c 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(vterminate.o) .debug_frame 0x0000306c 0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_type.o) .debug_frame 0x00003094 0x48c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(cp-demangle.o) .debug_frame 0x00003520 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_cr_sbrk.o) .debug_frame 0x0000354c 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_exit.o) .debug_frame 0x0000356c 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(getpid.o) .debug_frame 0x0000358c 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(kill.o) .debug_frame 0x000035ac 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_cr_check_heap.o) .debug_frame 0x000035cc 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-errno.o) .debug_frame 0x000035ec 0x48 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fputc.o) .debug_frame 0x00003634 0x40 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fputs.o) .debug_frame 0x00003674 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fvwrite.o) .debug_frame 0x000036b0 0x58 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fwrite.o) .debug_frame 0x00003708 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memchr.o) .debug_frame 0x00003734 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memcmp.o) .debug_frame 0x00003760 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memmove.o) .debug_frame 0x0000378c 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memset.o) .debug_frame 0x000037b8 0x48 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-putc.o) .debug_frame 0x00003800 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-realloc.o) .debug_frame 0x00003820 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-reallocr.o) .debug_frame 0x0000385c 0x64 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-sprintf.o) .debug_frame 0x000038c0 0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-strcmp.o) .debug_frame 0x000038f0 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-strcpy.o) .debug_frame 0x00003910 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-strlen.o) .debug_frame 0x00003930 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-strncmp.o) .debug_frame 0x0000395c 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-svfprintf.o) .debug_frame 0x00003998 0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-syswrite.o) .debug_frame 0x000039c0 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-wbuf.o) .debug_frame 0x000039fc 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-writer.o) .debug_frame 0x00003a28 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-wsetup.o) .debug_frame 0x00003a54 0x68 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-dtoa.o) .debug_frame 0x00003abc 0x40 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fflush.o) .debug_frame 0x00003afc 0x114 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-findfp.o) .debug_frame 0x00003c10 0x54 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fwalk.o) .debug_frame 0x00003c64 0x98 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-locale.o) .debug_frame 0x00003cfc 0x34 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-makebuf.o) .debug_frame 0x00003d30 0x244 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mprec.o) .debug_frame 0x00003f74 0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-s_fpclassify.o) .debug_frame 0x00003f9c 0x80 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-stdio.o) .debug_frame 0x0000401c 0x68 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-svfiprintf.o) .debug_frame 0x00004084 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-callocr.o) .debug_frame 0x000040b0 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-closer.o) .debug_frame 0x000040dc 0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fclose.o) .debug_frame 0x00004118 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fstatr.o) .debug_frame 0x00004144 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-isattyr.o) .debug_frame 0x00004170 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-lseekr.o) .debug_frame 0x0000419c 0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-readr.o) .debug_frame 0x000041c8 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(close.o) .debug_frame 0x000041e8 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(fstat.o) .debug_frame 0x00004208 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(isatty.o) .debug_frame 0x00004228 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(lseek.o) .debug_frame 0x00004248 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(read.o) .debug_frame 0x00004268 0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(write.o)
さっき追加したlibstdc++.aの関数に加えて、libc.aの関数も大量に増えています。殆どはstdio関連の関数で、「こんなの使ってないよ」なやつらばかりです・・
解決策(2012/10/16追記)
audinさんより、__cxa_pure_virtualに対するハンドラーをプロジェクト内で作ってやればリンカーエラーを解消できるとのコメントをいただきました。具体的には、以下のコードをcppファイルのどこかに追加します(今回はcr_startup_lpc176x.cppに追加)。
extern "C" void __cxa_pure_virtual() { while (1); }
__cxa_pure_virtual() はpure virutal function(純粋仮想関数)が呼ばれた場合のエラーハンドラーで、従来はOS環境(ランタイムライブラリ)にて提供されるものと理解。そのため、デフォルトの状態ではランタイム全体がリンクされてしまいコードサイズが肥大化するのですが、__cxa_pure_virtual() を単独で定義してしまえば、「最小構成でコンパイル」したときと同じ関数のみがリンクされるにとどまり、コードサイズを劇的に圧縮できました。
__cxa_pure_virtual() の処理は無限ループですが、純粋仮想関数が呼ばれた時点でプログラムが間違っていますので、エラー処理としてはこれでよいかと。
最終的なコードサイズは以下です:
text data bss dec hex filename
20688 1304 520 22512 57f0 LPC1769cpp_Xbee.axf
リンカー関連の設定はデフォルトでOKで、Manage Linker Scriptを有効にしても上記以上にコードサイズが増えることはありませんでした。また、- nostartfilesオプションの有無によるサイズの変化はありませんでした。
まとめ
最初はあきらめモードでしたが、コメントをいただくことによって実用的なコードサイズに圧縮できることが分かりました。そのため、LPCXpresso IDEでのC++プロジェクトの開発は、設定に手間がかかりますが十分可能と思います。
移植したXBee APIモードライブラリはもともとArduino用に開発されたもので、32KB以下のメモリで動かなければならないです。前回のサンプルと同じコードはArduinoでビルドできなかった(コンパイルエラーを解消できず)のですが、APIモードを使ったサンプルをビルドするとコードサイズは6KB程度でした。ArduinoもgccのC++を使っているわけですが半分以下に収まる感じです。対策後のコードでも、「この関数いるのか」みたいなのがいくつかリンクされているように見え、それらを最小限の薄い関数に置き換えるなどすれば、Arduinoのコードサイズに近づけることができるのかもしれません。
このサイトの情報(マイコン風雲録)だとAVRよりLPC2388の方がコードサイズが小さいとあるので、まだ改善の余地はありそうですが、今回はここまでで一段落とします。
上記の実験から、無償版のLPCXpresso IDEでは、マニュアル設定によってC++のプロジェクトを作成・ビルドは可能ですが、親に仮想関数を持つクラスを使うと、一気にコードサイズが増加します。なんとなく、C++で使うnewlibが組み込み用に最適化されていないように思うのですが、原因は分かりません。
この差はライブラリや開発環境の最適化度合いの差でしょうか。LPCXpresso LPC1769でもCの環境だと、FatFsを組み込んだコードで6KB、uIPを使ったコードが9KB程度に収まりますので(Releaseビルドにて)、LPC1769のコードサイズがAVRに比べて明らかに大きいということはないように思います(同一条件の比較ではないですが)。
C++を使いたい場合、Sourcery g++あたりを持ってきて自前で環境を作ったほうがよいということか・・
参考情報
- C++のスタートアップ(C++でカーネルコードを書きたい) -- プログラマ未満さん
- What is the purpose of __cxa_pure_virtual? -- stackOverflow
最近のコメント