Makefile 编译所有 tsc 而不管更改
Makefile compiles all tsc regardless of changes
问题
我写了一个 makefile 来将我所有的 typescript 文件编译成 javascript,而且 运行 它们通过 linter (tslint)。我写了下面的 makefile:
#binaries
SASS=./node_modules/node-sass/bin/node-sass
TSC=tsc
TSLINT=tslint
#source dirs
SASS_DIRS=./apps ./lib
TS_DIRS=./apps ./lib ./library
#source files
SASS_SRC ::= $(shell find $(SASS_DIRS) -name '*.scss')
TS_SRC ::= $(shell find $(TS_DIRS) -name '*.ts')
APPS_SASS_SRC ::= $(shell find ./apps -name 'app.scss')
MAIN_SASS_SRC=./library/incode/incode.scss
MAIN_SASS_DEST=./library/incode/incode.css
#compilation options/binary flags
SASS_FLAGS = --output-style compressed -q
TSC_FLAGS = --sourceMap -t ES5 --noEmitOnError
.PHONY: clean
all: tsc sass
sass scss: $(patsubst %.scss, %.css, $(SASS_SRC))
%.css: %.scss
$(SASS) $(SASS_FLAGS) $< > $@
tsc: $(patsubst %.ts, %.js, $(TS_SRC))
$(TSC) $(TSC_FLAGS) $(TS_SRC)
%.js: %.ts
$(TSLINT) $<
incodesass: $(MAIN_SASS_SRC)
touch $(APPS_SASS_SRC); $(SASS) $(SASS_FLAGS) $< > $(MAIN_SASS_DEST); make sass
clean:
$(shell for i in $(shell find -name '*.rej'); do rm $i; done; for i in $(shell find -name '*.orig'); do rm $i; done;)
问题是,任何时候我 运行 make
(或等同于 make all
),scss 和 tslint 规则仅 运行 适当地更改文件,但是即使我没有更改任何打字稿文件,tsc 配方 运行 也是命令 ($(TSC) $(TSC_FLAGS) $(TS_SRC)
)。我做错了什么?
备注
据我对打字稿的了解,即使只更改了一个文件,所有文件都需要重新编译,以便它可以理解它们之间的引用,我想这是公平的。考虑到这一点,这个 makefile 需要 运行 tslint
每个 个人 typescript 源文件,而且还必须 运行 tsc
所有 源打字稿文件,即使其中一个被更改。 (目前它确实如此,问题只是 tsc
运行s 即使没有任何改变)
奖金
你可能想知道为什么我把 sass/scss 的东西留在里面,这是因为 ./apps/
@import
中的每个 %.scss
文件都是我的主 scss 文件($(MAIN_SASS_SRC)
) 并且我希望它成为 运行 首先检查是否已更改的东西,如果是 touch
es 所有应用程序 scuzzy 文件所以他们重新导入它但不管 运行s sass/scss 食谱完成后。我想不出没有竞争条件(因为我使用的是 -j
)不涉及 运行ning make 两次或没有 submakes 的方法。总的来说,我对此很陌生,所以我很乐意接受评论中对此 makefile 任何部分的批评,以及针对该特定问题的解决方案。
您已告知 make 您正在创建文件 tsc
,但配方并未创建它。
使用输出文件本身作为依赖项
SASS_CSS := $(SASS_SRC:=.scss=.css)
TS_JS := $(TS_SRC:.ts=.js)
.PHONY: all js.stub
all: $(SASS_CSS) $(TS_JS)
%.css: %.scss
$(SASS) $(SASS_FLAGS) $< > $@
$(TS_JS): %.js: %.ts js.stub
$(TSLINT) $<
js.stub: $(TS_SRC)
$(TSC) $(TSC_FLAGS) $^
@touch $@
我知道我已经接受了一个答案,但我认为值得一提的是,还有一种不同的方法可以实现这一点。
#binaries
TSC=tsc
TSLINT=tslint
#source dir
TS_DIRS=./apps ./lib ./library
#source files
TS_SRC ::= $(shell find $(TS_DIRS) -name '*.ts')
#compilation options/binary flags
TSC_FLAGS = --sourceMap -t ES5 --noEmitOnError
#outfiles
JS_OUT ::= $(patsubst %.ts, %.js, $(TS_SRC))
.PHONY: all
all: $(word 1, $(JS_OUT))
$(word 1, $(JS_OUT)): $(TS_SRC)
$(TSLINT) $?
$(TSC) $(TSC_FLAGS) $(TS_SRC)
我大学的一位教授帮助我解决了这个问题。由于每当单个 .ts
源文件更改时,所有这些文件都需要重建,我可以将我的目标设为 javascript 输出文件中的任何一个。那样的话,我告诉 make the truth,这条规则将产生它的目标。 $?
获取已更改的配方的所有依赖项,因此只有已更改的文件通过 linter。相比之下,第二行直接编译了所有的源文件。
这样做的一个额外好处是,虽然 make -j
将为每个目标线程化每个配方,但构建必须按顺序执行,因此相对冗长的 tsc
步骤不会发生,如果一个的文件无法 lint,有效地提高了 makefile 的平均执行时间(因为我是一个总是搞砸的白痴)
奖金
我知道在 post 中提出多个问题可能会让人不悦,但我已经这样做了,既然我有了答案,我觉得有义务分享它。重建所有 .css
文件实际上非常简单:
#binaries
SASS=./node_modules/node-sass/bin/node-sass
#source dir
SASS_DIRS=./apps
#I used to rebuild './lib' every time, not necessary as it turns out.
#source files
SASS_SRC ::= $(shell find $(SASS_DIRS) -name '*.scss')
MAIN_SASS_SRC=./library/incode/incode.scss
MAIN_SASS_DEST=./library/incode/incode.css
#compilation options/binary flags
SASS_FLAGS = --output-style compressed -q
.PHONY: all
all: sass
sass: $(patsubst %.scss, %.css, $(SASS_SRC))
%.css: %.scss $(MAIN_SASS_DEST)
$(SASS) $(SASS_FLAGS) $< > $@
$(MAIN_SASS_DEST): $(MAIN_SASS_SRC)
$(SASS) $(SASS_FLAGS) $< > $(MAIN_SASS_DEST)
因为 每个 apps/*.scss
文件都是 @import
我的主 scuzzy 文件,我所要做的就是让每个文件都依赖于主文件.坦率地说,我对自己在没有帮助的情况下无法解决这个问题感到失望。
问题
我写了一个 makefile 来将我所有的 typescript 文件编译成 javascript,而且 运行 它们通过 linter (tslint)。我写了下面的 makefile:
#binaries
SASS=./node_modules/node-sass/bin/node-sass
TSC=tsc
TSLINT=tslint
#source dirs
SASS_DIRS=./apps ./lib
TS_DIRS=./apps ./lib ./library
#source files
SASS_SRC ::= $(shell find $(SASS_DIRS) -name '*.scss')
TS_SRC ::= $(shell find $(TS_DIRS) -name '*.ts')
APPS_SASS_SRC ::= $(shell find ./apps -name 'app.scss')
MAIN_SASS_SRC=./library/incode/incode.scss
MAIN_SASS_DEST=./library/incode/incode.css
#compilation options/binary flags
SASS_FLAGS = --output-style compressed -q
TSC_FLAGS = --sourceMap -t ES5 --noEmitOnError
.PHONY: clean
all: tsc sass
sass scss: $(patsubst %.scss, %.css, $(SASS_SRC))
%.css: %.scss
$(SASS) $(SASS_FLAGS) $< > $@
tsc: $(patsubst %.ts, %.js, $(TS_SRC))
$(TSC) $(TSC_FLAGS) $(TS_SRC)
%.js: %.ts
$(TSLINT) $<
incodesass: $(MAIN_SASS_SRC)
touch $(APPS_SASS_SRC); $(SASS) $(SASS_FLAGS) $< > $(MAIN_SASS_DEST); make sass
clean:
$(shell for i in $(shell find -name '*.rej'); do rm $i; done; for i in $(shell find -name '*.orig'); do rm $i; done;)
问题是,任何时候我 运行 make
(或等同于 make all
),scss 和 tslint 规则仅 运行 适当地更改文件,但是即使我没有更改任何打字稿文件,tsc 配方 运行 也是命令 ($(TSC) $(TSC_FLAGS) $(TS_SRC)
)。我做错了什么?
备注
据我对打字稿的了解,即使只更改了一个文件,所有文件都需要重新编译,以便它可以理解它们之间的引用,我想这是公平的。考虑到这一点,这个 makefile 需要 运行 tslint
每个 个人 typescript 源文件,而且还必须 运行 tsc
所有 源打字稿文件,即使其中一个被更改。 (目前它确实如此,问题只是 tsc
运行s 即使没有任何改变)
奖金
你可能想知道为什么我把 sass/scss 的东西留在里面,这是因为 ./apps/
@import
中的每个 %.scss
文件都是我的主 scss 文件($(MAIN_SASS_SRC)
) 并且我希望它成为 运行 首先检查是否已更改的东西,如果是 touch
es 所有应用程序 scuzzy 文件所以他们重新导入它但不管 运行s sass/scss 食谱完成后。我想不出没有竞争条件(因为我使用的是 -j
)不涉及 运行ning make 两次或没有 submakes 的方法。总的来说,我对此很陌生,所以我很乐意接受评论中对此 makefile 任何部分的批评,以及针对该特定问题的解决方案。
您已告知 make 您正在创建文件 tsc
,但配方并未创建它。
使用输出文件本身作为依赖项
SASS_CSS := $(SASS_SRC:=.scss=.css)
TS_JS := $(TS_SRC:.ts=.js)
.PHONY: all js.stub
all: $(SASS_CSS) $(TS_JS)
%.css: %.scss
$(SASS) $(SASS_FLAGS) $< > $@
$(TS_JS): %.js: %.ts js.stub
$(TSLINT) $<
js.stub: $(TS_SRC)
$(TSC) $(TSC_FLAGS) $^
@touch $@
我知道我已经接受了一个答案,但我认为值得一提的是,还有一种不同的方法可以实现这一点。
#binaries
TSC=tsc
TSLINT=tslint
#source dir
TS_DIRS=./apps ./lib ./library
#source files
TS_SRC ::= $(shell find $(TS_DIRS) -name '*.ts')
#compilation options/binary flags
TSC_FLAGS = --sourceMap -t ES5 --noEmitOnError
#outfiles
JS_OUT ::= $(patsubst %.ts, %.js, $(TS_SRC))
.PHONY: all
all: $(word 1, $(JS_OUT))
$(word 1, $(JS_OUT)): $(TS_SRC)
$(TSLINT) $?
$(TSC) $(TSC_FLAGS) $(TS_SRC)
我大学的一位教授帮助我解决了这个问题。由于每当单个 .ts
源文件更改时,所有这些文件都需要重建,我可以将我的目标设为 javascript 输出文件中的任何一个。那样的话,我告诉 make the truth,这条规则将产生它的目标。 $?
获取已更改的配方的所有依赖项,因此只有已更改的文件通过 linter。相比之下,第二行直接编译了所有的源文件。
这样做的一个额外好处是,虽然 make -j
将为每个目标线程化每个配方,但构建必须按顺序执行,因此相对冗长的 tsc
步骤不会发生,如果一个的文件无法 lint,有效地提高了 makefile 的平均执行时间(因为我是一个总是搞砸的白痴)
奖金
我知道在 post 中提出多个问题可能会让人不悦,但我已经这样做了,既然我有了答案,我觉得有义务分享它。重建所有 .css
文件实际上非常简单:
#binaries
SASS=./node_modules/node-sass/bin/node-sass
#source dir
SASS_DIRS=./apps
#I used to rebuild './lib' every time, not necessary as it turns out.
#source files
SASS_SRC ::= $(shell find $(SASS_DIRS) -name '*.scss')
MAIN_SASS_SRC=./library/incode/incode.scss
MAIN_SASS_DEST=./library/incode/incode.css
#compilation options/binary flags
SASS_FLAGS = --output-style compressed -q
.PHONY: all
all: sass
sass: $(patsubst %.scss, %.css, $(SASS_SRC))
%.css: %.scss $(MAIN_SASS_DEST)
$(SASS) $(SASS_FLAGS) $< > $@
$(MAIN_SASS_DEST): $(MAIN_SASS_SRC)
$(SASS) $(SASS_FLAGS) $< > $(MAIN_SASS_DEST)
因为 每个 apps/*.scss
文件都是 @import
我的主 scuzzy 文件,我所要做的就是让每个文件都依赖于主文件.坦率地说,我对自己在没有帮助的情况下无法解决这个问题感到失望。