Home > Mobile >  Incorrect C Makefiles to generate library and main program?
Incorrect C Makefiles to generate library and main program?

Time:11-24

Having a library and a main test driver in C, but although the library could be compiled successfully, the main test driver can't.

Here are the directory structures:

qxu@xqiang-mac-1:~/test/test_makefile$ ll
total 0
drwxr-xr-x  3 qxu  staff   96 Nov 23 13:19 include
drwxr-xr-x  6 qxu  staff  192 Nov 23 13:31 print_ascii_tree
drwxr-xr-x  5 qxu  staff  160 Nov 23 13:33 test_main_driver

qxu@xqiang-mac-1:~/test/test_makefile$ ll include/
total 8
-rw-r--r--  1 qxu  staff  706 Nov 23 12:12 print_ascii_tree.h

qxu@xqiang-mac-1:~/test/test_makefile$ ll print_ascii_tree/
total 32
-rw-r--r--  1 qxu  staff   250 Nov 23 13:31 Makefile
-rw-r--r--  1 qxu  staff  9122 Nov 23 12:12 print_ascii_tree.c

qxu@xqiang-mac-1:~/test/test_makefile$ ll test_main_driver/
total 16
-rw-r--r--@ 1 qxu  staff  616 Nov 23 13:33 Makefile
-rw-r--r--@ 1 qxu  staff  918 Nov 23 11:51 main.c

Here is the makefile for the library:

qxu@xqiang-mac-1:~/test/test_makefile/print_ascii_tree$ cat Makefile 
AR = ar -rcs
RM = rm -rf
CC = gcc
CFLAGS = -I../include

libprint_ascii_tree.a: print_ascii_tree.o
    $(AR) libprint_ascii_tree.a print_ascii_tree.o

print_ascii_tree.o: print_ascii_tree.c 
    $(CC) $(CFLAGS) -c print_ascii_tree.c

clean:
    $(RM) *.o *.a

This library could be compiled smoothly:

qxu@xqiang-mac-1:~/test/test_makefile/print_ascii_tree$ make
gcc -I../include -c print_ascii_tree.c
ar -rcs libprint_ascii_tree.a print_ascii_tree.o
qxu@xqiang-mac-1:~/test/test_makefile/print_ascii_tree$ ll
total 64
-rw-r--r--  1 qxu  staff   250 Nov 23 13:31 Makefile
-rw-r--r--  1 qxu  staff  7672 Nov 23 13:38 libprint_ascii_tree.a
-rw-r--r--  1 qxu  staff  9122 Nov 23 12:12 print_ascii_tree.c
-rw-r--r--  1 qxu  staff  7128 Nov 23 13:38 print_ascii_tree.o

Here is the Makefile for the test driver:

qxu@xqiang-mac-1:~/test/test_makefile/test_main_driver$ cat Makefile 
program_NAME := main.out

SRCS = main.c 
OBJS := ${SRCS:.c=.o}

CC = gcc
CFLAGS = -fsanitize=address -Wall -Wextra -g

program_INCLUDE_DIRS := ../include
program_LIBRARY_DIRS := ../print_ascii_tree
program_LIBRARIES := print_ascii_tree

CFLAGS  = $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir))
LDFLAGS  = $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir))
LDFLAGS  = $(foreach library,$(program_LIBRARIES),-l$(library))

LINK.c := $(CC) $(CFLAGS) $(LDFLAGS)

.PHONY: all

all: $(program_NAME)

$(program_NAME): $(OBJS)
    $(LINK.c) $(program_OBJS) -o $(program_NAME)

clean:
    rm -rf *.o *.out

This is the error:

qxu@xqiang-mac-1:~/test/test_makefile/test_main_driver$ make
gcc -fsanitize=address -Wall -Wextra -g -I../include   -c -o main.o main.c
gcc -fsanitize=address -Wall -Wextra -g -I../include -L../print_ascii_tree -lprint_ascii_tree  -o main.out
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main.out] Error 1
qxu@xqiang-mac-1:~/test/test_makefile/test_main_driver$ ll
total 32
-rw-r--r--@ 1 qxu  staff   617 Nov 23 13:39 Makefile
-rw-r--r--@ 1 qxu  staff   908 Nov 23 13:40 main.c
-rw-r--r--  1 qxu  staff  6496 Nov 23 13:40 main.o

Looks like main.o got compiled, but can't be linked with the library into the main executable?

Not sure what's wrong in the Makefile.

P.S. This is what's in main.c:

qxu@xqiang-mac-1:~/test/test_makefile/test_main_driver$ cat main.c
#include "print_ascii_tree.h"

int main()
{
    printf("asdf\n");
    // A sample use of these functions.  Start with the empty tree
    // insert some stuff into it, and then delete it
    NodePtr root;
    root = NULL;

    make_empty(root);

    printf("\nAfter inserting key 10..\n");
    root = insert(10, root);
    print_ascii_tree(root);

    printf("\nAfter inserting key 5..\n");
    root = insert(5, root);
    print_ascii_tree(root);

    printf("\nAfter inserting key 15..\n");
    root = insert(15, root);
    print_ascii_tree(root);

    printf("\nAfter inserting keys 9, 13..\n");
    root = insert(9, root);
    root = insert(13, root);
    print_ascii_tree(root);

    printf("\nAfter inserting keys 2, 6, 12, 14, ..\n");
    root = insert(2, root);
    root = insert(6, root);
    root = insert(12, root);
    root = insert(14, root);

    print_ascii_tree(root);

    make_empty(root);
}

CodePudding user response:

Here:

$(program_NAME): $(OBJS)
    $(LINK.c) $(program_OBJS) -o $(program_NAME)

you use program_OBJS variable, which is not defined. If you fix it to $(OBJS) or $^, then there is another problem with LINK.c. It is defined as:

LINK.c := $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)

which means the resulting command will have library first and main.o second:

-lprint_ascii_tree main.o

and the linker won't find symbols used in main.o, which are defined in the library.

I'm not sure if you can make it work using separate LINK.c variable, but this should work:

$(program_NAME): $(OBJS)
    $(CC) $(CFLAGS) $(CPPFLAGS) $^ $(LDFLAGS) -o $@
  • Related