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 $@
