web-dev-qa-db-ja.com

makefileにセパレータがありません

さて、私はこれに固執していて、何が間違っているのかわかりません。より複雑なメイクファイルですべてがうまく機能していましたが、突然「セパレータがありません」というエラーが発生しました。私はそれを非常に単純なシナリオに分離することができました:

test.mk

define Push_dir
$(info ${1})
endef

define pop_dir
$(info ${1})
endef

define include_submake
$(call Push_dir,${1})
$(call pop_dir,${1})
endef

シンプル

include test.mk

INITIAL_SUBMAKE:= includeme.mk
$(call include_submake,${INITIAL_SUBMAKE})

process:
    @echo Processed...

そして出力:

C:\project>make -f Simple process
includeme.mk
includeme.mk
Simple:4: *** missing separator.  Stop.

includeme.mkは実際には存在しません。ここで何がうまくいかないのかわかりません。私はさまざまなことを試しました。 include_submakeの呼び出しをinfoで囲むと、次のようになります。

$(info $(call include_submake,${INITIAL_SUBMAKE}))

セパレーターがないというエラーはなくなりました。また、include_submake定義で、関数の1つだけを呼び出すと、正常に機能します。さらに、関数をinclude_submakeではなく直接呼び出すと、次のように機能します。

include test.mk

INITIAL_SUBMAKE:= includeme.mk
$(call Push_dir,${INITIAL_SUBMAKE})
$(call pop_dir,${INITIAL_SUBMAKE})

process:
    @echo Processed...


C:\project>make -f Simple process
includeme.mk
includeme.mk
Processed...

ここで基本的なことを見落としているような気がします。ご協力いただきありがとうございます。

17
ThePosey

_missing separator_エラーは、空の戻り値_include_submake_が原因で発生します。これは、ケースでは単一の改行文字です。 Makeは、あるルールまたは別のディレクティブの一部であると想定されていない式で空白文字(つまり、スペースまたはタブ)を使用することのみを許可します。

昔ながらのMake変数の代入を使用して関数を書き直すと、エラーがなくなるはずです。

_Push_dir = \
    $(info $1)

pop_dir = \
    $(info $1)

include_submake = \
    $(call Push_dir,$1) \
    $(call pop_dir,$1)
_

UPD。:definevsプレーンな古い変数の割り当て

最初のコメントからの質問への回答。個人的には、いくつかのケースでdefineディレクティブを使用したいと思います。

eval関数での使用

GNUマニュアルで提案するように、defineディレクティブは eval関数 と組み合わせて使用​​すると非常に便利です。マニュアルの例(強調は私のものです):

 PROGRAMS = server client 
 
 server_OBJS = server.o server_priv.o server_access.o 
 server_LIBS = priv protocol 
 
 client_OBJS = client.o client_api.o client_mem.o 
 client_LIBS =プロトコル
 
#この後のすべては一般的です
 
。PHONY:すべて
すべて:$(PROGRAMS)
 
pROGRAM_templateを定義する
 $(1):$$($(1)_OBJS)$$($(1)_LIBS:%=-l%)
 ALL_OBJS + = $$($(1)_OBJS )
エンデフ
 
 $(foreach prog、$(PROGRAMS)、$(eval $(call PROGRAM_template、$(prog))))
 
 $(PROGRAMS): 
 $(LINK.o)$ ^ $(LDLIBS)-o $ @ 
 
 clean:
 rm -f $(ALL_OBJS)$(PROGRAMS)

ジェネレータテンプレート

逐語的変数は、GNU Makeからファイルを生成する場合に完全に適合します。たとえば、Makefileからの情報に基づいてヘッダーファイルを生成することを検討してください。

#引数:
#1。ヘッダー識別子。header_templateを定義します
/*このファイルはGNU Make $(MAKE_VERSION)。*/
 
#ifndef $(inclusion_guard)[.____によって生成されます。 ] #define $(inclusion_guard)
 
 $(foreach inc、$($ 1.includes)、
#include <$(inc).h>)
 
/*他の何か... * /

#endif/* $(inclusion_guard)*/

エンデフ#1。一意のヘッダー識別子。
 inclusion_guard =\
 __GEN_ $ 1_H 
 
#シェルエスケープ。
 sh_quote =\
 '$(subst'、 '"'" '、$ 1)' 
 
 foo.includes:= bar baz 
 
 HEADERS:= foo.h 
 
 $(HEADERS):%。h:
 @printf "%s" $(call sh_quote、$(call header_template 、$(* F)))> $ @ 

拡張Make構文

私たちのプロジェクトでは、 Mybuild と呼ばれる独自のビルドシステムを使用し、GNU Make。以前の低レベルのハックの1つとして完全に実装されています。 Makeの組み込み言語の貧弱な構文を改善し、関数定義に拡張構文を使用できるようにする 特別なスクリプト を開発しました。スクリプト自体もMakeで記述されているため、一種のMakeでのメタプログラミング。

特に、次のような機能を使用できます。

  • バックスラッシュを使用せずに複数行関数を定義する
  • 関数内でのコメントの使用(昔ながらのMakeコメントは、変数代入ディレクティブの外部でのみ発生します)
  • $(assert ...)$(lambda ...)などのカスタムマクロの定義
  • $(eq s1,s2)(文字列の等価性チェック)のような単純な関数のインライン化

これは、拡張構文を使用して関数を作成する方法の例です。これは有効なMake関数になり、$(def_all)の呼び出し後に通常どおり呼び出すことができることに注意してください。

#指定されたリストを逆にします。
#1。リスト
#戻り値:
#要素を逆順にしたリスト。リバースを定義する#空のリストから開始します。
 $(fold、$ 1、
 
 #新しい各要素($ 2)を
に追加します。#前の計算の結果。$(ラムダ$ 2 $ 1)エンデフ
 $(def_all)

これらの新機能を使用して、次のようないくつかの本当にクールなものを実装することができました(まあ、少なくともMake :-)の場合)

  • 動的なオブジェクト割り当て、クラス継承、メソッド呼び出しなどを備えたオブジェクト指向レイヤー
  • GOLD Parser Builder によって生成されたパーサー用のLALRパーサーランタイムエンジン
  • [〜#〜] emf [〜#〜] で生成されたモデルのランタイムサポートを備えたモデリングライブラリ

コード の任意の部分を自分のプロジェクトで自由に使用してください!

20

私は同じ問題に遭遇しました。 「タブ」を挿入し、「タブ」を削除し、念のため再挿入しました。同じエラーメッセージ。

しかし、私はこれらすべてをXCodem内で実行しましたが、驚いたことに、 '\ t'ではなく空白が挿入されました。別のエディターを使用すると、これらの「ファントム」エラーはなくなりました。

HTH.。

0
Heikki