Mbed forum

Linking mbed C++ library with C source code

(Christopher Koch) #1

I have a development kit whose firmware was developed using standard C source code. From what I can tell the mbed-client-c code doesn’t provide the full mbed client but only part of the solution. So, I will need to used the standard mbed-client for my solution. This however builds a C++ library. I have tried various ways to link the C++ library with the C source code but I always get the same error indicating the functions calls to the library are not referenced. I am currently just trying to link a basic C++ library I created to test the process. I am using Eclipse IDE on a Windows 8 64 bit machine.

I am extremely new to understanding make files and how they operate so I know I am missing a step somewhere. Has anyone had any luck linking the C++ mbed-client with C source code? Could you give me any linking tips?

Thank you, Chris

(Brian Jang) #2

=> i took my guess form this text " get the same error indicating the functions calls to the library are not referenced"

if you add new module in yotta_module then you should make “source” folder. if not yotta couldn’t any object and linking all them (even if your source is in the yotta_module)

for ex :
your_module_dir

  • your_module_dir : header file will be here
  • source : copy your source file to this “source” folder
    — your_src_folder_1
    — your_src_folder_2
    — your_src_folder_n
(Jan Jongboom) #3

If you want to use a C++ library from C, you’ll need a wrapper that exposes a C API. Something like:

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

Given that that’s not included in mbed-client, you’ll need to write some code yourself here.

You’ll also need to use g++ as linker, not gcc.

(Christopher Koch) #4

brianJang and janjongboom,

Thank you both for your replies. I am currently using Eclipse IDE to build the code. My plan is to build the mbed client libraries with yotta, then move these over to the Eclipse platform and link the libraries built with yotta to my C project. I feel like the SDK for the platform I am working with is already complete in Eclipse and that porting over this source and all of it’s library dependencies to yotta would be a large task for me.

As for creating the wrapper, my sample C++ library does exactly this and I have tried to link the code using both gcc and g++ but have had no luck. As I stated before I am very new to make files though and could potentially be doing something wrong there.

For reference here is the application.mk make file that does the linking,

where in settings.mk:

Build chain settings

ifneq ("(wildcard (TOOL_CHAIN_PATH))","")
CC = (TOOL_CHAIN_PATH)/arm-none-eabi-gcc CPLUS = (TOOL_CHAIN_PATH)/arm-none-eabi-g++
AR = (TOOL_CHAIN_PATH)/arm-none-eabi-ar OBJCOPY = (TOOL_CHAIN_PATH)/arm-none-eabi-objcopy
else
CC = arm-none-eabi-gcc
CPLUS = arm-none-eabi-g++
AR = arm-none-eabi-ar
OBJCOPY = arm-none-eabi-objcopy
export BUILD_LINUX = 1
endif
RMDIRS := rm -rf

application.mk starts here:

##################################################################

Makefile for generating the binary file of the application

##################################################################
MAKE_FILE_ROOT ?= .

include (MAKE_FILE_ROOT)/Settings.mk include (MAKE_FILE_ROOT)/Libraries.mk

Compiler settings

export CFLAGS_COMMON += -std=c99 -Wall -Wextra -Wstrict-prototypes -D$(DEVICE_ID) -D$(BST_LIBRARY_TYPE)
-mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections
(SERVAL_FEATURES_CONFIG) (CYASSL_FEATURES_CONFIG) -D$(HW_VERSION) -D$(SYSTEM_STARTUP_METHOD)
-DBLE_DEVICENAME="(UNIQUE_NAME)\" -DUNIQUE_MAC=(UNIQUE_MAC)

export CFLAGS_DEBUG_COMMON ?= (CFLAGS_COMMON) -O0 -g (DEBUG_FEATURES_CONFIG)
export CFLAGS_RELEASE_COMMON ?= $(CFLAGS_COMMON) -O0 -DNDEBUG

LDFLAGS_DEBUG += -Xlinker -Map=(APP_DEBUG_DIR)/(APP_NAME).map
-mcpu=cortex-m3 -mthumb -T $(LD_FILE) -Wl,–gc-sections

LDFLAGS_RELEASE += -Xlinker -Map=(APP_RELEASE_DIR)/(APP_NAME).map
-mcpu=cortex-m3 -mthumb -T $(LD_FILE) -Wl,–gc-sections

ASMFLAGS += -x assembler-with-cpp -Wall -Wextra -mcpu=cortex-m3 -mthumb

LIBS = -Wl,–start-group -lgcc -lc -lm -Wl,–end-group

#The static libraries of the platform and third party sources are grouped here. Inorder to scan the libraries
#for undefined reference again and again, the libraries are listed between the --start-group and --end-group.
DEBUG_LIBS_GROUP = -Wl,–start-group (LIBS_DEBUG) (THIRD_PARTY_LIBS) -Wl,–end-group
RELEASE_LIBS_GROUP = -Wl,–start-group (LIBS_RELEASE) (THIRD_PARTY_LIBS) -Wl,–end-group

LINTFLAGS =
-immediatetrans
-usereleased
-declundef
-zero

Source files

PLATFORM_SOURCE_FILES +=
(UTILS_DIR)/source/RSM_retargetStdioMessage/retargetio.c \ (EM_LIB_DIR)/usb/src/em_usbdint.c \

Startup files

APP_STARTUP_FILES =
startup_efm32gg.S

Object files

PLATFORM_C_OBJECT_FILES = (PLATFORM_SOURCE_FILES:.c=.o) APP_S_OBJECT_FILES = (APP_STARTUP_FILES:.S=.o)
APP_C_OBJECT_FILES = (patsubst (SOURCE_DIR)/%.c, %.o, (APP_SOURCE_FILES)) APP_OBJECT_FILES = (PLATFORM_C_OBJECT_FILES) (APP_C_OBJECT_FILES) (APP_S_OBJECT_FILES)

#This variable holds the depedency files for the application include files.
APP_DEPENDENCY_FILES = (addprefix (APP_DEBUG_OBJECT_DIR)/, (APP_OBJECT_FILES:.o=.d)) APP_OBJECT_FILES_DEBUG = (addprefix (APP_DEBUG_OBJECT_DIR)/, (APP_OBJECT_FILES))
APP_OBJECT_FILES_RELEASE = (addprefix (APP_RELEASE_OBJECT_DIR)/, $(APP_OBJECT_FILES))

APP_LINT_FILES =
(patsubst (APP_SOURCE_DIR)/%.c, %.lob, $(APP_SOURCE_FILES))

APP_DEBUG_LINT_FILES =
(addprefix (APP_DEBUG_LINT_PATH)/, $(APP_LINT_FILES))

#Create debug binary
.PHONY: debug
debug: (APP_DEBUG_DIR)/(APP_NAME).bin

#Create release binary
.PHONY: release
release: (APP_RELEASE_DIR)/(APP_NAME).bin

#Compile, assemble and link for debug target
#Compile the sources from plaform or library
(APP_DEBUG_OBJECT_DIR)/%.o: %.c @mkdir -p (@D)
@echo "Building file <" @(CC) (DEPEDENCY_FLAGS) (CFLAGS_DEBUG_COMMON) (INCLUDES) -c < -o $@

#Compile the sources from application
(APP_DEBUG_OBJECT_DIR)/%.o: (APP_SOURCE_DIR)/%.c
@mkdir -p (@D) @echo "Building file <"
@(CC) (DEPEDENCY_FLAGS) (CFLAGS_DEBUG_COMMON) (INCLUDES) -DBCDS_PACKAGE_ID=(BCDS_PACKAGE_ID) -c < -o $@

(APP_DEBUG_OBJECT_DIR)/%.o: %.S @mkdir -p (@D)
@echo "Assembling <" @(CC) (ASMFLAGS) (INCLUDES) -c < -o @

(APP_DEBUG_DIR)/(APP_NAME).out: (LIBS_DEBUG) (APP_OBJECT_FILES_DEBUG)
@echo "Creating .out @" @(CPLUS) (LDFLAGS_DEBUG) (APP_OBJECT_FILES_DEBUG) (DEBUG_LIBS_GROUP) (LIBS) -o $@

(APP_DEBUG_DIR)/(APP_NAME).bin: (APP_DEBUG_DIR)/(APP_NAME).out
@echo "Creating binary for debug @" @(OBJCOPY) -O binary (APP_DEBUG_DIR)/(APP_NAME).out $@

#Compile, assemble and link for release target

#Compile the sources from plaform or library
(APP_RELEASE_OBJECT_DIR)/%.o: %.c @mkdir -p (@D)
@echo "Building file <" @(CC) (DEPEDENCY_FLAGS) (CFLAGS_RELEASE_COMMON) (INCLUDES) -c < -o $@

#Compile the sources from application
(APP_RELEASE_OBJECT_DIR)/%.o: (APP_SOURCE_DIR)/%.c
@mkdir -p (@D) @echo "Building file <"
@(CC) (DEPEDENCY_FLAGS) (CFLAGS_RELEASE_COMMON) (INCLUDES) -DBCDS_PACKAGE_ID=(PACKAGE_ID) -c < -o $@

(APP_RELEASE_OBJECT_DIR)/%.o: %.S @mkdir -p (@D)
@echo "Assembling <" @(CC) (ASMFLAGS) (INCLUDES) -c < -o @

(APP_RELEASE_DIR)/(APP_NAME).out: (APP_OBJECT_FILES_RELEASE) (LIBS_RELEASE)
@echo "Creating .out @" @(CPLUS) (LDFLAGS_RELEASE) (APP_OBJECT_FILES_RELEASE) (RELEASE_LIBS_GROUP) (LIBS) -o $@

(APP_RELEASE_DIR)/(APP_NAME).bin: (APP_RELEASE_DIR)/(APP_NAME).out
@echo "Creating binary @" @(OBJCOPY) -R .usrpg -O binary (APP_RELEASE_DIR)/(APP_NAME).out $@

#if the header file is changed, compiler considers the change in a header file and compiles. Here no need to clean the application
#to take changes of header file during compilation
-include $(APP_DEPENDENCY_FILES)

Clean project

.PHONY: clean clean_libraries
clean: clean_libraries
@echo “Cleaning project in app.mk”
@(RMDIRS) (APP_DEBUG_DIR) $(APP_RELEASE_DIR)

cdt:
@echo “cdt”
(CC) (CFLAGS_DEBUG_COMMON) (INCLUDES) -E -P -v -dD -c {CDT_INPUT_FILE}
.PHONY: cdt

#Flash the .bin file to the target
flash_debug_bin: (APP_DEBUG_DIR)/(APP_NAME).bin
@(FLASH_TOOL_PATH) --address (APP_ADDRESS) -v -f $< -r
@echo “Flashing is completed successfully”

flash_release_bin: (APP_RELEASE_DIR)/(APP_NAME).bin
@(FLASH_TOOL_PATH) --address (APP_ADDRESS) -v -f $< -r
@echo “Flashing is completed successfully”

.PHONY: cleanlint
cleanlint:
@echo “Cleaning lint output files”
@rm -rf $(APP_DEBUG_LINT_PATH)

.PHONY: lint
lint: $(APP_DEBUG_LINT_FILES)
@echo “Lint End”

#(APP_DEBUG_LINT_PATH)/%.lob: (APP_SOURCE_DIR)/%.c

@echo “====================================”

@mkdir -p $(@D)

@echo $@

@(LINT_EXE) +d(DEVICE_TYPE) +d$(DEVICE_ID) (LINTFLAGS) (INCLUDES_LINT) +dDBG_ASSERT_FILENAME (LINT_CONFIG_FILE) < -oo[$@]

@echo “====================================”