Makefile
Makefile主要應用在Linux與Mac環境之中,通常在大型專案之中用來編譯C或C++,因為Makefile能夠判斷在一個專案中有哪些依賴的檔案需要重新編譯,哪些檔案可以忽略不再編譯
此外Make命令在Linux個發布版本與Mac都有內建,所以Make在距離第一版發布多年之後還是廣泛的被開發者使用
本文章的範例將使用play with docker建立的Linux環境,詳細可參考Docker Certified Associate(DCA)認證考試學習-準備環境
文章內容參考自makefile-cookbook
首先建立我們的測試環境,並建立以下檔案
mkdir hello-world && cd $_
vi Makefile
在 Makefile 輸入以下內容
hello:
echo "Hello, World"
最後在終端機輸入make
命令
[node1] (local) root@192.168.0.18 ~/hello-world
$ make
echo "Hello, World"
Hello, World
Makefile Syntax
首先我們先了解一下Makefile的語法:
targets: prerequisites
command
command
command
- targets 就像是dotnet中Method的名稱,它的作用範圍內可以包含多個命令,輸入完名稱之後需要使用
:
隔開 - command 為運作的命令,注意這邊在輸入命令需要用一個
TAB
開頭,不可以用空格 - prerequisites 為前置需求,在運作這個target之前要先運作,指定的target
以上就是make的最基礎語法,首先先看一下先前Makefile的內容:
第一行hello:
為targets
第二行 echo "Hello, World"
command
此範例沒有前置需求
那麼我們可以更進一步修改Makefile的內容
hello: hello-second
echo "Hello, World"
hello-second:
echo "Hello, World second"
這邊我建立了一個新的target hello-second
,並且在target hello
新增一個之前的前置需求,要求在運行hello
之前需要先執行hello-second
[node1] (local) root@192.168.0.18 ~/hello-world
$ make
echo "Hello, World second"
Hello, World second
echo "Hello, World"
Hello, World
Makefile Sample
接下來看另一個範例,這邊會將docker的範例程式clone下來,再透過Makefile將流程整合在一起 程式來自docker範例程式github
新增或修改Makefile添加以下內容
all: docker-run clean
docker-run: docker-build
docker run --name myhello hello-world
docker-build: file-copy
docker build -t hello-world .
file-copy: git-pull
cp hello-world/amd64/hello-world/hello .
git-pull:
git clone https://github.com/docker-library/hello-world
clean:
rm -rf hello*
這邊如果有多個targets,一般都是使用all作為預設執行的target
再新增一個Dockerfile添加以下內容
vi Dockerfile
FROM scratch
COPY hello /
CMD ["/hello"]
最後在終端機輸入make
[node1] (local) root@192.168.0.28 ~
$ make
git clone https://github.com/docker-library/hello-world
Cloning into 'hello-world'...
remote: Enumerating objects: 755, done.
remote: Counting objects: 100% (97/97), done.
remote: Compressing objects: 100% (59/59), done.
remote: Total 755 (delta 33), reused 79 (delta 22), pack-reused 658
Receiving objects: 100% (755/755), 574.50 KiB | 3.23 MiB/s, done.
Resolving deltas: 100% (313/313), done.
cp hello-world/amd64/hello-world/hello .
docker build -t hello-world .
Sending build context to Docker daemon 889.9kB
Step 1/3 : FROM scratch
--->
Step 2/3 : COPY hello /
---> 22851d3f8c16
Step 3/3 : CMD ["/hello"]
---> Running in 2a147ee248d2
Removing intermediate container 2a147ee248d2
---> 37873ba92f23
Successfully built 37873ba92f23
Successfully tagged hello-world:latest
docker run --name myhello hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
rm -rf hello*
Summary
從今天的測試中可以得知,Makefile除了可以編譯大型程式之外,也可以拿來做一些基礎的流程控制
有了Makefile之後,可以省下一些力氣背不同的指令,像在此處只需要記住一個指令make
即可完成許多事
而且只要專案有提供Makefile,都可以快速執行作者想要提供給我們的功能,非常方便。