2016-05-13 31 views
0

我有兩個目標,這幾乎是相同的:如何在訂單重要時將另一個目標打電話給另一個目標?

# install node modules from package.json and bring npm-shrinkwrap.json up to date 
npm-install: 
ifndef SHRINKWRAP_BIN 
    $(error `npm-shrinkwrap` not found. Please run `sudo npm install -g npm-shrinkwrap`) 
endif 
    $(NPM_BIN) install --no-shrinkwrap --loglevel=error --no-optional 
    $(NPM_BIN) prune --no-shrinkwrap --loglevel=error 
    $(NPM_BIN) dedupe --no-shrinkwrap --loglevel=error 
    npm-shrinkwrap --dev 
    touch $(NPM_TIMESTAMP) 

# update npm dependencies to their latest version given the semver constraints and re-write npm-shrinkwrap file 
npm-update: 
ifndef SHRINKWRAP_BIN 
    $(error `npm-shrinkwrap` not found. Please run `sudo npm install -g npm-shrinkwrap`) 
endif 
    $(NPM_BIN) update --save-dev --loglevel=error --no-optional 
    $(NPM_BIN) prune --no-shrinkwrap --loglevel=error 
    $(NPM_BIN) dedupe --no-shrinkwrap --loglevel=error 
    npm-shrinkwrap --dev 
    touch $(NPM_TIMESTAMP) 

有什麼辦法,我可以通過使它們都調用另一個目標去除一些重複?我不能只用公共部分增加的先決條件,以兩者因爲先決條件跑之前的命令和安裝/更新位必須跑第一(刪節/重複數據刪除/拆封之前)。

+0

所以這裏的區別是'install'與'update'在第二個shell行? –

+0

@EtanReisner'install --no-shrinkwrap'和'update --save-dev'。 – mpen

回答

1

我對此有幾點想法。首先是僅使用Makefile內的文本處理來明確減少重複。定義一個多行宏,然後調用它。

define NPM_COMMON_STEPS 
$(NPM_BIN) prune ... 
$(NPM_BIN) dedupe ... 
... 
endef 

因爲這沒有參數,我們沒有使用$(call ...)操作。簡而言之,在配方中我們將其稱爲:

$(NPM_COMMON_STEPS) 

然後還有其他方法。你可以讓虛擬先決條件目標處理所有的邏輯,並根據誰在「呼叫」切換它的一部分。我們如何知道這一點?爲什麼通過目標特定的變量!

.PHONY: all common-target a-target b-target 
all: a-target b-target 

common-target: 
     $(if $(CALLED_FOR_A), echo called for a-target) 
     $(if $(CALLED_FOR_B), echo called for b-target) 
     echo common recipe 

a-target: CALLED_FOR_A := y 
a-target: common-target 

b-target: CALLED_FOR_B := y 
b-target: common-target 

測試:

這可以通過一個完整的Makefile中所示

$ make 
echo called for a-target 
called for a-target 
echo common recipe 
common recipe 
$ make a-target 
echo called for a-target 
called for a-target 
echo common recipe 
common recipe 
$ make b-target 
echo called for b-target 
called for b-target 
echo common recipe 
common recipe 

正如你可以看到,有一個缺點,在這裏,如果我們更新目標all,然後GNU只做一次執行共享通用規則。當該規則代表a-target運行時,它將被視爲已更新,並且不會爲b-target運行。

如果我們不更新在同一運行兩個目標,但都一樣這沒關係,這是一個潛在的障礙:

$ make a-target b-target 
echo called for a-target 
called for a-target 
echo common recipe 
common recipe 
make: Nothing to be done for `b-target'. 

因此我會三思而後使用這種類型的前招。如果你不會在同一個調用中執行npm-updatenpm-install,那麼可以使用它。

這裏是文本替換溶液的完整樣品:

.PHONY: all a-target b-target 
all: a-target b-target 

define COMMON 
echo common recipe 
endef 

define COMMON_WITH_ARG 
echo common recipe with arg 1 == $(1) 
endef 

a-target: 
     echo a-target 
     $(COMMON) 
     $(call COMMON_WITH_ARG,a) 
     echo a-done 

b-target: 
     echo b-target 
     $(COMMON) 
     $(call COMMON_WITH_ARG,b) 
     echo b-done 

執行命令

$ make 
echo a-target 
a-target 
echo common recipe 
common recipe 
echo common recipe with arg 1 == a 
common recipe with arg 1 == a 
echo a-done 
a-done 
echo b-target 
b-target 
echo common recipe 
common recipe 
echo common recipe with arg 1 == b 
common recipe with arg 1 == b 
echo b-done 
b-done 
+0

好主意,但有點複雜。定義是一個好主意,但我會用最終樣本等參數處理它的第一個版本,並將整個主體放入定義中。 –

+0

@EtanReisner是的,這基本上是您在FOSS中適度複雜的GNU makefiles中看到的標準做法。 – Kaz

3

假設我正確讀取這和兩者之間的差別僅僅是字installnpm-installupdate in npm-update那麼這裏的解決方案就是在你正在運行的命令中使用目標(或其一部分)。

事情是這樣的:

# install node modules from package.json and bring npm-shrinkwrap.json up to date 
npm-install npm-update: 
ifndef SHRINKWRAP_BIN 
    $(error `npm-shrinkwrap` not found. Please run `sudo npm install -g npm-shrinkwrap`) 
endif 
    $(NPM_BIN) $(subst npm-,,[email protected]) --no-shrinkwrap --loglevel=error --no-optional 
    $(NPM_BIN) prune --no-shrinkwrap --loglevel=error 
    $(NPM_BIN) dedupe --no-shrinkwrap --loglevel=error 
    npm-shrinkwrap --dev 
    touch $(NPM_TIMESTAMP) 

你也可以使用$(word 2,$(subst -, ,[email protected]))$(patsubst npm-%,%,[email protected])或以上不切換--no-shrinkwrap--save-dev你可以使用這樣的事情(或用arg變量結合上面的[email protected]使用像這樣):

npm-install: command := install 
npm-install: arg := --no-shrinkwrap 
npm-update: command := update 
npm-update: arg :=--save-dev 

npm-install npm-update: 
     .... 
     $(NPM_BIN) $(command) $(arg) --loglevel=error --no-optional 
     .... 
相關問題