无论更改如何,Makefile都会编译所有tsc

时间:2016-08-30 21:24:00

标签: typescript makefile gnu-make

问题

我写了一个makefile来将我的所有打字稿文件编译成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))。我做错了什么?

注意

根据我对typescript的理解,即使只更改了一个文件,也需要重新编译所有文件,这样才能理解它们之间的引用,我认为这是公平的。考虑到这一点,此makefile需要在每个个人打字稿源文件上运行tslint,但也必须在所有源上运行tsc打字稿文件,即使其中只有一个被更改。 (目前它就是这样,问题只是tsc即使没有改变也会运行

加成

你可能想知道我为什么要留下sass / scss的东西,因为%.scss ./apps/中的每个@import文件都是我的主要scss文件({{ 1}})我希望运行首先检查是否已更改的内容,如果是$(MAIN_SASS_SRC)所有应用程序模糊的文件,以便重新导入它,但无论运行已经完成的sass / scss配方。在没有竞争条件的情况下(因为我使用touch)并不涉及运行make两次或没有submakes,我无法想到一种方法。总的来说,我对此很陌生,所以我很乐意接受评论中对此makefile的任何部分的批评,以及该特定问题的解决方案。

2 个答案:

答案 0 :(得分:0)

你告诉过你要创建文件P2,但是食谱不会创建它。

将输出文件本身用作依赖项

tsc

答案 1 :(得分:0)

我知道我已经接受了答案,但我认为值得一提的是,有一种不同的方法可以实现这一目标。

#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输出文件。这样,我说实话,这条规则会产生目标。 $?获取已更改的配方的所有依赖项,因此只有已更改的文件才会通过linter。相反,第二行直接编译所有源文件。

额外的好处是,虽然make -j将为每个目标线程化每个配方,但是必须按顺序执行构建,因此如果其中一个,则不会发生相对冗长的tsc步骤文件无法lint,有效地提高了makefile的平均执行时间(因为我是一个一直混淆的白痴)

加成

我知道在帖子中提出不止一个问题可能不赞成,但我已经做到了,因为我有答案,我觉得有必要分享。重建所有.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我的主要文件,我所要做的就是让每一个都依赖于主文件。坦率地说,我对自己没有帮助就没有把它弄清楚感到很失望。