Makefile

60 篇文章 3 订阅
41 篇文章 0 订阅

1. Makefile

1.1. PHONY 的作用

单词 phony (即 phoney) 的意思是: 伪造的, 假的。来自 collins 的解释是:

If you describe something as phoney, you disapprove of it because it is false rather than genuine.

那么, 在 Makefile 中, .PHONY 后面的 target 表示的也是一个伪造的 target, 而不是真实存在的文件 target, 注意 Makefile 的 target 默认是文件。

举个例子

Makefile 内容如下:

clean:
    rm -f test.txt

该目录下只有 test.txt 时, 执行 make, 得到结果如下:

rm -f test.txt

在该目录下 test.txtclean 两个文件, 这时执行 make 命令, 得到结果如下:

make: "clean" 是最新的。

可以看到 make 会将 clean 文件当成目标文件, 而执行失败

如果将 Makefile 修改为如下内容:

.PHONY:clean
clean:
	rm -f test.txt

然后再执行 make, 得到结果如下:

rm -f test.txt

即该 makefile 并没有将 clean 当成是目标文件, 所以执行成功

小结:

.PHONY: clean
    o means the word "clean" doesn't represent a file name in this Makefile;
    o means the Makefile has nothing to do with a file called "clean" 
为什么需要.PHONY?
栗子:
如果make后,如果新建一个:touch clean文件,再执行make clean时,将不会执行rm命令,因为make clean和文件clean重名问题。为了避免出现这个问题,需要在Makefile里增加:.PHONY: clean
 
Makefile中非常三个变量:$@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件。
 
1、创建hello.c文件
#include <stdio.h>
int main()
{
  printf(".PHONY 测试!\n");
}
 
2、编写Makefile
$(CC) = gcc
all:hello test //hello和test为两目标文件
hello :hello.c
  $(CC) -o $@ $<
test :hello.c
  $(CC) -o $@ $<
clean:
  rm hello
 
3、执行编译和删除命令
# make 
# make clean
 
4、在当前目录下创建clean文件,此时执行make clean
报log如下,没有执行删除hello操作
make clean
make: “clean”是最新的。
 
5、在Makefile修改如下,此时顺利执行
 
$(CC) = gcc
.PHONY:clean #增加
all:hello test 
hello :hello.c
  $(CC) -o $@ $<
test :hello.c
  $(CC) -o $@ $<
clean:
  rm hello   
 
总结:
  为了解决问题,我们将目标clean定义成伪目标。也就是添加:.PHONY:clean
  当一个目标被声明为伪目标后,make在执行规则时不会去试图去查找隐含规则来创建它。这样就提高了make的执行效率,也不用担心由于目标和文件名重名了。

1.2. golang Makefile

.PHONY: all build clean run check cover lint docker help
BIN_FILE=hello
all: check build
build:
    @go build -o "${BIN_FILE}"
clean:
    @go clean
    rm --force "xx.out"
test:
    @go test
check:
    @go fmt ./
    @go vet ./
cover:
    @go test -coverprofile xx.out
    @go tool cover -html=xx.out
run:
    ./"${BIN_FILE}"
lint:
    golangci-lint run --enable-all
docker:
    @docker build -t leo/hello:latest .
help:
    @echo "make 格式化 go 代码 并编译生成二进制文件"
    @echo "make build 编译 go 代码生成二进制文件"
    @echo "make clean 清理中间目标文件"
    @echo "make test 执行测试 case"
    @echo "make check 格式化 go 代码"
    @echo "make cover 检查测试覆盖率"
    @echo "make run 直接运行程序"
    @echo "make lint 执行代码检查"
    @echo "make docker 构建 docker 镜像"

1.2.1. @ 是什么意思

make 通常会把命令执行显示出来 加 @ 会隐藏

比如 @echo "hello world"

不加 @ 输出

echo "hello world"

hello world

加了 @ 就只输出

hello wolrd

1.2.2. build multiple platform executables

go-executable-build.bash:

#!/usr/bin/env bash

package=$1
if [[ -z "$package" ]]; then
  echo "usage: $0 <package-name>"
  exit 1
fi
package_split=(${package//\// })
package_name=${package_split[-1]}
	
platforms=("windows/amd64" "windows/386" "darwin/amd64")

for platform in "${platforms[@]}"
do
	platform_split=(${platform//\// })
	GOOS=${platform_split[0]}
	GOARCH=${platform_split[1]}
	output_name=$package_name'-'$GOOS'-'$GOARCH
	if [ $GOOS = "windows" ]; then
		output_name+='.exe'
	fi	

	env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
	if [ $? -ne 0 ]; then
   		echo 'An error has occurred! Aborting the script execution...'
		exit 1
	fi
done
./go-executable-build.bash github.com/mholt/caddy/caddy

1.3. 报错解决

1.3.1. Makefile missing separator. Stop.

有几个原因会引起这样的结果:

  1. Makefile 的命令行, 开头必须用 tab 键;
  2. 编码方式引起的原因, 需设定 UTF-8;

2. Linux 之简单调用 so 库及 Makefile 用法

1.test.h
#include <stdio.h>
//函数指针
typedef int (*ADD)(int,int);
 
2.test.c
#include <stdio.h>
int add(int a, int b){
  printf(".PHONY 测试! \n");
  return (a + b);
}
 
3. 测试程序 main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "test.h"
 
int main(){
  void *handle=dlopen("./libtest.so",RTLD_LAZY);  
  ADD add=NULL;
  
  *(void **)(&add)=dlsym(handle,"add");  
  int result=add(2,5);
  
  printf("a + b = %d\n",result);
  return 0;
}
 
4.Makefile
#$@--目标文件 (main), $^--所有的依赖文件 (main.c), $<--第一个依赖文件。
CC := gcc
.PHONY:all clean
# test
SOURCE  := $(wildcard *.c) #把*.c 赋值给 SOURCE
OBJS    := $(patsubst %.c,%.o,$(SOURCE)) #把*.c 替换成*.o
 
all: libtest.so main
libtest.so: test.o
	@echo $@ $^ "11111"
	$(CC) -shared -o $@ $^  #编译-shared 生成 so 共享库
 
test.o: test.c
	@echo $@ $^ "2222"
	$(CC) -c -fPIC -o $@ $^ #-c 只编译不链接; PIC: Position Independent Code	
 
main: main.c
	@echo $@ $^ "3333"
	$(CC) -o $@ $^ -ldl #不需指定 libtest.so 进行编译, 执行会在指定目录加载 so
	./main
	#ldd main
clean:
	rm  *.so *.o main
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云满笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值