语法规则
基本规则
目标 ... : 依赖 ...
命令1
命令2
. . .
1、目标即要生成的文件。如果目标文件的更新时间晚于依赖文件更新时间,则说明依赖文件没有改动,目标文件不需要重新编译。否则会进行重新编译并更新目标文件。
2、默认情况下Makefile的第一个目标为终极目标。
3、依赖:即目标文件由哪些文件生成。
4、命令:即通过执行命令由依赖文件生成目标文件。注意每条命令之前必须有一个tab保持缩进,这是语法要求(会有一些编辑工具默认tab为4个空格,会造成Makefile语法错误)。
5、all:Makefile文件默认只生成第一个目标文件即完成编译,但是我们可以通过all 指定所需要生成的目标文件。
清空编译
每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。这是一个“修养”(呵呵,还记得我的《编程修养》吗)。一般的风格都是:
clean:
rm edit $(objects)
更为稳健的做法是:
.PHONY : clean
clean :
-rm edit $(objects)
前面说过,.PHONY意思表示clean是一个“伪目标”,。而在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。当然,clean的规则不要放在文件的开头,不然,这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean从来都是放在文件的最后”
自动推导
常规写法如下:
objects = main.o kbd.o command.o display.o
insert.osearch.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
make很强大,它可以自动推导文件以及文件依赖关系后面的命令,只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来。于是上述可以更新如下:
objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
这也是makefile的隐晦规则。
常用指令
- 获取系统名字:
- UNAME := $(shell uname) 对于Linux,它可能返回"Linux",对于Mac OS,它可能返回"Darwin"
- OSNAME := $(shell ver) 命令的输出是 “Microsoft Windows [Version 10.0.19041.867]”
- 打印输出变量 @echo “Flags: $(CFLAGS)”
- find . -maxdepth 10 -type d 从当前目录搜索所有子级目录(搜素深度为10级),-type d表示只查找目录。
生成动态链接库
需要对外暴露的函数使用 __declspec(dllexport) 加在函数前。
-
生成命令:gcc -shared -o my.dll build/my.o build/fun1.o
-
c++ 加载动态库
注意visual studio中使用x64进行编译(因为gcc是64位版本),否则会加载动态库失败。#ifdef _MSC_VER #include <winsock2.h> /* For struct timeval */ #endif void DynamicUse() { // 运行时加载DLL库 HMODULE module = LoadLibraryA("xxx.dll"); // 根据DLL文件名,加载DLL,返回一个模块句柄 if (module == NULL) { printf("加载DLLTest1.dll动态库失败\n"); return; } typedef int(*AddFunc)(const char*, int,int,int,int); // 定义函数指针类型 AddFunc generate_mbd; // 导出函数地址 generate_mbd = (AddFunc)GetProcAddress(module, "generate_mbd"); // GetProcAddress返回指向的函数名的函数地址 string file_name = "./photo.png"; const char* name = file_name.c_str(); int sum = generate_mbd(name, 110, 105, 30, 1); printf("动态调用,sum = %d\n", sum); }
-
python 加载dll
from ctypes import * #dll = CDLL("export.dll") dll = windll.LoadLibrary("export.dll") dll.say_hello()
报错以及解决
注意 win系统下要在vscode 中的git bash下进行编译。
- “XXX is up to date”问题的解决办法 删除曾经makefile生成的文件。