Personal tools

Difference between revisions of "Makefile CCCP"

From MohidWiki

Jump to: navigation, search
(Special project folders)
(Special root folder's Nix.mk)
 
(56 intermediate revisions by the same user not shown)
Line 1: Line 1:
This section describes a Cross-Compiler, Cross-Platform (CCCP) [[makefile]] development methodology using the [[make]] tool from GNU, also known as gmake. The syntax  to use would be:
+
This section describes a Cross-Compiler, Cross-Platform (CCCP) [[makefile]] development methodology using the [[makefile|make]] tool from GNU, also known as gmake. The syntax  to use would be:
 
  make ''platform''.''action''
 
  make ''platform''.''action''
 
''(ex: make Win, make Unix.clean, etc...).''
 
''(ex: make Win, make Unix.clean, etc...).''
Line 7: Line 7:
 
A CCCP makefile project a bunch of library, modules and program folders within a single root folder.  
 
A CCCP makefile project a bunch of library, modules and program folders within a single root folder.  
  
===For each project folder===
+
===Tree description===
Every project folder must contain the following files:
 
  
; Files.mk: encapsulates a list of all the folder's source-files and meta-files.
+
====Example tree====
; Makefile: contains includes to all the actions that can be perfomed on the folder.
+
> tree cproj/
; Dependencies.mk: encapsulates the dependencies of the files within the lists defined in ''Files.mk''.
+
cproj/
 +
|-- Editme.mk
 +
|-- Makefile
 +
|-- Makefiles
 +
|  |-- Makefiles.mk
 +
|  |-- Makemodules.mk
 +
|  `-- Makefile
 +
|-- Nix.mk
 +
|-- lib1
 +
|  `-- Makefile
 +
|-- lib2
 +
|  `-- Makefile
 +
`-- prog1
 +
    `-- Makefile
  
====Special project folders====
+
====Regular folders====
There are two special folders, mandatory, and each containing special files
+
Every folder must contain the following files:
# '''the ''root'' folder'''
 
#; Actions.mk: is similar to ''Makefile'', but defines PHONY targets that executes the different actions defined in the ''Makefiles'' special folder.
 
#; Nix.mk: contains all the necessary configuration global variables specific to the CCCP solution. Configured by the Solution administrator.
 
#; Editme.mk: Each user must edit this configuration file before building the solution.
 
# '''the ''Makefiles'' folder''' (NOTE: it is extensible, one file per action or ''rule'')
 
#; All.mk: contains the makefile rules to compile and build programs.
 
#; Alllib.mk: contains the makefile rules to compile and build libraries.
 
#; Clean.mk: contains the makefile rules to erase every .obj, .mod, .lib and .exe file that was created by the CCCP solution.
 
#; Install.mk: contains the makefile rule to install the programs.
 
  
=== The project filetree ===
+
;;Makefile:: encapsulates a list of all the folder's source-files and meta-files, a bunch of includes containing the makefile rules and, last but not least, the target dependencies. Several local variables are defined within:
 +
;;INCS:
 +
;;LIBS: 
 +
;;SRCDIR: contains the path to the source files
 +
;;FILES: contains the list of source files (using the $(S) suffix)
 +
;;METAFILES: contains the list of files required by the Makefile to run in this project (using the ''.smk'' suffix) besides the ''Makefile'' itself (of course).
 +
;;TARGET: is the target name that the local makefile is supposed to build.
 +
;;MODULES: contains the list of modules (special root folder only).
 +
;;Dependencies: is a list of the dependent files and the respective dependencies.
  
 
+
====Special folders and special files====
=== The project makefiles distribution ===
+
There are two special folders, mandatory, and each containing special files, beyond the mandatory regular files listed above:
The root folder must contain:
+
# '''the ''root'' folder'''
*The Makefile (''Makefile'')
+
#; Makefile: it's completely different from the regular folder ''Makefile''. It contains the rules to build the Solution for a series of platform.
*One specific makefile per platform and per compiler (ex: ''win.mk'', ''unix.mk'', etc...)
+
#; Nix.mk: it contains the regular folder ''Makefile'' structure and content. It also contains all the necessary configuration global variables specific to the CCCP solution. It must be configured for a specific platform (Linux, windows,etc...) by the administrator.
*An auxiliary file included in the latter (''aux.mk'')
+
#; Editme.mk: Each user must edit this configuration file before building the solution. It contains the paths to required external libraries such as [[HDF5]] or [[Netcdf]].
 
+
# '''the ''Makefiles'' folder'''
And each module must contain:
+
#; Makemodules.mk: contains the makefile rules to build (all), clean, install, etc, the target modules. It is invoked only from the root file ''Nix.mk''.
*The module standard Makefile (''module/Makefile'')
+
#; Makefiles.mk: contains the makefile rules to build, clean, install, etc, the target files.
*The dependencies file included in the latter (''module/Dependencies.mk'')
 
*The local environment variables file included in the former (''module/Vars.mk'')
 
  
 
=== The makefile's global variables ===
 
=== The makefile's global variables ===
 
The idea is to use '''global variables''' to pass arguments to the different modules makefiles. Thus, each specific platform makefile in the root folder defines these global variables. Then, it calls the modules makefiles who will use the global variables in their syntax. If a systematic approach of using global variables is implemented, then it is fairly easy to have a cross-platform makefile project implemented; and easily extended.
 
The idea is to use '''global variables''' to pass arguments to the different modules makefiles. Thus, each specific platform makefile in the root folder defines these global variables. Then, it calls the modules makefiles who will use the global variables in their syntax. If a systematic approach of using global variables is implemented, then it is fairly easy to have a cross-platform makefile project implemented; and easily extended.
  
==The [[Mohid Makefile]] Project==
+
==A template CCCP makefile solution==
 
+
===Special root folder's ''Makefile''===
== A sample project for Mohid2D (DEPRECATED) ==
+
  SHELL = /bin/sh
Here we apply the methodology described above.
+
 
 
+
  export MAKE = make
=== ''Makefile'' ===
+
 
SHELL = /bin/sh
+
  .PHONY: default
 +
  default:
 +
  @echo Please choose your platform from:
 +
  @echo Type "make (win nix).(' '  clean install sos)".
 +
 
 +
  #make all (add other platforms "Nix Nix Nix_double Win" ...)
 +
  PLAT := Nix
 +
  .PHONY : $(PLAT)
 +
  $(PLAT):
 +
  $(MAKE) -f $@.mk all
 +
 
 +
  #make clean
 +
  PLATCLEAN := $(addsuffix .clean, $(PLAT))
 +
  .PHONY : $(PLATCLEAN)
 +
  $(PLATCLEAN) :
 +
  $(MAKE) -f $(@:.clean=).mk clean
 +
 
 +
  #make install
 +
  PLATINST := $(addsuffix .install, $(PLAT))
 +
  .PHONY : $(PLATINST)
 +
  $(PLATINST) :
 +
  $(MAKE) -f $(@:.install=).mk install
 
   
 
   
  export MAKE = make
+
===Special root folder's ''Editme.mk''===
  PLATCLEAN = win.clean nix.clean
+
  #Edit the prefix of the installed binaries
  PLAT = $(PLATCLEAN:.clean=)
+
  # > make nix.install
 +
  export VER = x64_single
 
   
 
   
  .PHONY: default $(PLATCLEAN) $(PLAT)
+
  #Where do you want to install the binary files?
 +
# > make nix.install
 +
export DESTDIR = /usr/bin/mohid
 
   
 
   
  default:
+
  #Where are the hdf5 libraries (with --enable-fortran) in your system?
@echo Please choose your platform from:
+
export HDF5 = /home/Projects/hdf5/hdf5-1.6.5/hdf5/lib
@echo $(PLAT).
 
@echo Type "make win(.clean)" or "make nix(.clean)".
 
 
   
 
   
  $(PLAT):
+
  #Where is the libz.a in your system?
$(MAKE) -f $@.mk all
+
  export ZLIBINC = /usr/lib64
 
  $(PLATCLEAN) :
 
$(MAKE) -f $(@:.clean=).mk clean
 
  
=== ''win.mk'' ===
+
===Special root folder's ''Nix.mk''===
 
  SHELL = /bin/sh
 
  SHELL = /bin/sh
 
   
 
   
  ###### WIN Exported variables #########
+
  #------User configuration file---------------
export DEL = del /Q
+
   
export O = obj
+
  include Editme.mk
export F = f90
 
export MOD = mod
 
export CC= ifort
 
export CCFLAGS  = -c -fpp -nologo # Debug: -g Profiling: -p
 
export LFLAGS  = -fpp -nologo # Profiling: -p
 
  export AR = ar rc
 
  export HDF5 = D:/Projectos/Mohid_v4/IntelLibs
 
export LIBS = \
 
        ../Library/Library.lib \
 
        ../Modulos/Modulos.lib \
 
        ../Boxdif_hidrodin/Boxdif_hidrodin.lib \
 
        ../Mohid_Base/Mohid_Base.lib \
 
        $(HDF5)/hdf5.lib \
 
        $(HDF5)/hdf5_hl.lib \
 
        $(HDF5)/hdf5c.lib \
 
        $(HDF5)/hdf5f90.lib \
 
        $(HDF5)/szlib.lib \
 
        $(HDF5)/zlib.lib
 
#### End of exported variables ####
 
 
   
 
   
  include aux.mk
+
  #-- NIX platform specific global variables --
 
 
=== ''nix.mk'' ===
 
SHELL = /bin/sh
 
 
   
 
   
  ###### NIX Exported variables #########
+
  export CP  = sudo cp
 
  export DEL = rm
 
  export DEL = rm
 
  export O = o
 
  export O = o
  export F = f90
+
  export F = F90
 
  export MOD = mod
 
  export MOD = mod
 
  export CC= ifort
 
  export CC= ifort
  export CCFLAGS  = -c -fpp -nologo # Debug: -g Profiling: -p
+
  export CCFLAGS  = -c -fpp -warn all -nologo -convert big_endian -D_USE_NIX# Debug: -g Profiling: -p
  export LFLAGS  = -fpp -nologo # Profiling: -p
+
  export LFLAGS  = -fpp -nologo -warn all -i-static -convert big_endian -D_USE_NIX# Profiling: -p
 +
export LLFLAGS  =
 
  export AR = ar rc
 
  export AR = ar rc
  export HDF5 = /opt/hdf5/hdf5/lib
+
  export SUFFLIB = .lib
  export LIBS = \
+
export SUFFPROG =
        ../Boxdif_hidrodin/Boxdif_hidrodin.lib \
+
export SRCBASE1 = ../../../Shared/MOHID.Base.1
        ../Mohid_Base/Mohid_Base.lib \
+
  export SRCBASE2 = ../../../Shared/MOHID.Base.2
        ../Modulos/Modulos.lib \
+
export SRCWATER = ../../../Modulus.Software/MOHID.Water
         ../Library/Library.lib \
+
export BASE1INC = ../Mohid_Base_1
         $(HDF5)/libhdf5_fortran.a \
+
export BASE1 = Mohid_Base_1.lib
         $(HDF5)/libhdf5.a \
+
export BASE2INC = ../Mohid_Base_2
         $(HDF5)/libhdf5_hl.a
+
export BASE2 = Mohid_Base_2.lib
  #### End of exported variables ####
+
export WATER = MohidWater
 +
export LHDF5FORTRAN = libhdf5_fortran.a
 +
export LHDF5 = libhdf5.a
 +
export LHDF5HL = libhdf5_hl.a
 +
export ZLIB = libz.a
 +
export BASELIBS = \
 +
         $(BASE1INC)/$(BASE1) \
 +
        $(BASE2INC)/$(BASE2) \
 +
         $(HDF5)/$(LHDF5FORTRAN) \
 +
         $(HDF5)/$(LHDF5) \
 +
         $(HDF5)/$(LHDF5HL) \
 +
        $(ZLIBINC)/$(ZLIB)
 +
export LNETCDF  = netcdf.a
 +
  export NETCDFLIBS := \
 +
                      $(BASELIBS) \
 +
                      $(NETCDFINC)/$(LNETCDF)
 
   
 
   
  include aux.mk
+
  #------Files and modules lists------
 
+
=== ''aux.mk'' ===
+
METAFILES = \
MODCLEAN = Modulos.clean Boxdif_hidrodin.clean Library.clean Mohid_Base.clean Mohid2D.clean
+
        README \
  MODULES = $(MODCLEAN:.clean=.all)
+
        Editme_template.smk \
 +
        Nix.smk
 +
  MODULES = \
 +
          Makefiles \
 +
          MohidWater \
 +
          Mohid_Base_2 \
 +
          Mohid_Base_1
 
   
 
   
  .PHONY: all clean $(MODULES) $(MODCLEAN)
+
  #------Makefile rules---------------
 
   
 
   
  all: $(MODULES)
+
  include Makefiles/Makemodules.mk
 
   
 
   
  clean: $(MODCLEAN)
+
  #------Modules dependencies----------
 
   
 
   
  $(MODULES):
+
  Mohid_Base_2.all : Mohid_Base_1.all
$(MAKE) -C $(@:.all=) all
+
MohidWater.all : Mohid_Base_2.all
 +
 
 +
===Special Makefiles folder's ''Makefile''===
 +
METAFILES = \
 +
        Makefiles.smk \
 +
        Makemodules.smk
 
   
 
   
  $(MODCLEAN):
+
  SHELL = /bin/sh
$(MAKE) -C $(@:.clean=) clean
 
 
   
 
   
  #Modules dependencies
+
  .PHONY: all
Mohid2D.all: Mohid_Base Library.all
+
  all:
  Mohid_Base.all: Boxdif_hidrodin.all
+
        @echo No such action in this module
Library.all: Modulos.all
 
  
=== ''ModuleA/Vars.mk'' ===
+
===Special Makefiles folder's ''Makefiles.mk''===
  SHELL = /bin/sh
+
  OBJS = $(FILES:.$(S)=.$(O))
 +
SRCF = $(SRCDIR)
 +
SUFF := $(suffix $(TARGET))
 
   
 
   
  INCS = -I../ -I$(HDF5)
+
  #Make all
  SRCS = \
+
  .PHONY: all
        ModuleGlobalData.$(F) \
+
all: $(TARGET)
        ModuleHDF5.$(F) \
 
        ModuleTime.$(F) \
 
        Module_EnterData.$(F) \
 
        ModuleOilSpill.$(F) \
 
        ModuleAppPART3D.$(F) \
 
        ModuleEuler.$(F) \
 
        ModuleOxygenSaturation.$(F)
 
TARGET = Modulos.lib
 
 
   
 
   
=== ''ModuleA/Makefile'' ===
+
$(TARGET) : $(OBJS) $(LIBS)
  include Vars.mk
+
ifeq ($(SUFF),$(SUFFLIB))
 +
        @$(AR) $@ $^
 +
else
 +
        @$(CC) $(LFLAGS) -o $@ $^ $(LLFLAGS)
 +
  endif
 +
        @echo Finished building $@.
 
   
 
   
  OBJS = $(SRCS:.$(F)=.$(O))  
+
  #Fortran compilation rule
 +
%.$(O) : $(SRCF)/%.$(F)
 +
        @$(CC) $(CCFLAGS) $(INCS) $<
 +
        @echo $* .................. [OK]
 
   
 
   
  .PHONY: all clean
+
#make clean
 +
  .PHONY: clean
 +
clean:
 +
        @-$(DEL) *.$(O) *.$(MOD) $(TARGET)
 +
        @echo erased $(TARGET) files.
 
   
 
   
  all: $(TARGET)
+
  #make install
 +
SOURCE := $(TARGET)
 +
.PHONY: install
 +
install: $(SOURCE)
 +
        @-$(CP) $< $(DESTDIR)/`date +%G%m%d`_$(addprefix $(VER), $<)
 +
        @echo Installed $<.
 
   
 
   
  $(TARGET) : $(OBJS)
+
===Special Makefiles folder's ''Makemodules.mk''===
@$(AR) $@ $^
+
#make all
  @echo Finished building $@.
+
  MODALL = $(addsuffix .all, $(MODULES))
 +
.PHONY: all $(MODALL)
 +
all: $(MODALL)
 +
$(MODALL):
 +
  -$(MAKE) -C $(@:.all=) all
 
   
 
   
  clean:
+
  #make clean
@-$(DEL) *.$(O) *.$(MOD) $(TARGET)
+
MODCLEAN = $(addsuffix .clean, $(MODULES))
@echo Erased $(TARGET) files.
+
.PHONY: clean $(MODCLEAN)
 
+
clean: $(MODCLEAN)
  %.$(O) : %.$(F)
+
  $(MODCLEAN):
  @$(CC) $(CCFLAGS) $(INCS) $<
+
  -$(MAKE) -C $(@:.clean=) clean
@echo $* .............. [OK]
 
 
   
 
   
  include Dependencies.mk
+
  #make install
 +
MODINSTALL = $(addsuffix .install, $(MODULES))
 +
.PHONY: install $(MODINSTALL)
 +
install: $(MODINSTALL)
 +
$(MODINSTALL) :
 +
-$(MAKE) -C $(@:.install=) install
  
=== ''ModuleA/Dependencies.mk'' ===
+
===Regular folder typical ''Makefile''===
  #Dependencies
+
  INCS = -I$(HDF5)
  ModuleHDF5.$(O) : ModuleGlobalData.$(O)
+
  LIBS =
Module_EnterData.$(O) : ModuleTime.$(O)
+
SRCDIR = $(SRCBASE1)
  ModuleOilSpill.$(O) : Module_EnterData.$(O)
+
FILES = \
  ModuleAppPART3D.$(O) : ModuleOilSpill.$(O)
+
        ModuleGlobalData.$(S) \
  ModuleEuler.$(O) : ../param.cmb
+
        ModuleDrainageNetwork.$(S) \
 +
        ModuleProfile.$(S)
 +
TARGET = $(BASE1)
 +
   
 +
SHELL = /bin/sh
 +
 +
include ../Makefiles/Makefiles.mk
 +
 +
ModuleMacroAlgae.${O} : ModuleFunctions.${O}
 +
  ModuleTimeSerie.${O} : ModuleEnterData.${O}
 +
  ModuleDischarges.${O} : ModuleFunctions.${O} \
 +
                      ModuleTimeSerie.${O} \
 +
                      ModuleDrawing.${O}
  
 
==See also==
 
==See also==

Latest revision as of 17:09, 17 July 2009

This section describes a Cross-Compiler, Cross-Platform (CCCP) makefile development methodology using the make tool from GNU, also known as gmake. The syntax to use would be:

make platform.action

(ex: make Win, make Unix.clean, etc...).

Description

A CCCP makefile project a bunch of library, modules and program folders within a single root folder.

Tree description

Example tree

> tree cproj/
cproj/
|-- Editme.mk
|-- Makefile
|-- Makefiles
|   |-- Makefiles.mk
|   |-- Makemodules.mk
|   `-- Makefile
|-- Nix.mk
|-- lib1
|   `-- Makefile
|-- lib2
|   `-- Makefile
`-- prog1
    `-- Makefile

Regular folders

Every folder must contain the following files:

Makefile
encapsulates a list of all the folder's source-files and meta-files, a bunch of includes containing the makefile rules and, last but not least, the target dependencies. Several local variables are defined within:
INCS
LIBS
SRCDIR
contains the path to the source files
FILES
contains the list of source files (using the $(S) suffix)
METAFILES
contains the list of files required by the Makefile to run in this project (using the .smk suffix) besides the Makefile itself (of course).
TARGET
is the target name that the local makefile is supposed to build.
MODULES
contains the list of modules (special root folder only).
Dependencies
is a list of the dependent files and the respective dependencies.

Special folders and special files

There are two special folders, mandatory, and each containing special files, beyond the mandatory regular files listed above:

  1. the root folder
    Makefile
    it's completely different from the regular folder Makefile. It contains the rules to build the Solution for a series of platform.
    Nix.mk
    it contains the regular folder Makefile structure and content. It also contains all the necessary configuration global variables specific to the CCCP solution. It must be configured for a specific platform (Linux, windows,etc...) by the administrator.
    Editme.mk
    Each user must edit this configuration file before building the solution. It contains the paths to required external libraries such as HDF5 or Netcdf.
  2. the Makefiles folder
    Makemodules.mk
    contains the makefile rules to build (all), clean, install, etc, the target modules. It is invoked only from the root file Nix.mk.
    Makefiles.mk
    contains the makefile rules to build, clean, install, etc, the target files.

The makefile's global variables

The idea is to use global variables to pass arguments to the different modules makefiles. Thus, each specific platform makefile in the root folder defines these global variables. Then, it calls the modules makefiles who will use the global variables in their syntax. If a systematic approach of using global variables is implemented, then it is fairly easy to have a cross-platform makefile project implemented; and easily extended.

A template CCCP makefile solution

Special root folder's Makefile

 SHELL = /bin/sh
 
 export MAKE = make
 
 .PHONY: default
 default:
 	@echo Please choose your platform from: 
 	@echo Type "make (win nix).(' '  clean install sos)".
 
 #make all (add other platforms "Nix Nix Nix_double Win" ...)
 PLAT := Nix
 .PHONY : $(PLAT)
 $(PLAT):
 	$(MAKE) -f $@.mk all
 
 #make clean
 PLATCLEAN := $(addsuffix .clean, $(PLAT))
 .PHONY : $(PLATCLEAN)
 $(PLATCLEAN) :
 	$(MAKE) -f $(@:.clean=).mk clean
 
 #make install
 PLATINST := $(addsuffix .install, $(PLAT))
 .PHONY : $(PLATINST)
 $(PLATINST) :
 	$(MAKE) -f $(@:.install=).mk install

Special root folder's Editme.mk

#Edit the prefix of the installed binaries
# > make nix.install
export VER = x64_single

#Where do you want to install the binary files?
# > make nix.install
export DESTDIR = /usr/bin/mohid

#Where are the hdf5 libraries (with --enable-fortran) in your system?
export HDF5 = /home/Projects/hdf5/hdf5-1.6.5/hdf5/lib

#Where is the libz.a in your system?
export ZLIBINC = /usr/lib64

Special root folder's Nix.mk

SHELL = /bin/sh

#------User configuration file---------------

include Editme.mk

#-- NIX platform specific global variables --

export CP  = sudo cp
export DEL = rm
export O = o
export F = F90
export MOD = mod
export CC= ifort
export CCFLAGS  = -c -fpp -warn all -nologo -convert big_endian -D_USE_NIX# Debug: -g Profiling: -p
export LFLAGS   = -fpp -nologo -warn all -i-static -convert big_endian -D_USE_NIX# Profiling: -p
export LLFLAGS  =
export AR = ar rc
export SUFFLIB = .lib
export SUFFPROG =
export SRCBASE1 = ../../../Shared/MOHID.Base.1
export SRCBASE2 = ../../../Shared/MOHID.Base.2
export SRCWATER = ../../../Modulus.Software/MOHID.Water
export BASE1INC = ../Mohid_Base_1
export BASE1 = Mohid_Base_1.lib
export BASE2INC = ../Mohid_Base_2
export BASE2 = Mohid_Base_2.lib
export WATER = MohidWater
export LHDF5FORTRAN = libhdf5_fortran.a
export LHDF5 = libhdf5.a
export LHDF5HL = libhdf5_hl.a
export ZLIB = libz.a
export BASELIBS = \
       $(BASE1INC)/$(BASE1) \
       $(BASE2INC)/$(BASE2) \
       $(HDF5)/$(LHDF5FORTRAN) \
       $(HDF5)/$(LHDF5) \
       $(HDF5)/$(LHDF5HL) \
       $(ZLIBINC)/$(ZLIB)
export LNETCDF  = netcdf.a
export NETCDFLIBS := \
                     $(BASELIBS) \
                     $(NETCDFINC)/$(LNETCDF)

#------Files and modules lists------

METAFILES = \
       README \
       Editme_template.smk \
       Nix.smk
MODULES = \
         Makefiles \
         MohidWater \
         Mohid_Base_2 \
         Mohid_Base_1

#------Makefile rules---------------

include Makefiles/Makemodules.mk

#------Modules dependencies----------

Mohid_Base_2.all : Mohid_Base_1.all
MohidWater.all : Mohid_Base_2.all

Special Makefiles folder's Makefile

METAFILES = \
        Makefiles.smk \
        Makemodules.smk

SHELL = /bin/sh

.PHONY: all
all:
        @echo No such action in this module

Special Makefiles folder's Makefiles.mk

OBJS = $(FILES:.$(S)=.$(O))
SRCF = $(SRCDIR)
SUFF := $(suffix $(TARGET))

#Make all
.PHONY: all
all: $(TARGET)

$(TARGET) : $(OBJS) $(LIBS)
ifeq ($(SUFF),$(SUFFLIB))
        @$(AR) $@ $^
else
        @$(CC) $(LFLAGS) -o $@ $^ $(LLFLAGS)
endif
        @echo Finished building $@.

#Fortran compilation rule
%.$(O) : $(SRCF)/%.$(F)
        @$(CC) $(CCFLAGS) $(INCS) $<
        @echo $* .................. [OK]

#make clean
.PHONY: clean
clean:
        @-$(DEL) *.$(O) *.$(MOD) $(TARGET)
        @echo erased $(TARGET) files.

#make install
SOURCE := $(TARGET)
.PHONY: install
install: $(SOURCE)
        @-$(CP) $< $(DESTDIR)/`date +%G%m%d`_$(addprefix $(VER), $<)
        @echo Installed $<.

Special Makefiles folder's Makemodules.mk

#make all
MODALL = $(addsuffix .all, $(MODULES))
.PHONY: all $(MODALL)
all: $(MODALL)
$(MODALL):
	-$(MAKE) -C $(@:.all=) all

#make clean
MODCLEAN = $(addsuffix .clean, $(MODULES))
.PHONY: clean $(MODCLEAN)
clean: $(MODCLEAN)
$(MODCLEAN):
	-$(MAKE) -C $(@:.clean=) clean

#make install
MODINSTALL = $(addsuffix .install, $(MODULES))
.PHONY: install $(MODINSTALL)
install: $(MODINSTALL)
$(MODINSTALL) :
	-$(MAKE) -C $(@:.install=) install

Regular folder typical Makefile

INCS = -I$(HDF5)
LIBS =
SRCDIR = $(SRCBASE1)
FILES = \
       ModuleGlobalData.$(S) \
       ModuleDrainageNetwork.$(S) \
       ModuleProfile.$(S)
TARGET = $(BASE1)

SHELL = /bin/sh

include ../Makefiles/Makefiles.mk

ModuleMacroAlgae.${O} : ModuleFunctions.${O}
ModuleTimeSerie.${O} : ModuleEnterData.${O}
ModuleDischarges.${O} : ModuleFunctions.${O} \
                     ModuleTimeSerie.${O} \
                     ModuleDrawing.${O}

See also