J'ai refactorisé mes makefiles, avec l'aide de Beta, Paul R et Sjoerd (merci les gars!).Makefile Makeover - Presque complet, je veux des commentaires
Ci-dessous mon produit DÉPART:
#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
... et le sous 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)/
Avec l'aide des utilisateurs ci-dessus et trouver quelques trucs chouettes sur mon propre comme bien (comme l'utilisation de caractères génériques), j'ai refactorisé les makefiles fortement, plus des commentaires ajoutés pour la postérité.
Voici le résultat de haut niveau:
####################################################
## -------------------------------
## - Monte Carlo Source Makefile -
## -------------------------------
##
## Author: Jason R. Mick
## Date: July 7, 2010
## Company: Wayne State University
##
## CHANGE LOG
## Author Date Description
##
##
##
####################################################
#################################
# These lines set up some basic vars
# such as compiler, flags, and dirs.
#################################
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
#################################
# Note use of wildcards to catch *.h and *.cpp files and all the sub_classes
# ... for future unit tests/classes, follow this approach, please
#################################
MOLECULE_UT_SOURCES := $(SOURCE_DIR)/molecule_test/main.cc \
$(SOURCE_DIR)/molecule_manager* \
$(SOURCE_DIR)/molecule_reader* \
$(SOURCE_DIR)/parameter_manager* \
$(SOURCE_DIR)/parser* \
$(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.*
PARAM_UT_SOURCES := $(SOURCE_DIR)/parameter_test/main.cc \
$(SOURCE_DIR)/parameter_manager* \
$(SOURCE_DIR)/parser* \
$(SOURCE_DIR)/common.h
PARAM_UT_DATA := $(DATA_DIR_TESTS)/molecule_test/par_oxalate_and_friends.inp
#################################
# Use sub-make inside subdirectory on test target
# NOTE: @ silences output of this call...
#################################
molecule_test : molecule_test_prepare_sources molecule_test_prepare_makefiles \
molecule_test_prepare_data_files
@$(MAKE) -C $(TEST_DIR)/molecule_unit_test/ ./bin/molecule_test
#################################
# NOTE: this target uses --preserve to keep base source modification date
# to prevent unnecessary rebuilds
#################################
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/
#################################
# NOTE: This mkdir command uses -p flag to create any missing parent dirs.
# If all dirs already exist, it also returns no error...
#################################
molecule_test_dir:
mkdir -p $(TEST_DIR)/molecule_unit_test/source
mkdir -p $(TEST_DIR)/molecule_unit_test/obj
mkdir -p $(TEST_DIR)/molecule_unit_test/bin
param_test : param_test_prepare_sources param_test_prepare_makefiles \
param_test_prepare_data_files
@$(MAKE) -C $(TEST_DIR)/param_unit_test/ ./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:
mkdir -p $(TEST_DIR)/param_unit_test/source
mkdir -p $(TEST_DIR)/param_unit_test/obj
mkdir -p $(TEST_DIR)/param_unit_test/bin
Voici le résultat sous-makefile:
####################################################
## -------------------------------
## - Monte Carlo Source Submake -
## -------------------------------
##
## Author: Jason R. Mick
## Date: July 7, 2010
## Company: Wayne State University
##
## CHANGE LOG
## Author Date Description
##
##
##
####################################################
################################
# These lines set up some basic vars
# such as compiler, flags, and dirs.
################################
CC=g++
CFLAGS=-c -Wall
SOURCE_DIR:=./source
INCDIRS := -I$(SOURCE_DIR)
OBJ_DIR:=./obj
EXE_DIR:=./bin
################################
#This line tells make what directories to search in for rules...
################################
VPATH = $(SOURCE_DIR)
################################
# INFO on the "magic" here:
#$^ is all the prerequisite (.o files), [email protected] is target, and % is wildcard
################################
$(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]
################################
# These are extra includes for the general
# rule at the end....
################################
$(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)/molecule_manager_main.o: molecule_manager.h
$(OBJ_DIR)/parameter_manager_lj_molecule.o: parser.h
$(OBJ_DIR)/molecule_reader_psf_pdb.o: molecule_reader.h
################################
# Special rule for main object
################################
$(OBJ_DIR)/main.o: $(SOURCE_DIR)/main.cc \
molecule_reader.h \
molecule_reader_psf_pdb.h common.h
$(CC) $(CFLAGS) $(INCDIRS) $< -o [email protected]
################################
# The GENERAL RULE for objects...
# INFO on the "magic" here:
#$< is the first prerequisite (.cpp file), [email protected] is target, and % is wildcard
################################
$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(SOURCE_DIR)/%.h $(SOURCE_DIR)/common.h
$(CC) $(CFLAGS) $(INCDIRS) $< -o [email protected]
... au fond, je suis assez satisfait, tout fonctionne, propre et bien documenté , mais je voulais voir si quelqu'un d'autre a des suggestions de choses que je devrais changer pour "les meilleures pratiques", etc. J'essaie d'apprendre autant que possible! Merci d'avance!!
Cheers, Jason
L'implémentation d'une marque non récursive vaut la confusion pour un projet avec moins de 200 fichiers? Une autre préoccupation est que la plupart des gens de mon groupe sont des ingénieurs chimistes avec de légères connaissances en informatique, donc si je devais le faire, je devrais le rendre aussi compréhensible/maintenable que possible ... ce qui semble être le cas difficile ... –
En fait, c'est assez facile. Les sous-makefiles sont très simples, tout le code de la chaudière est dans le makefile principal. Cela réduit beaucoup de duplication. Une fois configuré, l'ajout de nouveaux fichiers objets ou exécutables est trivial. L'ajout d'un nouveau sous-répertoire n'est pas beaucoup plus difficile. En outre, vous pouvez avoir seulement 200 fichiers maintenant, mais cela ne fera que monter. C'est plus facile de faire le changement maintenant. – KeithB