Search code examples
cmakefileshared-librariessharedta-lib

Undefined reference when using ta-lib/ta_lib.h file and Makefile


I want to use the ta_lib functions in my C code and am trying to import the ta_lib functions. The header file gets imported correctly but i cannot get the linker to find the actual library. I want to do the compiling process with MAKE and gcc.

Firstly I import the header

#include <ta-lib/ta_libc.h>

And then when i need to use a function


TA_ADOSC(0, CSV_LENGTH - 1, temp_high, temp_low, temp_close, temp_volume, 3, 10, &beginIdx, &endIdx, tmp_adosc);

The program compiles fine using my makefile


# create CC variable

CC = gcc

# create CFLAGS variable

CFLAGS =  -L/usr/local/lib -Wall -g

LDLIBS = -lta_lib -I/usr/local/include -lm

output: main.o
$(CC) $(CFLAGS) -o output main.o

main.o: main.c
$(CC) $(LDLIBS) -c main.c

# target: dependencies

# action

clean:
rm -f \*.o output

Once I try to run make i get the following


gcc -L/usr/local/lib -Wall -g -o output main.o
/usr/bin/ld: main.o: in function `calculate_indicators': main.c:(.text+0x226): undefined reference to `TA_ADOSC'
collect2: error: ld returned 1 exit status
make: \*\*\* \[Makefile:10: output\] Error 1

From my understanding I need to fix the linking to the shared library.

The library is installed:


ldconfig -p | grep libta_lib.so

Returns the following


    libta_lib.so.0 (libc6,x86-64) => /usr/local/lib/libta_lib.so.0
    libta_lib.so.0 (libc6,x86-64) => /lib/libta_lib.so.0
    libta_lib.so (libc6,x86-64) => /usr/local/lib/libta_lib.so
    libta_lib.so (libc6,x86-64) => /lib/libta_lib.so

Since i am fairly new to C and using external libraries I can't find what seems to be the problem


Solution

  • You are adding the libraries to the compile line. They need to be added to the link line. And preprocessor options like -I are used by the compiler, and "where to find libraries" options like -L are used by the linker.

    Also, libraries always must come at the end of the link line, after all the object files. And, the -L "where to search" option should come before the -l "what library to find" option.

    Write your rules like this:

    CFLAGS = -I/usr/local/include -Wall -g
    LDFLAGS = -L/usr/local/lib
    LDLIBS = -lta_lib -lm
    
    output: main.o
            $(CC) $(CFLAGS) $(LDFLAGS) -o output main.o $(LDLIBS)
    
    main.o: main.c
            $(CC) $(CFLAGS) -c main.c
    

    However, it's better to just let make do the work for you; it knows how to correctly compile things (as long as you set the standard variables). You don't need to include a rule to build main.o at all.