mkdirを使用しているときにmakefileで「ディレクトリがすでに存在する」エラーを防ぐ方法


109

makefileにディレクトリを生成する必要がありますが、簡単に無視できるにもかかわらず、「ディレクトリはすでに存在しています」というエラーが何度も表示されないようにしたいと思います。

私は主にmingw / msysを使用していますが、他のシェル/システムでも機能するものを望んでいます。

私はこれを試しましたが、うまくいきませんでした。

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif

回答:


106

UNIXの場合これを使用するだけです。

mkdir -p $(OBJDIR)

mkdirの-pオプションは、ディレクトリが存在する場合のエラーメッセージを防ぎます。


39
「一般的に、これらのプログラムの広くサポートされている(通常はposixで指定されている)オプションと機能を使用します。たとえば、「mkdir -p」を使用しないでください。いくつかのシステムではサポートされていないため、他のユーザーと一緒に実行しても、並列実行は安全ではありません。 " gnu.org/s/hello/manual/make/Utilities-in-Makefiles.html
greg.kindel

8
-pWindowsでは動作しません。これはおそらく質問が尋ねていることです。これがどのように受け入れられたのかはわかりません。
アンチモン、2014年


1
@Antimony MinGWシェルの外でGNU Makeを使用している場合、おそらく何か間違ったことをしたでしょう。しかし、あなたの選択。
yyny

「UNIXの場合、これを使用してください...」 - make -pUnixとLinuxのどちらですか?
jww 2018

122

公式のmakeドキュメントを見てこれを行うには良い方法があります:

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)

$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    mkdir -p $(OBJDIR)

|の使用法がここに表示されます。パイプ演算子、順序のみの前提条件を定義します。現在のターゲットを構築するために、$(OBJDIR)ターゲットは(より最近のものではなく)存在する必要があることを意味します。

私が使用しmkdir -pたことに注意してください。-pフラグは、ドキュメントの例と比較して加えました。別の選択肢については、他の回答を参照してください。


4
これは間違いなくこの問題の公式な方法です。
lcltj

@CraigMcQueen:私は本当に意味$(OBJDIR)ターゲットがあるべき存在。ファイルの存在(およびタイムスタンプ)をチェックして、ターゲットを構築する必要があるかどうかを判断します。したがって、ここで$(OBJDIR)は、存在しない場合は構築され、現在のターゲットを構築するために存在$(OBJS)ます。これは内部に作成されます。
ofavre

私は文字通りこれを見つける前にこの問題を解決する他のすべての組み合わせを試したと思います(私はwindows / linuxの間でできる限り一般的なmakefileを生成しようとしています)-これは私が働くことができる唯一のものですが、それはそれですとてもうまくいきます!:)
code_fodder 2018

67

testコマンドを使用できます。

test -d $(OBJDIR) || mkdir $(OBJDIR)

7
これは、makefileがWindows(gnuwin32とPowerShellを使用)とPOSIX準拠のOSの両方で機能する必要がある場合に推奨される方法です。
クリスハーディ

6
「テスト」ユーティリティを提供するためのgnuwin32 CoreUtilsパッケージがあることを提供します。
davenpcj 2013

2
ここで遅くなりますがmake -j、ディレクトリの存在がテストされてから作成されるまでの競合状態により、このソリューションが並列でビルドするときに失敗する可能性があることを指摘しておきます()。あるジョブはそこにないことをテストできますが、作成する前に別のジョブがディレクトリを作成します。その後、最初に作成しようとすると、ディレクトリがすでに存在するため失敗します。この場合の最良の解決策は、@ TeKaの回答(これは受け入れられた回答であるべきです)で述べられているように、順序のみの前提条件を使用することです。
C0deH4cker 2014

@MarcusJは私のOS X El Capitanで動作します。どのバージョンがそれを壊しましたか?
Franklin Yu

@ C0deH4cker-私の無知を許して... TeKaはどちらの答えですか?TeKaさんはコメントしてから名前が変わったと思います。
jww 2018

18

以下は、コンパイラの出力ディレクトリを作成するためにGNU makeで使用するトリックです。最初にこのルールを定義します。

  %/.d:
          mkdir -p $(@D)
          touch $@

次に、ディレクトリに移動するすべてのファイルを、そのディレクトリの.dファイルに依存するようにします。

 obj/%.o: %.c obj/.d
    $(CC) $(CFLAGS) -c -o $@ $<

$ ^の代わりに$ <を使用していることに注意してください。

最後に、.dファイルが自動的に削除されないようにします。

 .PRECIOUS: %/.d

.dファイルをスキップすると、ディレクトリに直接依存していても機能しません。ディレクトリにファイルが書き込まれるたびにディレクトリ変更時刻が更新されるため、makeを呼び出すたびに再構築が強制されるためです。


1
ああ、ありがとう、私はこのようなものを働かせようとしていました。いくつかの目標で「test -d foo || mkdir foo」を使用したくないので、「make -j2」を使用すると、同時にテストされます。両方のテストでfalseが返され、2つのプロセスがmkdirを試行します。それらの最後の失敗。
10

13

ディレクトリが既に存在することが問題ではない場合は、そのコマンドのstderrをリダイレクトして、エラーメッセージを取り除くことができます。

-mkdir $(OBJDIR) 2>/dev/null

これには、Windowsでも作業できるという利点があります。makeがベイルしないように、コマンドの前にある「-」を忘れないでください。
マイケル・バー

11

makefile内:

target:
    if test -d dir; then echo "hello world!"; else mkdir dir; fi

10

Windowsの場合

if not exist "$(OBJDIR)" mkdir $(OBJDIR)

Unixの場合| Linux

if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi

これはWindows用です。
チェックサム

/bin/sh: 1: Syntax error: end of file unexpected (expecting "then")
wotanii

最初のバージョンはWindows用で、2番目のオプションは@checksumが言ったようにLinuxで機能します
Edgard Leal

最初のWindowsバージョンはアトミックではないため、別のプロセス(たとえば、並列モードのルール)が「存在しない」と「mkdir」の間にディレクトリを作成する場合は機能しません。
PetrVepřek18年


6
$(OBJDIR):
    mkdir $@

これは、複数のディレクトリでも機能します。

OBJDIRS := $(sort $(dir $(OBJECTS)))

$(OBJDIRS):
    mkdir $@

$(OBJDIR)最初のターゲットとして追加するとうまくいきます。


3

mingw32 / msys / cygwin / linuxで動作します

ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif

0

戻りコードを明示的に無視してエラーストリームをダンプすると、makeはエラーが発生しても無視します。

mkdir 2>/dev/null || true

これは並列makeでレースの危険を引き起こすことはないはずですが、確認するためにテストしていません。


0

ラースの答えよりも少し簡単です:

something_needs_directory_xxx : xxx/..

そして一般的なルール:

%/.. : ;@mkdir -p $(@D)

クリーンアップまたは.PRECIOUSを作成するタッチファイルはありません:-)

別の小さな一般的なgmakeトリックを見たい場合、または最小限のスキャフォールディングで再帰的でないmakeに興味がある場合は、そのブログの2つのさらに安価なgmakeトリックと他のmake関連の投稿をチェックしてみてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.