如何使用 make 构建 CS50 程序
How to build CS50 programs with make
我正在尝试在 linux 上学习 cs50,我下载了在 github 上找到的所有内容,但现在我无法使用 make 编译我的第一个程序,但我可以改用 clang clang hello.c -lcs50 -o hello
效果很好,但是当我尝试使用 make hello
进行编译时,我得到
:~/cs50/pset1# make hello
cc hello.c -o hello
/usr/bin/ld: /tmp/cczILfhu.o: in function 'main':
hello.c:(.text+0x1a): undefined reference to 'get_string'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: hello] Error 1
我什至把我下载的libcs50文件夹移到/usr/include/
但我仍然得到相同的结果。
在我用 clang 编译之后,然后执行 make hello
它说
make: 'hello' 是最新的。
我知道这听起来很垃圾,但我仍然是新手,正在寻求帮助。
提前致谢。
对于 cs50 库中的链接(您应该根据那里的说明从 https://github.com/cs50/libcs50 安装),您的链接命令应该指定 -lcs50
参数。
make
通常需要一个 Makefile
来控制构建。如果它不存在,它可以使用一些隐式规则来猜测构建过程,例如 hello.o
可以从 hello.c
构建并且 hello
可以从 hello.o
链接等等,但它肯定猜不到 libcs50
应该被链接进来。
幸运的是,隐式链接规则正确地包含了变量 LDLIBS
的内容,因此您可以通过在同一目录中编写一个简单的 Makefile
来解决这个问题,只包含 [=42] =]
LDLIBS += -lcs50
即“将字符串 -lcs50
附加到 LDLIBS
的当前值”。
之后make hello
会使用隐式规则和LDLIBS
的新值来执行
cc hello.c -lcs50 -o hello
另请注意,cc
命令通常是 GCC,而不是 Clang,这在 CS50 中并不重要。可以用Makefile
中的CC
变量配置:
CC := clang
最后,在 compilation 标志中启用警告和迂腐确实有意义,例如:
CFLAGS += -Wall -Wextra -Werror -pedantic -std=c11
有了所有这 3 个,make hello
将实际执行
clang -Wall -Wextra -Werror -pedantic -std=c11 hello.c -lcs50 -o hello
这意味着我们确实节省了大量的输入并获得了更多有用的诊断!
当然,对于更复杂的构建过程,您需要使用依赖规则编写更复杂的 Makefile
- 假设您的 helloworld
程序由 hello.c
和 world.c
链接在一起,你可以通过隐式规则得到,只需声明 helloworld
取决于 hello.o
和 world.o
并且应该从这些链接在一起:
helloworld: hello.o world.o
$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS)
# the command *must* be indented by a *single* tab character, not spaces!
# unfortunately SO editor does not make it easy to write tabs.
我正在尝试在 linux 上学习 cs50,我下载了在 github 上找到的所有内容,但现在我无法使用 make 编译我的第一个程序,但我可以改用 clang clang hello.c -lcs50 -o hello
效果很好,但是当我尝试使用 make hello
进行编译时,我得到
:~/cs50/pset1# make hello
cc hello.c -o hello
/usr/bin/ld: /tmp/cczILfhu.o: in function 'main':
hello.c:(.text+0x1a): undefined reference to 'get_string'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: hello] Error 1
我什至把我下载的libcs50文件夹移到/usr/include/
但我仍然得到相同的结果。
在我用 clang 编译之后,然后执行 make hello
它说
make: 'hello' 是最新的。
我知道这听起来很垃圾,但我仍然是新手,正在寻求帮助。
提前致谢。
对于 cs50 库中的链接(您应该根据那里的说明从 https://github.com/cs50/libcs50 安装),您的链接命令应该指定 -lcs50
参数。
make
通常需要一个 Makefile
来控制构建。如果它不存在,它可以使用一些隐式规则来猜测构建过程,例如 hello.o
可以从 hello.c
构建并且 hello
可以从 hello.o
链接等等,但它肯定猜不到 libcs50
应该被链接进来。
幸运的是,隐式链接规则正确地包含了变量 LDLIBS
的内容,因此您可以通过在同一目录中编写一个简单的 Makefile
来解决这个问题,只包含 [=42] =]
LDLIBS += -lcs50
即“将字符串 -lcs50
附加到 LDLIBS
的当前值”。
之后make hello
会使用隐式规则和LDLIBS
的新值来执行
cc hello.c -lcs50 -o hello
另请注意,cc
命令通常是 GCC,而不是 Clang,这在 CS50 中并不重要。可以用Makefile
中的CC
变量配置:
CC := clang
最后,在 compilation 标志中启用警告和迂腐确实有意义,例如:
CFLAGS += -Wall -Wextra -Werror -pedantic -std=c11
有了所有这 3 个,make hello
将实际执行
clang -Wall -Wextra -Werror -pedantic -std=c11 hello.c -lcs50 -o hello
这意味着我们确实节省了大量的输入并获得了更多有用的诊断!
当然,对于更复杂的构建过程,您需要使用依赖规则编写更复杂的 Makefile
- 假设您的 helloworld
程序由 hello.c
和 world.c
链接在一起,你可以通过隐式规则得到,只需声明 helloworld
取决于 hello.o
和 world.o
并且应该从这些链接在一起:
helloworld: hello.o world.o
$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS)
# the command *must* be indented by a *single* tab character, not spaces!
# unfortunately SO editor does not make it easy to write tabs.