【发布时间】:2017-01-10 16:04:19
【问题描述】:
我的任务是将古老的基于 C++ 的代码从 Unix 环境迁移到 Linux。 该项目由多个 Makefile 组成,用于库的不同“模块”。 我已经解决了一些问题,但是现在遇到了包含指令的问题。
显然,Makefile 的构造方式是为不同的文件设置一个单独的包含指令,并且它在 Unix 服务器中工作了多年。
例如:
include ../../../../util/genmake.def
processControl.slOBJS = processControl.o
outputControlOBJS = outputControl.o
inputControlOBJS = inputControl.o
cleanList = *.o *.C *.out processControl.sl outputControl inputControl
all: processControl.sl outputControl inputControl
processControl.sl: $(processControl.slOBJS)
include ../../../../util/genmake.slinc
outputControl: $(outputControlOBJS)
include ../../../../util/genmake.exeinc
inputControl: $(inputControlOBJS)
include ../../../../util/genmake.exeinc
include ../../../../util/genmake.inc
你可以在这里看到,标签式包含,只指指定的目标!它们是实现该目标的秘诀的一部分。
但是,这个结构在 Linux 中不起作用,我得到这个错误:
include ../../../../util/genmake.slinc
make: include: Command not found
make: *** [processControl.sl] Error 127
显然我不能只删除选项卡,因为包含应该只针对该目标...
所以,我尝试用 shell 'source' 命令替换它来获取包含的文件,例如:
source ../../../../util/genmake.slinc
这显然不起作用,我还尝试将包含的代码直接引入到包含文件中(注释掉包含命令) - 这会处理与 Makefile 相关的错误,但这不是一个好的解决方案,因为它会迁移和维护它真的很困难,必须将整个项目中的相同代码复制到所有模块中,然后当然每一个微小的变化我都必须反映在所有文件中。
任何Make专家都可以就这个问题提出建议吗? 此外,通常欢迎任何有关如何最好地处理此迁移任务的建议:)
谢谢!
编辑- 额外信息: genmake.slinc 的内容:
#######################################################################
## This include will inherit the target and dependent files in
## a make file that inlcudes it.
## The inclusion of this file should look like:
##
## {target}: {dependent file list}
## include genmake.slinc
##
#######################################################################
@echo "----------------------------------------------------------------"
@echo " (G) Creating shared library $@ from $($(MaKeObJs:x=$(@)OBJS))";
@echo "----------------------------------------------------------------"
@echo "$(CPP) -b -o $@ $($(MaKeObJs:x=$(@)OBJS))"
@$(CPP) -b -o $@ $($(MaKeObJs:x=$(@)OBJS))
@echo " Moving shared library to $(SHLIBINSTALL) as lib$(@)"
@$(MV) $@ $(SHLIBINSTALL)/lib$(@)
@echo "----------------------------------------------------------------"
那些是@之前的制表符。
现在genmake.exeinc的内容:
#######################################################################
## This include will inherit the target and dependent files in
## a make file that inlcudes it.
## The inclusion of this file should look like:
##
## {target}: {dependent file list}
## include /opt/app/fba/util/genmake.exeinc
##
#######################################################################
@cp $(SHLIBINSTALL)/* $(TEMP_SHLIB_DIR)/.
@echo "----------------------------------------------------------------"
@echo " (G) Linking $($(MaKeObJs:x=$(@)OBJS)) to make $@ "
@echo " LDOPTS set to: $(LDOPTS)"
# @echo " $(PURIFY) $(LD) "
@echo " SHLIB Temp Path: $(TEMP_SHLIB_DIR)
@echo " FBA libraries: $(FBALIB)"
@echo " Application libraries: $(APPLIBS)"
$(PURIFY) $(LD) -o $@ $($(MaKeObJs:x=$(@)OBJS)) \
$(CXXOPTS) \
$(LDFLAGS) \
$(FBALIB) \
$(PROLDLIBS) \
`cat /usr/local/opt/oracle/product/t1c3d771/lib/ldflags` \
`cat /usr/local/opt/oracle/product/t1c3d771/lib/sysliblist` \
$(APPLIBS)
@echo " Moving executable to $(EXEINSTALL) "
@$(MV) $@ $(EXEINSTALL)
@echo "----------------------------------------------------------------"
如果我转到 Makefile,并删除包含的前导选项卡,我会收到以下错误: ../../../../util/genmake.slinc:10: *** 命令在第一个目标之前开始。停下来。
【问题讨论】:
-
@DOUG 如果删除标签,则包含不再是配方的一部分。
-
来自 GNU Make:“行首允许并忽略多余的空格,但第一个字符不能是制表符(或 .RECIPEPREFIX 的值)——如果行以选项卡,它将被视为一个配方行。包含和文件名之间以及文件名之间需要空格;额外的空格在该处和指令末尾被忽略。最后允许以“#”开头的注释行的。如果文件名包含任何变量或函数引用,它们将被扩展。请参阅如何使用变量。“也许 Make 已更改?
-
如果 make 确实从 UNIX 更改为 Linux,您建议我如何解决 make 文件中每个目标的多个不同包含的问题?也很高兴确切地知道此行为在哪个版本中发生了更改,因为这听起来像是从更高级的功能退了一步。
-
有趣。我(目前)认为 Make 在开始处理任何规则之前会读取所有 makefile 和所有包含 makefile。因此,包含顺序(w.r.t. 配方行)不应该有所作为。恕我直言,你的例子似乎与此相矛盾。您是否尝试过删除选项卡以查看构建是否仍然有效?如果它们相互矛盾,不知道该怎么办。
-
@Doug:我不在办公室,明天会检查,尽管我认为我确实尝试过.. 不记得结果是什么,也不记得为什么它不可接受。明天早上更新。