Makefile没有使用正确的常量?

时间:2014-07-24 12:20:22

标签: c makefile c-preprocessor

我今天遇到了Makefile的问题。这是相关的代码:

我有以下目录结构:

/bin
/obj
/headers
    config.h
    test-config.h
/lib
/src
/test
    /src
    /bin
    /obj
    Makefile
 Makefile

根目录是我的应用程序代码所在的位置,测试目录是我编写测试代码的地方。主Makefile是很正常的,并按预期编译所有内容。测试目录mv中的Makefile是config.h文件的.bak文件,然后将test-config.h移动为新的config.h,然后编译主代码,将根obj /中的所有内容移动到test的obj文件夹中。然后继续编译测试。

我的问题是主配置文件中的常量仍然出现在我的代码中。所以我假设配置文件出错并编译根级代码。这是我的测试Makefile:

#Configurations and setup
CC = cc
CFLAGS = -std=gnu99 -pedantic -Wall -Wextra -Werror -g -I../headers -Isrc
LINKFLAGS = $(CFLAGS)
LIBS = ../lib/wolkykim-qdecoder-63888fc/src/libqdecoder.a

OBJECTS := $(patsubst src/%.c,obj/%.o,$(wildcard src/*.c))
TARGETS := $(patsubst src/%.c,bin/%.out,$(wildcard src/*.c))

#internals are non cgi scripts that we need
INTERNAL := $(patsubst src/internal/%.c,obj/%.o,$(wildcard ../src/internal/*.c))

#Commands to help test and run programs:    
valgrind = valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes

.PHONY: clean 

all: ${TARGETS} 

$(TARGETS): copyobjects $(OBJECTS)
    ${CC} ${LINKFLAGS} -g -o $@ $(patsubst bin/%.out, obj/%.o, $@ ) $(INTERNAL) ${LIBS}

clean:
    rm -f obj/*.o ${TARGETS}
    rm -f ../obj/*.o

copyobjects:
    -mv ../headers/config.h ../headers/config.h.bak
    -mv ../headers/test-config.h ../headers/config.h
    rm -f obj/*.o 
    cd ../ && make && cd test
    cp ../obj/*.o obj/
    -mv ../headers/config.h ../headers/test-config.h
    -mv ../headers/config.h.bak ../headers/config.h

$(OBJECTS): obj/%.o : src/%.c
    ${CC} ${CFLAGS} -c -o $@ $<

test: $(TARGETS)
    -@rm /tmp/data-test || true #remove any test data created so far
    $(valgrind) ./$<

麻烦的定义是:

//config.h
#ifndef DATA_DIR
#define DATA_DIR "/path/to/program/data/"
#endif

//test-config.h
#undef DATA_DIR
#ifndef DATA_DIR
#define DATA_DIR "/tmp/data-test/"
#endif

您可以在此处找到整个项目的检查源代码:https://github.com/EJEHardenberg/pChat

我很困惑为什么它不能正常工作并且在与Makefile协调运行预处理器时尝试使用Google搜索,但我找不到任何看似相关的东西。

我的测试程序如下:

//test-init.c
#include "testp.h"

int main(){
    pci_init();
    /* There should now be a DATA_DIR directory and a users index */

    assert( directory_exists(DATA_DIR) == 1 );
    assert( file_exists(DATA_DIR USERS_INDEX) == 1 );
}

//testp.h
#ifndef __TEST_H__
#define __TEST_H__

/* Set the Data Directory to the test Directory */
#undef DATA_DIR
#define DATA_DIR "/tmp/data-test/"
#include "base.h"
#include <assert.h>

#endif

断言失败: test-init.out:src / test-init.c:7:main:断言`directory_exists(“/ tmp / data-test /”)== 1'失败。

目录存在的是一个测试显而易见的函数并返回0或1

使用makefile输出编辑:

user@Turing ~/Programming/C/pChat/test $ make test
mv ../headers/config.h ../headers/config.h.bak
mv ../headers/test-config.h ../headers/config.h
rm -f obj/*.o 
cd ../ && make clean all && cd test
make[1]: Entering directory `/home/user/Programming/C/pChat'
rm -f obj/*.o bin/heartbeat.cgi
cc -std=gnu99 -pedantic -Wall -Wextra -Werror -g -I./headers -c -o obj/heartbeat.o src/heartbeat.c
cc -std=gnu99 -pedantic -Wall -Wextra -Werror -g -I./headers -c src/internal/data-manip.c -o obj/data-manip.o 
cc -std=gnu99 -pedantic -Wall -Wextra -Werror -g -I./headers -c src/internal/fasthash.c -o obj/fasthash.o 
cc -std=gnu99 -pedantic -Wall -Wextra -Werror -g -I./headers -o bin/heartbeat.cgi  obj/heartbeat.o  obj/data-manip.o  obj/fasthash.o lib/wolkykim-qdecoder-63888fc/src/libqdecoder.a
make[1]: Leaving directory `/home/user/Programming/C/pChat'
cp ../obj/*.o obj/
mv ../headers/config.h ../headers/test-config.h
mv ../headers/config.h.bak ../headers/config.h
cc -std=gnu99 -pedantic -Wall -Wextra -Werror -g -I../headers -Isrc -c -o obj/test-init.o src/test-init.c
cc -std=gnu99 -pedantic -Wall -Wextra -Werror -g -I../headers -Isrc -g -o bin/test-init.out  obj/test-init.o ../src/internal/data-manip.c ../src/internal/fasthash.c ../lib/wolkykim-qdecoder-63888fc/src/libqdecoder.a
rm: cannot remove `/tmp/data-test': No such file or directory
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./bin/test-init.out
==4083== Memcheck, a memory error detector
==4083== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==4083== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==4083== Command: ./bin/test-init.out
==4083== 
Could not run init for Private Chat. Could not create directory: /home/user/Programming/pChat/data/
test-init.out: src/test-init.c:7: main: Assertion `directory_exists("/tmp/data-test/") == 1' failed.
==4083== 
==4083== FILE DESCRIPTORS: 3 open at exit.
==4083== Open file descriptor 2: /dev/pts/0
==4083==    <inherited from parent>
==4083== 
==4083== Open file descriptor 1: /dev/pts/0
==4083==    <inherited from parent>
==4083== 
==4083== Open file descriptor 0: /dev/pts/0
==4083==    <inherited from parent>
==4083== 
==4083== 
==4083== HEAP SUMMARY:
==4083==     in use at exit: 0 bytes in 0 blocks
==4083==   total heap usage: 3 allocs, 3 frees, 502 bytes allocated
==4083== 
==4083== All heap blocks were freed -- no leaks are possible
==4083== 
==4083== For counts of detected and suppressed errors, rerun with: -v
==4083== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
make: *** [test] Aborted (core dumped)

1 个答案:

答案 0 :(得分:0)

所以我修好了。这是如何:

在我的Makefile的copyobjects目标中,我有以下内容:

copyobjects:
    -mv ../headers/config.h ../headers/config.h.bak
    -mv ../headers/test-config.h ../headers/config.h
    rm -f obj/*.o 
    cd ../ && make && cd test
    cp ../obj/*.o obj/
    -mv ../headers/config.h ../headers/test-config.h
    -mv ../headers/config.h.bak ../headers/config.h

test: $(TARGETS)
    -@rm /tmp/data-test || true #remove any test data created so far
    $(valgrind) ./$<

我按照预期移动了配置文件。这就是现在的工作:

copyobjects:
    -mv ../headers/config.h ../headers/config.h.bak
    -mv ../headers/test-config.h ../headers/config.h
    rm -f obj/*.o 
    cd ../ && make && cd test
    cp ../obj/*.o obj/

test: $(TARGETS)
    -@rm /tmp/data-test || true #remove any test data created so far
    $(valgrind) ./$<
    -@mv ../headers/config.h ../headers/test-config.h
    -@mv ../headers/config.h.bak ../headers/config.h

问题似乎是定义在链接时间之前没有“编织”到实际的二进制文件中,所以如果我编译成带有标题X或标题Y的目标文件并不重要,它只在我链接时才重要反对。

简而言之:#define实际上是在cc编译的链接阶段被替换而不是编译阶段(我原先想到的)我查看了man cc对于这样说的东西,但该手册页非常长。我发现有相互矛盾的证据here说preprocesser在链接之前在源上运行。但是:at this link (我更信任它)它说

  

无论您是通过gcc还是cpp使用预处理器,都会首先运行编译器驱动程序。该程序的目的是将您的命令转换为执行实际工作的程序的调用。他们的命令行界面与文档界面相似但不完全相同,如有更改,恕不另行通知。

因此,首先运行编译器(获取我的.o文件)然后运行定义。如果不是这种情况,请在下面给出适当的参考意见。

如下所述,预处理器在编译器和链接器之前运行。真正的问题是我的Makefile配置和依赖的顺序。