生成库和主程序的 C Makefile 不正确?
Incorrect C Makefiles to generate library and main program?
有C语言的库和主测试驱动,虽然库可以编译成功,但是主测试驱动却不能。
目录结构如下:
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
这是库的 makefile:
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
这个库可以顺利编译:
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
这是测试驱动程序的 Makefile:
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
这是错误:
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
看起来 main.o
已编译,但无法与库链接到主要可执行文件中?
不确定 Makefile 中有什么问题。
P.S。这是 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);
}
这里:
$(program_NAME): $(OBJS)
$(LINK.c) $(program_OBJS) -o $(program_NAME)
您使用了 program_OBJS
变量,该变量未定义。如果你把它固定为 $(OBJS)
或 $^
,那么 LINK.c
就会有另一个问题。它被定义为:
LINK.c := $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
这意味着生成的命令首先是库,然后是 main.o
:
-lprint_ascii_tree main.o
并且链接器不会找到在库中定义的 main.o
中使用的符号。
我不确定你是否可以使用单独的 LINK.c
变量让它工作,但这应该工作:
$(program_NAME): $(OBJS)
$(CC) $(CFLAGS) $(CPPFLAGS) $^ $(LDFLAGS) -o $@
有C语言的库和主测试驱动,虽然库可以编译成功,但是主测试驱动却不能。
目录结构如下:
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
这是库的 makefile:
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
这个库可以顺利编译:
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
这是测试驱动程序的 Makefile:
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
这是错误:
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
看起来 main.o
已编译,但无法与库链接到主要可执行文件中?
不确定 Makefile 中有什么问题。
P.S。这是 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);
}
这里:
$(program_NAME): $(OBJS)
$(LINK.c) $(program_OBJS) -o $(program_NAME)
您使用了 program_OBJS
变量,该变量未定义。如果你把它固定为 $(OBJS)
或 $^
,那么 LINK.c
就会有另一个问题。它被定义为:
LINK.c := $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
这意味着生成的命令首先是库,然后是 main.o
:
-lprint_ascii_tree main.o
并且链接器不会找到在库中定义的 main.o
中使用的符号。
我不确定你是否可以使用单独的 LINK.c
变量让它工作,但这应该工作:
$(program_NAME): $(OBJS)
$(CC) $(CFLAGS) $(CPPFLAGS) $^ $(LDFLAGS) -o $@