Makefile learning notes

Makefile learning notes

make, use it

  1. Exercise file preparation
// main.c
#include<stdio.h>
#include "input.h"
#include "calcu.h"

int main(int argc, char *argv[])
{
	int a, b, num;
	
	input_int(&a, &b);
	printf("%d + %d = %d", a, b, calcu(a, b));
	return 0;
}
// calcu.c
#include "calcu.h"

int calcu(int a, int b)
{
	return (a+b);
}
// input.c
#include<stdio.h>
#include "input.h"

void input_int(int *a, int *b)
{
	printf("input two number:");
	scanf("%d %d", a, b);
	printf("\r\n");
}
// input.h
#ifndef _INPUT_H
#define _INPUT_H
	
void input_int(int *a, int *b);
	
#endif
// calcu.h
#ifndef _CALCU_H
#define _CALCU_H

int calcu(int a, int b);

#endif
  1. Compile the above file into an executable file with gcc command
gcc main.c input.c calcu.c -o demo

Disadvantages: using a gcc command to compile and link. c files is not a problem if there are few files, but if a project has tens of thousands of source code files, for one thing, such a long gcc command is very annoying, and for another, the biggest problem is that every time you modify the code of a source file, all files will be recompiled. If there are too many files, Every time a small part is modified, the whole project will be recompiled again. It is farting and taking off your pants - asking for trouble. If the project is large, it is very laborious to compile a small change, which is simply thankless

  1. Replace the above command with the following command
gcc -c main.c
gcc -c input.c
gcc -c calcu.c
gcc -o demo main.o input.o calcu.o

After using this command, you don't have to compile all the source files with every small change. You just need to compile the source files with the corresponding changes, generate the corresponding. o files, and then link them. However, the problem is that you still have to type such a long command every time

  1. make

In order to avoid the above problems again, a make command appears under Linux. Make calls gcc to automatically compile the whole project according to the contents of Makefile, that is, write it once and for all

Principle of make

  • For the modification of the source file, you only need to recompile the source file and then link it to generate a new executable file
  • For the modification of the header file, all modules referenced to the header file are compiled
# How does Makefile write
demo: main.o input.o calcu.o
	gcc -o demo main.o input.o calcu.o
	
main.o: main.c
	gcc -c main.c
input.o: input.c
	gcc -c input.c
calcu.o: calcu.c
	gcc -c calcu.c

clean:
	rm *.o
	rm ./demo

After writing the Makefile, open the shell in the current folder and enter the make command to achieve the effect of automatic compilation

How to use make well

To use make well, you must master some writing methods of Makefile

Composition of Makefile

target: rely on
	shell command
	......

Makefile is composed of targets, dependencies and commands. A makefile must have an end target. Generally, the end target is to generate an executable file. By default, the end target is the first, and then other auxiliary targets can be out of order without considering the order

main: main.o input.o calcu.o
	gcc -o demo main.o input.o calcu.o

The above makefile statement is that the main target depends on the three files of main.o input.o calcu.o. calling the target is to execute a series of shell statements under the target statement. The statement below the target is to link main.o input.o calcu.o to generate the executable demo

Makefile variable

All variables in Makefile are strings

# Define variables
var = value
# Use variables
$(var)

How to use variables

# The previous makefile can be simplified to
obj = main.o input.o calcu.o
main: $(obj)
	gcc -o demo $(obj)

Assignment statement

# = 
value = hello
currval = $(value)
value = hello1
main:
	echo $(currval)   # Output hello1
# := 
value = hello
currval := $(value)
value = hello1
main:
	echo $(currval)   # Output hello
# ?=
value ?= hello # If value has been defined, then no operation is performed. If not, then value=hello
# +=
value = hello
value += world  # Add

Pattern rules

main.o: main.c
	gcc -c main.c
input.o: input.c
	gcc -c input.c
calcu.o: calcu.c
	gcc -c calcu.c
	
# The above operation is too complex and can be replaced by this

%.o: %.c  # %Represents matching all characters
	gcc -c $<.c
	
a%.o: a%.o # All. o files starting with a depend on. c files starting with a

Automation variable

Automation variableexplain
$@Represents the target file name of the rule. If the target is a document file (in Linux, the. A file is usually a document file or a static library file), it represents the file name of the document. In the multi-objective pattern rule, it represents the file name that triggers the rule to be executed.
$%When the target file is a static library file, it represents a member name of the static library.
$<The first dependent file name of the rule. If a target file is reconstructed using implicit rules, it represents the first dependent file added by implicit rules.
$?List of all dependent files that are newer than the target file, separated by spaces. If the target file is a static library file, it represents a library file (. o file).
$^Represents a list of all dependent files, separated by spaces. If the target is a static library file, it can only represent all library member (. o file) names. A file can repeatedly appear in the dependency of the target, including variables“ " only remember record it of The first one second lead use of feeling condition . Just yes say change amount " ^"Records only its first reference. That is, variables“ ”Only record its first reference. That is, the variable "^" will remove the duplicate dependent files.
$+Similar to "$^", but it retains the files that appear repeatedly in the dependent files. It is mainly used for cross reference of library when linking programs.
$*In pattern rules and static pattern rules, it represents "stem". "Stem" is the part represented by "%" in the target pattern (when there is a directory in the file name, "stem" also includes the directory Part).

Pseudo target

.PHONY:Target name


# No. PHONY
clean:
	rm *.o
	rm ./demo
# If clean is the file in the current folder, an error will be reported when you execute make clean

# Yes. PHONY
.PHONY:clean
clean:
	rm *.o
	rm ./demo
# Even if there is a clean file, there will be no error when executing make clean

Precede the command with@

# Adding @ before the command means that the command will not output what I executed on the shell window
zouren@ubuntu:~/Cmake_Learn$ make
echo hello1  # Without @, the command executed is displayed
hello1
zouren@ubuntu:~/Cmake_Learn$ make
hello1		 # With @, the executed command is not displayed
zouren@ubuntu:~/Cmake_Learn$ 

Tags: C++ Makefile

Posted on Sat, 23 Oct 2021 11:00:47 -0400 by derzok