Add C++ support to Makefile, and proof-of-concept simple.cpp example

This is a work in progress based on @mikejac's work.

Missing:
* No 'new' operator.
* I don't think STL is currently supported.
This commit is contained in:
Angus Gratton 2015-08-10 15:51:57 +10:00
parent 372827ac42
commit cc97067fa1
5 changed files with 92 additions and 3 deletions

View file

@ -178,6 +178,9 @@ void xPortSysTickHandle (void)
//OpenNMI(); //OpenNMI();
} }
static bool sdk_compat_initialised;
void sdk_compat_initialise(void);
/* /*
* See header file for description. * See header file for description.
*/ */
@ -186,6 +189,14 @@ portBASE_TYPE xPortStartScheduler( void )
_xt_isr_attach(INUM_SOFT, SV_ISR); _xt_isr_attach(INUM_SOFT, SV_ISR);
_xt_isr_unmask(BIT(INUM_SOFT)); _xt_isr_unmask(BIT(INUM_SOFT));
/* ENORMOUS HACK: Call the sdk_compat_initialise() function.
This can be removed happily once we have open source startup code.
*/
if(!sdk_compat_initialised) {
sdk_compat_initialised = true;
sdk_compat_initialise();
}
/* Initialize system tick timer interrupt and schedule the first tick. */ /* Initialize system tick timer interrupt and schedule the first tick. */
sdk__xt_tick_timer_init(); sdk__xt_tick_timer_init();

View file

@ -220,13 +220,15 @@ $(1)_DEFAULT_ROOT := $(dir $(lastword $(MAKEFILE_LIST)))
$(1)_ROOT ?= $$($(1)_DEFAULT_ROOT) $(1)_ROOT ?= $$($(1)_DEFAULT_ROOT)
$(1)_OBJ_DIR = $(call lc,$(BUILD_DIR)$(1)/) $(1)_OBJ_DIR = $(call lc,$(BUILD_DIR)$(1)/)
### determine source files and object files ### ### determine source files and object files ###
$(1)_SRC_FILES ?= $$(foreach sdir,$$($(1)_SRC_DIR), \ $(1)_SRC_FILES ?= $$(foreach sdir,$$($(1)_SRC_DIR), \
$$(wildcard $$(sdir)/*.c) $$(wildcard $$(sdir)/*.S)) \ $$(wildcard $$(sdir)/*.c) $$(wildcard $$(sdir)/*.S) \
$$(wildcard $$(sdir)/*.cpp)) \
$$($(1)_EXTRA_SRC_FILES) $$($(1)_EXTRA_SRC_FILES)
$(1)_REAL_SRC_FILES = $$(foreach sfile,$$($(1)_SRC_FILES),$$(realpath $$(sfile))) $(1)_REAL_SRC_FILES = $$(foreach sfile,$$($(1)_SRC_FILES),$$(realpath $$(sfile)))
$(1)_REAL_ROOT = $$(realpath $$($(1)_ROOT)) $(1)_REAL_ROOT = $$(realpath $$($(1)_ROOT))
# patsubst here substitutes real component root path for the relative OBJ_DIR path, making things short again # patsubst here substitutes real component root path for the relative OBJ_DIR path, making things short again
$(1)_OBJ_FILES_C = $$(patsubst $$($(1)_REAL_ROOT)%.c,$$($(1)_OBJ_DIR)%.o,$$($(1)_REAL_SRC_FILES)) $(1)_OBJ_FILES_CXX = $$(patsubst $$($(1)_REAL_ROOT)%.cpp,$$($(1)_OBJ_DIR)%.o,$$($(1)_REAL_SRC_FILES))
$(1)_OBJ_FILES_C = $$(patsubst $$($(1)_REAL_ROOT)%.c,$$($(1)_OBJ_DIR)%.o,$$($(1)_OBJ_FILES_CXX))
$(1)_OBJ_FILES = $$(patsubst $$($(1)_REAL_ROOT)%.S,$$($(1)_OBJ_DIR)%.o,$$($(1)_OBJ_FILES_C)) $(1)_OBJ_FILES = $$(patsubst $$($(1)_REAL_ROOT)%.S,$$($(1)_OBJ_DIR)%.o,$$($(1)_OBJ_FILES_C))
# the last included makefile is our component's component.mk makefile (rebuild the component if it changes) # the last included makefile is our component's component.mk makefile (rebuild the component if it changes)
$(1)_MAKEFILE ?= $(lastword $(MAKEFILE_LIST)) $(1)_MAKEFILE ?= $(lastword $(MAKEFILE_LIST))
@ -244,6 +246,12 @@ $$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.c $$($(1)_MAKEFILE) $(wildcard $(ROOT)*
$$($(1)_CC_ARGS) -c $$< -o $$@ $$($(1)_CC_ARGS) -c $$< -o $$@
$$($(1)_CC_ARGS) -MM -MT $$@ -MF $$(@:.o=.d) $$< $$($(1)_CC_ARGS) -MM -MT $$@ -MF $$(@:.o=.d) $$<
$$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.cpp $$($(1)_MAKEFILE) $(wildcard $(ROOT)*.mk) | $$($(1)_SRC_DIR)
$(vecho) "C++ $$<"
$(Q) mkdir -p $$(dir $$@)
$$($(1)_CXX_ARGS) -c $$< -o $$@
$$($(1)_CXX_ARGS) -MM -MT $$@ -MF $$(@:.o=.d) $$<
$$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.S $$($(1)_MAKEFILE) $(wildcard $(ROOT)*.mk) | $$($(1)_SRC_DIR) $$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.S $$($(1)_MAKEFILE) $(wildcard $(ROOT)*.mk) | $$($(1)_SRC_DIR)
$(vecho) "AS $$<" $(vecho) "AS $$<"
$(Q) mkdir -p $$(dir $$@) $(Q) mkdir -p $$(dir $$@)

View file

@ -14,3 +14,18 @@ void IRAM *zalloc(size_t nbytes)
{ {
return calloc(1, nbytes); return calloc(1, nbytes);
} }
extern void (*__init_array_start)(void);
extern void (*__init_array_end)(void);
/* Do things which should be done as part of the startup code, but aren't.
Can be replaced with _start() once we have open source startup code.
*/
void sdk_compat_initialise()
{
/* Call C++ constructors or C functions marked with __attribute__((constructor)) */
void (**p)(void);
for ( p = &__init_array_start; p != &__init_array_end; ++p)
(*p)();
}

View file

@ -0,0 +1,3 @@
# Simple makefile for simple example
PROGRAM=simple
include ../../common.mk

View file

@ -0,0 +1,52 @@
/* A very basic C++ example, really just proof of concept for C++
This sample code is in the public domain.
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
class Counter
{
private:
uint32_t _count;
public:
Counter(uint32_t initial_count)
{
this->_count = initial_count;
printf("Counter initialised with count %ld\r\n", initial_count);
}
void Increment()
{
_count++;
}
uint32_t getCount()
{
return _count;
}
};
static Counter static_counter(99);
void task1(void *pvParameters)
{
Counter local_counter = Counter(12);
while(1) {
Counter &counter = rand() % 2 ? static_counter : local_counter;
counter.Increment();
printf("local counter %ld static counter %ld\r\n", local_counter.getCount(),
static_counter.getCount());
vTaskDelay(100);
}
}
extern "C" void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
printf("SDK version:%s\n", sdk_system_get_sdk_version());
xTaskCreate(task1, (signed char *)"tsk1", 256, NULL, 2, NULL);
}