简体   繁体   English

C如何管理多个源文件之间的#include关系并创建正确的Makefile

[英]C How to manage #include relationship among multiple source files and create correct makefile

I again re-edited my question and this time it is final. 我再次重新编辑了我的问题,这次是最终的。

note: the program is working (thanks for all the help). 注意:程序正在运行(感谢所有帮助)。 But I still have some confusion about how the dependency/linkage actually works. 但是对于依存关系/链接实际上是如何工作的,我仍然有些困惑。 Specifically I would like to be walked through the process that the makefile compiles and runs. 具体来说,我想逐步了解makefile编译和运行的过程。 (example, the compiler first looks at main.c, starting from line 1, which is main.h, goes into main.h, starting from line 1, which points to function1.h, and so on.) (例如,编译器首先从main.h的第1行开始查看main.c,然后从指向function1.h的第1行开始进入main.h,依此类推。)

My main question here is though: is it true that compiler/makefile operates in a backwards way, that is once the compiler reaches the last stop (no more link), it started to gather the content recursively and put it in the object file. 不过,我的主要问题是:编译器/ makefile是否确实以向后的方式运行,也就是说,一旦编译器到达最后一站(没有更多链接),它便开始递归收集内容并将其放入目标文件中。 And what happens if we have multiple object file and the connect is cross-linked? 如果我们有多个目标文件并且连接是交叉链接的,那会发生什么呢? Should each object file be independent from each other? 每个目标文件应该彼此独立吗?

Below is my final result. 以下是我的最终结果。 I know it is a lot of parts, but I have tried my best to put them in a organized way and added description. 我知道这是很多部分,但是我已尽力将它们整理得井井有条,并增加了说明。

FINALE MAKEFILE / DEPENDENCY 最终的MAKEFILE /依赖

File layout 文件布局

primary module: main.c supplementary modules: builder1.c, builder2.c builder1_function.c builder2_function.c header files: main.h control.h builder1.h builder2.h builder1_function.h builder2_function.h builder1_shared.h builder2_shared.h 主模块:main.c辅助模块:builder1.c,builder2.c builder1_function.c builder2_function.c头文件:main.h control.h builder1.h builder2.h builder1_function.h builder2_function.h builder1_shared.h builder2_shared.h

1) main.c uses calls one primary function from each of builder1.c and builder2.c 1)main.c使用从builder1.c和builder2.c中的每个调用一个主要函数

2) builder1_function, builder2_function store child functions used by the primary function in builder1.c and builder2.c 2)builder1_function和builder2_function存储在builder1.c和builder2.c中主要功能使用的子功能

3) builder1 has a set of new structures just used by it, builder2 has another set of new structures just used by it. 3)builder1刚刚使用了一组新结构,builder2刚刚使用了另一组新结构。 These structures are declared in builder1_shared.h and builder2_shared.h. 这些结构在builder1_shared.h和builder2_shared.h中声明。

4) function prototypes are declared in builder1.h builder2.h main.h 4)函数原型在builder1.h中声明builder2.h main.h

5) main.c, builder1.c, builder2.c share some constants and all uses standard libraries. 5)main.c,builder1.c,builder2.c共享一些常量,并且都使用标准库。 These constants are declared in control.h 这些常量在control.h中声明

6) control.h: declare system-wide constants 6)control.h: 声明系统范围的常量

HEADER DEPENDENCY 标头依赖

main.c: *include* main.h and *define* system-wide constants (declared in control.h)
main.h: *include* all std libs, *include* control.h, *include* builder1.h, *include* builder2.h

builder1.c: *include* builder1.h, uses system-wide constants, child functions of builder1, and new structures of builder1, stdlib
build1.h: *include* builder1_funcion.h *include* builder1_share.h *include* primary function prototype

builder1_function.c: *include* builder1_function.h
builder1_function.h: *include* builder1_shared.h *include* child function prototype

builder_shared.h: *include* main.h, declare new structure for buidler1

builder2.c: *include* builder2.h, uses system-wide constants, child functions of builder2, and new structures of builder2, stdlib
build2.h: *include* builder2_funcion.h *include* builder2_share.h *include* primary function prototype

builder2_function.c: *include* builder2_function.h
builder2_function.h: *include* builder2_shared.h *include* child function prototype

builder_shared.h: *include* main.h, declare new structure for buidler2

MAKEFILE MAKEFILE

main: main.o builder1.o builder1_function.o builder2.o builder2_function.o
gcc -o main main.c builder1.c builder1_function.c builder2.c builder2_function.c -g

builder1.o: builder1.c
gcc -c  builder1.c

builder1_function.o: builder1_function.c
gcc -c builder1_function.c

builder2.o: builder2.c
gcc -c builder2.c

builder2_function.o: builder2_function.c
gcc -c builder2_function.c

Headers provide information to multiple source files. 标头将信息提供给多个源文件。 If a source file doesn't provide any services to other files, it doesn't need any header. 如果源文件不向其他文件提供任何服务,则不需要任何头。 That means main.h might not be needed, but functions.h is needed. 这意味着可能不需要main.h ,但需要functions.h A header should contain the minimum necessary code to allow consumers to use the functions (and variables) defined in the source code. 标头应包含最低限度的必需代码,以允许使用者使用源代码中定义的功能(和变量)。 Any other headers should be included directly in the source code (so the headers should be small, and self-contained, and idempotent). 其他任何标头都应直接包含在源代码中(因此标头应小巧,独立且幂等)。

Note that the main source file corresponding to a header ( main.c for main.h , or functions.h for functions.c ) should include the header as the first included file. 请注意,与标头( main.h main.c ,或functions.hfunctions.c )相对应的主源文件应将标头作为第一个包含的文件。 This ensures that the header is self-contained; 这样可以确保标题是独立的。 it won't compile if it is not. 如果不是,它将不会编译。 Each consumer of services from another source file should include the corresponding header. 来自另一个源文件的每个服务使用者都应包括相应的标头。 Each non-static function (and global variable if you have any) should be declared in precisely one header; 每个非静态函数(以及全局变量,如果有的话)都应该在一个头文件中声明; that header should be used wherever the function (or global variable) is needed. 该标头应在需要函数(或全局变量)的任何地方使用。

Given your problem, it appears that functions.c should include main.h (and main.h is therefore needed). 鉴于您的问题,似乎functions.c应该包含main.h (因此需要main.h )。

In your makefile, you should probably use: 在您的makefile中,您可能应该使用:

OBJECTS = main.o functions.o

all:  main

main: ${OBJECTS}
    ${CC} -o $@ ${OBJECTS} ${CFLAGS} ${LDFLAGS} ${LDLIBS}

main.o:      main.h functions.h
functions.o: functions.h main.h

See also: 也可以看看:

#include is a pre-processing command that just does text inclusion - nothing more complex or magic than that. #include是只执行文本包含的预处理命令-没什么比这更复杂或神奇的了。

So: 所以:

  • if a .c file has code that uses a structure, then it needs to include the header file that defines that structure. 如果.c文件包含使用结构的代码,则它需要包括定义该结构的头文件。

  • if a .c file implements or calls a function, then it needs to include the header file that decares that function's prototype (this is usually the header file that matches the .c file that implements the function). 如果.c文件实现或调用了函数,则它需要包括不重视该函数原型的头文件(通常是与实现该功能的.c文件匹配的头文件)。

  • if a .c file uses certain system calls or types, then it needs to include the relevant system header file 如果.c文件使用某些系统调用或类型,则它需要包括相关的系统头文件

Once you've got used to the concept of #include , you'll be able to work out how to structure your modules and header files efficiently and elegantly, for easy reading and maintenance. #include的概念后,您将可以弄清楚如何有效,优雅地构造模块和头文件,以便于阅读和维护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM