Discuss here different C compiler set ups, and compiling executables for the ESP8266

User avatar
By joostn
#2560 Hi,

I'm trying to compile a c++ application for the ESP8266. I've set up g++ through 'git clone -b lx106-g++' as explained above.

It's mostly working, except for the fact that constructors of global objects are not being called. For example:
Code: Select allclass TestClass
{
public:
   TestClass()
      : m_a(5) {}
   int m_a;
};

TestClass tc;

extern "C" void user_init(void)
{
 // if I print tc.m_a here, it will show 0 instead of 5.
}


These are my compiler and linker options:
Code: Select all"/opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin/xtensa-lx106-elf-g++"  -Wl,-EL -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -fmessage-length=0 -fverbose-asm -ffunction-sections -fdata-sections  -Iinclude -I../../esp8266/esp_iot_sdk_V0.9.2/include/ -I../../cppcomponents/ -Wall -Wundef -Wno-unused-local-typedefs -Wextra -Wno-unused-parameter -Wno-unused-variable -Wno-unused-but-set-variable -Werror=return-type -Wpointer-arith -D_NDEBUG -O3 --std=c++11 -ftree-ter -Wno-reorder -fno-rtti -fno-exceptions -fno-unwind-tables -fno-threadsafe-statics -fno-stack-protector -c -o build/obj/main.o user/main.cpp
AR build/test1_app.a
LD build/test1.out1
"/opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc" -L../../esp8266/esp_iot_sdk_V0.9.2/lib -L ../../esp8266/esp_iot_sdk_V0.9.2/ld/ -Teagle.app.v6.ld -Wl,--no-check-sections -u call_user_start -Wl,-static -nostdlib  -Xlinker -Map=build/test1.map -Wl,--gc-sections -Wl,--start-group -lc -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lupgrade  build/test1_app.a -Wl,--end-group -o build/test1.out1


If I omit -nostdlib and use -nodefaultlibs, the linker complains about crt1-sim.o and _vectors.o missing.

Can anyone help me out? BTW I don't need the C++ standard libraries, I just need to be able to work with my own C++ classes.

Thanks!
User avatar
By Squonk
#2577 Take a look here:
https://github.com/qca/open-ath9k-htc-f ... s/src/xtos

It looks like there are sources for both crt1-sim.o and _vectors.o

However, even if you don't care about C++ standard libraries, it looks like you are missing some pre-main code to initialize the global objects.
User avatar
By jcmvbkbc
#2579
joostn wrote:It's mostly working, except for the fact that constructors of global objects are not being called.

Right, these constructors are normally called from crtbegin.o/crtend.o, but looks like we should be able to call them ourselves from the user_main.

joostn wrote:If I omit -nostdlib and use -nodefaultlibs, the linker complains about crt1-sim.o and _vectors.o missing.

Right, these defaults are hard-coded in the gcc. We don't need them, because we're not building for sim and exception vector handlers are in the ROM.

joostn wrote:Can anyone help me out? BTW I don't need the C++ standard libraries, I just need to be able to work with my own C++ classes.

Let me look a bit more at our startup sequence...
User avatar
By jcmvbkbc
#2584
jcmvbkbc wrote:
joostn wrote:Can anyone help me out? BTW I don't need the C++ standard libraries, I just need to be able to work with my own C++ classes.

Let me look a bit more at our startup sequence...


Ok, there may be straighter ways of doing that, but the easiest that I've found is that: add the following code to your user_main:
(UPD: the original code did wrong constructors array address calculation, thanks to igrr for pointing it. Below is the fixed version.)

Code: Select allextern void (*__init_array_start)(void);
extern void (*__init_array_end)(void);

static void do_global_ctors(void)
{
        void (**p)(void);
        for (p = &__init_array_start; p != &__init_array_end; ++p)
                (*p)();
}

extern "C" void user_init(void)
{
        do_global_ctors();
}


And the following three lines to your linker script:
Code: Select all--- eagle.app.v6.ld.orig        2014-10-24 16:51:40.000000000 +0300
+++ eagle.app.v6.ld     2014-11-14 02:31:13.658457791 +0300
@@ -96,11 +96,14 @@
     *(.gnu.linkonce.e.*)
     *(.gnu.version_r)
     *(.eh_frame)
+    . = (. + 3) & ~ 3;
     /*  C++ constructor and destructor tables, properly ordered:  */
+    __init_array_start = ABSOLUTE(.);
     KEEP (*crtbegin.o(.ctors))
     KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
     KEEP (*(SORT(.ctors.*)))
     KEEP (*(.ctors))
+    __init_array_end = ABSOLUTE(.);
     KEEP (*crtbegin.o(.dtors))
     KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
     KEEP (*(SORT(.dtors.*)))
Last edited by jcmvbkbc on Fri Nov 21, 2014 3:15 am, edited 1 time in total.