Skip to content

Instantly share code, notes, and snippets.

@pavly-gerges
Created June 6, 2024 20:00
Show Gist options
  • Save pavly-gerges/3445a0242d24698134ff4ab1141667f4 to your computer and use it in GitHub Desktop.
Save pavly-gerges/3445a0242d24698134ff4ab1141667f4 to your computer and use it in GitHub Desktop.
Error due to `n-tuple` duplicates when putting an object definition in headers and including the headers in multiple compilation units, resulting in `n-tuple` duplicate definitions during the linking procedure.
[100%] Linking C executable hello_comm.c-a.elf
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x70): multiple definition of `serial'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x70): first defined here
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x54): multiple definition of `parallel'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x54): first defined here
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x0): multiple definition of `usbfs'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x0): first defined here
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x1c): multiple definition of `pci'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x1c): first defined here
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x38): multiple definition of `socket'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x38): first defined here
@pavly-gerges
Copy link
Author

Error due to n-tuple duplicates when putting an object definition in headers and including the headers in multiple compilation units, resulting in n-tuple duplicate definitions during the linking procedure.

@pavly-gerges
Copy link
Author

Here is the code that leads to this (quite common in my style! I know very bad indication!):

[comm.h]

#ifndef _ELECTROSTATIC_COMM_H_
#define _ELECTROSTATIC_COMM_H_

#include <stdio.h>
#include <inttypes.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    char* name;
    int descriptor;
    char* protocol_name;
    char* file_system;
} device_metadata;

typedef struct {
    device_metadata (*open)(void**);
    uint8_t (*init)(void**);
    uint8_t (*deinit)(void**);
    uint64_t (*read)(void**);
    uint64_t (*write)(void**);
    uint8_t (*close)(void**);
    device_metadata (*get_metadata)(void**);
} comm_protocol;

/**
 * Defines function tables for communication protocols.
 */
comm_protocol serial;
comm_protocol parallel;
comm_protocol socket;
comm_protocol pci;
comm_protocol usbfs;

extern uint8_t init_protocol(comm_protocol*, const comm_protocol*);
extern uint8_t init_protocols_default();

#ifdef __cplusplus
}
#endif

#endif //_ELECTROSTATIC_COMM_H_

[init_protocol.c -> init_protocol.o]

#include<electrostatic/comm/comm.h>

static device_metadata test_serial(void** args) {
    device_metadata metadata = {
    };
    printf("%s", "Test Serial!\n");
    return metadata;
}

static device_metadata test_parallel(void** args) {
    device_metadata metadata = {
    };
    printf("%s", "Test Parallel!\n");
    return metadata;
}

const static comm_protocol serial_table = {
    &test_serial  
};

const static comm_protocol parallel_table = {
    &test_parallel  
};

extern uint8_t init_protocol(comm_protocol* comm, const comm_protocol* from) {
    if (&from == NULL) {
        return -1;
    }
    comm->open = from->open;
    comm->init = from->init;
    comm->deinit = from->deinit;
    comm->read = from->read;
    comm->write = from->write;
    comm->close = from->close;
    return 0;
}

extern uint8_t init_protocols_default() {
    // initialize serial constructors
    init_protocol(&serial, &serial_table);
    
    // initialize parallel constructors
    init_protocol(&parallel, &parallel_table);
    
    // initialize your new protocol drivers here!
    
    return 0;
}

[hello_comm.c + include(comm.h) -> hello_comm.o ---ld---> +init_protocol.o + include(comm.h)]

#include <stdio.h>
#include <electrostatic/comm/comm.h>

int main() {
    init_protocols_default();
    parallel.open(0);
    serial.open(0);
    return 0;
}

Full Error logs:

Run cd ./electrostatic-sandbox-framework && ./helper-scripts/ci-cd/test-electrostatic.sh
  cd ./electrostatic-sandbox-framework && ./helper-scripts/ci-cd/test-electrostatic.sh
  shell: /usr/bin/bash -e {0}
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Project: electrostatic-examples
-- GCC: /usr/bin/gcc
-- GPP: /usr/bin/g++
-- Compiler Options: -fPIC -O[2](https://github.com/Electrostat-Lab/Electrostatic-Sandbox/actions/runs/9406421515/job/25909824916?pr=9#step:5:2)
-- Target architecture: x86-64
-- Toolchain Includes: /usr/include/
-- Included-library: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core/
-- Runnable-example: hello_comm.c
-- Compiling for 64-bit Intel Chipset
-- Configuring done
-- Generating done
-- Build files have been written to: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-examples/build/x86-64
Scanning dependencies of target hello_comm.c.elf
[ 25%] Building C object CMakeFiles/hello_comm.c.elf.dir/src/hello_comm.c.o
[ 50%] Linking C executable hello_comm.c.elf
[ 50%] Built target hello_comm.c.elf
Scanning dependencies of target hello_comm.c-a.elf
[ 75%] Building C object CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o
[100%] Linking C executable hello_comm.c-a.elf
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86-64/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x100): multiple definition of `serial'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x100): first defined here
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86-64/libelectrostatic-a.a(init_protocol.c.o):(.bss+0xc0): multiple definition of `parallel'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0xc0): first defined here
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86-64/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x0): multiple definition of `usbfs'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x0): first defined here
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86-64/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x40): multiple definition of `pci'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x40): first defined here
/usr/bin/ld: /home/runner/work/Electrostatic-Sandbox/Electrostatic-Sandbox/electrostatic-sandbox-framework/electrostatic-core//build/x86-64/libelectrostatic-a.a(init_protocol.c.o):(.bss+0x80): multiple definition of `socket'; CMakeFiles/hello_comm.c-a.elf.dir/src/hello_comm.c.o:(.bss+0x80): first defined here
collect2: error: ld returned 1 exit status
gmake[2]: *** [CMakeFiles/hello_comm.c-a.elf.dir/build.make:104: hello_comm.c-a.elf] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:124: CMakeFiles/hello_comm.c-a.elf.dir/all] Error 2
gmake: *** [Makefile:10[3](https://github.com/Electrostat-Lab/Electrostatic-Sandbox/actions/runs/9406421515/job/25909824916?pr=9#step:5:3): all] Error 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment