使用特殊的编译标志编译目录中的某些文件

compile certain files in a directory with special compilation flags

提问人:H.atyq 提问时间:10/26/2023 最后编辑:Peter CordesH.atyq 更新时间:10/27/2023 访问量:62

问:

我在项目目录中有几个文件,我想使用非常具体的编译选项编译某些文件,并使用标准编译选项编译其他文件,我想使用其他文件来处理文件。

我目前遇到的问题,程序在if语句上崩溃,你能帮我吗?

对于信息,我使用Windows cmd.exe

低于预期结果,非常感谢您的帮助

生成文件:

SPECIAL_FILES := Fee_PBcfg.obj Fee.obj Can_17_McmCan_PBcfg.obj Dio.obj 
Dio_Lcfg.obj Mcu.obj  Can_17_McmCan_Isr.obj Can_17_McmCan.obj 
McalLib.obj  Spi_PBcfg.obj Spi.obj EcuM_Callout_Stubs.obj EcuM_Cfg.obj 
EcuM_Init_Cfg.obj 



%.$(OBJ_EXT): %.c $(MCS_H)_mcs.h $(COMPILER_OPT_FILE)
if exist $(BUILD_PATH)\$*.obj del $(BUILD_PATH)\$*.obj
if exist $(BUILD_PATH)\$*.d del $(BUILD_PATH)\$*.d
if exist $(BUILD_PATH)\$*.i del $(BUILD_PATH)\$*.i
if exist $(BUILD_PATH)\$*.s del $(BUILD_PATH)\$*.s
if $(filter $*, $(SPECIAL_FILES))
    $(DBGOUT)
    echo Compile $* with $(COPT_ECHO_MCAL) option
    $(CC) $(TARGET) $(CFLAGS_MCAL) $(INCLUDES_PATH) -o 
$(BUILD_PATH)/$*.obj $< 2>$(BUILD_PATH)/$*.warn || type 
$(BUILD_PATH)\$*.warn && $(FALSE)
else
    $(DBGOUT)
    echo Compile $* with $(COPT_ECHO) option
    $(CC) $(TARGET) $(CFLAGS) $(INCLUDES_PATH) -o $(BUILD_PATH)/$*.obj 
$< 2>$(BUILD_PATH)/$*.warn || type $(BUILD_PATH)\$*.warn && $(FALSE)
endif

The Expected result

c makefile gnu-make 编译器优化

评论

1赞 MadScientist 10/26/2023
吉伊请编辑您的问题以确保文本格式正确,也请不要在编程问题中插入图像;而是剪切和粘贴带有格式的文本。谢谢!
2赞 MadScientist 10/27/2023
在 makefile 中,缩进至关重要,但在您的示例中,缩进缺失或不清晰。
0赞 chqrlie 10/28/2023
缩进是至关重要的,更准确地说,是命令中使用 TAB,原始 Unix make 命令的创建者 Stuart Feldman 对此一直道歉。40年前,我在贝尔实验室见过他一次:在我的一位同事介绍他是制造的发明者后,他对我说的第一句话是“是的......对不起 TAB”。

答:

3赞 MadScientist 10/26/2023 #1

您不能使用 etc.,因为它们类似于预处理器语句:它们在读入 makefile 时被处理。但是,配方直到很久以后才构建,当 make 将构建目标时。ifeq

在 GNU Make 手册中,你会发现像这样的自动变量只在配方中有效;这里的“配方内部”是指配方脚本中,即由 TAB 字符缩进并传递给 shell 的规则部分。make 运算符,如 etc. 是(如上所述)进行预处理器语句,而不是配方的一部分。$*ifeq

为了满足您的要求,您可以使用特定于目标的变量。像这样的东西:

$(SPECIAL_FILES) : CFLAGS := $(CFLAGS_MCAL)

%.$(OBJ_EXT): %.c $(MCS_H)_mcs.h $(COMPILER_OPT_FILE)
        ...
        echo Compile $* with $(CFLAGS) option
        $(CC) $(TARGET) $(CFLAGS) $(INCLUDES_PATH) -o $(BUILD_PATH)/$*.obj $< 2>$(BUILD_PATH)/$*.warn || type $(BUILD_PATH)\$*.warn && $(FALSE)

或者,如果您愿意,您可以保持大多数 CFLAGS 相同,只需为特殊目标添加一些额外的 CFLAG:

EXTRA_CFLAGS =
$(SPECIAL_FILES) : EXTRA_CFLAGS := $(MCAL_FLAGS)

%.$(OBJ_EXT): %.c $(MCS_H)_mcs.h $(COMPILER_OPT_FILE)
        ...
        echo Compile $* with $(EXTRA_CFLAGS) option
        $(CC) $(TARGET) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDES_PATH) -o $(BUILD_PATH)/$*.obj $< 2>$(BUILD_PATH)/$*.warn || type $(BUILD_PATH)\$*.warn && $(FALSE)

伊塔

请注意,配方的每一行都是在单独的 shell 中调用的。因此,您不能创建跨越多行的语句;例如:

        if $(filter $*, $(SPECIAL_FILES))
           $(DBGOUT)
           echo Compile $* with $(COPT_ECHO_MCAL) option
           $(CC) $(TARGET) $(CFLAGS_MCAL) $(INCLUDES_PATH) -o $(BUILD_PATH)/$*.obj $< 2>$(BUILD_PATH)/$*.warn || type $(BUILD_PATH)\$*.warn && $(FALSE)

是一个错误,因为只有第一行(语句)被传递给 shell,这是无效的语法。if

如果您使用的是 POSIX shell,它很好地支持在同一行上编写复杂的脚本(您在语句之间添加并且它具有常规语法),这是很有可能的。;

我的怀疑是,如果您使用巴洛克式的 Windows cmd shell 编写 makefile,那么以这种方式操作不会取得多大成功,因为如果不使用换行符,很难编写长批处理命令。但是,如果你想这样做,你需要问那些对 Windows 批处理文件的复杂性非常了解的人这个问题:这并不是一个真正的制造问题。

您可以尝试的一件事是添加 .ONESHELL:makefile 的伪目标,它告诉 make 在单个 shell 中运行整个配方。也许这会有所帮助。

我的建议是避免所有这些,而是使用 GNU Make 功能将这些复杂性限制在您的 makefile 中,而不是尝试在进行调用的 shell 中运行它们。