85

我正在尝试设置一个 Makefile 来搜索和复制一些文件(if-else 条件),但我无法弄清楚它到底有什么问题?(你我很确定这是因为空格/制表符的组合写在错误的地方)。请问我能得到一些帮助吗?

这是我目前拥有的:

obj-m = linuxmon.o

KDIR = /lib/modules/$(shell uname -r)/build
UNAME := $(shell uname -m)

all:

    $(info Checking if custom header is needed)
    ifeq ($(UNAME), x86_64)
        $(info Yes)
        F1_EXISTS=$(shell [ -e /usr/include/asm/unistd_32.h ] && echo 1 || echo 0 )
        ifeq ($(F1_EXISTS), 1)
            $(info Copying custom header)
            $(shell sed -e 's/__NR_/__NR32_/g' /usr/include/asm/unistd_32.h > unistd_32.h)
        else    
            F2_EXISTS=$(shell [[ -e /usr/include/asm-i386/unistd.h ]] && echo 1 || echo 0 )
            ifeq ($(F2_EXISTS), 1)
                $(info Copying custom header)
                $(shell sed -e 's/__NR_/__NR32_/g' /usr/include/asm-i386/unistd.h > unistd_32.h)
            else
                $(error asm/unistd_32.h and asm-386/unistd.h does not exist)
            endif
        endif
        $(info No)
    endif

    @make -C $(KDIR) M=$(PWD) modules

clean:
    make -C $(KDIR) M=$(PWD) clean
    rm unistd_32.h

无论如何,这将打印两次“是”,“复制标题”,然后它会退出说 sed 无法读取/usr/include/asm-i386/unistd.h(当然它无法读取,因为我在 x64 系统上)。我可以说make只是不理解 if/else 而是逐行运行所有内容。

4

2 回答 2

167

您可以简单地使用 shell 命令。如果要禁止回显输出,请使用“@”符号。例如:

clean:
    @if [ "test" = "test" ]; then\
        echo "Hello world";\
    fi

请注意,每行的结尾;\是必要的

(这是因为make将每一行解释为单独的命令,除非它以 结尾\

于 2015-06-11T07:07:33.720 回答
88

这里有几个问题,所以我将从我通常的高级建议开始:从小而简单开始,一次增加一点复杂性,每一步都进行测试,永远不要添加不起作用的代码。(我真的应该有那个热键。)

您正在以一种令人眼花缭乱的方式混合 Make 语法和 shell 语法。你不应该让它在没有测试的情况下变得这么大。让我们从外部开始,向内工作。

UNAME := $(shell uname -m)

all:
    $(info Checking if custom header is needed)
    ifeq ($(UNAME), x86_64)
    ... do some things to build unistd_32.h
    endif

    @make -C $(KDIR) M=$(PWD) modules

因此,您希望在调用第二个之前构建(可能) unistd_32.h make,您可以将其作为先决条件。而且由于您仅在特定情况下才需要它,因此可以将其放在条件中:

ifeq ($(UNAME), x86_64)
all: unistd_32.h
endif

all:
    @make -C $(KDIR) M=$(PWD) modules

unistd_32.h:
    ... do some things to build unistd_32.h

现在建设unistd_32.h

F1_EXISTS=$(shell [ -e /usr/include/asm/unistd_32.h ] && echo 1 || echo 0 )
ifeq ($(F1_EXISTS), 1)
    $(info Copying custom header)
    $(shell sed -e 's/__NR_/__NR32_/g' /usr/include/asm/unistd_32.h > unistd_32.h)
else    
    F2_EXISTS=$(shell [[ -e /usr/include/asm-i386/unistd.h ]] && echo 1 || echo 0 )
    ifeq ($(F2_EXISTS), 1)
        $(info Copying custom header)
        $(shell sed -e 's/__NR_/__NR32_/g' /usr/include/asm-i386/unistd.h > unistd_32.h)
    else
        $(error asm/unistd_32.h and asm-386/unistd.h does not exist)
    endif
endif

您正在尝试unistd.hunistd_32.h; 唯一的窍门是它unistd_32.h可能在两个地方之一。清理它的最简单方法是使用vpath指令:

vpath unistd.h /usr/include/asm /usr/include/asm-i386

unistd_32.h: unistd.h
    sed -e 's/__NR_/__NR32_/g' $< > $@
于 2013-04-12T18:13:20.833 回答