ESP8266 NONOS SDK: How to compile C++ code?
I'm somehow not able to compile C++ code using the ESP8266 NONOS SDK.
I use the gen_misc.sh-script to configure and compile the program,
but it outputs the following error:
start...
make[1]: Entering directory '/repos/esp/ESP8266_NONOS_SDK/diplomarbeit-firmware/user'
xtensa-lx106-elf-g++ -Os -g -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-sections -fno-builtin-printf -DICACHE_FLASH -DSPI_FLASH_SIZE_MAP=3 -I include -I ./ -I ../../include/ets -I ../include -I ../../include -I ../../include/eagle -I ../../driver_lib/include -o .output/eagle/debug/obj/user_main.o -c user_main.cpp
xtensa-lx106-elf-ar ru .output/eagle/debug/lib/libuser.a .output/eagle/debug/obj/user_main.o
make[1]: Leaving directory '/repos/esp/ESP8266_NONOS_SDK/diplomarbeit-firmware/user'
xtensa-lx106-elf-gcc -L../lib -nostdlib -T../ld/eagle.app.v6.ld -Wl,--no-check-sections -Wl,--gc-sections -u call_user_start -Wl,-static -Wl,--start-group -lc -lgcc -lhal -lphy -lpp-lnet80211 -llwip -lwpa -lcrypto -lmain -ldriver user/.output/eagle/debug/lib/libuser.a -Wl,--end-group -o .output/eagle/debug/image/eagle.app.v6.out
../lib/libmain.a(app_main.o): In function `user_uart_wait_tx_fifo_empty':
(.irom0.text+0x6a0): undefined reference to `user_pre_init'
../lib/libmain.a(app_main.o): In function `user_uart_wait_tx_fifo_empty':
(.irom0.text+0x6b8): undefined reference to `user_init'
../lib/libmain.a(app_main.o): In function `flash_data_check':
(.irom0.text+0x718): undefined reference to `user_pre_init'
../lib/libmain.a(app_main.o): In function `flash_data_check':
(.irom0.text+0xac1): undefined reference to `user_init'
collect2: error: ld returned 1 exit status
../Makefile:398: recipe for target '.output/eagle/debug/image/eagle.app.v6.out' failed
make: *** [.output/eagle/debug/image/eagle.app.v6.out] Error 1
My code looks like that:
user_main.cpp
#include "user_interface.h"
#include "osapi.h"
#include "partition.h"
void ICACHE_FLASH_ATTR user_pre_init ()
{
// register partition table here
if (!system_partition_table_regist(partition_table,
sizeof(partition_table) / sizeof(partition_table[0]),
SPI_FLASH_SIZE_MAP))
{
os_printf("FAIL TO REGISTER PARTITION TABLE");
while (1) {}
}
}
class MyClass {
};
void user_init ()
{
os_printf("Hello world!\n");
}
I really don't know how to fix this problem.
The header files you are including are C header files, not C++. The C++ compiler will mangle the function names, leading to the above error you see. You need to wrap them in an extern block like this to tell the compiler not to mangle them:
extern "C" {
#include "user_interface.h"
#include "osapi.h"
#include "partition.h"
}
Related
I'm have a C Wasm module with the following import:
__attribute__((import_module("env"), import_name("runtime_exit"))) void exit(int);
I'm compiling with Clang 12.0.0 on Linux:
clang --target=wasm32 --no-standard-libraries \
-c -Ofast -o out.o in.c
With the package from my package manager (xbps), this works fine. In Nix (see below for the derivation), however (Clang 12.0.1), I get the following warning on nix-build:
tests/test.h:1:16: warning: unknown attribute 'import_module' ignored [-Wunknown-attributes]
__attribute__((import_module("env"), import_name("runtime_exit"))) void exit(int);
^~~~~~~~~~~~~~~~~~~~
tests/test.h:1:38: warning: unknown attribute 'import_name' ignored [-Wunknown-attributes]
__attribute__((import_module("env"), import_name("runtime_exit"))) void exit(int);
This is just a warning, but linking later fails: in fact, clang is attempting to link with ld, not wasm-ld or even lld.
My default.nix specifies:
{ pkgs ? import <nixpkgs> {} }:
let
stdenv = pkgs.llvmPackages_12.stdenv;
src = ./.; # etc, etc
in
stdenv.mkDerivation {
# --- snip ---
buildPhase = ''
clang --target=wasm32 --no-standard-libraries \
-c -Ofast -o $out/out.o in.c
'';
# --- snip ---
buildInputs = [ pkgs.clang_12 pkgs.lld_12 ];
}
I don't see why this shouldn't work, but all the different variations of packages I've tried using seem to suggest that I'm getting at the LLVM toolchain incorrectly.
If this isn't enough information, please let me know. Thanks!
Edit
It looks like Nix isn't respecting the --target argument:
$ nix-shell
[nix-shell:~/...]$ clang -target wasm32 --print-target-triple
x86_64-unknown-linux-gnu
[nix-shell:~/...]$ exit
$ clang --target=wasm32 --print-target-triple
wasm32
Despite the above, clang wasm32 as an available target.
The clang wrapper script given by Nix seems to do something. The compiler should be called with clang-[VERSION] instead of clang, for example as:
clang-12 --target=wasm32 --no-standard-libraries \
-c -std=c99 -Ofast -Wall -Werror -pedantic \
input.c -o output.o
The following line generate the executable :
arm-none-eabi-ld -L/home/th/opt/arm-none-eabi/lib/ -L/home/th/opt/lib/gcc/arm-none-eabi/8.2.0/ -T /home/th/autoreverse/game/game.ld main.cpp.obj init.cpp.obj syscalls.cpp.obj queue.cpp.obj echange.cpp.obj echangeur.cpp.obj startup.s.obj -lstdc++ -lc -lgcc -o game.elf
...but replacing ld call by g++ call, do not do the job :
arm-none-eabi-g++ -L/home/th/opt/arm-none-eabi/lib/ -L/home/th/opt/lib/gcc/arm-none-eabi/8.2.0/ -T /home/th/autoreverse/game/game.ld main.cpp.obj init.cpp.obj syscalls.cpp.obj queue.cpp.obj echange.cpp.obj echangeur.cpp.obj startup.s.obj -lstdc++ -lc -lgcc -o game.elf
/home/th/opt/lib/gcc/arm-none-eabi/8.2.0/../../../../arm-none-eabi/bin/ld: main.cpp.obj: in function `std::__ioinit':
/home/th/autoreverse/game/main.cpp:43: multiple definition of `__dso_handle'; /home/th/opt/lib/gcc/arm-none-eabi/8.2.0/crtbegin.o:(.data+0x0): first defined here
/home/th/opt/lib/gcc/arm-none-eabi/8.2.0/../../../../arm-none-eabi/bin/ld: /home/th/opt/lib/gcc/arm-none-eabi/8.2.0/../../../../arm-none-eabi/lib/crt0.o: in function `_start':
/home/th/tools/newlib-cygwin-build/arm-none-eabi/libgloss/arm/semihv2m/../../../../../newlib-cygwin/libgloss/arm/crt0.S:430: undefined reference to `__bss_start__'
/home/th/opt/lib/gcc/arm-none-eabi/8.2.0/../../../../arm-none-eabi/bin/ld: /home/th/tools/newlib-cygwin-build/arm-none-eabi/libgloss/arm/semihv2m/../../../../../newlib-cygwin/libgloss/arm/crt0.S:430: undefined reference to `__bss_end__'
collect2: error: ld returned 1 exit status
What is going wrong ?
Problem solved.
Calling g++ with arguments "-v" print the complete g++ command. That's when I saw that g++ include some C runtime files : crtbegin, crti and crt0.
One of thoses files requests for bss_start' and bss_end'.
I don't need thoses files ! Remove theses with "-nostdlib" argument.
I'm writing my own Makefile to compile my minimum standalone clang tool consisting of the following code:
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
static llvm::cl::OptionCategory ToolingSampleCategory("MetaLift Clang Frontend");
int main (int argc, const char **argv)
{
CommonOptionsParser op(argc, argv, ToolingSampleCategory);
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
return 0;
}
Is there a "proper" order to import the clang libraries? My current order is:
-lclangTooling -lclangSerialization -lclangFrontend
But I keep running into undefined symbols issues.
I find using CMake to be the easiest way to build a libTooling-based application. Here is a minimalistic snippet to compile your example:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
# Find CMake file for Clang
find_package(Clang REQUIRED)
# Add path to LLVM modules
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${LLVM_CMAKE_DIR}"
)
# import LLVM CMake functions
include(AddLLVM)
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${CLANG_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
add_definitions(${CLANG_DEFINITIONS})
add_llvm_executable(myTool main.cpp)
set_property(TARGET myTool PROPERTY CXX_STANDARD 11)
target_link_libraries(myTool PRIVATE clangTooling)
// main.cpp
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
static llvm::cl::OptionCategory
ToolingSampleCategory("MetaLift Clang Frontend");
int main(int argc, const char **argv) {
CommonOptionsParser op(argc, argv, ToolingSampleCategory);
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
return 0;
}
I checked the actual commands happening during the build:
c++ -DGTEST_HAS_RTTI=0 -I${CLANG}/include -O3 -DNDEBUG -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -fno-exceptions -fno-rtti -std=gnu++11 -o CMakeFiles/myTool.dir/main.cpp.o -c /Users/vsavchenko/source/c++/clang-makefile/main.cpp
c++ -O3 -DNDEBUG -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names -Wl,-dead_strip CMakeFiles/myTool.dir/main.cpp.o -o myTool -Wl,-rpath,#loader_path/../lib -Wl,-rpath,${CLANG}/lib ${CLANG}/lib/libclangTooling.a ${CLANG}/lib/libclangASTMatchers.a ${CLANG}/lib/libclangFormat.a ${CLANG}/lib/libclangFrontend.a ${CLANG}/lib/libclangDriver.a ${CLANG}/lib/libclangParse.a ${CLANG}/lib/libLLVMMCParser.a ${CLANG}/lib/libclangSerialization.a ${CLANG}/lib/libclangSema.a ${CLANG}/lib/libclangEdit.a ${CLANG}/lib/libclangAnalysis.a ${CLANG}/lib/libLLVMBitReader.a ${CLANG}/lib/libLLVMProfileData.a ${CLANG}/lib/libclangToolingCore.a ${CLANG}/lib/libclangAST.a ${CLANG}/lib/libclangRewrite.a ${CLANG}/lib/libclangLex.a ${CLANG}/lib/libclangBasic.a ${CLANG}/lib/libLLVMCore.a ${CLANG}/lib/libLLVMBinaryFormat.a ${CLANG}/lib/libLLVMMC.a ${CLANG}/lib/libLLVMOption.a ${CLANG}/lib/libLLVMSupport.a -lz -lcurses -lm /Users/vsavchenko/bin/clang/lib/libLLVMDemangle.a
It looks like the problem is not with the order of Clang libraries, but rather an insufficient set of them. The following command finishes without linking errors:
LIBRARY_PATH=${CLANG}/lib clang++ -std=c++11 -lclangTooling -lclangASTMatchers -lclangFormat -lclangFrontend -lclangDriver -lclangParse -lLLVMMCParser -lclangSerialization -lclangSema -lclangEdit -lclangAnalysis -lLLVMBitReader -lLLVMProfileData -lclangToolingCore -lclangAST -lclangRewrite -lclangLex -lclangBasic -lLLVMCore -lLLVMBinaryFormat -lLLVMMC -lLLVMOption -lLLVMSupport -lz -lcurses -lLLVMDemangle -I${CLANG}/include main.cpp
Happy hacking with Clang!
I am trying to compile the files after generating from these steps:-
(1) wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
(2) soapcpp2 -j -CL calc.h
(3) Creating a main.cpp with the following code:-
#include "calc.nsmap" // XML namespace mapping table (only needed once at the global level)
#include "soapcalcProxy.h" // the proxy class, also #includes "soapH.h" and "soapStub.h"
int main()
{
calcProxy calc;
double sum;
if (calc.add(1.23, 4.56, sum) == SOAP_OK)
std::cout << "Sum = " << sum << std::endl;
else
calc.soap_stream_fault(std::cerr);
calc.destroy(); // same as: soap_destroy(calc.soap); soap_end(calc.soap);
}
After it I compile issuing the command:-
g++ -o calcclient main.cpp soapcalcProxy.cpp soapC.cpp -lgsoap++
I get the following errors:-
/tmp/ccA5Ergj.o: In function `soap_ignore_element(soap*)':
soapC.cpp:(.text+0x112d): undefined reference to `soap_ignore'
/tmp/ccA5Ergj.o: In function `soap_putelement':
soapC.cpp:(.text+0x149b): undefined reference to `soap_element_empty'
collect2: error: ld returned 1 exit status
Please help in compiling.
I solved this. I was thinking the lib is in /usr/lib but it was in /usr/local/lib. I included -L/usr/local/lib while compiling, and it worked.
My program uses the documented autoconf macro AM_PROG_LEX. It builds fine on RHEL 6.5 and other distros, but fails on RHEL 6.6 and later.
The configure script cannot compile its tests. When it tries gcc with -ll, -lfl, linking fails with:
/usr/bin/ld: cannot find -lfl
When it tries gcc without extra libraries, linking fails with:
undefined reference to `yywrap'
libfl.a or libfl.so is missing from official repos of those systems. On RHEL 6.5 it's part of flex package.
RHEL 6.5
configure:5334: checking whether yytext is a pointer
configure:5351: gcc -o conftest -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -O0 conftest.c -lfl >&5
configure:5351: $? = 0
configure:5359: result: yes
RHEL 6.8
configure:5196: checking whether yytext is a pointer
configure:5217: gcc -o conftest -g -O2 conftest.c >&5
/tmp/ccNJtVgv.o: In function `input':
/home/git/rpmbuild/BUILD/snacc-1.3.1_16_g23ba7a6/lex.yy.c:1168: undefined reference to `yywrap'
/tmp/ccNJtVgv.o: In function `yylex':
/home/git/rpmbuild/BUILD/snacc-1.3.1_16_g23ba7a6/lex.yy.c:867: undefined reference to `yywrap'
/tmp/ccNJtVgv.o: In function `main':
/home/git/rpmbuild/BUILD/snacc-1.3.1_16_g23ba7a6/conftest.l:17: undefined reference to `yywrap'
collect2: ld returned 1 exit status
configure:5224: $? = 1
configure: failed program was:
...
configure:5246: result: no
libfl contains two and only two functions, both of which are normally unnecessary in production use of flex:
int main() { extern int yylex(void); while (yylex()) ; return 0; }
int yywrap(void) { return 1; }
The yywrap implementation (which essentially disables the yywrap functionality) is not necessary if you use the option
%option noyywrap
in your flex definition, or if you pass the command-line option --noyywrap to flex.
For quick-and-dirty flex scanners, or for debugging, it is sometimes handy to be able to use libfl to fill in the above functions. But it also can create problems on systems which provide both 32- and 64-bit environments. For this reason, libfl was removed from the RHEL flex rpm in 2014. See this RedHat bug fix advisory for details.
So you could install the appropriate flex-devel rpm in order to have libfl available. Or you could compile it yourself using the above code (which is not precisely the source code you'll find in the flex source bundle, but should produce precisely the same library).
Or you could try to fix autoconf so that it doesn't depend on libfl. It didn't used to have any such dependency; if it couldn't find libfl, it would just assume that it wasn't required for the program being compiled.
Workaround is to install flex-devel package containing libfl.a. RHEL version available to subscribers ony. Alternative is CentOS package or recompiling from source.