After getting used to writing build commands using SRC in package.json, I saw that there was a Makefile in the element-UI repository. So I googled it, and I saw how powerful this thing is.

A Makefile is a C/C++ tool that was originally used in UNIX as an engineering tool to perform a series of compilation and concatenation operations through the make command. If there is a Makefile in a directory that has a make environment. Typing make will execute one of the target commands in the Makefile.

I metMakefile

Use the Element-UI Makefile directly as an example.

.PHONY: dist test
default: help

install:
	npm install

new:
	node build/bin/new.js $(filter-out $@,$(MAKECMDGOALS))

deploy:
	@npm run deploy

help:
	@echo "\033[35mmake\033[0m \033[1m Command Instructions \033[0m"
Copy the code

On a MAC, you can run the make command directly. Windows Download the GUN tool of make

If you already have make installed globally on your computer, when you clone the element code and execute make install in the root directory, it will have the same effect as NPM install. Take a look at what make Install does.

  1. performmakeCommand to find it in this directoryMakefileFile.
  2. findMakefileFile corresponding to the command line parameterinstallThe goal of. The goal here is thatinstall:
  3. performnpm installThe following statement.npm run dev

MakefileThe file format

The make command itself is not difficult; it simply executes the target that follows. The target details are in the Makefile.

A Makefile is made up of a series of rules, and each rule needs to know two things: what the build goal is, and how to build it. Each rule follows the following format:

<target> : <prerequisites>
[tab] <commands>
Copy the code

The first line is:It’s divided into two parts.

  • The first part is the targettargetThat is to performmake targetCommand to match the target.
  • The latter part is the precondition (dependent target), if the first line is written astarget1: target2 target3, then in executionmake target1“, you need to execute the command firstmake target2 make target3It’s executed at the endtarget1The followingcommondsStatements.

The second row must consist of onetabKey, followed by the statement that needs to be executed

Target for each rule is required, both Prerequisites and the second line are optional, but there must be at least one in between.

This is just enough for the Makefile code in the Element-UI project to make sense of most of it. But if you look at the first line of the code, PHONY: dist test, what is that?

Target and Phony Target

Each rule contains a target, which in make is usually a file name that identifies the object that the rule needs to build. The destination can be one or more file names separated by Spaces.

Of course, the name of a target can also be the name of a specific operation, which is called a phony target. For example, remove below is a pseudo target. His role is to delete files.

remove:
	rm *.js
Copy the code

However, if make remove is executed again and there is a file named remove in the directory, the command will not be executed because make finds that the file already exists and there is no need to rebuild it, it will ignore the command.

To avoid this, you can proactively declare remove as a pseudo target.

.PHONY: remove
remove:
	rm *.js
Copy the code

When.PHONY: actively declares remove to be a PHONY target, make does not check for the existence of files that contain remove, but instead executes the remove command every time. You can also see that.phony: dist test is declared in the first line of the Makefile in the Element project, again to prevent the command from being executed because the file name already exists in the directory.

Echo @

In a Makefile, # denotes a comment.

test:
	# This is a comment
	touch a.js
Copy the code

When make test is executed, a comment is printed and the a.js file is created.

When preceded by an @, the echo is turned off. (Since echo is also equivalent to typing an echo, it is common to precede both comments and echo with @.)

test:
	@# This is a test
	@echo some
Copy the code

In Element, if the make new some project generates a new component, let’s analyze node build/bin/new.js $(filter-out $@,$(MAKECMDGOALS)). Let’s see what we know about make.

variable

Makefiles allow variables to be customized with an equal sign and called with $().

txt = hello world
test: 
	@echo $(txt)
Copy the code

Automatic variables$@

The Make command also provides automatic variables whose values are relevant to the current rule.

$@ refers to the current target, which is matched by the make command. For example, when we make foo, $@ is foo

This variable is used to abbreviate the current target:

a.js b.js c.js:
	touch $@
Copy the code

Special variablesMAKECMDGOALS

When make executes, it sets a special variable, MAKECMDGOALS, that keeps track of the list of targets specified by the command-line arguments. That is, using this variable, we can get arguments from the command line.

create:
	@echo $(MAKECMDGOALS)
Copy the code

Executing the make create newCom command will print the create newCom fields.

function

Make can also use functions in the following format:

$(function arguments)
# or
${function arguments}
Copy the code

filter-outInverse filter function

Filter out all content with pattert in objs in the format:

$(filter-out pattert, objs)

objs = aa bb cc dd ee 
pattert = bb cc ee 
out: 
	@echo $(filter-out $(pattert), $(objs))
Copy the code

Run make out to print aa DD

node build/bin/new.js $(filter-out $@,$(MAKECMDGOALS))

Either executing make new some or making new-lang some logic in Element passes a parameter to a script file. This command first uses Node to run the build/bin/new.js file and then uses the filter-out function to remove the current target from the arguments on the command line.

We can create a new build/bin/new.js file, write the following code, and look at the input.

<! -- build/bin/new.js --> console.log(process.argv)Copy the code

Makefile

new:
	node build/bin/new.js $(filter-out $@, $(MAKECMDGOALS))
Copy the code

Run the make new testCom command.

[ 'C:\\Program Files\\nodejs\\node.exe'.'C:\\Users\\***\\Desktop\\***\\a.js'.'testCom' ]
Copy the code

In new.js we can use process.argv[2] to get command-line arguments for further scripting.