2010-06-29 1 views
0

У меня есть Makefile:Нужна помощь ж/досадные ошибки Makefile - г ++: г ++ и оболочка ошибка - и Multi-Makefile дизайны советы

#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. Я бы тоже хотел советовать, как оптимизировать эти файлы (без лишней «магии») и как исправить эти две ошибки ...

Прежде всего, я должен сказать, что все работает, так сказать. Когда я создаю свою цель, он создает все каталоги справа и генерирует исполняемый файл. И все мои файлы копируются правильно и перекомпилируются, когда я касаюсь файлов в исходном каталоге базового уровня. Так что это не «настоящие» ошибки, так сказать, просто раздражающий текст ошибки. Я хочу избавиться от ...

Первая ошибка возникает при запуске сборки make molecule_test, которая требует от нее что-то сделать. Как бы то ни нужно сделать, может быть сделано, но я также получаю:

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 

..AGAIN сборка прошла успешно, создание исполняемого файла правильно

Вторая ошибка я получаю происходит, когда нет ничего, чтобы сделать ... когда это произойдет, я получаю:

/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 учебник, но там, кажется, скачок между созданием небольшой программы с горсткой местного источники и большая программа с необходимостью вложенных каталогов, данные f iles и т. д. Я пытаюсь сделать этот прыжок ... к сожалению, у меня нет передовой практики make-файлов из прошлого кода, поскольку я нахожусь в небольшой исследовательской группе в университете, а не в корпоративной атмосфере.

Мой основной подход заключается в создании базового каталога с помощью следующей

[dir] source/ 
[dir] data/ 
[dir] makefiles/ 
[dir] build/ **gets created 
Makefile 

Makefile, верхний уровень создает подкаталог в каталоге сборки, копирует необходимые источники (скажем, для конкретной программы испытаний и необходимые данные файлы и make-файл, чтобы сделать все источники. Затем makefile верхнего уровня вызывает make-файл на уровне сборки.

Я был бы открыт для размышлений о том, как оптимизировать этот процесс, но был бы признателен, если бы мы FIRST разрешили ошибки .

Спасибо заранее!

P.S. Я работаю на Centos 5.4, GNU Make 3.81, gcc версии 4.1.2 20080704 (Red Hat 4.1.2-44) .... GNU Make и gcc - это 64-разрядные версии ...

ответ

2

Это исправление, кажется, очистить оба ваши ошибки:

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 ...) для вызова оболочки вне правила.Здесь нет необходимости использовать его, так как это команда в правиле - это уже происходит в подоболочке. Также обратите внимание, что это использует $(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 

Что касается рационализации, есть много вы можете сделать. Вы можете уменьшить длину вашего второго файла makefile примерно на половину и исправить то, что кажется множеством ошибок, и с первым вы можете сделать еще лучше. Это зависит от того, сколько «магии» вы можете терпеть. Вот быстрая попытка упорядочить ваш второй Makefile (так как у меня нет ваших файлов, чтобы проверить его, я не могу обещать, что он будет работать без некоторых прикосновений).

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 [email protected] 

$(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) $< [email protected] 

$(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 [email protected] 
+1

Я думаю, вам нужно '-o' перед' $ @ 'в последней строке? –

+0

@Paul R: Вы правы, спасибо, исправлены. И, вероятно, у него будет более серьезная ошибка или два, которые выйдут на тестирование. – Beta

+0

Спасибо вам оба !! Попробуй это сейчас. :) –

0

Для вы можете избавиться от всех команд mv и использовать встроенные переменные make, например

$(OBJ_DIR)/parameter_manager.o: $(SOURCE_DIR)/parameter_manager.cpp $(SOURCE_DIR)/common.h 
    $(CC) $(CFLAGS) -o [email protected] $< 
+0

Каким образом '$ @' и '$ <' work ... будут ли они удалять объекты в моей папке объектов (где выполняется моя окончательная сборка)? Я хотел бы оставить их отдельными ... –

+0

@ Джейсон Р. Мик: они являются автоматическими переменными (см. Руководство по gnu make). '$ @' расширяется до цели, а '$ <' распространяется на первое предварительное условие. – Beta

+0

Ahh. Быстрый вопрос; Я работаю в лаборатории, где большинство людей знают гораздо меньше, чем кодирование, чем я, поэтому поддерживать этот проект может быть трудно сказать по меньшей мере. Я боюсь, что такие хорошие трюки усугубят эту ситуацию. Я не уверен, должен ли я пытаться писать свой код/​​make-файлы для удобства чтения для новичков или для оптимальной грамматики, так сказать. Предложения ?? И НЕТ ОДНОГО есть идея о моих первоначальных ошибках системы сборки ????? –