【问题标题】:automake with CUDA/custom language and $(eval) rule creation使用 CUDA/自定义语言和 $(eval) 规则创建的 automake
【发布时间】:2016-02-26 23:51:38
【问题描述】:

我需要构建一些混合纯 C 文件和 CUDA 文件的内部库。此外,可以使用不同的预处理器选项从相同的源构建不同的库。

我设法得到了一些有用的东西,但是我不喜欢 当可以从 _SOURCES var 中轻松推断出 CUDA 对象时,我必须显式定义它们

$ cat Makefile.am

AUTOMAKE_OPTIONS = foreign

NVCC=cc
cuda_libs = libfoobar1.a libfoobar2.a

noinst_LIBRARIES = $(cuda_libs)

foobar_sources = foo.c bar.cu
libfoobar1_a_SOURCES  = $(foobar_sources)
libfoobar1_a_CPPFLAGS = -DLIB1
libfoobar1_a_LIBADD   = libfoobar1_a-bar.o # CUDA object explicit definition 
libfoobar2_a_SOURCES  = $(foobar_sources)
libfoobar2_a_CPPFLAGS = -DLIB2
libfoobar2_a_LIBADD   = libfoobar2_a-bar.o # CUDA object explicit definition 

$(eval include cuda.mk) # why eval? Check comment #1

clean-local:
    rm -rf libfoobar2_a-bar.o libfoobar1_a-bar.o

$ cat cuda.mk

# $(get_conincal names)
get_canonical = $(subst .,_,$(1))

# $(call cuda_rule prefix) http://blog.jgc.org/2012/01/using-gnu-makes-define-and-eval-to.html
define cuda_rule
$(1)-%.o: %.cu
    $(NVCC) $(CUDA_CFLAGS) $($(1)_CPPFLAGS) --compiler-options="$($(1)_CFLAGS)" -c -o $$@ $$<
endef

$(foreach cuda_prefix,$(call get_canonical,$(cuda_libs)),$(eval $(call cuda_rule,$(cuda_prefix))))

如果我尝试概括 CUDA 对象定义,将它们移动到规则生成中,如下所示:

define cuda_rule
$(1)_LIBADD = $(addsuffix .o,$(addprefix $(1)-,$(basename $(filter %.cu,$($(1)_SOURCES)))))
[...]
endef

make 现在似乎没有得到规则,并且不知道如何构建 CUDA 对象:

ar cru libfoobar1.a libfoobar1_a-foo.o libfoobar1_a-bar.o
ar: libfoobar1_a-bar.o: No such file or directory

有什么想法吗? 提前致谢。

阿尔伯特

附: All files 如果你想和这个一起玩,你需要这个

【问题讨论】:

  • 这几乎可以肯定是不相关的,但你为什么要eval-ing include cuda.mk
  • 因为否则 automake 会解析包含的文件,并且当它发现时认为 $(1)_LIBADD 不喜欢并会抱怨。 stackoverflow.com/questions/7437116/…
  • 好的。我认为这回答了你的问题。由于 automake 扫描 _LIBADD/etc。在 automake 的时候,如果你在 make 之前不生成这些变量,你真的不能指望它工作,对吗?除非您只需要它在生成时使用变量的值,但我不认为这些不会那样工作。如果可能的话,您可能需要在自动生成时进行循环。
  • 感谢 cmets @EtanReisner 您为我指出了解决方案

标签: c++ cuda eval gnu-make automake


【解决方案1】:

这完全是关于如何读取 Makefile 和如何扩展变量。

检查由 automake 生成的 Makefile 可以看到 $eval 调用最终出现在 Makefile 的末尾。最终 Makefile 中的顺序似乎是:AM vars、user vars、AM 规则,最后是用户规则。由于我们正在修改 AM 规则的先决条件,因此我们必须在规则本身被解析之前执行此操作,因为规则先决条件会立即扩展。

无论形式如何,规则总是以相同的方式展开:

立即:立即;延期

         deferred

https://www.gnu.org/software/make/manual/html_node/Reading-Makefiles.html

由于 eval 函数始终为空字符串,我们可以将其分配给一次性变量,强制立即展开。然后,它将在最终 Makefile 中与用户变量一起放置在 AM 规则定义之前。

ignore:=$(eval include cuda.mk)

【讨论】:

  • 这行得通,因为 automake 将赋值内联但“随机”代码放在最后?
  • 是的,或多或少。据我所知,顺序似乎是 am vars、user vars、am rules、user rules。
  • 在答案中可能值得一提。但是很好的技巧。
  • 答案已修改,谢谢
猜你喜欢
  • 2017-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
  • 1970-01-01
相关资源
最近更新 更多