Zach466920
Zach466920

Reputation: 165

How Do I get Compiler to Recognize Reference to Library?

I downloaded the json-c library and was trying to do some basic tests in my environment (Ubuntu with Atom and gcc). However, I seem to be missing something in my makefile because every time I try to compile I get undefined reference errors. Below is what I'm trying to run,

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


int main() {
    struct json_object *jobj;
    char *str = "{ \"msg-type\": [ \"0xdeadbeef\", \"irc log\" ], \
        \"msg-from\": { \"class\": \"soldier\", \"name\": \"Wixilav\" }, \
        \"msg-to\": { \"class\": \"supreme-commander\", \"name\": \"[Redacted]\" }, \
        \"msg-log\": [ \
            \"soldier: Boss there is a slight problem with the piece offering to humans\", \
            \"supreme-commander: Explain yourself soldier!\", \
            \"soldier: Well they don't seem to move anymore...\", \
            \"supreme-commander: Oh snap, I came here to see them twerk!\" \
            ] \
        }";

    printf("str:\n---\n%s\n---\n\n", str);

    jobj = json_tokener_parse(str);
    printf("jobj from str:\n---\n%s\n---\n", json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY));

    return 0;
}

According to website, I'm supposed to use the two flags to link to the library.

CFLAGS += $(shell pkg-config --cflags json-c)
LDFLAGS += $(shell pkg-config --libs json-c)

I do that in the makefile below but it still doesn't work.

CFLAGS += $(shell pkg-config --cflags json-c)
LDFLAGS += $(shell pkg-config --libs json-c)

CCBIN=/usr/bin/gcc
CC=$(CCBIN) $(CFLAGS) $(LDFLAGS) -Wall -Wextra -pedantic -std=c99 -g -fsanitize=address

default: json

json: json_type.c
    $(CC) -O3 -o json json_type.c -lm

.PHONY: clean
clean:
    rm -Rf *.o lib/*.o json *.dSYM

.PHONY: package
package:
    tar -cvzf json.tar *

When I run 'make json' I get the following errors,

make json
/usr/bin/gcc -I/usr/local/include/json-c -L/usr/local/lib -ljson-c -Wall -Wextra -pedantic -std=c99 -g -fsanitize=address -O3 -o json json_type.c -lm
/tmp/ccXo2zav.o: In function `main':
/home/zachary/Atom_Projects/Projects/SandBox/JSON/json_type.c:25: undefined reference to `json_tokener_parse'
/home/zachary/Atom_Projects/Projects/SandBox/JSON/json_type.c:26: undefined reference to `json_object_to_json_string_ext'
collect2: error: ld returned 1 exit status
makefile:10: recipe for target 'json' failed
make: *** [json] Error 1

I'm really new to writing makefiles so hopefully it's something silly. Any advice would be helpful, thanks!

Upvotes: 0

Views: 829

Answers (1)

John Bollinger
John Bollinger

Reputation: 181244

The order of object files and libraries on the linker command line is significant. Libraries are searched in the order they are encountered in order to find function to satisfy dependencies in the preceding objects. You are putting all the libraries before the objects that need them, so they won't actually be used to resolve any of those undefined references.

Additionally, you are using some well-known make variables unconventionally, and making no use at all of make's built-in defaults:

  • variable CC, if you choose to redefine it, should contain the essential command for running the C compiler. Usually this does not include any flags:

    CC = gcc
    # or
    CC = /usr/bin/gcc
    
  • you would then put all the C compilation flags you need into the CFLAGS variable:

    CFLAGS = -O3 $(shell pkg-config --cflags json-c) -Wall -Wextra -pedantic -std=c99 -g -fsanitize=address
    
  • I have to assume that json-c means to give you an illustrative example, not a recipe, when it suggests putting the json-c library options in LDFLAGS. With GNU make, the output of pkg-config --libs would be better put in variable LDLIBS:

    LDLIBS = $(shell pkg-config --libs json-c)
    
  • With that said, using built-in variables in the conventional way matters most if you also rely on make's built-in rules. These will be entirely sufficient for your case, so you don't actually have to express a build command in your makefile, just the appropriate depedencies:

    json: json_type.o
    

So, supposing that json-c and pkg-config are properly installed, and you're using GNU make, this Makefile should be sufficient:

CC = /usr/bin/gcc

CFLAGS  = -std=c99 -O3 -g
CFLAGS += $(shell pkg-config --cflags json-c)
CFLAGS += -fsanitize=address -Wall -Wextra -pedantic

LDLIBS = $(shell pkg-config --libs json-c)

all: json
json: json_type.o

clean:
    rm -rf *.o json

.PHONY: clean

Upvotes: 1

Related Questions