我需要构建一些混合纯 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
$猫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如果你想玩这个,你需要它
最佳答案
这都是关于如何读取 Makefile 和如何扩展变量的。
检查 automake 生成的 Makefile 可以看到 $eval
调用最终出现在 Makefile 的末尾。最终 Makefile 中的顺序似乎是:AM 变量、用户变量、AM 规则,最后是用户规则。当我们修改 AM 规则的先决条件时,我们必须在解析规则本身之前完成此操作,因为规则先决条件会立即扩展。
A rule is always expanded the same way, regardless of the form:
immediate : immediate ; deferred
deferred
https://www.gnu.org/software/make/manual/html_node/Reading-Makefiles.html
由于 eval 函数始终为空字符串,因此我们可以将其分配给一次性变量,强制立即扩展。然后,它将与用户变量一起放置在最终 Makefile 中的 AM 规则定义之前。
ignore:=$(eval include cuda.mk)
关于c++ - 使用 CUDA/自定义语言和 $(eval) 规则创建的 automake,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33895351/