0

I have a project I'm working on that currently has a matrix.c file containing a some functions and has a corresponding header matrix.h. I made a shared library libccalc.so using matrix.c and another file. I am trying to create a directory in /usr/local/lib and a directory in /usr/local/include, both called ccalc to house the respective .so and .h files which can then later be used to compile programs using the functionality of libccalc.so. However, when I do this I am getting an error.

To be precise, matrix.c contains functions:
Matrix *mat_create(int rows, int cols),
void mat_fill(Matrix *mat, double *entries) and
void mat_print(Matrix *mat)
which are declared in matrix.h. I place the files in their respective directories as explained above, I run ldconfig /usr/local/lib/ccalc and I make a new file test.c in some other directory with the following:

// test.c

#include <stdio.h>
#include "matrix.h"

int main() {
    Matrix *m = mat_create(2, 2);
    double entries[4] = {1, 2, 3 ,4};
    mat_fill(m, entries);

    mat_print(m);

    return 0; 
}

matrix.h contains the following:

// matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#define MAX_SIZE 50

typedef struct Matrix Matrix;

struct Matrix {
    int rows;
    int cols;
    double *data;
};

Matrix *mat_create(int n, int p);
void mat_fill(Matrix *mat, double *entries);
void mat_print(Matrix *mat);

#endif

When I enter the command: gcc -I/usr/local/include/ccalc -L/usr/local/lib/ccalc -lccalc test.c -o test, I get the error:

/usr/bin/ld: /tmp/ccesD44J.o: in function `main':
test.c:(.text+0x26): undefined reference to `mat_create'
/usr/bin/ld: test.c:(.text+0x71): undefined reference to `mat_fill'
/usr/bin/ld: test.c:(.text+0x7d): undefined reference to `mat_print'
collect2: error: ld returned 1 exit status

However, when I place libccalc.so and matrix.h in /usr/local/lib and /usr/local/include, enter ldconfig and enter the command gcc -L/usr/local/lib/ccalc -lccalc test.c -o test, and run ./test, it works perfectly

Can someone tell me what I am doing wrong?

Carson James
  • 167
  • 6
  • can you include the contents of `matrix.h` if at all possible? – Jad Jan 13 '21 at 17:36
  • yup, just updated and added contents of `matrix.h` – Carson James Jan 13 '21 at 17:46
  • 2
    It would be more conventional to put the header directly in `/usr/local/include` and the library directly in `/usr/local/lib` or possibly `/usr/local/lib64`. If you instead put them in subdirectories of those then you will need to configure the dynamic linker with the correct library directory, and you will need to either tell the compiler which directory to search for the header, or else include the subdirectory in the `#include` directive. – John Bollinger Jan 13 '21 at 17:49
  • @JohnBollinger Is this normal? in my `/usr/local/lib` and `/usr/lib` there is are directories for python3 stuff. I had read that `libm.so` is in `/usr/lib` but when I checked, I couldnt find it, just a bunch of directories, so I thought that is what people do – Carson James Jan 13 '21 at 18:22
  • @CarsonJames, on most Unix-y systems, including most Linuxes, it is common to install libraries directly into .../lib or .../lib64, and to install headers directly into .../include, and if you do so then it is easier to find them at compile time *and* run time. Python is a rather special case, and should not be regarded as a model. libm and the rest of the C standard library, too -- we're talking about add-on C and C++ libraries, such as yours. – John Bollinger Jan 13 '21 at 19:06
  • @JohnBollinger ah gotcha, thanks for the clarification – Carson James Jan 13 '21 at 19:21

1 Answers1

0

The order of program arguments to gcc matters a lot. Please read the documentation about Invoking GCC.

Also, test is often a builtin command. See test(1).

So (on Linux) rename test.c as prog.c then compile your program with

   gcc -Wall -Wextra -g prog.c -L/usr/local/lib/ccalc -lccalc -o prog

Then use strace(1) and gdb(1) to understand the behavior of prog, and ldd(1), objdump(1) with readelf(1) to analyze prog. See also elf(5) and ld.so(8).

Regarding building shared libraries, read Drepper's paper How to write shared libraries

You probably want to compile matrix.c into libcalc.so using

gcc -fPIC -Wall -O -shared -g matrix.c -o libcalc.so

but you might need other program arguments.

Regarding matrix operations, this answer could be inspirational.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • thanks, I added `-I/usr/local/include/ccalc` to the command you gave me and it worked, so I think my problem was me not using the correct order – Carson James Jan 13 '21 at 18:02