C/C++ Development - Unable to start application from toradex extension for VSCODE

Hello!

I am new to embedded linux development. Following the online available documents, I have been able to successfully create and debug C# and Python applications. However, when I start a new C/C++ Project from the extension, I get the following error:

I am using windows as development pc with wsl2 and ubuntu 22.04. VSCode is running in remote through ubuntu 22.04.

Kindly guide me whether I am missing any steps.

Best Regards,
Hassan.

Hi @geopaxpvtltd ,

Welcome to our community! Feel free to explore other topics of interest.

It looks like you don’t have the Remote/Dev Containers extension installed, and it is needed for C/C++ projects with our extension, as mentioned in this article: C/C++ Development and Debugging on TorizonCore Using Visual Studio Code | Toradex Developer Center.

Try installing it and see if this solves your issue.

Best regards,
Lucas Akira

Hello Lucas! Thank you for the input.

The remote/Dev Containers were installed. I spent approximately 3 days resolving the issue. However, I finally tried with the ApolloX extension and it seems to be working now.

Would you be able to point me towards a sample of uart communication using C++? I have found python and C# samples and they are working.
Also, in the V1 extension, there is a way to share resources such as uarts with the containers using the extension. There seems to be no way to do this from the V2 extension. Any articles regarding this would also be welcome.

Best Regards,
Hassan.

Hi @geopaxpvtltd ,

The remote/Dev Containers were installed. I spent approximately 3 days resolving the issue. However, I finally tried with the ApolloX extension and it seems to be working now.

Glad you were able to overcome the issue using ApolloX, though it is a strange behavior on V1 of the extension. I’ll report this to the extension team. Thanks for the feedback!

Also, in the V1 extension, there is a way to share resources such as uarts with the containers using the extension. There seems to be no way to do this from the V2 extension. Any articles regarding this would also be welcome.

You mean giving the container access to the UART devices? On ApolloX you do so by altering the docker-compose.yml file in your project, similar to the example in this article: How to Use UART on Torizon OS | Toradex Developer Center

Would you be able to point me towards a sample of uart communication using C++? I have found python and C# samples and they are working.

I don’t think we have a sample C/C++ code for UART in our developer site, though this article UART (Linux) | Toradex Developer Center has a sample C code to set the baud rate.

I did a quick search and found this outside article Linux Serial Ports Using C/C++ | mbedded.ninja that could be useful for learning serial communication with C/C++. Given that it is for Linux in general, its content should apply when developing for TorizonCore, though I can’t guarantee it.

Best regards,
Lucas Akira

1 Like

Thank you for the input, Lucas.

I apologize for asking questions unrelated to the thread but I am using ubuntu’s libserial library Ubuntu Manpage: LibSerial - LibSerial Documentation

I have the library installed in /usr/include

However, when I call the library from the code, the compiler is unable to build.

I have tried to manually copy the headers from /usr/include to the project/includes folder but it seems unnatural and gives other errors.

Can you provide any pointers? I have tried adding libserial-dev into deps.json in the .conf folder and torizonPackages.json in the app folder.

I must add, the link you shared based on termios, it works and I can open the requisite ports and communicate with them. But just for knowledge, I wanted to use an external library for development, in case I need to use any others in future.

Best Regards
Hassan.

The following is the error I get from the terminal. It seems to be a linking issue.

Executing task: DOCKER_HOST="" docker run --rm -it -v /home/ha-01/testapp12cpp:/app cross-toolchain-arm64-testapp12cpp make ARCH=aarch64 CC=aarch64-linux-gnu-g++ debug 

aarch64-linux-gnu-g++ -Iincludes/ -g aarch64/debug/main.o -o aarch64/debug/testapp12cpp 
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: aarch64/debug/main.o: in function `linuxseriallibtest()':
/app/src/main.cpp:113: undefined reference to `LibSerial::SerialStream::SerialStream()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:114: undefined reference to `LibSerial::SerialStream::SerialStream()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:119: undefined reference to `LibSerial::SerialStream::Open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::_Ios_Openmode const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:120: undefined reference to `LibSerial::SerialStream::Open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::_Ios_Openmode const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:129: undefined reference to `LibSerial::SerialStream::SetBaudRate(LibSerial::BaudRate const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:130: undefined reference to `LibSerial::SerialStream::SetBaudRate(LibSerial::BaudRate const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:133: undefined reference to `LibSerial::SerialStream::SetCharacterSize(LibSerial::CharacterSize const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:134: undefined reference to `LibSerial::SerialStream::SetCharacterSize(LibSerial::CharacterSize const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:137: undefined reference to `LibSerial::SerialStream::SetFlowControl(LibSerial::FlowControl const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:138: undefined reference to `LibSerial::SerialStream::SetFlowControl(LibSerial::FlowControl const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:141: undefined reference to `LibSerial::SerialStream::SetParity(LibSerial::Parity const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:142: undefined reference to `LibSerial::SerialStream::SetParity(LibSerial::Parity const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:145: undefined reference to `LibSerial::SerialStream::SetStopBits(LibSerial::StopBits const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:146: undefined reference to `LibSerial::SerialStream::SetStopBits(LibSerial::StopBits const&)'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:164: undefined reference to `LibSerial::SerialStream::DrainWriteBuffer()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:165: undefined reference to `LibSerial::SerialStream::DrainWriteBuffer()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:193: undefined reference to `LibSerial::SerialStream::DrainWriteBuffer()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:194: undefined reference to `LibSerial::SerialStream::DrainWriteBuffer()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:247: undefined reference to `LibSerial::SerialStream::Close()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:248: undefined reference to `LibSerial::SerialStream::Close()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:114: undefined reference to `LibSerial::SerialStream::~SerialStream()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:113: undefined reference to `LibSerial::SerialStream::~SerialStream()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:114: undefined reference to `LibSerial::SerialStream::~SerialStream()'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /app/src/main.cpp:113: undefined reference to `LibSerial::SerialStream::~SerialStream()'
collect2: error: ld returned 1 exit status
make: *** [Makefile:47: aarch64/debug/testapp12cpp] Error 1

@lucas_a.tx Hello!

I finally seem to be able to start a C/C++ project using Toradex v1 extension. The trick was to disconnect from WSL (if connected) > install torizon extension v1 in windows mode > create new C/C++ application > then it created a dev container to work in.

With the external library, I have added it to devpackages and extrapackages and the libserial is accessible from the visual studio code. However, I am unable to build the project using external library (libserial). I am using cmakelists and have included the headers. The following is the current cmakelists file:

cmake_minimum_required(VERSION 3.0.0)

# set the project name
project(AppTest17WinSide VERSION 1.0)

# add the executable
add_executable(AppTest17WinSide 
AppTest17WinSide.cpp
/usr/include/libserial/SerialPort.h
/usr/include/libserial/SerialStream.h
)
# find_library(LIBSERIAL_LIBRARY SerialPort.h HINTS /usr/include/libserial/)
# target_link_libraries(AppTest17WinSide PUBLIC ${LIBSERIAL_LIBRARY})

# install (please be aware that changing the target folder may lead to issues during deployment and debugging)
install(TARGETS AppTest17WinSide DESTINATION bin)

Hi @geopaxpvtltd ,

I have tried to manually copy the headers from /usr/include to the project/includes folder but it seems unnatural and gives other errors.

Can you provide any pointers? I have tried adding libserial-dev into deps.json in the .conf folder and torizonPackages.json in the app folder.

In order to add an external library to your ApolloX project you have to add it to your SDK container and in your debug/release container as well. For instance, in order to add LibSerial you have to change the following files:

  • Dockerfile.sdk: Add libserial-dev:arm64 in the apt-get install command, similar to this:
# __deps__
RUN apt-get -q -y update && \
    apt-get -q -y install \
    # ADD YOUR PACKAGES HERE
    libserial-dev:arm64 \
    && \
    apt-get clean && apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*
# __deps__
  • Dockerfile.debug (debug container) and Dockerfile (release container): Similar to above, add libserial-dev or libserial1 to the apt-get install command.

You also have to include the library flag to your Makefile, as otherwise you’ll get the undefined reference errors. To do this add -lserial to LDFLAGS in your Makefile:

LDFLAGS := -lserial

Once that’s done you can try to compile and deploy your program. You can ignore any include errors related to your library, as it will be installed in the containers.

With the steps above I was able to successfully run on ApolloX this sample code from the LibSerial repository: https://github.com/crayzeewulf/libserial/blob/master/examples/serial_port_read.cpp

EDIT: For the code above I also had to add /dev/ttyUSB0 as a device in docker-compose.yml:

    devices:
      - "/dev/ttyUSB0:/dev/ttyUSB0"

As for the V1 issues, if devpackages has libserial-dev:arm64 and extrapackages has libserial1 or libserial-dev then the problem can be a linking issue similar to the one you faced before. I don’t know for sure how to do this with CMake, but try to find an equivalent option to the -lserial Makefile flag I mentioned above.

Hope this helps you.

Best regards,
Lucas Akira

1 Like

Hello Lucas!

Thank you for your reply. I appreciate it. I will retry in the morning and let you know.

Best regards,
Hassan.

This keyword seems to be the solution to every problem in cmake and the ApolloX extension as well. May I ask how you found it?
in my cmakelists I was adding:

target_link_libraries(${PROJECT_NAME} libserial)

but as soon as I changed it to:

target_link_libraries(${PROJECT_NAME} -lserial)

It started working.

Thank you for the suggestions and your patience.

Best Regards,
Hassan.

Hi @geopaxpvtltd ,

Glad I was able to help!

The -l<library_name> expression is a gcc/g++ option when compiling, telling the compiler to search for a library called <library_name> during the linking stage. This is usually needed when using an external library in C/C++ projects.

<library-name> is the name of the .so or .a file without the lib part at the beginning. So for libserial.so, <library-name> would be serial.

You can find more information about this option in these external links:

Best regards,
Lucas Akira

1 Like

Hello lucas! I hope I can bother you regarding another question.

I have been able to develop my application using many libraries the way you taught me. However, I am at a point where I need to work with a library named RTKLIB to work with some RTCM messages.

since the library isnt available on package feeds, the only way to work with the library is by building yourself. How can I configure my project in a way to build and include this library. currently, I have it cloned into my appconfig_0 folder. I started trying to follow External libraries with Torizon visual studio extension - #8 by matheus.castello but lost the way when they instruct to “Include in Project”

i hope you would be kind enough to guide me.

Hi @geopaxpvtltd ,

since the library isnt available on package feeds, the only way to work with the library is by building yourself. How can I configure my project in a way to build and include this library. currently, I have it cloned into my appconfig_0 folder. I started trying to follow External libraries with Torizon visual studio extension - #8 by matheus.castello but lost the way when they instruct to “Include in Project”

Keep in mind that the link you referenced above is for Visual Studio, not Visual Studio Code, so the procedures there don’t necessarily apply to your case.

Are you using V2 of the IDE extension (previously known as ApolloX)? If that’s the case and you are working with our C++ project template you have a Makefile in which you can add compilation instructions for the external library. You probably need to add the library source files to your VSCode project then add the appropriate instructions in the Makefile.

While I can’t help you with the Makefile itself I’d recommend that you see these links for more details on how to use it:


You said that RTKLIB isn’t available in the feeds, but I did find a package named librtklib-dev on the bookworm feeds: Debian -- Details of package librtklib-dev in bookworm. If the container images you’re using are based on bookworm you can try using that as a possible alternative.

Best regards,
Lucas Akira

1 Like

Hello @geopaxpvtltd,

Do you have any updates on this topic?

Well I sorted it out using another cmakelists file for the RTKLIB and added a sub-directory to it in my main cmakelists file and it built the RTKLIB code along with the main app. then I could also use the headers etc as needed.

I can post the cmakelists if you need it.

Hello @geopaxpvtltd,

Glad to hear that you could solve the issue. It would be nice if you can post the CMakeLists.txt file just so that it could help others who might run into the same problem.

# Include RTKLIB subdirectory
add_subdirectory(appconfig_0/RTKLIB/src)

# Link the libraries
target_link_libraries(
 ${PROJECT_NAME}  
 RTKLIB
 -lpthread
 )

and inside the RTKLIB folder, the I added a cmakelists file:

cmake_minimum_required(VERSION 3.0.0)
project(RTKLIB)
set(SOURCES
    convkml.c
    convrnx.c
    datum.c
    download.c
    ephemeris.c
    geoid.c
    ionex.c
    lambda.c
    options.c
    pntpos.c
    postpos.c
    ppp.c
    ppp_ar.c
    preceph.c
    # qzslex.c
    rcvraw.c
    rinex.c
    rtcm.c
    rtcm2.c
    rtcm3.c
    rtcm3e.c
    rtkcmn.c
    rtkpos.c
    rtksvr.c
    sbas.c
    solution.c
    stream.c
    streamsvr.c
    tle.c
    rcv/binex.c
    rcv/crescent.c
    # rcv/gw10.c
    rcv/javad.c
    rcv/novatel.c
    rcv/nvs.c
    # rcv/rcvlex.c
    rcv/rt17.c
    rcv/septentrio.c
    rcv/ss2.c
    rcv/ublox.c
)
add_library(RTKLIB STATIC ${SOURCES})
# Add include directory
target_include_directories(RTKLIB PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/rcv)