Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

gcc – Linking multiple shared library

background knowledge:

First I explain what do I understand of these gcc flags so far:

-L: As the gcc manual states, this flag add specified directory "to the list of directories to be searched for -l"

-l: Again as manual said, "Search the library named library when linking."

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

So, what I understand of these two, is first one adds directories to a list which, named library by the second one will be searched in, by the linker!

-I: As for this, manual says: "Add the directory dir to the list of directories to be searched for header files during preprocessing"! So I assume this one does the same as -L but for header files.

-Wl: The -Wl portion sends comma-separated options to the linker

What I’m trying to do:

I want to compile/build an executable which uses 3 .so shared libraries; And 2 of those (libpq and libsqlite3) are provided by official 3rd party vendors (Postgresql and Sqlite); And installed with apt install.
The 3rd one is one of mine; I wrote it myself and trying to link it with my executable to be able to use it at runtime.

What I tried so far:

If I compile my code without my own library (and respective function inside the code) using below command, it works fine:

g++ -std=c++20 full.cpp -o loadTester -L/usr/include/postgresql/libpq -lpq -lsqlite3

However, using these command, to also link my own library with my code, I get errors:

gcc -std=gnu17 -shared -o liblogwritter.so -fPIC logWritter.c
g++ -std=c++20 full-with-logger.cpp -o loadTester -L/usr/include/postgresql/libpq -L./ -lpq -lsqlite3 -llogwritter -Wl,-rpath=./ -I./

I’ve also tried by replacing ./ parts with the full path: /home/username/Desktop/Current/.

Error:

/usr/bin/ld: /tmp/ccSFD38J.o: in function `pgConncetionInit(char const*)':
full-with-logger.cpp:(.text+0xc3): undefined reference to `logWritter(char const*)'
/usr/bin/ld: /tmp/ccSFD38J.o: in function `pgInsertQuery(char**)':
full-with-logger.cpp:(.text+0x709): undefined reference to `logWritter(char const*)'
/usr/bin/ld: /tmp/ccSFD38J.o: in function `main':
full-with-logger.cpp:(.text+0x1994): undefined reference to `logWritter(char const*)'
/usr/bin/ld: full-with-logger.cpp:(.text+0x19e2): undefined reference to `logWritter(char const*)'
/usr/bin/ld: full-with-logger.cpp:(.text+0x1b0e): undefined reference to `logWritter(char const*)'
collect2: error: ld returned 1 exit status

Code for the library:

logWriter.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SV_SOCK_PATH "/tmp/shahab_logger"

int logWritter(const char* messageData)
{
    struct sockaddr_un addr;

    // Create a new client socket with domain: AF_UNIX, type: SOCK_STREAM, protocol: 0
    int sfd = socket(AF_UNIX, SOCK_STREAM, 0);

    // Construct server address, and make the connection.
    memset(&addr, 0, sizeof(struct sockaddr_un));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1);

    if (connect(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1)
    {
        fprintf(stderr, "Error connecting to server\n");
        return 0;                
    }

    write(sfd, messageData, strlen(messageData));

    close(sfd);
    return 0;
}

logWriter.h:

#ifndef LOGWRITTER_H
#define LOGWRITTER_H
 
int logWritter(const char* messageData);
 
#endif  // LOGWRITTER_H

myprogram.cpp:

... //Several lines removed

logWritter(jobExecTime.c_str());

... //Several lines removed

Note:

I made a simple driver program for my library as below and it was working fine (Provided that I ran the server.c before to accept socket connection):

#include <stdio.h>
#include <stdlib.h>
#include "logWritter.h"

int main()
{
    printf("Test driver program!\n");
    if (logWritter("Test driver program!") > 0)
    {
        printf("Error!\n");
        exit(1);
    }

    return 0;
}

And I compiled this driver program as below:

gcc -c -Wall -Werror -fpic logWritter.c
gcc -shared logWritter.o -o liblogwritter.so
gcc -Wall testDriver.c -o testDriver -L/home/username/Desktop/logger/ -llogwritter -Wl,-rpath=/home/username/Desktop/logger/

Note 2:

Here is the list of files inside /home/username/Desktop/Current/ (which all files exist) just in case:

activity_main.db  full.cpp  full-with-logger.cpp  liblogwritter.so  logServer
logWritter.c  logWritter.h  postgresInit.sql  run.sh  server.c  sqliteInit.sql  unix_socket.h

Question:

I think it obvious at this point, after reading such lengthy post (my greatest regards and appreciation for your king effort and time in advance) but to follow standards here:

  1. Are my understanding which I explained in the first section, correct?
  2. What am I missing (knowledge-wise)?
  3. How should I compile my executable? Please explain for both two cases which I copied the header file in /usr/include/ and shared library file in /usr/local/lib, or if I want to link them from current working folder, as it is now in the case of examples above.

>Solution :

Since you define logWritter in .c, it must be declared with C linkage when used in C++, hence logWriter.h must be

#ifndef LOGWRITTER_H
#define LOGWRITTER_H
#ifdef __cplusplus
extern "C" {
#endif

int logWritter(const char* messageData);

#ifdef __cplusplus
}
#endif
#endif
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading