この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で生成されたモデルのランタイムサポートを備えたモデリングライブラリ
自分のプロジェクトでコードの任意の部分を自由に使用してください!