2017-03-05 7 views
0

私はmakeを初めて使用しており、makeファイルを正しく設定する方法を理解しようとしています。特に、私はパターンに従うルールや扶養家族を扱う方がはるかに優れていると思います。しかし、私はこの点について実際にマニュアルを理解することはできません。メイクファイルを何度も何度も繰り返しないように最適化するには

OSXとLinux上で動作するmakefileを持っていますが、私はgnu makeと仮定していますが、私が理解していない手法を使用することでかなり短縮できると期待しています。それはそれのいたるところに異なるディレクトリのパターンを繰り返す。次のように改善する方法を教えてください。短縮するたびにどの施設が使用されているか教えてください。

# Include this file NOT stored in repository which defines which environment to use 
include Makefile.local 
# Work out the pas version 
PAS=${shell git describe --abbrev=0} 
# Version of node being used 
VERSION = 7.6.0 

\.dockerimage: access/.dockerimage evening/.dockerimage server/.dockerimage 
    touch .dockerimage 
server/.dockerimage: client/client/.dockerimage server/.env $(shell find server \! -name pacakge.json \! -name .dockerimage -depth 1 -type f) 
    docker image build -t server:${PAS} -t server:latest server 
    touch server/.dockerimage 
server/.env: environments/common/server.env environments/${enviro}/server.env 
    cat environments/common/server.env > server/.env 
    cat environments/${enviro}/server.env >> server/.env 
access/.dockerimage: request/.dockerimage access/.env $(shell find access \! -name pacakge.json \! -name .dockerimage -depth 1 -type f) 
    docker image build -t access:${PAS} -t access:latest access 
    touch access/.dockerimage 
access/.env: environments/common/access.env environments/${enviro}/access.env 
    cat environments/common/access.env > access/.env 
    cat environments/${enviro}/access.env >> access/.env 
evening/.dockerimage: request/.dockerimage evening/.env $(shell find evening \! -name pacakge.json \! -name .dockerimage -depth 1 -type f) 
    docker image build -t evening:${PAS} -t evening:latest evening 
    touch evening/.dockerimage 
evening/.env: environments/common/evening.env environments/${enviro}/evening.env 
    cat environments/common/evening.env > evening/.env 
    cat environments/${enviro}/evening.env >> evening/.env 
pcode/.dockerimage: libs/.dockerimage pcode/.env $(shell find pcode \! -name pacakge.json \! -name .dockerimage -depth 1 -type f) 
    docker image build -t pcode:${PAS} -t pcode:latest pcode 
    touch pcode/.dockerimage 
pcode/.env: environments/common/pcode.env environments/${enviro}/pcode.env 
    cat environments/common/pcode.env > pcode/.env 
    cat environments/${enviro}/pcode.env >> pcode/.env 
test-client/.dockerimage: client/client/.dockerimage 
    docker image build -t test-client:${PAS} test-client:latest test-client 
    touch test-client/.dockerimage 
test-server/.dockerimage: services/.dockerimage 
    docker image build -t test-server:${PAS} -t test-server:latest test-server 
    touch test-server/.dockerimage 
client/client/.dockerimage: services/.dockerimage $(shell find client/client \! -name .dockerimage -type f) 
    docker image build -t client:${PAS} -t client:latest client/client 
    touch client/client/.dockerimage 
services/.dockerimage: client/.dockerimage $(shell find services \! -name .dockerimage -type f -print0) 
    docker image build -t services:${PAS} -t services:latest services --build-arg PAS_VERSION=${PAS} 
    touch services/.dockerimage 
client/.dockerimage: libs/.dockerimage $(shell find client \! -name .dockerimage -depth 1 -type f) 
    docker image build -t components:${PAS} -t components:latest client 
    touch client/.dockerimage 
libs/.dockerimage: request/.dockerimage $(shell find libs \! -name .dockerimage -type f) 
    docker image build -t libs:${PAS} -t libs:latest libs 
    touch libs/.dockerimage 
request/.dockerimage: node/.dockerimage $(shell find request \! -name .dockerimage -type f) 
    docker image build -t request:${PAS} -t request:latest request 
    touch request/.dockerimage 
node/.dockerimage: node/Dockerfile-${ARCH} node/.dockerignore 
    docker image build -f node/Dockerfile-${ARCH} -t node:${VERSION} -t node:latest node 
    touch node/.dockerimage 
clean: clean-images clean-above clean-env 
    rm node/.dockerimage 
    docker image rm -f node:latest 
    docker image rm -f node:${VERSION} 
clean-above: 
    for dir in server access evening pcode client/client services test-client test-server servies client libs request; \ 
     do rm $$dir/.dockerimage; done 
clean-env: 
    for dir in access evening pcode server; do rm $$dir/.env; done 
clean-images: clean-above 
    for dir in access access evening pcode client/client services test-client test-server services client libs request; \ 
    do docker image rm -f $$dir:latest; docker image rm -f $$dir:${PAS}; done 
.PHONY: run clean clean-above clean-images clean-env 

必須ではないが、それは、Windows上のgit-はbash(これにMAKE.EXEを追加する)の下で実行することも有用であろう。

答えて

1

StackOverflowは実際にあなたのコードを書き換える人を尋ねる場所ではありません。

最初に、重複を減らすために、make variablesについて学ぶ必要があります。重複した項目を変数に入れて、複数回すべてを書き込む代わりにそれらを使用することができます。これは簡単です。

次に、implicit rules、特にpattern rulesを調べる必要があります。ルール間に重複があるため、すべてのターゲットに対して個別の明示的なルールを作成するのではなく、いくつかの異なるパターンルールを作成する必要があるようです。これはやや高度なトピックです。

メイクファイルを変更して何が起こるかを確認することができます。試行錯誤はしばしば学習に最適な方法であり、安価で簡単にmakeを実行することができます。あなたが解決できない問題に遭遇した場合、StackOverflowの適切な具体的な質問があります:)。

ああ最後の一つです:あなたが特にあなたの$(shell ...)呼び出しのsimply expanded変数(すなわち、割り当てのない=ため:=を使用)、使用することを検討すべきです。はるかに効率的になります。

+0

コードを書き直したくありませんでした。これは私が探していた答えの一種です。まったく新しいものを作るためには、どのセクションを見るかを知ることさえ知ることは非常に困難です。私は、CとC++のいくつかのルールが組み込まれている暗黙のルールを考えました。制御できるものではなく、 – akc42

+0

OKです。 _それをより良くする方法を教えてください... git-bash_の下で実行すると便利ですが、誰かに書き直しを求めているようですが、おそらく私はそれを誤って解釈したでしょう。 makeに組み込まれているRe C/C++ルールは、(GNU makeマニュアルで)「組み込みルール」と呼ばれています。すべての組み込みルールは必ず暗黙的ですが、十分でない場合や適切でない場合は、組み込みルールを拡張または置き換える独自の暗黙ルールを定義することができます。がんばろう! – MadScientist

0

メイクファイルを単純化すると、反復すると良い結果が得られます。小さなステップから始めて、関数/変数/暗黙のルールで2つの繰り返しパターンを折り返し、何度も繰り返します。私はsome_prerequisites機能を導入した最初の繰り返しで

some_prerequisites = $1/.env $(shell find $1 \! -name pacakge.json \! -name .dockerimage -depth 1 -type f) 

environment_recipe = cat environments/common/$1.env environments/${enviro}/$1.env > [email protected] 
dockerimage_recipe = docker image build -t $1:${PAS} -t $1:latest $1 && touch [email protected] 

\.dockerimage: access/.dockerimage evening/.dockerimage server/.dockerimage 
    touch [email protected] 
server/.dockerimage: client/client/.dockerimage $(call some_prerequisites, server) 
    $(call dockerimage_recipe,server) 
server/.env: environments/common/server.env environments/${enviro}/server.env 
    $(call environment_recipe,server) 
access/.dockerimage: request/.dockerimage $(call some_prerequisites, access) 
    $(call dockerimage_recipe,access) 
access/.env: environments/common/access.env environments/${enviro}/access.env 
    $(call environment_recipe,access) 
evening/.dockerimage: request/.dockerimage $(call some_prerequisites, evening) 
    $(call dockerimage_recipe,evening) 
evening/.env: environments/common/evening.env environments/${enviro}/evening.env 
    $(call environment_recipe,evening) 
pcode/.dockerimage: libs/.dockerimage $(call some_prerequisites, pcode) 
    $(call dockerimage_recipe,pcode) 
pcode/.env: environments/common/pcode.env environments/${enviro}/pcode.env 
    $(call environment_recipe,pcode) 

: 次はあなたのメイクファイル内の規則の一部を簡略化する私の試みです。それで、makefileがちょっと混乱しなくなったら、私はenvironment_recipedockerimage_recipeを追加しました。

これは#2の繰り返しです:

some_prerequisites = $1/.env $(shell find $1 \! -name pacakge.json \! -name .dockerimage -depth 1 -type f) 

environment_recipe = cat environments/common/$1.env environments/${enviro}/$1.env > [email protected] 
dockerimage_recipe = docker image build -t $1:${PAS} -t $1:latest $1 && touch [email protected] 

\.dockerimage: access/.dockerimage evening/.dockerimage server/.dockerimage 
    touch [email protected] 
server/.dockerimage: client/client/.dockerimage $(call some_prerequisites, server) 
    $(call dockerimage_recipe,server) 
access/.dockerimage: request/.dockerimage $(call some_prerequisites, access) 
    $(call dockerimage_recipe,access) 
evening/.dockerimage: request/.dockerimage $(call some_prerequisites, evening) 
    $(call dockerimage_recipe,evening) 
pcode/.dockerimage: libs/.dockerimage $(call some_prerequisites, pcode) 
    $(call dockerimage_recipe,pcode) 

$(foreach e, pcode evening access server \ 
    $(eval $e/.env: environments/common/$e.env environments/${enviro}/$e.env; \ 
     $$(call environment_recipe,$e) \ 
    ) \ 
) 

これは#3の繰り返しです:

some_prerequisites = $1/.env $(shell find $1 \! -name pacakge.json \! -name .dockerimage -depth 1 -type f) 

environment_recipe = cat environments/common/$1.env environments/${enviro}/$1.env > [email protected] 
dockerimage_recipe = docker image build -t $1:${PAS} -t $1:latest $1 && touch [email protected] 

\.dockerimage: access/.dockerimage evening/.dockerimage server/.dockerimage 
    touch [email protected] 
server/.dockerimage: client/client/.dockerimage 
access/.dockerimage: request/.dockerimage 
evening/.dockerimage: request/.dockerimage 
pcode/.dockerimage: libs/.dockerimage 

$(foreach e, pcode evening access server \ 
    $(eval $e/.env: environments/common/$e.env environments/${enviro}/$e.env; \ 
     $$(call environment_recipe,$e) \ 
    ) \ 
    $(eval $e/.dockerimage: $(call some_prerequisites, $e); \ 
     $$(call dockerimage_recipe,$e) \ 
    )\ 
) 

私の心へのこれはあなたのメイクファイル内のルールのいくつかのために十分な単純化です。他のものは同じパターンに従って単純化することができる。

0

@MadScientistのおかげで、私は暗黙のパターンを探求してきました。私は別のSOの質問/答えで解決された拡張に関する1つの問題を抱えていました。私はどこに行ってもいいと思う。オリジナルの質問以来、makefileにはかなり多くのオプションが追加されています。そのため、1つの比較のためのものではありません。

# Include this file NOT stored in repository which defines which environment to use 
include Makefile.local 
#work out architecture from envonment 
ARCH := ${shell cat environments/${enviro}/arch} 
# Work out the pas version 
PAS := ${shell git describe --abbrev=0} 
# None standard dependancies for each of the images 
server-IMAGEDEPS := libs/database/index.js libs/log/index.js libs/utils/index.js\ 
    $(shell find services/manager -type f -not -name package.json -print0) $(shell find services/web -type f -not -name package.json) \ 
    $(shell find client -type f -not -name .bowerrc -not -name bower.json -not -name package.json -not -name DOCKBUILDfile -print0) 
server-BASEDEPS := services/.dockerimage 
server-LINKDEPS := pasv5-database pasv5-manager pasv5-web 
access-IMAGEDEPS := libs/request/index.js 
access-BASEDEPS := libs/.dockerimage 
access-LINKDEPS := pasv5-request 
evening-IMAGEDEPS := libs/request/index.js libs/log/index.js 
evening-BASEDEPS := libs/.dockerimage 
evening-LINKDEPS := pasv5-request pasv5-log 
pcode-IMAGEDEPS := libs/database/index.js libs/log/index.js libs/utils/index.js 
pcode-BASEDEPS := libs/.dockerimage 
pcode-LINKDEPS := pasv5-database pasv5-log pasv5-utils 
manage-LINKDEPS := pasv5-utils pasv5-log 
web-LINKDEPS := pasv5-log 
daily-LINKDEPS := pasv5-database 

LINKMODULEDIRS := libs/database libs/log libs/utils libs/request services/manager services/web 
NODEMODULEDIRS := $(LINKMODULEDIRS) access evening pcode server daily 

# Standard docker build command 
DOCKBUILD = docker image build -t $(@D)-base:stable $(@D); touch [email protected] 

all: server/.dockerimage evening/.dockerimage pcode/.dockerimage access/.dockerimage 

daily/.env: pcode/.env 
    cp pcode/.env daily/.env 
services/.dockerimage: client/.dockerimage services/Dockerfile services/package.json services/manager/package.json services/web/package.json 
    @(DOCKBUILD) 
client/.dockerimage: libs/.dockerimage client/Dockerfile client/package.json client/.bowerrc client/bower.json 
    @(DOCKBUILD) 
libs/.dockerimage: node/.dockerimage libs/Dockerfile libs/package.json libs/database/package.docker libs/log/package.json libs/utils/package.json \ 
    libs/request/package.json libs/request/akc-crt.pem 
    @(DOCKBUILD) 
node/.dockerimage: node/Dockerfile-${ARCH} node/.dockerignore 
    docker image build -f node/Dockerfile-${ARCH} -t node:latest node 
    $(eval VERSION := $(shell docker run node:latest node --version | cut -c 2-)) 
    docker image tag node:latest node:${VERSION} 
    docker image tag node:latest docker.hartley-consultants.com/node:${VERSION} 
    touch [email protected] 
# stable version of node 
node-stable: 
    docker image tag node:latest node:stable 
clean: clean-images clean-above clean-env 
    rm node/.dockerimage 
    docker image rm -f node:latest 
    docker image rm -f node:${VERSION} 
clean-above: 
    for dir in server access evening pcode client services libs; do [ -f $$dir/.dockerimage ] && rm $$dir/.dockerimage; [ -f $$dir/.dockerbase ] && rm $$dir/.dockerbase; done; exit 0 
clean-env: 
    for dir in access evening pcode server; do rm $$dir/.env; done 
clean-images: clean-above 
    for img in access evening pcode server; \ 
    do docker image rm -f $$img-base:stable; docker image rm -f $$img-${enviro}:${PAS}; rm $$img/.dockerimage; rm $$img/.dockerbase; done 
    for img in services client libs; do docker image rm -f $$img:stable; rm $$img/.dockerimage; done 

# sets up to run system without docker images 
local: server/.env evening/.env pcode/.env access/.env daily/.env $(foreach dir,$(NODEMODULEDIRS), $(dir)/node_modules) 
    npm install -g bower && cd client && bower install 

pasv5-database: 
    cd libs/database; npm link 
pasv5-log: 
    cd libs/log; npm link 
pasv5-utils: 
    cd libs/utils; npm link 
pasv5-request: 
    cd libs/request; npm link 
pasv5-manager: 
    cd services/manager; npm-link 
pasv5-web: 
    cd services/web; npm-link 
clean-local: 
    $(foreach dir,$(NODEMODULEDIRS), $(shell rm -rf $(dir)/node_modules)) 
.SECONDEXPANSION: 
# pattern rules 
%/.env: envionments/common/%.env environments/${enviro}/%.env; cat $^ > [email protected] 
%/.dockerbase: %/Dockerfile %/package.docker %/.env $$(%-BASEDEPS) 
    $(DOCKBUILD) 
%/.dockerimage: %/.dockerbase %/server.js Dockerfile-% $$(%-IMAGEDEPS) 
    docker image build -t $(@D)-${enviro}:${PAS} --build-arg PAS_VERSION=${PAS} -f Dockerfile-${@D} . 
ifeq ($(enviro), production) 
    docker tag $(@D)-production:${PAS} docker.hartley-consultants.com/pas/$(@D):${PAS} 
endif 
    touch [email protected] 
%/node_modules: $$(%-LINKDEPS) 
    cd $*; npm install; for link in $^ ; do npm link $$link ; done 


.PHONY: all clean clean-above clean-images clean-env node-stable local clean-local pasv5-database pasv5-log pasv5-utils pasv5-request pasv5-manager pasv5-web 
関連する問題