如何创建自定义后缀规则以使用另一个目录中的标题?

Posted

技术标签:

【中文标题】如何创建自定义后缀规则以使用另一个目录中的标题?【英文标题】:How to create a custom suffix rule to use a header in another directory? 【发布时间】:2020-07-29 21:28:54 【问题描述】:

我有一个像下面这样的 Makefile.am 来使用 automake 为 Qt 编译 MOC 文件。

bin_PROGRAMS = test

test_qtheaders = window.h

test_moc_sources = $(test_qtheaders:.h=_moc.cpp)

test_SOURCES =               \
    main.cpp                 \
    main-window.cpp          \
    window.cpp               \
    $(test_moc_sources)

test_CPPFLAGS = -I/usr/include -I/usr/local/include -I$(QT5_INCL) -I$(QT5_INCL)/QtWidgets -I$(QT5_INCL)/QtCore

test_LDFLAGS = -L/usr/lib64 -L/usr/local/lib64 -L/usr/local/lib -L$(QT5_LIBS)

test_LDADD = -lrt -lQt5Core -lQt5Gui -lQt5Widgets

SUFFIXES = .h _moc.cpp

# this suffix rule is not finding the headers from src/includes/gui
.h_moc.cpp:
    $(QT_MOC) -o $@ $(test_CPPFLAGS) $(CPPFLAGS) $<

我收到以下错误。

make[4]: *** No rule to make target 'window_moc.cpp', needed by 'test-window_moc.o'.  Stop.

我的目录结构如下:

myproj
|- configure.ac
|- Makefile.am
|- ...
` src
    |- Makefile.am
    |- includes
    |    `- gui 
    |        |- main-window.h
    |        `- window.h    // file required to generate *.cpp.
    |
    `- gui
        |- Makefile.am
        |- main.cpp
        |- main-window.cpp
        `- window.cpp   // output of MOC, does not yet exist.

如果我将 main-window.h 文件放在 src/gui 目录中,MOC 会找到并构建它。将 src/includes/gui 路径添加到 test_CPPFLAGS 不会这样做。我也尝试将 ../../includes/gui/$ 添加到命令中,但无济于事。

所以我的问题是,如果文件位于 Makefile.am 的外部目录中,如何告诉后缀规则在哪里找到文件?

【问题讨论】:

【参考方案1】:

如何创建自定义后缀规则以使用另一个目录中的标头?

你不能。后缀规则的本质是它们适用于在同一目录中具有相应先决条件的目标。不可能,因为make 对路径结构一无所知。也就是说,尽管目标名称和先决条件名称可以包含目录组件,make 只是将它们视为平面字符串(当它将此类字符串传递给 C 库或将它们插入到 shell 命令中时,它会做正确的事情)。*

特别是这个后缀规则...

.h_moc.cpp:
    $(QT_MOC) -o $@ $(test_CPPFLAGS) $(CPPFLAGS) $<

...,根据您的后缀声明进行解释,描述如何从名为 的相应先决条件构建具有 _moc.cpp 形式名称的目标em>.h。假设您要构建的目标实际上是gui/window_moc.cpp(不是问题中显示的gui/window.cpp),则相关前缀将是gui/window。相应的先决条件将是gui/window.h,这与include/gui/window.h 完全不同。

如果您想从include/gui/ 中的源代码构建gui/ 中的目标,并根据Autotools 的建议坚持可移植的make 语法和功能,那么您将需要编写普通的目标规则,而不是后缀规则:

gui/window_moc.cpp: include/gui/window.h
    $(QT_MOC) -o $@ $(test_CPPFLAGS) $(CPPFLAGS) $<

我认为您想要一个后缀规则来避免编写多个常规目标规则,这是一个完全合理的想法。但是,如果您需要问题中描述的源和目标布局,则根本不是一种选择。


* Autotools 在这里基本上是无关紧要的,因为它们对出现在您的 Makefile.am 中的自定义规则所做的主要工作是将它们原封不动地传递给最终的 makefile。

【讨论】:

以上是关于如何创建自定义后缀规则以使用另一个目录中的标题?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Magento 1 中应用我的自定义目录价格规则条件?

具有多个参数的 Laravel 自定义验证规则 [重复]

我将如何引用使用 C++ 中的另一个库创建的自定义库?

如何将方法调用传递到自检器中的 Action、Func 或 Delegate 以获取自定义规则?

流明自定义验证

如何使用自定义组名添加 Windows 防火墙规则?