关于make:makefile-build-报错-『Makefile9-missing-separator-Stop』
起因很简略,make 是辨别 tab 和 空格的 而有些博客网站,会把你的 tab 替换成 4 个空格 而 vscode 这类编辑器,当你输出 tab 的时候,也会主动替换为 4 个空格 所以,就导致了『Makefile:9: * missing separator. Stop.』
起因很简略,make 是辨别 tab 和 空格的 而有些博客网站,会把你的 tab 替换成 4 个空格 而 vscode 这类编辑器,当你输出 tab 的时候,也会主动替换为 4 个空格 所以,就导致了『Makefile:9: * missing separator. Stop.』
源代码下载: Makefile-cn Makefile 用于定义如何创立指标文件, 比方如何从源码到可执行文件. 创立这一工具的指标是缩小不必要的编译或者工作.是传说中的 Stuart Feldman 在 1976 年花了一个周末写进去的, 而今依然应用宽泛, 特地是在 Unix 和 Linux 零碎上. 尽管每个语言可能都有相应的或多或少提供 make 的性能, 比方 ruby 的 rake, node 的 gulp, broccoli, scala 的 sbt 等等. 然而 make 的简洁与高效, 和只做一件事并做到极致的格调, 使其至今仍是无可替代的,甚至与其余构建工具一起应用也并无抵触. 只管有许多的分支和变体, 这篇文章针对是规范的 GNU make. # 这行示意正文# 文件名肯定要叫 Makefile, 大小写辨别, 应用 `make <target>` 生成 target# 如果想要取别的名字, 能够用 `make -f "filename" <target>`.# 重要的事件 - 只意识 TAB, 空格是不认的, 然而在 GNU Make 3.82 之后, 能够通过# 设置参数 .RECIPEPREFIX 进行批改#-----------------------------------------------------------------------# 高级#-----------------------------------------------------------------------# 创立一个 target 的规定非常简单# targets : prerequisites# recipe# …# prerequisites(依赖) 是可选的, recipe(做法) 也能够多个或者不给.# 上面这个工作没有给 prerequisites, 只会在指标文件 file0.txt 文件不存在时执行file0.txt: echo "foo" > file0.txt # 试试 `make file0.txt` # 或者间接 `make`, 因为第一个工作是默认工作. # 留神: 即便是这些正文, 如果后面有 TAB, 也会发送给 shell, 留神看 `make file0.txt` 输入# 如果提供 prerequisites, 则只有 prerequisites 比 target 新时会执行# 比方上面这个工作只有当 file0.txt 比 file1.txt 新时才会执行.file1.txt: file0.txt cat file0.txt > file1.txt # 这里跟shell里的命令式截然不同. @cat file0.txt >> file1.txt # @ 不会把命令打印到 stdout. -@echo 'hello' # - 意思是产生谬误了也没关系. # 试试 `make file1.txt` 吧.# targets 和 prerequisites 都能够是多个, 以空格宰割file2.txt file3.txt: file0.txt file1.txt touch file2.txt touch file3.txt# 如果申明反复的 target, make 会给一个 warning, 前面会笼罩后面的# 比方反复定义 file2.txt 会失去这样的 warning# Makefile:46: warning: overriding commands for target `file2.txt'# Makefile:40: warning: ignoring old commands for target `file2.txt'file2.txt: file0.txt touch file2.txt# 然而如果不定义任何 recipe, 就不会抵触, 只是多了依赖关系file2.txt: file0.txt file3.txt#-----------------------------------------------------------------------# Phony(假的) Targets#-----------------------------------------------------------------------# phony targets 意思是 tagets 并不是文件, 能够设想成一个工作的名字而已.# 因为不是文件, 无奈比对是否有更新, 所以每次make都会执行.all: maker process# 依赖于 phony target 的 target 也会每次 make 都执行, 即便 target 是文件ex0.txt ex1.txt: maker# target 的申明程序并不重要, 比方下面的 all 的依赖 maker 当初才申明maker: touch ex0.txt ex1.txt# 如果定义的 phony target 与文件名重名, 能够用 .PHONY 显式地指明哪些 targets 是 phony.PHONY: all maker process# This is a special target. There are several others.# 罕用的 phony target 有: all clean install ...#-----------------------------------------------------------------------# 变量与通配符#-----------------------------------------------------------------------process: file*.txt | dir/a.foo.b # 能够用通配符匹配多个文件作为prerequisites @echo $^ # $^ 是 prerequisites @echo $@ # $@ 代表 target, 如果 target 为多个, $@ 代表以后执行的那个 @echo $< # $< prerequisite 中的第一个 @echo $? # $? 须要更新的 prerequisite 文件列表 @echo $+ # $+ 所有依赖, 包含反复的 @echo $| # $| 竖线前面的 order-only prerequisitesa.%.b: @echo $* # $* match 的target % 那局部, 包含门路, 比方 `make dir/a.foo.b` 会打出 `dir/foo`# 即使离开定义依赖, $^ 仍然能拿到process: ex1.txt file0.txt# 十分智能的, ex1.txt 会被找到, file0.txt 会被去重.#-----------------------------------------------------------------------# 模式匹配#-----------------------------------------------------------------------# 能够让 make 晓得如何转换某些文件到其余格局# 比方 从 svg 到 png%.png: %.svg inkscape --export-png $^# 一旦有须要 foo.png 这个工作就会运行# 门路会被疏忽, 所以下面的 target 能匹配所有 png# 然而如果加了门路, make 会找到最靠近的匹配, 如果# make small/foo.png (在这之前要先有 small/foo.svg 这个文件)# 则会匹配上面这个规定small/%.png: %.svg inkscape --export-png --export-dpi 30 $^%.png: %.svg @echo 反复定义会笼罩后面的, 当初 inkscape 没用了# make 曾经有一些内置的规定, 比方从 *.c 到 *.o#-----------------------------------------------------------------------# 变量#-----------------------------------------------------------------------# 其实是宏 macro# 变量都是字符串类型, 上面这俩是一样一样的name = Tedname2="Sarah"echo: @echo $(name) @echo ${name2} @echo $name # 这个会被蠢蠢的解析成 $(n)ame. @echo \"$(name3)\" # 未声明的变量会被解决成空字符串. @echo $(name4) @echo $(name5)# 你能够通过4种形式设置变量.# 按以下程序由高到低:# 1: 命令行参数. 比方试试 `make echo name3=JICHAO`# 2: Makefile 外面的# 3: shell 中的环境变量# 4: make 预设的一些变量name4 ?= Jean# 问号意思是如果 name4 被设置过了, 就不设置了.override name5 = David# 用 override 能够避免命令行参数设置的笼罩name4 +=grey# 用加号能够连贯 (两头用空格宰割).# 在依赖的中央设置变量echo: name2 = Sara2# 还有一些内置的变量echo_inbuilt: echo $(CC) echo ${CXX)} echo $(FC) echo ${CFLAGS)} echo $(CPPFLAGS) echo ${CXXFLAGS} echo $(LDFLAGS) echo ${LDLIBS}#-----------------------------------------------------------------------# 变量 2#-----------------------------------------------------------------------# 加个冒号能够申明 Simply expanded variables 即时扩大变量, 即只在申明时扩大一次# 之前的等号申明时 recursively expanded 递归扩大var := hellovar2 := $(var) hello# 这些变量会在其援用的程序求值# 比方 var3 申明时找不到 var4, var3 会扩大成 `and good luck`var3 := $(var4) and good luck# 然而个别的变量会在调用时递归扩大, 先扩大 var5, 再扩大 var4, 所以是失常的var5 = $(var4) and good luckvar4 := good nightechoSEV: @echo $(var) @echo $(var2) @echo $(var3) @echo $(var4) @echo $(var5)#-----------------------------------------------------------------------# 函数#-----------------------------------------------------------------------# make 自带了一些函数.# wildcard 会将前面的通配符变成一串文件门路all_markdown: @echo $(wildcard *.markdown)# patsubst 能够做替换, 比方上面会把所有 markdown# 后缀的文件重命名为 md 后缀substitue: * @echo $(patsubst %.markdown,%.md,$* $^)# 函数调用格局是 $(func arg0,arg1,arg2...)# 试试ls: * @echo $(filter %.txt, $^) @echo $(notdir $^) @echo $(join $(dir $^),$(notdir $^))#-----------------------------------------------------------------------# Directives#-----------------------------------------------------------------------# 能够用 include 引入别的 Makefile 文件# include foo.mksport = tennis# 流程管制语句 (如if else 等等) 顶格写report:ifeq ($(sport),tennis) @echo 'game, set, match'else @echo "They think it's all over; it is now"endif# 还有 ifneq, ifdef, ifndeffoo = true# 不只是 recipe, 还能够写在里面哟ifdef $(foo)bar = 'bar'endifhellobar: @echo bar资源GNU Make 官网文档 HTML PDFsoftware carpentry tutoriallearn C the hard way ex2 ex28有倡议?或者发现什么谬误?在Github上开一个issue,或者发动pull request! ...
Makefile 文件能够这么写: NAME = ponponon/ideaboomVERSION = 1.0.1.PHONY: build up stop logsbuild: docker-buildup: docker-compose-upstop: docker-compose-stoplogs: docker-compose-logsdocker-build: docker build -t "${NAME}" .docker-compose-up: docker-compose up -ddocker-compose-stop: docker-compose stopdocker-compose-logs: docker-compose logs --tail=100 -f
问题起因,编译安装 PHP 7.3.7 的过程中 configure 是正常的,但是 make 时一直提示 make: * [sapi/cli/php] Error 1自己花了好久才找到解决方法,便想到记录在这里,可能会对后面遇到同样问题的人有所帮助 以下是解决方法汇总: 如果在错误信息中有看到类似undefined reference to libiconv_open 之类的提示,可以通过在 make 时附加上对应的库来解决,例如 make ZEND_EXTRA_LIBS='-liconv'。这里是网上能够搜索到的解决方法,但是作者自己遇到的并不是这种或者类似的情形。系统中先是装了一个 openssl 版本和自己 yum 安装的 devel 版本不对应,可以通过 yum remove openssl-devel 卸载后再编译,这里自己遇到的就是这种情况。
Go语言中new和make都是用来内存分配的原语(allocation primitives)。简单的说,new只分配内存,make用于slice,map,和channel的初始化。 newnew(T)函数是一个分配内存的内建函数。 我们都知道,对于一个已经存在变量,可对其指针进行赋值。 示例 var p intvar v *intv = &p*v = 11fmt.Println(*v)那么,如果不是已经存在的变量会如何呢?能对其直接赋值吗? 示例 var v *int*v = 8fmt.Println(*v)结果会报如下错误 panic: runtime error: invalid memory address or nil pointer dereference[signal 0xc0000005 code=0x1 addr=0x0 pc=0x48df66] 如何解决?通过Go提供了new来初始化一地址就可以解决。 var v *intv = new(int)*v = 8fmt.Println(*v)那么我们来分析一下 var v *int fmt.Println(*v)fmt.Println(v) //<nil>v = new(int) fmt.Println(*v)//fmt.Println(v)//0xc00004c088我们可以看到初始化一个指针变量,其值为nil,nil的值是不能直接赋值的。通过new其返回一个指向新分配的类型为int的指针,指针值为0xc00004c088,这个指针指向的内容的值为零(zero value)。 同时,需要注意的是不同的指针类型零值是不同的。 示例 type Name struct { P string}var av *[5]intvar iv *intvar sv *stringvar tv *Nameav = new([5]int)fmt.Println(*av) //[0 0 0 0 0 0]iv = new(int)fmt.Println(*iv) // 0sv = new(string) fmt.Println(*sv) //tv = new(Name)fmt.Println(*tv) //{}上面讲了对普通类型new()处理过后是如何赋值的,这里再讲一下对复合类型(数组,slice,map,channel等),new()处理过后,如何赋值。 ...
npm 的 scripts 下写的命令太多就很容易很乱,各种第三方轮子都只能解决一部分问题,总感觉不是很好用,想找个类似 make 的工具只能找到 jake, 可是 jake 的 API 太老,居然很多都不支持 promise, 代码也不多,就干脆自己造轮子了, 感觉效果还行。特点:基于 promise 的任务和内置工具函数(fs/shell), 无缝支持 async/await类似于 shelljs 的跨平台 shell dsl, 人人都会写 shell易学易用,无需为写仅仅几个 build 命令而花费几个小时去寻找和学习第三方包很小的安装成本foy: gulp: grunt: 无缝和第三方支持 promise 的工具包整合,不需要封装成插件就能用使用:安装yarn add -D foy # or npm i -D foy# Or Install globally withyarn add -g foy # or npm i -g foy在项目根目录下增加一个 Foyfile.js (或者 Foyfile.ts, 需要安装 ts-node)import { task, desc, option, strict, fs } from ‘foy’task(‘build’, async ctx => { await ctx.exec(’tsc’)})desc(‘Build ts files with tsc’)option(’-w, –watch’, ‘watch file changes’)strict() // This will throw an error if you passed some options that doesn’t defined via option()task(‘build2’, async ctx => { await ctx.exec(tsc ${ctx.options.watch ? '-w' : ''})})task(’task’, async ctx => { await fs.rmrf(’/some/dir/or/file’) // Remove directory or file await fs.copy(’/src’, ‘/dist’) // Copy folder or file let json = await fs.readJson(’./xx.json’) await ctx.env(‘NODE_ENV’, ‘production’) await ctx.cd(’./src’) await ctx.exec(‘some command’) // Execute an command let { stdout } = await ctx.exec(’ls’, { stdio: ‘pipe’ }) // Get the stdout, default is empty because it’s redirected to current process via stdio: 'inherit'.})然后就可以运行任务了# 安装在本地 node_modules 目录下npx foy buildnpx foy build1npx foy task # 安装在全局foy buildfoy build1 ...