Gianni Spear
Gianni Spear

Reputation: 7924

undefined reference to function using Clion IDE

I writing a (my first) program in C on linux using Clion - Jetbrain IDE. When I try to compile in debug mode I have the following error message "undefined reference to" referred to thefunction that i wrote in two *.c files (accessory.c and logmanager.c).

I try to follow all instructions I found online and on stackoverflow to set as well as possible the *.c and header *.h file.

I am wondering if a problem to set the Cmakelist insede my ETCS project in Clion.

error:

/opt/clion-2018.2/bin/cmake/linux/bin/cmake --build /home/alessandro/CLionProjects/ETCS/cmake-build-debug --target ETCS -- -j 1
Scanning dependencies of target ETCS
[ 50%] Building C object CMakeFiles/ETCS.dir/serverRCB.c.o
[100%] Linking C executable ETCS
CMakeFiles/ETCS.dir/serverRCB.c.o: nella funzione "main":
/home/alessandro/CLionProjects/ETCS/serverRCB.c:72: undefined reference to "dispaly_array"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:75: rundefined reference to "dispaly_array"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:118: undefined reference to "create_logfile"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:143: rundefined reference to "get_train_name"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:144: undefined reference to "get_track_name"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:145: undefined reference to "get_track_name"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:165: undefined reference to "update_logfileETCS2"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:195: undefined reference to "update_logfileETCS2"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:219: undefined reference to "update_logfileETCS2"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:239: undefined reference to "update_logfileETCS2"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:263: undefined reference to "update_logfileETCS2"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:271: undefined reference to "dispaly_array"
/home/alessandro/CLionProjects/ETCS/serverRCB.c:275: undefined reference to "dispaly_array"
collect2: error: ld returned 1 exit status
CMakeFiles/ETCS.dir/build.make:83: set di istruzioni per l'obiettivo "ETCS" non riuscito
make[3]: *** [ETCS] Errore 1
CMakeFiles/Makefile2:72: set di istruzioni per l'obiettivo "CMakeFiles/ETCS.dir/all" non riuscito
make[2]: *** [CMakeFiles/ETCS.dir/all] Errore 2
CMakeFiles/Makefile2:84: set di istruzioni per l'obiettivo "CMakeFiles/ETCS.dir/rule" non riuscito
make[1]: *** [CMakeFiles/ETCS.dir/rule] Errore 2
Makefile:118: set di istruzioni per l'obiettivo "ETCS" non riuscito
make: *** [ETCS] Errore 2

main: serverRBC.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>

#include "accessory.h"
#include "logfilemanager.h"


#define SIZE 256

#define NUMBER_TRAINS 5
#define NUMBER_TRACKS 16
#define NUMBER_STATIONS 8

#define SERVER_SOCK_FILE  "servertest"
#define CLIENT_SOCK_FILE  "clientsocket"
#define SERVERNAME "RCB"


char * train;
char * actual;
char * request;
char name_train[3];
char name_actual[5];
char name_request[5];



int get_actual_index(int fd, int size);
int get_request_index(int fd, int size);
int get_train_index(int fd, int size);


int main(int argc , char *argv[]) {

    int tracks_array[NUMBER_TRACKS];
    int stations_array[NUMBER_STATIONS];
    char server_name[10];

    char * logprint;
    char * display_tracks;
    char * display_stations;

    int sockfd;
    int clientfd;
    int fdlog;

    socklen_t client_len;
    size_t len_socket_structure;
    struct sockaddr_un server_socketaddr;
    struct sockaddr_un client_socketaddr;

    client_len = sizeof(client_socketaddr);



    memset(tracks_array, 0, sizeof(display_tracks));
    memset(stations_array, 0, sizeof(stations_array));
    memset(server_name, 0, sizeof(server_name));


    // AGGIUNGERE INFORMAZIONI RICEVUTE DAL PADRE

    /* upddate Stations Array*/



    display_tracks = dispaly_array(tracks_array, NUMBER_TRACKS);
    printf("Tracks: %s - \n", display_tracks);

    display_stations = dispaly_array(stations_array, NUMBER_STATIONS);
    printf("Tracks: %s - \n", display_stations);


    /* Clear address structure */
    memset(&server_socketaddr, 0, sizeof(server_socketaddr));
    memset(&server_socketaddr, 0, sizeof(client_socketaddr));


    /* first call to socket() function*/
    sockfd = socket(AF_UNIX , SOCK_STREAM , 0);
    if (sockfd == -1) {
        perror("ERROR Server socket");
        exit(1);
    }
    puts("Server socket created");


    /* Initialize the server_socketaddr socket address. */
    server_socketaddr.sun_family = AF_LOCAL;
    strncpy(server_socketaddr.sun_path, SERVER_SOCK_FILE, sizeof(server_socketaddr.sun_path)-1);
    unlink(server_socketaddr.sun_path);

    /* lenght of the structure */
    len_socket_structure = strlen(server_socketaddr.sun_path) + sizeof(server_socketaddr.sun_family);

    /* assigning a name to a socket */
    if(bind(sockfd, (struct sockaddr *) &server_socketaddr, len_socket_structure) == -1)
    {
        perror("ERROR Server bind");
        exit(1);
    };

    puts("Server binding completed\n");

    if(listen(sockfd, NUMBER_TRAINS) == -1){
        perror("ERROR Server listen");
        exit(1);
    };

    puts("listening server\n");

    strcpy(server_name, SERVERNAME);
    fdlog = create_logfile(server_name, SIZE);


    while(1)
    {
        clientfd = accept(sockfd, (struct sockaddr *) &client_socketaddr, &client_len);
        while(clientfd == -1)
        {
            perror("ERROR Server accept");
            clientfd = accept(sockfd, (struct sockaddr *) &client_socketaddr, &client_len);
        }

        int train_index;
        int actual_index;
        int request_index;
        int status;

        memset(name_train, '\0', sizeof(name_train));
        memset(name_actual, '\0', sizeof(name_actual));
        memset(name_request, '\0', sizeof(name_request));

        train_index = get_train_index(clientfd, SIZE);
        actual_index = get_actual_index(clientfd, SIZE);
        request_index = get_request_index(clientfd, SIZE);

        train = get_train_name(train_index);
        actual = get_track_name(actual_index);
        request = get_track_name(request_index);

        strcpy(name_train, train);
        strcpy(name_actual, actual);
        strcpy(name_request, request);

        printf("Train %s: from %s to %s\n", name_train, name_actual, name_request);
        fflush(stdout);

        /* Server protocol */

        if(request_index > 20)
        {

            /* From Track to Station */
            printf("Train %s: required authorisation to move in %s\n", name_train, name_request);
            fflush(stdout);
            printf("Server %s: authorisation granted\n", SERVERNAME);
            fflush(stdout);
            write(clientfd, "0", 10);
            logprint = update_logfileETCS2(fdlog, train_index, actual_index, request_index, 0);
            printf("Server %s: %s\n", SERVERNAME, logprint);
            fflush(stdout);

            // RISPOSTA da TRENO WHILE


            printf("Train %s: leaving the track %s\n", name_train, name_actual);
            fflush(stdout);
            tracks_array[actual_index - 1] = 0;
            printf("Train %s: entered in the station %s\n", name_train, name_request);
            fflush(stdout);
            stations_array[request_index - 21] = 1;

        } else {

            if(actual_index > 20)
            {
                /* From Station to Track */
                printf("Train %s: required authorisation to move in %s\n", name_train, name_request);
                fflush(stdout);

                status = tracks_array[request_index - 1];

                if(status == 0)
                {

                    printf("Server %s: authorisation granted\n", SERVERNAME);
                    fflush(stdout);
                    write(clientfd, "0", 10);
                    logprint = update_logfileETCS2(fdlog, train_index, actual_index, request_index, 0);
                    printf("Server %s: %s\n", SERVERNAME, logprint);
                    fflush(stdout);



                    // RISPOSTA da TRENO WHILE



                    printf("Train %s: leaving the station %s\n", name_train, name_actual);
                    fflush(stdout);
                    stations_array[actual_index - 21] = 0;

                    /* update array*/
                    printf("Train %s: entered in the track %s\n", name_train, name_request);
                    fflush(stdout);
                    tracks_array[request_index - 1] = 1;

                } else {

                    printf("Server %s: authorisation denied\n", SERVERNAME);
                    fflush(stdout);
                    write(clientfd, "1", 10);
                    logprint = update_logfileETCS2(fdlog, train_index, actual_index, request_index, 1);
                    printf("Server %s: %s\n", SERVERNAME, logprint);
                    fflush(stdout);

                }

            } else {

                /* From Track to Track */
                printf("Train %s: required authorisation to move in %s\n", name_train, name_request);
                fflush(stdout);

                status = tracks_array[request_index - 1];

                if(status == 0)
                {

                    printf("Server %s: authorisation granted\n", SERVERNAME);
                    fflush(stdout);
                    write(clientfd, "0", 10);
                    logprint = update_logfileETCS2(fdlog, train_index, actual_index, request_index, 0);
                    printf("Server %s: %s\n", SERVERNAME, logprint);
                    fflush(stdout);



                    // RISPOSTA da TRENO WHILE



                    printf("Train %s: leaving the track %s\n", name_train, name_actual);
                    fflush(stdout);
                    tracks_array[actual_index - 21] = 0;

                    /* update array*/
                    printf("Train %s: entered in the track %s\n", name_train, name_request);
                    fflush(stdout);
                    tracks_array[request_index - 1] = 1;

                } else {

                    printf("Server %s: authorisation denied\n", SERVERNAME);
                    fflush(stdout);
                    write(clientfd, "1", 10);
                    logprint = update_logfileETCS2(fdlog, train_index, actual_index, request_index, 1);
                    printf("Server %s: %s\n", SERVERNAME, logprint);
                    fflush(stdout);

                }
            }
        }

        display_tracks = dispaly_array(tracks_array, NUMBER_TRACKS);
        printf("Tracks: %s - \n", display_tracks);
        fflush(stdout);

        display_stations = dispaly_array(stations_array, NUMBER_STATIONS);
        printf("Tracks: %s - \n", display_stations);
        fflush(stdout);

        printf("Server %s is closed connection with %s\n", SERVERNAME, name_train);
        fflush(stdout);
        close(clientfd);

    } /* end of while*/
}


int get_actual_index(int fd, int size)
{
    int track_index;
    char buffer[size];
    size_t nbytes;
    ssize_t bytes_read;

    memset(buffer, '\0', sizeof(buffer));
    nbytes = sizeof(buffer);

    bytes_read = read(fd, buffer, nbytes);
    if(bytes_read < 0)
    {
        perror("ERROR reading from get_current_index()");
        exit(1);
    }
    track_index = atoi(buffer);
    return track_index;
}


int get_request_index(int fd, int size)
{
    int track_index;
    char buffer[size];
    size_t nbytes;
    ssize_t bytes_read;

    memset(buffer, '\0', sizeof(buffer));
    nbytes = sizeof(buffer);

    bytes_read = read(fd, buffer, nbytes);
    if(bytes_read < 0)
    {
        perror("ERROR reading from get_request_index()");
        exit(1);
    }
    track_index = atoi(buffer);
    return track_index;
}


int get_train_index(int fd, int size)
{
    int train_index;
    char buffer[size];
    size_t nbytes;
    ssize_t bytes_read;

    memset(buffer, '\0', sizeof(buffer));
    nbytes = sizeof(buffer);

    bytes_read = read(fd, buffer, nbytes);
    if(bytes_read < 0)
    {
        perror("ERROR reading from get_train_index()");
        exit(1);
    }
    train_index = atoi(buffer);
    return train_index;
}

accessory.h

char * get_cwd(int size);
char * get_file_name(char *name, char *ext, int size);
void create_track_file(char *name, char *ext, int size);
int map_index(char *name, char *prefix);
char * get_track_name(int index);
char * get_train_name(int index);
char * read_file(char *name, char *ext, int size);
int count_elements(char *line);
int get_suffix(char *string, char *prefix);
int * get_route(char *name, char *ext, int size);
int check_track_file(int n_tracks, int size);
void print_route(char *name, int *route);
void print_create_file(char *name, int i, int n);
char * dispaly_array(int array[], int len);

accessory.c

#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>

#include "accessory.h"


char * get_cwd(int size){
    char *file_path = malloc(sizeof(char)*size + 1);
    char cwd[size];
    if(getcwd(cwd, sizeof(cwd)) == NULL)
        perror("getcwd() error");
    strcpy(file_path, cwd);
    return file_path;
}

// reach the limit of Stackoverflow ///
.........
.........

// reach the limit of Stackoverflow ///

char * dispaly_array(int array[], int len)
{
    char * input_print = calloc(256, sizeof(char));
    char value_char[5];

    int value_int;

    memset(value_char, '\0', sizeof(value_char));

    strcpy(input_print, "[ ");

    for(int i = 0; i < len-1; i++)
    {
        value_int = array[i];
        sprintf(value_char, "%d", value_int);
        strcat(value_char, ", ");
        strcat(input_print, value_char);
        memset(value_char, '\0', sizeof(value_char));
    }

    value_int = array[len-1];
    sprintf(value_char, "%d", value_int);
    strcat(value_char, "]");
    strcat(input_print, value_char);
    return input_print;
}

logmanager.h

int create_logfile(char *name, int size);
char * update_logfileETCS1(int fd, int step, int *route);
char * update_logfileETCS2(int fd, int train_index, int actual_index, int request_index, int authorisation);

logmanager.c

#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>

#include "accessory.c"
#include "logfilemanager.h"


int create_logfile(char *name, int size)
{
    char * file_name = get_file_name(name, ".log", size);
    umask(0);
    int fd = open(file_name, O_WRONLY | O_CREAT | O_APPEND | O_TRUNC, 0777);
    if (fd == -1)
    {
        perror("STATUS");
        exit(1);
    }
    return fd;
}

char * get_data_time()
{
    char months_of_year[12][9+1] = {
            "Gennaio",
            "Febbraio",
            "Marzo",
            "Aprile",
            "Maggio",
            "Giugno",
            "Luglio",
            "Agosto",
            "Settembre",
            "Ottobre",
            "Novembre",
            "Dicembre"
    };

    char * data_time_string = malloc(sizeof(char)*50 + 1);

    time_t current_time;
    struct tm *local_time;

    current_time = time(NULL); // get current time
    local_time = localtime (&current_time); // Convert to local time format

    char day[2];
    char month[9];
    char year[4];
    char hour[2];
    char minute[2];
    char second[2];

    sprintf(day, "%d", (local_time -> tm_mday));
    strcpy(month, months_of_year[local_time -> tm_mon]);
    sprintf(year, "%d", ((local_time -> tm_year) + 1900));
    sprintf(hour, "%d", (local_time -> tm_hour));
    sprintf(minute, "%d", (local_time -> tm_min));
    sprintf(second, "%d", (local_time -> tm_sec));

    strcpy(data_time_string, day);
    strcat(data_time_string, " ");
    strcat(data_time_string, month);
    strcat(data_time_string, " ");
    strcat(data_time_string, year);
    strcat(data_time_string, " ");
    strcat(data_time_string, hour);
    strcat(data_time_string, ":");
    strcat(data_time_string, minute);
    strcat(data_time_string, ":");
    strcat(data_time_string, second);

    return data_time_string;
}


char * update_logfileETCS1(int fd, int step, int *route)
{
    char * input_print = calloc(256, sizeof(char));
    char * actual;
    char * next;
    char * time_date;
    char name_actual[5];
    char name_next[5];
    char first[20];
    char second[20];
    char third[20];

    memset(name_actual, '\0', sizeof(name_actual));
    memset(name_next, '\0', sizeof(name_next));
    memset(first, '\0', sizeof(first));
    memset(second, '\0', sizeof(second));
    memset(third, '\0', sizeof(third));

    actual = get_track_name(route[step]);
    strcpy(name_actual, actual);
    strcpy(name_next, "--");
    if(step < route[0])
    {
        next = get_track_name(route[step+1]);
        strcpy(name_next, next);
    }
    first[20] = "[Attuale: ";
    second[20] = "], [Next: ";
    third[20] = "], ";
    strcpy(input_print, first);
    strcat(input_print, name_actual);
    strcat(input_print, second);
    strcat(input_print, name_next);
    strcat(input_print, third);
    time_date = get_data_time();
    strcat(input_print, time_date);
    strcat(input_print,"\n");
    write(fd, input_print, strlen(input_print));
    return input_print;
}



char * update_logfileETCS2(int fd, int train_index, int actual_index, int request_index, int authorisation)
{
    char * input_print = calloc(256, sizeof(char));
    char * train;
    char * actual;
    char * request;
    char * t_date;
    char name_train[3];
    char name_actual[5];
    char name_request[5];
    char time_date[20];
    char first[20];
    char second[20];
    char third[20];
    char fourth[20];
    char fifth[20];
    char sixth[20];

    memset(name_train, '\0', sizeof(name_train));
    memset(name_actual, '\0', sizeof(name_actual));
    memset(name_request, '\0', sizeof(name_request));
    memset(time_date, '\0', sizeof(time_date));
    memset(first, '\0', sizeof(first));
    memset(second, '\0', sizeof(second));
    memset(third, '\0', sizeof(third));
    memset(fourth, '\0', sizeof(fourth));
    memset(fifth, '\0', sizeof(fifth));
    memset(sixth, '\0', sizeof(sixth));

    first[20] = "[TRENO RICHIEDENTE AUTORIZZAZIONE: ";
    second[20] = "], [SEGMENTO ATTUALE: ";
    third[20] = "], [SEGMENTO RICHIESTO: ";
    fourth[20] = "], [AUTORIZZATO: ";
    fifth[20] = "], [DATA: ";
    sixth[20] = "]\n";

    actual = get_track_name(actual_index);
    strcpy(name_actual, actual);
    strcpy(name_request, "--");
    if(request_index > 0)
    {
        request = get_track_name(request_index);
        strcpy(name_request, request);
    }

    train = get_train_name(train_index);
    strcpy(name_train, train);
    strcpy(input_print, first);
    strcat(input_print, name_train);
    strcat(input_print, second);
    strcat(input_print, name_actual);
    strcat(input_print, third);
    strcat(input_print, name_request);
    strcat(input_print, fourth);
    if(authorisation > 0)
    {
        strcat(input_print, "NO");
    } else {
        strcat(input_print, "SI");
    }
    strcat(input_print, fifth);

    t_date = get_data_time();
    strcpy(time_date, t_date);
    strcat(input_print, time_date);

    strcat(input_print, time_date);
    strcat(input_print, sixth);
    write(fd, input_print, strlen(input_print));
    return input_print;
}

Cmakelist

cmake_minimum_required(VERSION 3.12)
project(ETCS C)

set(CMAKE_C_STANDARD 99)

add_executable(ETCS serverRCB.c)

Upvotes: 1

Views: 2697

Answers (1)

Your add executable doesn't have the other sources and headers. It should be,

add_executable(ETCS serverRBC.c accessory.h accessory.c logmanager.h logmanager.c)

However, the name of your main has to be main.c. If your main() method is in serverRBC.c, you have to change its name to main.c. The final add_executable should be,

add_executable(ETCS main.c accessory.h accessory.c logmanager.h logmanager.c)

Upvotes: 2

Related Questions