web-dev-qa-db-ja.com

GNUユーザー定義関数内の条件関数$(if ...)を常にtrueに評価する

空のファイルをタッチ/作成したり、可能な場合はアクセス許可、ユーザー、グループを設定したり、そうでない場合は警告したりするmake関数を記述しようとしています。ただし、私の関数内のすべての条件付きチェックはtrueと評価されるようです。

私のメイクファイルの本質は

_INSTALL_USER  := fileUser
INSTALL_GROUP := fileGroup

.PHONY: test
test:
    $(call touchFile,~/test.ini)

define touchFile
$(eval fileName := $(strip $(1)))
-touch $(fileName)
-chmod -c 664 $(fileName)

$(info filename info $(fileName))
$(info $(Shell stat -c "%a %U:%G" $(fileName)))

$(if ifeq  "foo" "bar", @echo match is broken, @echo match works)
$(if ifneq "foo" "bar", @echo match works, @echo match is broken)

$(if ifneq ($(Shell stat -c %a $(fileName)),664), $(warning Error - $(fileName) does not have expected permissions of 664))
-chgrp -c $(INSTALL_GROUP) $(fileName)
$(if ifneq ($(Shell stat -c %G $(fileName)),$(INSTALL_GROUP)), $(warning Error - $(fileName) does not belong to $(INSTALL_GROUP) group))
-chown -c $(INSTALL_USER) $(fileName)
$(if ifneq ($(Shell stat -c %U $(fileName)),$(INSTALL_USER)), $(warning Error - $(fileName) does not belong to $(INSTALL_USER) user))
endef
_

_make test_出力の実行

_filename info ~/test.ini
664 myUserName:myGroup
Makefile:7: Error - ~/test.ini does not have expected permissions of 664
Makefile:7: Error - ~/test.ini does not belong to common group
Makefile:7: Error - ~/test.ini does not belong to netserve user
touch ~/test.ini
chmod -c 664 ~/test.ini
match is broken
match works
chgrp -c fileGroup ~/test.ini
changed group of `/home/myUserName/test.ini' to fileGroup
chown -c fileUser ~/test.ini
chown: changing ownership of `/home/myUserName/test.ini': Operation not permitted
make: [test] Error 1 (ignored)
_

私は次のことを検討/試しました:

  • $(if ...)は、関数がパラメーター付きで呼び出される前に、「コンパイル時」に評価されます。ただし、ハードコードされた_ifeq "foo" "bar"_も無効な結果を返します。さらに、$(info ...)$(fileName)を「コンパイル時」に正しく評価します。
  • documentation は実際には例を示していないため、$(if ifeq...)に加えて、無視されているように見える$(ifeq ...)も試しました。
  • 「非機能」if(つまり、$(if...)なしのifeq)は、関数内で_/bin/sh: ifeq: command not found_を返します。

誰かが私の条件文が期待通りに動作しない理由(またはなぜ私が間違ったことを期待しているのか)を特定するのを手伝ってくれませんか?

警告:ファイルが存在しない場合でも解決すべきバグがあることはわかっていますが、このハードルに比べればそれは簡単なはずです。

12
nshew

$(if ...)条件付き関数 渡された最初の引数が空でない場合、trueと評価されます。あなたの場合、条件はリテラルテキストです:ifeq "foo" "bar"、明らかに、空ではありません。

ifeq/ifneq conditionals は実際には関数ではなくディレクティブです。変数定義の内部や関数では使用できません。

例に戻り、条件内で文字列が等しいかどうかをテストするには、 filterおよびfindstring などの関数を使用します。

$(if $(filter foo,bar),@echo match is broken,@echo match works)
$(if $(filter-out foo,bar),@echo match works,@echo match is broken)

ところでこれは、読みやすくするためにインライン形式に変えることもできます:

@echo match $(if $(filter foo,bar),is broken,works)
@echo match $(if $(filter-out foo,bar),works,is broken)
44

この問題に直面し、「フィルター」関数の結果を「if」関数の「条件」部分で使用できることがわかりました。これは、Linux(「evince」を使用)、またはOSXで「open」を使用してPDFを開くのに役立つ例です。

uname     :=$(Shell uname -s)
is_darwin :=$(filter Darwin,$(uname))
viewpdf   :=$(if $(is_darwin), open, evince)
7
user5122888

あなたは方法を誤解しているようです$(if機能します。 make info docsから:

$(if CONDITION、THEN-PART [、ELSE-PART]) '`if'関数は、関数コンテキストでの条件付き展開をサポートします

最初の引数CONDITIONは、最初にすべての前後の空白を取り除き、次に展開されます。空でない文字列に展開された場合、条件は真と見なされます。空の文字列に展開される場合、条件はfalseと見なされます。

すべての例で、条件はifeq SOMETHING OTHERTHING-これは空ではない文字列であり(他のものに関係なくifeqから)、そのためtrueとして扱われます。

2
Chris Dodd

oSのバージョンがLinuxまたはその他であることを確認したい場合、およびLinuxの場合はメッセージを出力したい場合は、次の手順に従います。

ifneq ($(TARGETOS), Linux)
    target: server
    @echo
    @echo $(MSG) $(TARGETOS)
else
target: server
    @echo $(MSG) $(TARGET)
endif

ifeqで試す前に、else部分のみを出力しました。私のOSはLinux、ubuntuです。

誰かがこの答えを見つけた場合は修正する必要があるので、これについてもより良い答えを与えることができます。

1
amit pandya