Libraries not found VS Code

Hello,

I am using TorizonCore with a debian based docker image and debugging and flashing it trough VS Code with ApolloX.
The code I’m writing is on C++.
The problem that I have is that some of the libraries I have are not recognized and give me error in the code that I am using.

One of the libraries is the filesystem library. I changed the C++ compiler on VS Code to be for C+17 which is the version from which it is supported but it’s still not recognized.
Another one is the curl library. I checked, the library is installed both on my WSL2 on the pc and on the docker image on my board but it still gives me a “cannot open source file” error.
pthread is another library which isn’t recognized. All of these are libraries which I need to use in my project.

Tried also by updating the docker version to the newest “ARG CROSS_SDK_BASE_TAG=3.0.2-20230323-bookworm” but this didn’t help also.

Is there something extra I need to do for these libraries to work since they should be working on the device?

Greetings @Svetoslav,

This sounds very similar to your other thread here: Filesystem library problems

Just to clarify is it the same or similar issue, or is there something different? If it is the same could you continue the discussion on the initial thread so the details stay together.

Best Regards,
Jeremias

I don’t think it’s the same issue.
I am missing filesystem which is a basic C++ library and pthread should be also of the included C++ libraries, also the curl is installed on my docker as I already mentioned.
As I mentioned in VS Code they’re not recognized for some reason.

I do not know if I have to change something in the tasks.json file or what I should do to make them work.
If the library is installed on the docker but it doesn’t work on the VS Code program shouldn’t then there be a problem in the VS Code configuration of the project?
I used for the configuration ApolloX.

Just to be clear are these issues at runtime? Or are these issues at compile-time?

Could you provide some example code that we can use to reproduce what you’re seeing. Also please provide any project configurations you’ve done. Basically provide a step by step of what you’re doing so we can try and reproduce.

Best Regards,
Jeremias

For pthread I am just using a basic code to check if it works first:

#include <iostream>
#include <pthread.h>

// Function executed by the thread
void *thread_func(void *arg) {
    int *p = static_cast<int*>(arg);
    std::cout << "Thread: Hello World! Argument passed: " << *p << std::endl;
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    int arg = 42;

    // Create the thread
    if (pthread_create(&thread, NULL, thread_func, static_cast<void*>(&arg))) {
        std::cerr << "Error creating thread." << std::endl;
        return 1;
    }

    std::cout << "Main: Thread created with ID " << thread << std::endl;

    // Wait for the thread to finish
    if (pthread_join(thread, NULL)) {
        std::cerr << "Error joining thread." << std::endl;
        return 1;
    }

    std::cout << "Main: Thread finished." << std::endl;

    return 0;
}

The same thing I do for filesystem:

#include <iostream>
#include <filesystem>

int main() {
    // create a directory
    std::filesystem::create_directory("test_dir");
    
    // check if the directory exists
    if (std::filesystem::exists("test_dir")) {
        std::cout << "Directory created successfully!" << std::endl;
    } else {
        std::cout << "Error creating directory." << std::endl;
        return 1;
    }
    
    // create a file inside the directory
    std::ofstream("test_dir/test.txt");
    
    // check if the file exists
    if (std::filesystem::exists("test_dir/test.txt")) {
        std::cout << "File created successfully!" << std::endl;
    } else {
        std::cout << "Error creating file." << std::endl;
        return 1;
    }
    
    // remove the file
    std::filesystem::remove("test_dir/test.txt");
    
    // check if the file was removed
    if (!std::filesystem::exists("test_dir/test.txt")) {
        std::cout << "File removed successfully!" << std::endl;
    } else {
        std::cout << "Error removing file." << std::endl;
        return 1;
    }
    
    // remove the directory
    std::filesystem::remove("test_dir");
    
    // check if the directory was removed
    if (!std::filesystem::exists("test_dir")) {
        std::cout << "Directory removed successfully!" << std::endl;
    } else {
        std::cout << "Error removing directory." << std::endl;
        return 1;
    }
    
    return 0;
}

The configurations are as follows:
Dockerfile.sdk:

# ARGUMENTS --------------------------------------------------------------------
ARG CROSS_SDK_BASE_TAG=2.7-bullseye

##
# Board architecture
# arm or arm64
##
ARG IMAGE_ARCH=


# BUILD ------------------------------------------------------------------------
FROM torizon/debian-cross-toolchain-${IMAGE_ARCH}:${CROSS_SDK_BASE_TAG}

# __deps__
RUN apt-get -q -y update && \
    apt-get -q -y install \
    # ADD YOUR PACKAGES HERE
    && \
    apt-get clean && apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*
# __deps__

# automate for torizonPackages.json
RUN apt-get -q -y update && \
    apt-get -q -y install \
# DOES NOT REMOVE THIS LABEL: this is used for VS Code automation
    # __torizon_packages_dev_start__
    # __torizon_packages_dev_end__
# DOES NOT REMOVE THIS LABEL: this is used for VS Code automation
    && \
    apt-get clean && apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app

Makefile:

# tool macros
CC := g++
CCFLAGS := -Iincludes/ 
DBGFLAGS := -g
LDFLAGS :=  
CCOBJFLAGS := $(CCFLAGS) -c
ARCH :=

# path macros
BIN_PATH := $(ARCH)/bin
OBJ_PATH := $(ARCH)/obj
SRC_PATH := src
DBG_PATH := $(ARCH)/debug

# compile macros
TARGET_NAME := pesho
TARGET := $(BIN_PATH)/$(TARGET_NAME)
TARGET_DEBUG := $(DBG_PATH)/$(TARGET_NAME)

# src files & obj files
SRC := $(foreach x, $(SRC_PATH), $(wildcard $(addprefix $(x)/*,.c*)))
OBJ := $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
OBJ_DEBUG := $(addprefix $(DBG_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))

# clean files list
DISTCLEAN_LIST := $(OBJ) \
					$(OBJ_DEBUG)

CLEAN_LIST := $(TARGET) \
				$(TARGET_DEBUG) \
				$(DISTCLEAN_LIST)

# default rule
default: makedir all

# non-phony targets
$(TARGET): $(OBJ)
	$(CC) $(CCFLAGS) -o $@ $(OBJ) $(LDFLAGS)

$(OBJ_PATH)/%.o: $(SRC_PATH)/%.c*
	$(CC) $(CCOBJFLAGS) -o $@ $<

$(DBG_PATH)/%.o: $(SRC_PATH)/%.c*
	$(CC) $(CCOBJFLAGS) $(DBGFLAGS) -o $@ $<

$(TARGET_DEBUG): $(OBJ_DEBUG)
	$(CC) $(CCFLAGS) $(DBGFLAGS) $(OBJ_DEBUG) -o $@ $(LDFLAGS)

# phony rules
.PHONY: makedir
makedir:
	@mkdir -p $(BIN_PATH) $(OBJ_PATH) $(DBG_PATH)

.PHONY: all
all: $(TARGET)

.PHONY: debug
debug: $(TARGET_DEBUG)

.PHONY: clean
clean:
	@echo CLEAN $(CLEAN_LIST)
	@rm -f $(CLEAN_LIST)

.PHONY: distclean
distclean:
	@echo CLEAN $(CLEAN_LIST)
	@rm -f $(DISTCLEAN_LIST)

Dockerfile.debug:

# ARGUMENTS --------------------------------------------------------------------
##
# Board architecture
##
ARG IMAGE_ARCH=
# For armv7 use:
#ARG IMAGE_ARCH=arm

##
# Base container version
##
ARG BASE_VERSION=2.5-bullseye

##
# Application Name
##
ARG APP_EXECUTABLE=app

##
# Debug port
##
ARG SSH_DEBUG_PORT=

##
# Run as
##
ARG SSHUSERNAME=

# BUILD ------------------------------------------------------------------------
##
# Deploy Step
##
FROM --platform=linux/${IMAGE_ARCH} \
    torizonextras/debian:${BASE_VERSION} AS Debug

ARG IMAGE_ARCH
ARG SSH_DEBUG_PORT
ARG APP_EXECUTABLE
ARG SSHUSERNAME
ENV APP_EXECUTABLE ${APP_EXECUTABLE}

# SSH for remote debug
EXPOSE ${SSH_DEBUG_PORT}

# Make sure we don't get notifications we can't answer during building.
ENV DEBIAN_FRONTEND="noninteractive"

# your regular RUN statements here
# Install required packages
RUN apt-get -q -y update && \
    apt-get -q -y install \
    openssl \
    openssh-server \
    rsync \
    file \
    curl \
    gdb && \
    apt-get clean && apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*

# automate for torizonPackages.json
RUN apt-get -q -y update && \
    apt-get -q -y install \
# DOES NOT REMOVE THIS LABEL: this is used for VS Code automation
    # __torizon_packages_dev_start__
    # __torizon_packages_dev_end__
# DOES NOT REMOVE THIS LABEL: this is used for VS Code automation
    && \
    apt-get clean && apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*

# ⚠️ DEBUG PURPOSES ONLY!!
# copies RSA key to enable SSH login for user
COPY .conf/id_rsa.pub /id_rsa.pub

# create folders needed for the different components
# configures SSH access to the container and sets environment by default
RUN mkdir /var/run/sshd && \
    sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' \
        -i /etc/pam.d/sshd && \
    if test $SSHUSERNAME != root ; \
        then mkdir -p /home/$SSHUSERNAME/.ssh ; \
        else mkdir -p /root/.ssh ; fi && \
    if test $SSHUSERNAME != root ; \
        then cp /id_rsa.pub /home/$SSHUSERNAME/.ssh/authorized_keys ; \
        else cp /id_rsa.pub /root/.ssh/authorized_keys ; fi && \
    echo "PermitUserEnvironment yes" >> /etc/ssh/sshd_config && \
    echo "Port ${SSH_DEBUG_PORT}" >> /etc/ssh/sshd_config && \
    su -c "env" $SSHUSERNAME > /etc/environment

RUN rm -r /etc/ssh/ssh*key && \
    dpkg-reconfigure openssh-server

CMD [ "/usr/sbin/sshd", "-D" ]

HI @Svetoslav

VS Code will look for the headers configured in the includePath of your project .vscode/c_cpp_properties.json file.

The SDK container is only used to cross compile the application, if you want to have the headers to be used on VS Code you have to also install it locally.

If you want a way to reproduce the dev environment with others, you can add the packages from the library you are using in the .conf/deps.json, this file will be used by the extension to ask the user to install the local dependencies.

Let me know if this works for you.

1 Like

Hi,
So I intalled the following which should be the pthread to the PC from which I’m working: sudo apt-get install libpthread-stubs0-dev.
Also added it in Dockerfile.sdk so it’s installed on the docker.
In deps.json I added the last pacage like that:

{
    "packages": [
        "openssh-client",
        "sshpass",
        "build-essential",
        "make",
        "gdb",
        "g++",
        "libpthread-stubs0-dev"
    ]
}

But I am not sure if this is the way to add it because it still gives the errors when I try to run the code:

p/src/main.cpp:60: undefined reference to `pthread_join'
collect2: error: ld returned 1 exit status
make: *** [Makefile:47: armhf/debug/pesho] Error 1

Is that what you meant or am I doing something wrong?

And for the filesystem, since it’s a C++ library and I’ve updated my packages on both the target device and PC shouldn’t it work without any additional configurations? It just needs to support C++17 or higher from what I know.

Hi @Svetoslav !

This is usually caused by a compilation issue where your code uses pthread but the linker is not capable of finding the library to link against.

You need to set up this variable accordingly by adding -lpthread in your case.

AFAIK, you shouldn’t need to install libpthread manually. As an example, you can see that libc in my computer (Ubuntu, Debian based) “owns” libpthreads:

[  9:04 ]  [ ~ ]
 $ dpkg -L libc6 | rg pthread
/lib/x86_64-linux-gnu/libpthread.so.0

Best regards,

Thank you for your help.

When I added LDFLAGS := -lpthread
And also apt-get -q -y install libpthread-stubs0-dev:armhf to the Docker files, the program compiled and was able to run.

Hi @Svetoslav !

Good to know that it worked!

Please take your time to test it without adding the libpthread-stubs package to your Docker image. I think that it should work without it.

Best regards,