Personal tools

Makefile CCCP

From MohidWiki

Revision as of 12:52, 17 July 2009 by Guillaume (talk | contribs) (Special folders and special files)
Jump to: navigation, search

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/
|-- Actions.mk
|-- Dependencies.mk
|-- Editme.mk
|-- Files.mk
|-- Makefile
|-- Makefiles
|   |-- All.mk
|   |-- AllLib.mk
|   |-- Clean.mk
|   |-- Dependencies.mk
|   |-- Files.mk
|   |-- Install.mk
|   `-- Makefile
|-- Nix.mk
|-- lib1
|   |-- Dependencies.mk
|   |-- Files.mk
|   `-- Makefile
|-- lib2
|   |-- Dependencies.mk
|   |-- Files.mk
|   `-- Makefile
`-- prog1
    |-- Dependencies.mk
    |-- Files.mk
    `-- Makefile

Regular folders

Every folder must contain the following files:

Files.mk
encapsulates a list of all the folder's source-files and meta-files. Several variables are defined:
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)
TARGET
is the target name that the local makefile is supposed to build.
MODULES
contains the list of modules (special root folder only).
Makefile
contains includes to all the actions that can be perfomed on the folder.
Dependencies.mk
encapsulates the dependencies of the files within the lists defined in Files.mk.

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
    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.
  2. 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 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 Actions.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

Special root folder's Nix.mk

SHELL = /bin/sh

###### NIX Exported 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 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)
#### End of exported variables ####

include Editme.mk
include Files.mk
include Actions.mk
include Dependencies.mk

Special root folder's Editme.mk, Files.mk, and Dependencies.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
METAFILES = \
        README.txt \
		Nix.smk \
        Files.smk \
        Dependencies.smk \
        Actions.smk
MODULES = \
          Makefiles \
          MohidWater \
          Mohid_Base_2 \
          Mohid_Base_1 \
TARGET = $$
#Modules dependencies
Mohid_Base_2.all : Mohid_Base_1.all
MohidWater.all : Mohid_Base_2.all

Special Makefiles folder's Makefile and Files.mk

SHELL = /bin/sh

include Files.mk

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

METAFILES = \
        Files.smk \
        All.smk \
        Clean.smk \
        Install.smk
TARGET = Makefiles

Special Makefiles folder's AllLib.mk, All.mk, Clean.mk, Install.mk

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

.PHONY: allLib

allLib: $(TARGET)

$(TARGET) : $(OBJS)
	@$(AR) $@ $^
	@echo Finished building $@.

%.$(O) : $(SRCF)/%.$(F)
	@$(CC) $(CCFLAGS) $(INCS) $<
	@echo $* .................. [OK]
OBJS = $(FILES:.$(S)=.$(O))
SRCF = $(SRCDIR)

.PHONY: all

all: $(TARGET)

$(TARGET) : $(OBJS) $(LIBS)
	@$(CC) $(LFLAGS) -o $@ $^ $(LLFLAGS)
	@echo Finished building $@.

%.$(O) : $(SRCF)/%.$(F)
	@$(CC) $(CCFLAGS) $(INCS) $<
	@echo $* .................. [OK]
.PHONY: clean
clean:
	@-$(DEL) *.$(O) *.$(MOD) $(TARGET)
	@echo erased $(TARGET) files.
SOURCE := $(TARGET)

.PHONY: install

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

Regular folder typical Files.mk, Makefile and Dependencies.mk

INCS = -I$(HDF5)
LIBS =
SRCDIR = $(SRCBASE1)
FILES = \
       ModuleGlobalData.$(S) \
       ModuleDrainageNetwork.$(S) \
       ModuleProfile.$(S)
METAFILES = \
        Files.smk \
        Dependencies.smk
TARGET = $(BASE1)
SHELL = /bin/sh

include Files.mk
include ../Makefiles/Install.mk
include ../Makefiles/Clean.mk
include ../Makefiles/Alllib.mk
include Dependencies.mk
ModuleMacroAlgae.${O} : ModuleFunctions.${O}
ModuleTimeSerie.${O} : ModuleEnterData.${O}
ModuleDischarges.${O} : ModuleFunctions.${O} \
                     ModuleTimeSerie.${O} \
                     ModuleDrawing.${O}

See also