需要带有恼人的Makefile错误的帮助--g++;:g++;和shell错误——以及多Makefile设计建议

需要带有恼人的Makefile错误的帮助--g++;:g++;和shell错误——以及多Makefile设计建议,makefile,gnu-make,multiple-makefiles,makefile-project,Makefile,Gnu Make,Multiple Makefiles,Makefile Project,我有一个生成文件: #Nice, wonderful makefile written by Jason CC=g++ CFLAGS=-c -Wall BASE_DIR:=. SOURCE_DIR:=$(BASE_DIR)/source BUILD_DIR:=$(BASE_DIR)/build TEST_DIR:=$(BASE_DIR)/build/tests MAKEFILE_DIR:=$(BASE_DIR)/makefiles DATA_DIR:=$(BASE_DIR)/data DATA_

我有一个生成文件:

#Nice, wonderful makefile written by Jason
CC=g++
CFLAGS=-c -Wall
BASE_DIR:=.
SOURCE_DIR:=$(BASE_DIR)/source
BUILD_DIR:=$(BASE_DIR)/build
TEST_DIR:=$(BASE_DIR)/build/tests
MAKEFILE_DIR:=$(BASE_DIR)/makefiles
DATA_DIR:=$(BASE_DIR)/data
DATA_DIR_TESTS:=$(DATA_DIR)/tests
MOLECULE_UT_SOURCES :=  $(SOURCE_DIR)/molecule_test/main.cc \
    $(SOURCE_DIR)/molecule_manager.h \
    $(SOURCE_DIR)/molecule_manager.cpp \
    $(SOURCE_DIR)/molecule_manager_main.h \
    $(SOURCE_DIR)/molecule_manager_main.cpp \
    $(SOURCE_DIR)/molecule_reader.h \
    $(SOURCE_DIR)/molecule_reader.cpp \
    $(SOURCE_DIR)/molecule_reader_psf_pdb.h \
    $(SOURCE_DIR)/molecule_reader_psf_pdb.cpp \
    $(SOURCE_DIR)/parameter_manager_lj_molecule.h \
    $(SOURCE_DIR)/parameter_manager_lj_molecule.cpp \
    $(SOURCE_DIR)/parameter_manager.h \
    $(SOURCE_DIR)/parameter_manager.cpp \
    $(SOURCE_DIR)/parser.h \
    $(SOURCE_DIR)/parser.cpp \
    $(SOURCE_DIR)/common.h
MOLECULE_UT_DATA := \
    $(DATA_DIR_TESTS)/molecule_test/par_oxalate_and_friends.inp \
    $(DATA_DIR_TESTS)/molecule_test/dicarboxy-octane_4.pdb \
    $(DATA_DIR_TESTS)/molecule_test/dicarboxy-octane_4.psf
PARAM_UT_SOURCES :=  $(SOURCE_DIR)/parameter_test/main.cc \
    $(SOURCE_DIR)/parameter_manager_lj_molecule.h \
    $(SOURCE_DIR)/parameter_manager_lj_molecule.cpp \
    $(SOURCE_DIR)/parameter_manager.h \
    $(SOURCE_DIR)/parameter_manager.cpp \
    $(SOURCE_DIR)/parser.h \
    $(SOURCE_DIR)/parser.cpp \
    $(SOURCE_DIR)/common.h
PARAM_UT_DATA := $(DATA_DIR_TESTS)/molecule_test/par_oxalate_and_friends.inp

molecule_test : molecule_test_prepare_sources molecule_test_prepare_makefiles \
    molecule_test_prepare_data_files
    @$(shell cd $(TEST_DIR)/molecule_unit_test/; \
    make ./bin/molecule_test)

molecule_test_prepare_sources: molecule_test_dir
    @echo Copying sources...
    @cp --preserve $(MOLECULE_UT_SOURCES) \
    $(TEST_DIR)/molecule_unit_test/source

molecule_test_prepare_makefiles: $(MAKEFILE_DIR)/Makefile.molecule_test
    @cp  --preserve $(MAKEFILE_DIR)/Makefile.molecule_test \
    $(TEST_DIR)/molecule_unit_test/Makefile

molecule_test_prepare_data_files:
    cp --preserve $(MOLECULE_UT_DATA) $(TEST_DIR)/molecule_unit_test/bin/

molecule_test_dir:
    @if test -d $(BUILD_DIR); then \
        echo Build exists...; \
        else \
        echo Build directory does not exist, making build dir...; \
    mkdir $(BUILD_DIR); \
        fi
    @if test -d $(TEST_DIR); then \
        echo Tests exists...; \
        else \
        echo Tests directory does not exist, making tests dir...; \
    mkdir $(TEST_DIR); \
        fi
    @if test -d $(TEST_DIR)/molecule_unit_test; then \
        echo Molecule unit test directory exists...; \
        else \
        echo Molecule unit test directory does \
        not exist, making build dir...; \
        mkdir $(TEST_DIR)/molecule_unit_test; \
        fi
    @if test -d $(TEST_DIR)/molecule_unit_test/source; then \
        echo Molecule unit test source directory exists...; \
        else \
        echo Molecule unit test source directory does \
        not exist, making build dir...; \
        mkdir $(TEST_DIR)/molecule_unit_test/source; \
        fi
    @if test -d $(TEST_DIR)/molecule_unit_test/obj; then \
        echo Molecule unit test object directory exists...; \
        else \
        echo Molecule unit test object directory does \
        not exist, making object dir...; \
        mkdir $(TEST_DIR)/molecule_unit_test/obj; \
        fi
    @if test -d $(TEST_DIR)/molecule_unit_test/bin; then \
        echo Molecule unit test executable directory exists...; \
        else \
        echo Molecule unit test executable directory does \
        not exist, making executable dir...; \
        mkdir $(TEST_DIR)/molecule_unit_test/bin; \
        fi

param_test : param_test_prepare_sources param_test_prepare_makefiles \
    param_test_prepare_data_files
    @$(shell cd $(TEST_DIR)/param_unit_test/; \
    make ./bin/param_test)

param_test_prepare_sources: param_test_dir
    @echo Copying sources...
    @cp --preserve $(PARAM_UT_SOURCES) $(TEST_DIR)/param_unit_test/source

param_test_prepare_makefiles: $(MAKEFILE_DIR)/Makefile.param_test
    @cp  --preserve $(MAKEFILE_DIR)/Makefile.param_test \
    $(TEST_DIR)/param_unit_test/Makefile

param_test_prepare_data_files:
    cp --preserve $(PARAM_UT_DATA) $(TEST_DIR)/param_unit_test/bin/

param_test_dir:
    @if test -d $(BUILD_DIR); then \
        echo Build exists...; \
        else \
        echo Build directory does not exist, making build dir...; \
    mkdir $(BUILD_DIR); \
        fi
    @if test -d $(TEST_DIR); then \
        echo Tests exists...; \
        else \
        echo Tests directory does not exist, making tests dir...; \
    mkdir $(TEST_DIR); \
        fi
    @if test -d $(TEST_DIR)/param_unit_test; then \
        echo Param unit test directory exists...; \
        else \
        echo Param unit test directory does \
        not exist, making build dir...; \
        mkdir $(TEST_DIR)/param_unit_test; \
        fi
    @if test -d $(TEST_DIR)/param_unit_test/source; then \
        echo Param unit test source directory exists...; \
        else \
        echo Param unit test source directory does \
        not exist, making build dir...; \
        mkdir $(TEST_DIR)/param_unit_test/source; \
        fi
    @if test -d $(TEST_DIR)/param_unit_test/obj; then \
        echo Param unit test object directory exists...; \
        else \
        echo Param unit test object directory does \
        not exist, making object dir...; \
        mkdir $(TEST_DIR)/param_unit_test/obj; \
        fi
    @if test -d $(TEST_DIR)/param_unit_test/bin; then \
        echo Param unit test executable directory exists...; \
        else \
        echo Param unit test executable directory does \
        not exist, making executable dir...; \
        mkdir $(TEST_DIR)/param_unit_test/bin; \
        fi
它在创建并填充目录结构后调用第二个makefile

第二个makefile如下所示:

#Nice, wonderful makefile written by Jason
CC=g++
CFLAGS=-c -Wall
SOURCE_DIR:=./source
OBJ_DIR:=./obj
EXE_DIR:=./bin

$(EXE_DIR)/molecule_test : $(OBJ_DIR)/main.o \
    $(OBJ_DIR)/parameter_manager_lj_molecule.o \
    $(OBJ_DIR)/parameter_manager.o $(OBJ_DIR)/parser.o \
    $(OBJ_DIR)/molecule_manager.o $(OBJ_DIR)/molecule_manager_main.o \
    $(OBJ_DIR)/molecule_reader.o \
    $(OBJ_DIR)/molecule_reader_psf_pdb.o
    @$(CC) $(OBJ_DIR)/main.o $(OBJ_DIR)/parameter_manager.o \
    $(OBJ_DIR)/parser.o $(OBJ_DIR)/parameter_manager_lj_molecule.o \
    $(OBJ_DIR)/molecule_manager.o $(OBJ_DIR)/molecule_manager_main.o \
    $(OBJ_DIR)/molecule_reader.o \
    $(OBJ_DIR)/molecule_reader_psf_pdb.o \
    -o molecule_test
    @mv molecule_test $(EXE_DIR)/ 

$(OBJ_DIR)/main.o: $(SOURCE_DIR)/parameter_manager.h \
    $(SOURCE_DIR)/parameter_manager_lj_molecule.h \
    $(SOURCE_DIR)/molecule_manager.h \
    $(SOURCE_DIR)/molecule_manager_main.h \
    $(SOURCE_DIR)/molecule_reader.h \
    $(SOURCE_DIR)/molecule_reader_psf_pdb.h \
    $(SOURCE_DIR)/common.h $(SOURCE_DIR)/main.cc
    $(CC) $(CFLAGS) $(SOURCE_DIR)/main.cc
    @mv main.o $(OBJ_DIR)/

$(OBJ_DIR)/molecule_reader.o: $(SOURCE_DIR)/parameter_manager.h \
    $(SOURCE_DIR)/parameter_manager_lj_molecule.h \
    $(SOURCE_DIR)/molecule_manager.h \
    $(SOURCE_DIR)/molecule_manager_main.h \
    $(SOURCE_DIR)/molecule_reader.h \
    $(SOURCE_DIR)/common.h
    $(CC) $(CFLAGS) $(SOURCE_DIR)/molecule_reader.cpp
    @mv molecule_reader.o $(OBJ_DIR)/

$(OBJ_DIR)/molecule_reader_psf_pdb.o: $(SOURCE_DIR)/parameter_manager.h \
    $(SOURCE_DIR)/parameter_manager_lj_molecule.h \
    $(SOURCE_DIR)/molecule_manager.h \
    $(SOURCE_DIR)/molecule_manager_main.h \
    $(SOURCE_DIR)/molecule_reader.h \
    $(SOURCE_DIR)/molecule_reader_psf_pdb.h \
    $(SOURCE_DIR)/common.h
    $(CC) $(CFLAGS) $(SOURCE_DIR)/molecule_reader_psf_pdb.cpp
    @mv molecule_reader_psf_pdb.o $(OBJ_DIR)/

$(OBJ_DIR)/molecule_manager.o: $(SOURCE_DIR)/molecule_manager.h \
    $(SOURCE_DIR)/common.h
    $(CC) $(CFLAGS) $(SOURCE_DIR)/molecule_manager.cpp
    @mv molecule_manager.o $(OBJ_DIR)/

$(OBJ_DIR)/molecule_manager_main.o: $(SOURCE_DIR)/molecule_manager.h \
    $(SOURCE_DIR)/molecule_manager_main.h \
    $(SOURCE_DIR)/common.h
    $(CC) $(CFLAGS) $(SOURCE_DIR)/molecule_manager_main.cpp
    @mv molecule_manager_main.o $(OBJ_DIR)/

$(OBJ_DIR)/parameter_manager_lj_molecule.o: $(SOURCE_DIR)/common.h \
    $(SOURCE_DIR)/parameter_manager.h \
    $(SOURCE_DIR)/parser.h
    $(CC) $(CFLAGS) $(SOURCE_DIR)/parameter_manager_lj_molecule.cpp
    @mv parameter_manager_lj_molecule.o $(OBJ_DIR)/

$(OBJ_DIR)/parameter_manager.o: $(SOURCE_DIR)/common.h
    $(CC) $(CFLAGS) $(SOURCE_DIR)/parameter_manager.cpp
    @mv parameter_manager.o $(OBJ_DIR)/

$(OBJ_DIR)/parser.o: $(SOURCE_DIR)/parser.h
    @$(CC) $(CFLAGS) $(SOURCE_DIR)/parser.cpp
    @mv parser.o $(OBJ_DIR)/

$(OBJ_DIR)/common.o: $(SOURCE_DIR)/common.h
    $(CC) $(CFLAGS) $(SOURCE_DIR)/common.h
    mv common.h.gch $(OBJ_DIR)/
我承认我在Makefiles方面是个新手。我想知道如何简化这些文件(没有太多的“魔法”)以及如何修复这两个错误

首先我必须说,可以说,一切都在运转。当我构建目标时,它会正确地创建所有目录并生成可执行文件。我的所有文件都得到了正确的复制,并且在我接触基本源目录中的文件时得到了重新编译。所以可以说,这些不是“真正的”错误,只是我想摆脱的恼人的错误文本

第一个错误发生在我运行build
makemolecular\u测试时,该测试要求它执行某些操作。无论它需要做什么都会完成,但我也会:

g++: g++: No such file or directory
g++: g++: No such file or directory
g++: g++: No such file or directory
g++: g++: No such file or directory
g++: g++: No such file or directory
g++: g++: No such file or directory
make: *** [molecule_test] Error 1
..构建再次成功,正确创建可执行文件

我遇到的第二个错误发生在无事可做的情况下…发生这种情况时,我得到:

/bin/sh: -c: line 0: unexpected EOF while looking for matching ``'
/bin/sh: -c: line 1: syntax error: unexpected end of file
请温柔一点。。。我读过基本的makefile教程,包括gnu makefile教程,但是在创建一个包含少量本地源的小程序和一个需要嵌套目录、数据文件等的大程序之间似乎有一个飞跃。我正在尝试实现这一飞跃。。。不幸的是,我没有过去代码中的最佳实践生成文件,因为我在一所大学的一个小型研究小组,而不是在一个公司氛围中

我的基本方法是使用以下内容创建一个基本目录

[dir] source/
[dir] data/
[dir] makefiles/
[dir] build/    **gets created
Makefile
顶级makefile在构建目录中创建一个子目录,复制所需的源(例如,特定测试程序的源)、所需的数据文件和生成所有源的makefile。顶级makefile然后调用构建级makefile

我愿意接受关于如何简化此过程的想法,但如果我们首先解决错误,我将不胜感激

提前感谢


另外,我运行的是Centos 5.4、GNU Make 3.81、gcc版本4.1.2 20080704(Red Hat 4.1.2-44)…GNU Make和gcc都是64位版本…

首先,您可以去掉所有的mv命令并使用Make的内置变量,例如

$(OBJ_DIR)/parameter_manager.o: $(SOURCE_DIR)/parameter_manager.cpp $(SOURCE_DIR)/common.h
    $(CC) $(CFLAGS) -o $@ $<
$(OBJ\u DIR)/parameter\u manager.o:$(SOURCE\u DIR)/parameter\u manager.cpp$(SOURCE\u DIR)/common.h
$(CC)$(CFLAGS)-o$@$<

此修复程序似乎可以清除您的两个错误:

molecule_test : molecule_test_prepare_sources molecule_test_prepare_makefiles \
  molecule_test_prepare_data_files
    @cd $(TEST_DIR)/molecule_unit_test && $(MAKE) ./bin/molecule_test
$(shell…
命令用于在规则之外调用shell。这里不需要使用它,因为这是规则中的一个命令--它已经在子shell中发生。还要注意,这使用了
$(MAKE)
而不是
MAKE
(原因有点微妙,只要将其视为一个好习惯即可)

您可以更简洁、更安静地进行:

molecule_test : molecule_test_prepare_sources molecule_test_prepare_makefiles \
  molecule_test_prepare_data_files
    @$(MAKE) -s -C $(TEST_DIR)/molecule_unit_test ./bin/molecule_test
至于优化,你可以做很多。你可以将第二个生成文件的长度减少一半左右,并修复一些似乎存在的错误,而使用第一个生成文件,你可以做得更好。这取决于你能容忍多少“魔法”。下面是一个简化第二个生成文件的快速尝试(因为我没有你的文件来测试它,所以我不能保证它在没有润色的情况下工作)

CC=g++
CFLAGS=-c-墙
SOURCE\U DIR:=/源
INCDIRS:=-I$(源目录)
对象目录:=/对象目录
EXE_DIR:=/bin
VPATH=$(源目录)
$(EXE\u DIR)/分子测试:$(OBJ\u DIR)/main.o\
$(OBJ_DIR)/parameter_manager_lj_molecular.o\
$(OBJ_DIR)/parameter_manager.o$(OBJ_DIR)/parser.o\
$(OBJ_DIR)/molecular_manager.o$(OBJ_DIR)/molecular_manager\u main.o\
$(OBJ_DIR)/molecular_reader.o\
$(OBJ_DIR)/molecular_reader_psf_pdb.o
@$(CC)$^-o$@
$(OBJ_DIR)/main.o$(OBJ_DIR)/molecular_reader.o\
$(OBJ_DIR)/molecular_reader_psf_pdb.o:\
分子管理器\
分子管理器\
参数_manager.h\
参数_manager _lj _molecular.h
$(对象目录)/main.o:main.cpp\
分子读取器\
分子读取器psf pdb.h common.h
$(CC)$(CFLAGS)$(INCDIRS)$<$@
$(OBJ_DIR)/molecular_reader_psf_pdb.o:molecular_reader.h
$(OBJ_DIR)/parameter_manager_lj_molecular.o:parser.h
%.o:%.cpp%.h普通.h
$(CC)$(CFLAGS)$(INCDIRS)$<-o$@

$@
$@Jason R.Mick:它们是自动变量(请参阅gnu制作手册).
$@
扩展到目标,并且
$啊。快速问一个问题;我在一个实验室工作,那里大多数人对编码的了解都比我少得多,因此维护这个项目可能一点也不好说。我担心使用这样的好技巧会使情况恶化。我不确定是否应该尝试为r新手可读性或最佳语法,可以这么说。建议??也没有人知道我最初的make系统错误????@Jason:理想情况下,你希望简化makefile,这可能会使它更神秘,但这将有望被易于维护所压倒-查看GNU make手册中的默认规则,使用
%
通配符。您应该能够设置一些默认规则,然后您不太开明的同事只需更新依赖项,这应该非常简单,不需要理解makefile中更神秘的部分。谢谢。Paul。但是,对于上述错误仍然没有答案??有人吗?我认为您没有在最后一行中的
$@
之前添加了一个
-o
?@Paul R:你说得对,谢谢,修复了。它可能有一两个更严重的错误将在测试中出现。谢谢你们!!现在将尝试此方法。:)嗯,我得到了错误:
make[1]:***没有规则设置目标
main.cpp',这是
obj/main.o.需要的。停止。
…当我尝试设置第二个目标时…好的,通过将main.o目标中的.cpp更改为.cc修复了我以前的错误…但是现在我得到了这个错误…
obj/main.o:文件未识别:文件格式未识别CC=g++
CFLAGS=-c -Wall
SOURCE_DIR:=./source
INCDIRS := -I$(SOURCE_DIR)
OBJ_DIR:=./obj
EXE_DIR:=./bin

VPATH = $(SOURCE_DIR)

$(EXE_DIR)/molecule_test : $(OBJ_DIR)/main.o \
  $(OBJ_DIR)/parameter_manager_lj_molecule.o \
  $(OBJ_DIR)/parameter_manager.o $(OBJ_DIR)/parser.o \
  $(OBJ_DIR)/molecule_manager.o $(OBJ_DIR)/molecule_manager_main.o \
  $(OBJ_DIR)/molecule_reader.o \
  $(OBJ_DIR)/molecule_reader_psf_pdb.o
    @$(CC) $^ -o $@

$(OBJ_DIR)/main.o $(OBJ_DIR)/molecule_reader.o \
  $(OBJ_DIR)/molecule_reader_psf_pdb.o: \
  molecule_manager.h \
  molecule_manager_main.h \
  parameter_manager.h \
  parameter_manager_lj_molecule.h

$(OBJ_DIR)/main.o: main.cpp \
  molecule_reader.h \
  molecule_reader_psf_pdb.h common.h
    $(CC) $(CFLAGS) $(INCDIRS) $< $@

$(OBJ_DIR)/molecule_reader_psf_pdb.o: molecule_reader.h

$(OBJ_DIR)/parameter_manager_lj_molecule.o: parser.h

%.o: %.cpp %.h common.h
    $(CC) $(CFLAGS) $(INCDIRS) $< -o $@