17

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

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 $(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...

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

4

2 に答える 2

20

この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.:define対プレーンな古い変数の割り当て

最初のコメントからの質問に答える。define個人的には、いくつかの場合にディレクティブを使用したいと思います。

eval関数で使用する

GNU Makeマニュアルが示唆しているように、 directiveは関数defineと組み合わせて非常に便利です。マニュアルからの例(強調は私のものです):eval

プログラム=サーバークライアント

server_OBJS = server.o server_priv.o server_access.o
server_LIBS=privプロトコル

client_OBJS = client.o client_api.o client_mem.o
client_LIBS=プロトコル

#この後のすべては一般的です

.PHONY:すべて
すべて:$(プログラム)

PROGRAM_templateを定義する
  $(1):$$($(1)_OBJS)$$($(1)_LIBS:%=-l%)
  ALL_OBJS + = $$($(1)_OBJS)
エンデフ

$(foreach prog、$(PROGRAMS)、$(eval $(call PROGRAM_template、$(prog))))

$(プログラム):
    $(LINK.o)$ ^ $(LDLIBS)-o $ @

綺麗:
    rm -f $(ALL_OBJS)$(プログラム)

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

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

#Args:
#1。ヘッダー識別子。
header_templateを定義します
/*このファイルはGNUMake$(MAKE_VERSION)によって生成されます。* /

#ifndef $(inclusion_guard)
#define $(inclusion_guard)

$(foreach inc、$($ 1.includes)、
#include <$(inc).h>)

/*何か他のもの...*/

#endif / * $(inclusion_guard)* /

エンデフ

#1。一意のヘッダー識別子。
include_guard = \
    __GEN_ $ 1_H

#シェルエスケープ。
sh_quote = \
    '$(subst'、'"'"'、$ 1)'

foo.includes:= bar baz

ヘッダー:= foo.h

$(HEADERS):%。h:
    @printf "%s" $(call sh_quote、$(call header_template、$(* F)))> $ @

拡張Make構文

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

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

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

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

#指定したリストを反転します。
#1。リスト
# 戻る:
#要素が逆の順序になっているリスト。
define reverse 
    #空のリストから開始します。
    $(fold、$ 1、

        #新しい各要素($ 2)をに追加する
        #以前の計算の結果。
        $(ラムダ$ 2 $ 1)endef
$(def_all)

これらの新機能を使用して、次のようないくつかの非常に優れた機能を実装できました(少なくとも、Make :-))。

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

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

于 2012-06-04T15:38:14.457 に答える
1

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

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

HTH..。

于 2014-02-18T03:03:10.790 に答える