first, the introduction of the Experiment--makefile Rule Advanced (2)
This experiment will introduce the method of using Wildcard,vpath,vpath,gpath,-lname in Makefile and the method of file path preservation. 1.1 Experiment Content function wildcard use of VPATH and VPATH use file path save and Gpath use-lname file use 1.2 experimental knowledge points cannot be used directly when variable definition or function reference With the wildcard function instead of the VPATH variable, you can specify a search path for a dependent file, separate multiple paths with a space or a colon VPATH keyword is more flexible than VPATH, you can specify a search path for files that match the pattern, and you can clear the search path
The file path save algorithm for make is as follows:
1 Search the target file in the current working directory, and execute the directory search if it does not exist;
2 the same processing method is used for dependent documents;
3 decide whether the goal needs to be rebuilt by making the following choices:
3.1 The full pathname of all files in the rule is not required to be rebuilt;
3.2) When reconstruction is needed, the full path of the target is invalidated, the target is being rebuilt in the current working directory, not the directory when the directory is searched, but the full path of the dependent file is still valid, and if the destination file's full path exists in the Gpath variable list, make uses the full path to rebuild the target. Instead of the current working directory when the file name is-lname, make finds the libname.so, finds the Libname.a file when the file does not exist, and the path search order is: current directory > VPATH or VPATH specified directory >/lib/> /usr/lib/>/usr/local/lib/-lname are expanded into libname.so or libname.so are by variables ". Libpatterns " 1.3 experimental environment specified
Ubuntu system, GNU GCC Tool, GNU make tool 1.4 for crowd
This course is moderately difficult, suitable for students who have already learned the makefile rules. 1.5 Code Acquisition
You can get code from the following command:
$ git clone https://github.com/darmac/make_example.git
second, the experimental principle
According to the basic rules of makefile to conduct positive and negative experiments to learn and understand the use of rules. Iii. Development and preparation
Enter the experimental building course can be. IV. structure of the project document
.
├──gpath_code: For testing gpath
│ ├──main
│ └──makefile
├──lib_code: Use for testing-lname
│ ├──lib │ │ ├──foo_dynamic.c │ │ └──foo_static.c
│ ├──main.c
│ └──makefile
├──vpath_code: For testing Vpath and Vpath
│ ├──main.c
│ ├──makefile │ └──vpath.mk
└──wild_code: For testing the wildcard
function
├──foo1.c
├──foo1.h
├──foo2.c ├──foo2.h
├──main.c
├──makefile
└──pat_make.mk
v. Steps of the Experiment
the use of 5.1 function wildcard
5.1.1 Crawl Source code
Use the following cmd to get the GitHub source code and enter the appropriate section:
CD ~/code/
git clone https://github.com/darmac/make_example.git
CD Make_example/chapter5
the time of use of 5.1.2 wildcard
The previous section describes the use of file wildcards, where wildcards are automatically expanded, but wildcard characters are invalidated when variable definitions and function references are used.
Use the wildcard function if you need to use a wildcard character at this point.
Its syntax format is: $ (wildcard pattern ...).
In makefile, it is expanded to a list of all files that already exist, separated by spaces, that match this pattern. 5.1.3 uses wildcard to match all. c files in the current directory
Here we use the code compilation process to test, first into the Wild_code directory:
CD Wild_code
The files in the Wild_code directory are as follows:
├──foo1.c
├──foo1.h
├──foo2.c
├──foo2.h
├──main.c
└──makefile
FOO1.C defines the foo1 () function, prints "Hello foo1!", foo2.c defines the Foo2 () function, and prints "Hello foo2!".
MAIN.C calls Foo1 () and Foo2 () in turn.
The contents of the makefile file are as follows:
#this is a makefile for wildcard code test
. Phony:all Clean
code=$ (wildcard *.c)
aim=wildtest all:$
(code)
@echo "Objs inlude:" $ (code)
$ (CC )-O $ (AIM) $ (code) Clean
:
$ (RM) $ (AIM)
Its ultimate goal all depends on all the. c files in the current directory.
Rebuilding the target all prints the dependent file and links it to the Wildtest file using CC.
Perform make See effect:
Make
Terminal printing:
Objs inlude: foo1.c main.c foo2.c cc-o wildtest foo1.c main.c
Executive Wildtest:
./wildtest
Terminal printing:
Hello foo1!
Hello foo2!
Visible Wildtest program conforms to the expected process. 5.1.4 more complex usage
In actual project management, we usually use the. o file as a dependency rather than the. c file, where you need to use a nested call to the function.
We can use $ (patsubst src_pattern,dest_pattern,full_str) for string substitution and replace the. c file with an. o File:
objs=$ (Patsubst%.c,%.o,$ (wildcard *.c))
This allows you to convert the. c file list under the current directory to an. o file list, and then compile it automatically using the implied rules of make.
The specific use method can refer to Pat_make.mk file:
#this is a makefile for wildcard code test
. Phony:all clean
objs=$ (patsubst%.c,%.o,$ (wildcard *.c))
aim=wildtest2 all:$
(OBJS)
@echo "Objs Inlude: "$ (OBJS)
$ (CC)-O $ (AIM) $ (OBJS) Clean
:
$ (RM) $ (OBJS)
$ (RM) $ (AIM)
Execute Make:
Make-f pat_make.mk
Terminal printing:
CC -c-o foo1.o foo1.c
cc -c-o foo2.o foo2.c
cc -c-o main.o
main.c objs inlude: foo 1.O foo2.o main.o
cc-o wildtest2 foo1.o foo2.o MAIN.O
Visible foo1.c,main.c,foo2.c have been replaced with the corresponding. o file.
The experimental process is shown in the following illustration:
5.2 VPATH variables and the use of VPATH keywords 5.2.1 VPATH Variable test
The VPATH variable can specify a search path for the file, and if the dependent or destination file for the rule does not exist in the current directory, make will look for dependent files in the directory specified by this variable.
VPATH can define multiple directories, which are separated by ":", and the directory search order is in accordance with the order defined in VPATH.
Enter into the Vpath_code directory:
Cd.. /vpath_code
Here is a copy of the MAIN.C document, which reads as follows:
#include <stdio.h>
extern void foo1 (void);
extern void Foo2 (void);
int main (void)
{
foo1 ();
Foo2 ();
return 0;
}
The implementation of the main function is consistent with the Mian function in 5.1, each calling foo1 () and Foo2 () respectively.
But here, Extern declares that foo1 () and Foo2 () are external functions, and that they are no longer declared by including header files.
This makes the MAIN.C itself not concerned about where the header files of these two functions are placed, as long as the. o files in the link can contain their implementations.
The function implementations of foo1 () and Foo2 () are in the chapter5/wild_code/directory, and we can tell makefile their paths by VPATH variables.
The contents of the makefile file are as follows:
#this is a makefile for VPATH test
. Phony:all clean
depen=main.o foo1.o foo2.o
aim=main all:$
(depen)
@echo "Objs inlude:" $ (Depen) c15/>$ (CC)-O $ (AIM) $ (depen) Clean
:
$ (RM) $ (depen) $
(RM) $ (AIM)
It simply specifies three dependencies, respectively MAIN.O,FOO1.O and FOO2.O, and links the three to the main file when the all target is rebuilt.
What happens when you execute make directly.
Make
Terminal printing:
CC -c-o main.o main.c make
: * * * * target ' foo1.o ', needed by ' all '. Stop.
Because make cannot find the FOO1.O, there is no foo1.c file under the current path and cannot automatically rebuild the FOO1.O by relying on the implied rules, so make the error and exit execution.
Now we set VPATH for. /wild_code/and pass to make execution:
Make vpath= ... /wild_code/
Expected Terminal printing:
CC -c-o main.o main.c
cc -c-o foo1.o. /wild_code/foo1.c
cc -c-o foo2.o. /wild_code/foo2.c
objs inlude: main.o foo1.o foo2.o cc-o
main MAIN.O foo1.o
But in the experimental building environment print as follows:
Objs inlude: foo1.o foo2.o cc-o
main MAIN.O foo1.o foo2.o cc:error:main.o:no Such
file or director Y
cc:error:foo1.o:no such file or directory
cc:error:foo2.o:no such file or directory
cc:fatal error:n o Input Files
compilation terminated.
Make: * * * [ALL] Error 4
Not only can not find FOO1.O and foo2.o, and even main.o implicit rules have not been executed.
The build version for the lab building is 3.81, and the expected print is available in the Make 4.1 version, indicating that the 3.81 make tool does not correctly support the VPATH variable. But it doesn't matter, next we use a more flexible, more recommended way to specify the search directory. use of 5.2.2 vpath keywords
The Vpath keyword works like a vpath variable, and you can specify a directory of dependent or target files.
But the use of vpath is more flexible, and its usage is as follows:
1 Vpath Pattern DIR: Specifies the search directory for files that match patterns mode.
2 Vpath pattern: Clears the search directory that matches the file settings of patterns.
3) Vpath: Clears all search directories.
Refer to Vpath.mk's content, consistent with makefile, just one more line:
Vpath%.c. /wild_code/
This line specifies the search directory for all. c files.
Clean out the last compilation results, and then perform a new makefile test:
Make clean; Make-f vpath.mk
Terminal printing:
Rm-f main.o foo1.o foo2.o
rm-f main
cc-c-o MAIN.O main.c cc-c-o foo1.o . /wild_code/foo1.c
cc -c-o foo2.o. /wild_code/foo2.c
objs inlude: main.o foo1.o foo2.o cc-o
main MAIN.O foo1.o
The effect of VPATH.MK is consistent with the use of Vpath.
Interested students can then experiment Vpath clear the function of the search directory.
The experimental process is shown in the following illustration:
5.3 File path preservation and the use of Gpath 5.3.1 File path Save
As the previous experiment shows, sometimes some dependent or target files need to be searched for VPATH or VPATH specified directories.
Therefore, subsequent processes need to determine whether the full path to the directory search is to be retained or discarded.
Make the Save/discard algorithm for the file path when parsing the makefile file is as follows:
1 Find the file in the current directory, and search for the specified path if it does not exist.
2 If the directory search succeeds, the full path is saved as a temporary filename.
3 The dependent file uses the full path name directly.
4 The destination file uses the full pathname if it does not need to be rebuilt, otherwise the full pathname is discarded.
More difficult to understand is the 4th, simply means that the target file will be rebuilt in the current path. 5.3.2 File path rule validation
The following rule validation, first clear off the results of the last experiment and switch directories:
Make-f vpath.mk Clean; Cd.. /gpath_code/
The Gpath_code directory contains a copy of the makefile document, which reads as follows:
#this is a makefile for Gpath test
. Phony:all clean
vpath%.c. /wild_code/
depen=main.o foo1.o foo2.o
aim=main all:$
(depen)
@echo "Objs inlude:" $ (Depen)
$ (CC )-O $ (AIM) $^ Clean
:
$ (RM) $ (Depen)
$ (RM) $ (AIM)
The search path for the. c and. o files is also specified here compared to the previous makefile.
In addition, the automation variable $^ is used instead of $ (depen) when the all target is rebuilt, and the $^ variable expands the specified target file to the full pathname.
But all of the. c files are in. /wild_code/directory, according to the file path of the save rules, its corresponding. o file to be generated under the current path.
Perform make to test:
Make;ls
Terminal printing:
CC -c-o main.o. /WILD_CODE/MAIN.C
cc -c-o foo1.o. /wild_code/foo1.c
cc -c-o foo2.o. /wild_code/foo2.c
objs inlude: main.o foo1.o foo2.o cc-o
main main.o foo1.o foo2.o foo1.o C10/>main MAIN.O Makefile
You can find that foo1.o foo2.o ' MAIN.O ' main is generated in the current path. the use of 5.3.3 Gpath variables
If you do not want to generate the target file in the current directory, you can use the Gpath variable.
If the destination file matches the directory specified by the Gpath variable, its full pathname will not be discarded, and the target file will be rebuilt in the searched directory.
To test the effect of the Gpath variable, we first remove the file from the last Test and switch to ... /wild_code/directory compilation Gets the corresponding. o File:
Make CLEAN;LS;CD ... /wild_code;
Cc-c foo1.c;touch foo1.c
cc-c foo2.c;touch foo2.c cc-c main.c;touch main.c
FOO1.O foo2.o main.o files already exist under the Wild_code directory.
Cut back to the Gpath_code directory and use the Gpath variable when you execute make:
Cd.. /gpath_code/; Make gpath= ... /wild_code/;ls
Terminal printing:
CC -c-o main.o. /WILD_CODE/MAIN.C
cc -c-o foo1.o. /wild_code/foo1.c
cc -c-o foo2.o. /wild_code/foo2.c
objs inlude: main.o foo1.o foo2.o cc-o
main main.o foo1.o foo2.o foo1.o C10/>main MAIN.O Makefile
From the result of LS, the. o file is still generated under the current path, not in line with expectations, why.
Check the makefile file and discover:
Vpath%.c. /wild_code/
But we did not specify a directory for the. o target file.
To modify makefile, add a rule to the following line in the Vpath keyword:
Vpath%.O. /wild_code/
Clear the last execution result and execute it again:
Touch. /WILD_CODE/MAIN.C Touch
. /WILD_CODE/FOO1.C Touch
. /wild_code/foo2.c make
clean;ls;make gpath=. /wild_code/;ls
Terminal printing:
Rm-f main.o foo1.o foo2.o
rm-f main
makefile
cc -c-o. /WILD_CODE/MAIN.O.. /WILD_CODE/MAIN.C
cc -c-o. /WILD_CODE/FOO1.O.. /wild_code/foo1.c
cc -c-o. /WILD_CODE/FOO2.O.. /wild_code/foo2.c
objs inlude: main.o foo1.o foo2.o
main ... /WILD_CODE/MAIN.O.. /WILD_CODE/FOO1.O.. /WILD_CODE/FOO2.O
main Makefile
Visible this time only the main file is generated under the current path, and the remaining. o files are in the. Rebuilt in the/wild_code/.
The experimental process is shown in the following illustration:
use of 5.4-lname files 5.4.1-lname's Search
You can use-lname to link shared libraries and static libraries in makefile. The-lnmae in the file list will be resolved to a file named Libname.so or Libname.a.
The process of make search-lname is as follows:
1 searches the current directory for a file named libname.so;
2 if not exist, search for the path defined by VPATH or VPATH;
3 If still does not exist, make will search the system default directory, in order for/lib,/usr/lib,/usr/local/lib;
4 If you still cannot find the file, make will look for the file named Libname.a in the order listed above. 5.4.2 Library file Search rule validation:
The experiment steps are as follows:
1 Write the same name dynamic library files and static library files, using the same API internal printing of different information;
2 Write main file call library file API;
3 Compile library file to generate static library and dynamic library;
4) Makefile use-lname dependencies to link to verify which library file is used;
5 Delete previously linked to the library file again to perform make to confirm another library file can be successfully linked;
The sample code is already in the chapter5/lib_code/directory, and the file is as follows:
.
├──lib
│ ├──foo_dynamic.c
│ └──foo_static.c
├──main.c
└──makefile
Under lib/, there are two. c Files foo_dynamic.c and FOO_STATIC.C, which define the same function, Foo (), and return 1 and 2, which are used to generate dynamic and static library files, respectively.
The MAIN.C in the home directory calls the Foo () function and prints the resulting results.
The makefile provides methods for generating library files and linking MAIN.O, as follows:
#this is a makefile for-lname test
. Phony:all clean static_lib dynamic_lib
vpath=lib/
all:main.o-lfoo
$ (CC)-o main $^
static_lib:foo_ STATIC.O
$ (AR) RC libfoo.a $^;\
mv libfoo.a lib/
dynamic_lib:foo_dynamic.o
$ (CC) $^-fpic-shared-o Lib foo.so;\
mv libfoo.so lib/clean
:
$ (RM) *.O *.a *.so main
$ (RM) Lib/*.a Lib/*.soso
Dynamic library and Static library links, we have been tested in Chapter0, and now first build dynamic libraries and static library files.
Perform:
Cd.. /lib_code make
static_lib;make dynamic_lib;ls lib/
Terminal printing:
CC -c-o foo_static.o lib/foo_static.c
ar rc libfoo.a foo_static.o;\
mv libfoo.a lib/
cc -c-o FOO_DYNAMIC.O lib/foo_dynamic.c
cc foo_dynamic.o-fpic-shared-o libfoo.so;\
mv libfoo.so lib/
foo_ DYNAMIC.C foo_static.c libfoo.a libfoo.so
Then execute make to see which library file is linked to the ultimate goal:
make;./main
Terminal printing:
CC -c-o main.o main.c
cc-o main main.o lib/libfoo.so get
i=1
Visible-lname Precedence is resolved to a dynamic library.
Delete dynamic library compile execution again:
RM lib/libfoo.so make
;/main
Terminal printing:
Cc-o main MAIN.O lib/libfoo.a get
i=2
When a dynamic library file does not exist, make attempts to locate and link the static library file.
The expansion of the-lname is determined by the variable. Libpatterns to specify that the value defaults to "Lib%.so lib%.a".
Interested students can try to print and modify this variable themselves.
The experimental process is shown in the following illustration:
Vi. Summary of the experiment
This experiment has tested the Wildcard,vpath,vpath,gpath,-lname method and the file path preserving algorithm. post-class exercises
Try to test the VPATH feature with Release 4.1.