Makefile中的条件链接

Makefile中的条件链接,makefile,linker,conditional,Makefile,Linker,Conditional,在我的Makefile中,我只想链接到机器上安装的库。因此,例如,如果库是hwloc,我想执行以下操作: xfoo : foo.o if (hwloc installed) gcc foo.o -o $@ -lhwloc else gcc foo.o -o $@ 有没有办法做这样的事?i、 e.是否可以检查是否安装了特定的库,并将其作为Makefile中的条件使用?以下是错误的答案: xfoo : foo.o if (hwloc installed);

在我的Makefile中,我只想链接到机器上安装的库。因此,例如,如果库是
hwloc
,我想执行以下操作:

xfoo : foo.o
   if (hwloc installed)
      gcc foo.o -o $@ -lhwloc
   else
      gcc foo.o -o $@

有没有办法做这样的事?i、 e.是否可以检查是否安装了特定的库,并将其作为Makefile中的条件使用?

以下是错误的答案:

xfoo : foo.o
   if (hwloc installed); then gcc foo.o -o $@ -lhwloc; else gcc foo.o -o $@; fi
从Makefile执行的命令不必只是简单的单个命令。shell可以执行的任何内容都可以从Makefile调用。包括整个脚本,夹在一行中

以下是正确答案:

然而,上述方法是错误的。你会发现很多自由软件包一直都在做这种事情:在一个库中有条件地链接,如果它可用的话

但它的实现方式是在运行make之前运行一个单独的
configure
脚本。去抓取你选择的随机免费软件包的源代码tarball,阅读安装说明。它们都会告诉您在运行
make
之前,首先运行
configure
脚本

绝大多数自由软件包都使用GNU工具链来创建构建系统——
configure
脚本和
Makefile
。GNU工具链包括
autoconf
automake
工具(在许多情况下也是
libtool
)。更多信息,请点击谷歌

还有一些其他的不太流行的工具链,但是GNU工具链是最常用的一个,用于这类事情。所以,要按照你想做的事情去做,通常的做法是:

configure.ac
文件中:

AC_CHECK_LIB(hwloc,some_function_in_the_hwloc_library,[LINK_HWLOC=-lhwloc])
AC_SUBST(LINK_HWLOC)
hwloc_LDADD=@LINK_HWLOC@
Makefile.am
文件中:

AC_CHECK_LIB(hwloc,some_function_in_the_hwloc_library,[LINK_HWLOC=-lhwloc])
AC_SUBST(LINK_HWLOC)
hwloc_LDADD=@LINK_HWLOC@

就这样。大多数自由软件包需要无数次这样做
autoconf
automake
将负责编写实现此功能的shell脚本和makefile。

如果您不想参与autotools/etc的话(虽然对于这样简单的事情,合理的解决方案也是合理的)而且你不想玩猜谜游戏,猜测人们可能在哪里安装了这个
hwloc
库,那么你最好让人们手动打开这个功能

使用三(或四)个make变量<代码>使用HWLOC,
HWLOC\u LDLIBS
HWLOC\u CFLAGS
以及可能的
HWLOC\u LDFLAGS

然后,当定义了
USE\u HWLOC
时,您可以链接库,并使用其他三个变量,以防它们也被设置

ifdef USE_HWLOC
HWLOC:=-lhwloc
else
HWLOC:=
HWLOC_LDLIBS:=
HWLOC_LDFLAGS:=
HWLOC_CFLAGS:=
endif

xfoo : foo.o
   gcc foo.o -o $@ $(HWLOC_LDLIBS) $(HWLOC)

我目前没有访问Linux机器的权限,所以请原谅,我的答案将未经测试

我将恭敬地反对我的两位前任

首先,使用自动工具修改现有的Makefile是一个坏主意。自动工具是为了避免在一个简单的用例中创建一个好的Makefile。这就像OP问“如何在我的Python脚本中将
+
更改为
-
”,答案是“编写一个shell脚本来修改脚本,将其保存在临时文件中并执行该文件”

第二个答案是,当可以毫无痛苦地自动完成某件事时,为什么要手动完成

因此,正确答案是,这正是
$(通配符)
的使用案例:


注意:库已安装或未提前安装,但未在构建期间制作。

我无法理解使用模型-假设计算机上未安装heloc,哪个实体将解析其“引用”符号?这些引用符号将使用预处理器禁用。因此,foo.o对于这两种情况并不完全相同。很抱歉对这个简短的示例产生误解。值得考虑的另一个选择是让用户在Makefile顶部使用一个简单的变量来配置是否/如何链接hwloc。您能解释一下这是如何工作的吗?我不熟悉
$(通配符)
。是的。在此生成之前,库是否已安装。@Rakib很抱歉。。。请不要生气,但是,您现在必须去阅读手册,了解函数
通配符
patsubst
的工作原理。很好。我试试看。谢谢