Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Makefile(05)_ automatically generates dependencies

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/03 Report--

11. Automatically generate dependencies on 11.0. Experimental raw materials

Source and header files required for labs in this section:

Original file: func.c

# include "stdio.h" # include "func.h" void foo () {printf ("void foo ():% s\ n", HELLO);}

Original file: main.c

# include # include "func.h" int main () {foo (); return 0;}

Header file func.c

# ifndef FUNC_H#define FUNC_H#define HELLO "Hello D.T." void foo (); # endif11.1. Problems and solutions

Question:

Does the target file .o depend only on the source file .c? How does the compiler compile source and header files?

The compiler processes the code in the header file directly into the source file, and the compiler only generates the target file through the preprocessed original file. Therefore, the rule depends on the source file, and the command may not be executed. Is there a problem with Makefile next?

OBJS: = func.o main.ohello.out: $(OBJS) @ gcc-o $@ $^ @ echo "Target File = > $@" $(OBJS):% .o:% .c @ gcc-o $@-c $@ clean: $(RM) $(DEPS)

Output result:

We have successfully generated the dependency files main.dep and func.dep at this time and recorded the relationship between the target and the dependency in the file.

Consider: what if an organization relies on file-related rules and source code compilation-related rules to form a fully functional Makefile?

13. Automatically generate dependencies _ under 13.1. Remaining problems

How do I organize .dep files to a specified directory in makefile?

The solution is as follows:

When include discovers that the .dep file does not exist, it creates a deps folder through rules and commands, creates all .dep files into the deps folder, and records the dependencies of the target files in the .dep file.

$(DIR_DEPS): $(MKDIR) $@ $(DIR_DEPS) /%. Dep: $(DIR_DEPS)%. C @ echo "Creating $@..." @ set-e;\ $(CC)-MM-E $^ | sed's,\ (.*\)\ .o [:] *, objs/\ 1.o:, g'> $@

This does solve the above problem, generating the deps folder:

But at the same time, we see two problems:

1. Because the dependency contains the deps folder, it is meaningless to use the deps folder as the input of gcc-MM, and the warning is reported, so use the following method to filter out the deps folder

$(CC)-MM-E $(filter% .c, $^) | sed's,\ (.*\)\ .o [:] *, objs/\ 1.o:, g'> $@

2.func.dep has been created repeatedly?

Analysis of the nature of the problem:

The time attribute of the deps folder changes depending on file creation, and when make finds that the deps folder is updated compared to the target, it will trigger the reinterpretation of the corresponding rules and the execution of the command.

Solution: use ifeq to dynamically determine the dependencies of .dep goals

Ifeq ("$(wildcard $(DIR_DEPS))", ") $(DIR_DEPS) /%. Dep: $(DIR_DEPS)% .celse $(DIR_DEPS) /% .dep:% .cendif 13.2.Include dark operation

1. Use-turns off not only warnings issued by include, but also errors that make ignores when errors occur.

two。 If the include trigger rule creates a file, the following occurs:

/ / Dark operation if when using include (if the target file does not exist) {/ / find and execute with the file name as the rule If (file created in the found rule) {/ / include the successfully created object file in the current makefile}} else / / if the target file exists {/ / include the target file in the current makefile if (find whether there is a corresponding rule by the target file name) {if (compare the dependency of the rule) Decide whether to execute the command of the rule) {/ / (depending on file update, execute)} else {/ / No Action}} else {/ / No Action}}

The object file included in the experimental 1:include does not exist, and a rule targeting the file name exists, and a file is created in the rule

.PHONY: all-include test.txtall: @ echo "this is all" test.txt: @ echo "creating $@..." @ echo "other:; @ echo" this is other "" > test.txt

We expect the output to be: this is all, because all is the first (default) target.

Running result:

The reason is that when the above situation occurs: the file name is used as the rule to find and execute, and if the file is created in the found rule, the successfully created target file is included in the current makefile, and the first target in makefile becomes other.

Lab 2:

.PHONY: all-include test.txtall: @ echo "this is all" test.txt: b.txt @ echo "creating $@..."

The result of running when there is no b.txt:

When b.txt exists, but the b.txt file is older than the test.txt file, the result of running:

The result of running when a b.txt exists but the b.txt file is newer than the test.txt file:

Conclusion: if the object file exists: include the target in the current makefile and find out whether there are corresponding rules with the target file name

If there is a dependency of the rule, decide whether to execute the command of the rule (depending on the file update, then execute), and if the command in the rule updates the target file, replace what was previously included. If it is not updated, there is no action.

Use the target file name to find out whether there is a corresponding rule. If it cannot be found, there is no action.

Lab 3:

.PHONY: all-include test.txtall: @ echo "$@: $^" test.txt: b.txt @ echo "creating $@..." @ echo "all: c.txt" > test.txt

A.txt content:

All: a.txt

When all the required files in the file exist and the contents of the test.txt are up to date, the make all outputs the result:

When the b.txt file is up to date, make all outputs the result:

14. Automatically generate dependencies _ Cont.

After learning the previous skills, we can now complete the idea of automatically generating dependencies.

Note:

Consider: is there a problem with the makefile we finally created in Section 13?

When the .dep file is generated, if the dependency between files is changed dynamically, then make may not be able to detect the change and make a wrong judgment.

Example:

Output result:

Solution:

Add the file name of the dependency file as the target to the automatically generated dependency relationship, judge whether the rule is executed or not when the dependency file is loaded by include, regenerate the dependency file when the rule is executed, and finally load the new dependency file.

For example, Chestnut: when we compiled before (generated a dependency file), and added a new header file, then according to the dark operation of include, to check whether the rule with the same name as the dependency file contained in include exists, if so, check whether the dependency corresponding to this target has been updated, and if so, execute the corresponding rule.

Final plan:

.PHONY: all clean rebuildMKDIR: = mkdirRM: = rm-frCC: = gccDIR_DEPS: = depsDIR_EXES: = exesDIR_OBJS: = objsDIRS: = $(DIR_DEPS) $(DIR_EXES) $(DIR_OBJS) EXE: = app.outEXE: = $(addprefix $(DIR_EXES) /, $(EXE)) SRCS: = $(wildcard * .c) OBJS: = $(SRCS:.c=.o) OBJS: = $(addprefix $(DIR_OBJS) / $(OBJS)) DEPS: = $(SRCS:.c=.dep) DEPS: = $(addprefix $(DIR_DEPS) /, $(DEPS)) all: $(DIR_OBJS) $(DIR_EXES) $(EXE) ifeq ("$(MAKECMDGOALS)", "all") include $(DEPS) endififeq ("$(MAKECMDGOALS)", ") include $(DEPS) endif$ (EXE): $(OBJS) $(CC)-o $@ $@ echo" Success! Target = > $@ "$(DIR_OBJS) /% .o:% .c $(CC)-o $@-c $(filter% .c, $^) # $(CC)-o $@-c $(filter% .c, $^) $(DIRS): $(MKDIR) $@ ifeq (" $(wildcard $(DIR_DEPS)) " ") $(DIR_DEPS) /% .dep: $(DIR_DEPS)% .celse $(DIR_DEPS) /% .dep:% .cendif @ echo" Creating $@... "@ set-e \ $(CC)-MM-E $(filter% .c, $^) | sed's,\ (.*\)\ .o [:] *, objs/\ 1.o $@:, g'> $@ clean: $(RM) $(DIRS) rebuild: @ $(MAKE) clean @ $(MAKE) all

Summary:

In Makefile, the dependencies of targets can be split and written to different places.

The include keyword can trigger the execution of the corresponding rules

If the execution of the rule results in dependent updates, it may cause the corresponding rule to be interpreted and executed again.

Dependent files can rely on source files to make correct compilation decisions.

Automatic generation of file dependencies can improve the portability of Makefile.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report