#!/bin/bash
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of Intel Corporation nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8 ****************************************
# This script will create a basic makefile for all the source code
# files found in the present directory.
#
# It handles the following special cases automatically:
# if the directory name is Test, a unit test makefile is build
# to unit test the parent directory's library
# if the directory is a top level directory, a project makefile is built
# if the directory is a middle level directory, a middle makefile is built
# if the directory is sub-directory of a module which has a
# Makerules.module file, a module sub-directory makefile is built
# (it is best to build the module top level makefile first
# then buildMakefile for sub-directories will properly build)
# For other directories, a library Makefile is built
# Any source files which should not be processed by the Makefile
# should have the strings: "INTERNAL USE ONLY" or "DO NOT BUILD"
# "INTERNAL USE ONLY" should be used for non-public headers
# "DO NOT BUILD" should be used for source which is not ready yet
#
# In update mode (-u) an existing makefile is rebuilt, retaining selected
# customizations. The original is renamed Makefile-old
#
# Other Options:
# -x - create a makefile for building an executable
# -d - create a makefile for building a driver
# -k - create a makefile for building a darwin kernel extension
# -s - create a makefile for building a shared library
# -a - create a makefile for building an archive library (the default)
# -m - create a makefile for the toplevel directory of a module
# -c dir - create a makefile which builds code from this directory and dir
# (dir is relative to MOD_DIR)
# this option is only valid within a module style tree
# -p project - project name, default is current dir name
# Known Limitations:
# The update option (-u) only handles LOCALDEPLIBS and DS_SUBPROJECTS
# other customizations will be lost
# All include files will be installed as visible to other modules
# one exception is file containing the string "INTERNAL USE ONLY"
# on "DO NOT BUILD"
# out of the ordinary situations are not handled
# all non-special sub-directories are simply included in the Makefile
# .rc, .idl, .def files not handled
# misc source files not handled
# building of shared libraries not handled
# building makefiles for integration tests is not supported
. $ICSBIN/funcs.sh
tempFiles=
foundSource=n
# This will always be run when we exit, so it can do all our cleanup
trap 'rm -f $tempFiles' 0 1 2 9 15
Usage() {
echo "Usage: buildMakefile [-p project] [-u] [-m] [-c dir] [-x|-sad]" >&2
echo " -p project project name, default is current dir name" >&2
echo " -x create a makefile for building an executable" >&2
echo " -d create a makefile for building a driver" >&2
echo " -k create a makefile for building a darwin kernel extension" >&2
echo " -s create a makefile for building a shared library" >&2
echo " -a create a makefile for building an archive library (the default)" >&2
echo " -m create a makefile for the toplevel directory of a module" >&2
echo " -c dir create a makefile which builds code from this directory and dir" >&2
echo " (dir is relative to MOD_DIR)" >&2
echo " this option is only valid within a module style tree" >&2
echo " -u In update mode (-u) an existing makefile is rebuilt, retaining selected" >&2
echo " customizations. The original is renamed Makefile-old" >&2
exit 2
}
grepValue()
{
# grep for the value of a variable in the present Makefile
# $1 = variable name
# returns on stdout, the value of the variable
# leading spaces are removed from the value
grep "^$1" Makefile|cut -f2- -d=|sed -e's/^[ ]*//'
}
uflag=n
xflag=n
sflag=n
aflag=n
dflag=n
kflag=n
mflag=n
cdir=
project=
while getopts uxsadkmc:p: opt
do
case $opt in
u) uflag=y;;
x) xflag=y;;
s) sflag=y;;
a) aflag=y;;
d) dflag=y;;
k) dflag=y # -d implied by -k
kflag=y;;
m) mflag=y;;
c) cdir=$OPTARG;;
p) project=$OPTARG;;
?) Usage;;
esac
done
shift `expr $OPTIND - 1`
if [ $# != 0 ]
then
Usage
fi
if [ "$xflag" = y ]
then
if [ "$aflag" = y -o "$sflag" = y -o "$dflag" = y ]
then
Usage
fi
fi
if [ -f Makefile ]
then
if [ "$uflag" = n ]
then
echo "buildMakefile aborted. A Makefile already exists in this directory!" >&2
echo "To update an existing makefile, use buildMakefile -u" >&2
exit 1
else
ds_subprojects=`grepValue DS_SUBPROJECTS`
shlib_version=`grepValue SHLIB_VERSION`
localdeplibs=`grepValue LOCALDEPLIBS`
clocal=`grepValue CLOCAL`
cclocal=`grepValue CCLOCAL`
copt=`grepValue COPT`
ccopt=`grepValue CCOPT`
local_include_dirs=`grepValue LOCAL_INCLUDE_DIRS`
libfiles=`grepValue LIBFILES`
mv Makefile Makefile-old
fi
else
ds_subprojects=""
shlib_version=""
localdeplibs=""
clocal=""
cclocal=""
copt=""
ccopt=""
if [ "$mflag" = y ]
then
libfiles='FILL IN libraries built to $(MOD_LIB_DIR)'
else
libfiles=
fi
if [ "$uflag" = y ]
then
uflag=n # ignore -u, no existing makefile
echo "buildMakefile: ignoring -u, no existing Makefile"
fi
fi
extractModuleDir()
{
# extract the module sub-directory from a full path
# and set module_dir to the resulting sub-directory path
# $1 = full path to module (should be within TL_DIR)
module_dir=`expr "$1" : "$TL_DIR/\(.*\)"`
}
findModuleDir()
{
# sets module_dir to the sub-directory under TL_DIR for this module
# if this is not a module, module_dir is set to ""
# uses $TL_DIR
full_module_dir="$pwd"
while [ ! -f "$full_module_dir/Makerules.module" ]
do
full_module_dir=`dirname $full_module_dir`
if [ "$full_module_dir" = "/" -o "$full_module_dir" = "$TL_DIR" -o -f "$full_module_dir"/Makerules/Makerules.global ]
then
full_module_dir=""
module_dir=""
return
fi
done
extractModuleDir "$full_module_dir"
}
formatFileList()
{
# Create a variable specifying a source file list
# and output the value to the given temp file
# $1 = output temp file name
# $2 = list of directories to process
# $3 = prefix to use for filenames not in directory .
# cheat for now, assumes dir list is only . and 1 other
# hence we can get away with a single prefix
# $4 = list of extra filenames to explicitly add to list
# $5 = heading to declare variable for list
# $6 ... = suffixes for files to include in list
output=$1
list_dirs=$2
dir_prefix=$3
extra="$4"
heading=$5
shift; shift; shift; shift; shift
echo "$heading \\" > $output
{
for file in $extra
do
echo " $file \\"
done
for suffix in $*
do
for dir in $list_dirs
do
for i in $dir/*.$suffix
do
if [ -f "$i" ]
then
foundSource=y
base=`basename $i`
if egrep 'DO NOT BUILD|INTERNAL USE ONLY' $i > /dev/null
then
> /dev/null
elif [ "$base" != "$extra" ]
then
# This is a cheat, should test extra as a list, but for now we know it only has 1 filename
if [ "$dir" != "." -a "$dir_prefix" != "" ]
then
echo " $dir_prefix/$base \\"
else
echo " $base \\"
fi
fi
fi
done
done
done
} > temp$$
sort < temp$$ >> $output
echo " # Add more $* files here" >> $output
rm -f temp$$
tempFiles="$tempFiles $output temp$$"
}
formatVariable()
{
# Create a variable specifying a target file or 1 line list
# and output the value to the given temp file
# $1 = output temp file name
# $2 = heading to declare variable
# $3 = value for variable
if [ "$2" = "" ]
then
> $1
else
echo "$2 $3" > $1
fi
tempFiles="$tempFiles $1"
}
formatOptionalVariable()
{
# Create a variable specifying a target file or 1 line list
# and output the value to the given temp file
# If the value ($3) is null, an empty file is created
# $1 = output temp file name
# $2 = heading to declare variable
# $3 = value for variable
if [ x"$3" = "x" ]
then
formatVariable "$1" "" ""
else
formatVariable "$1" "$2" "$3"
fi
}
formatRule()
{
# Create a makefile rule line
# and output the line to the given temp file
# $1 = output temp file name
# $2 = rule line
echo -e "$2" > $1
tempFiles="$tempFiles $1"
}
CommonMakefileEdits()
{
# Edits of Makefile applicable to most Makefiles
ex Makefile <<!
/^DS_SUBPROJECTS/d
.-1
r DS_SUBPROJECTS.tmp
/^EXECUTABLE/d
.-1
r EXECUTABLE.tmp
/^DIRS/d
.-1
r DIRS.tmp
/^CFILES/d
.-1
r CFILES.tmp
/^CCFILES/d
.-1
r CCFILES.tmp
/^LFILES/d
.-1
r LFILES.tmp
/^LIBFILES/d
.-1
r LIBFILES.tmp
/^INCLUDE_TARGETS/d
.-1
r INCLUDE_TARGETS.tmp
/^DSP_SOURCES/
.+1
s/\$(MAKEFILE)/\$(MAKEFILE) $message_file/
/^LIB_TARGETS_ARLIB/d
.-1
r LIB_TARGETS_ARLIB.tmp
/^SHLIB_VERSION/d
.-1
r SHLIB_VERSION.tmp
/^CMD_TARGETS_SHLIB/d
.-1
r CMD_TARGETS_SHLIB.tmp
/^CMD_TARGETS_DRIVER/d
.-1
r CMD_TARGETS_DRIVER.tmp
/^CMD_TARGETS_KEXT/d
.-1
r CMD_TARGETS_KEXT.tmp
/^CLEAN_TARGETS_MISC/d
.-1
r CLEAN_TARGETS_MISC.tmp
/^LOCALDEPLIBS/d
.-1
r CLOCAL.tmp
r CCLOCAL.tmp
r LOCAL_INCLUDE_DIRS.tmp
r LOCALDEPLIBS.tmp
/Makerules.project/d
.-1
r rules.tmp
/Overrides/
/^#=====/
.-1
r COPT.tmp
r CCOPT.tmp
/runtest/d
.-1
r runtest.tmp
w
q
!
}
buildProjectMakefile()
{
if [ ! -f Makerules.project ]
then
sed -e "s/<FILL IN PROJECT NAME>/$project/" < $TL_DIR/MakeTemplates/Makerules.project > Makerules.project
fi
sed -e "s/<FILL IN PROJECT NAME>/$project/" < $TL_DIR/MakeTemplates/Makefile.projHeading > Makefile
cat $TL_DIR/MakeTemplates/Makefile.basic >> Makefile
CommonMakefileEdits
ex Makefile <<!
/^DSP_SOURCES/
.+1
s/\$(MAKEFILE)/\$(MAKEFILE) Makerules.project/
w
q
!
echo "edit BSP_SPECIFIC_DIRS line in Makefile"
}
buildModuleMakefile()
{
if [ ! -f Makerules.module ]
then
sed -e "s/<FILL IN MODULE NAME>/$project/" < $TL_DIR/MakeTemplates/Makerules.module > Makerules.module
ex Makerules.module <<!
/^MOD_DIR/d
.-1
r MOD_DIR.tmp
w
q
!
fi
sed -e "s/<FILL IN MODULE NAME>/$project/" < $TL_DIR/MakeTemplates/Makefile.modHeading > Makefile
cat $TL_DIR/MakeTemplates/Makefile.basic >> Makefile
CommonMakefileEdits
ex Makefile <<!
/^DSP_SOURCES/
.+1
s/\$(MAKEFILE)/\$(MAKEFILE) Makerules.module/
/Maketargets.install/
s/Maketargets.install/Maketargets.moduleinstall/
/Maketargets.stage/
s/Maketargets.stage/Maketargets.modulestage/
/runtest/
a
clobber:: clobber_module
.
w
q
!
}
buildBasicMakefile()
{
# Create a basic Makefile using the temp files created
echo "# Makefile for ${project}" > Makefile
echo >> Makefile
if [ "$foundSource" = n ]
then
cat $TL_DIR/MakeTemplates/Makefile.middle >> Makefile
ex Makefile <<!
/^DS_SUBPROJECTS/d
.-1
r DS_SUBPROJECTS.tmp
/^DIRS/d
.-1
r DIRS.tmp
/Makerules.project/d
.-1
r rules.tmp
w
q
!
else
cat $TL_DIR/MakeTemplates/Makefile.basic >> Makefile
CommonMakefileEdits
fi
}
rm -f $tempFiles
TL_DIR=`findTopDir`
pwd=`pwd`
if [ -f Makerules/Makerules.global ]
then
projectDir=y
if [ "$mflag" = y ]
then
echo "Project level directories cannot be module Makefiles" 2>&1
exit 1
fi
module_dir=""
else
projectDir=n
if [ "$mflag" = y ]
then
extractModuleDir "$pwd"
else
findModuleDir
fi
fi
dirName=`basename $pwd`
if [ "$cdir" != "" -a "$module_dir" = "" ]
then
echo "-c option is not valid outside a module Makefile tree" 2>&1
exit 1
fi
# find all directories
dirs=
for i in *
do
if [ -d "$i" -a "$i" != CVS -a "$i" != "builtbin" -a "$i" != builtinclude \
-a "$i" != builtlibs -a "$i" != stage -a "$i" != Makerules \
-a "$i" != MakeTools \
-a "$i" != MakeTemplates -a "$i" != CodeTemplates ]
then
if [ "$i" = Test ]
then
# translate to make variable so unit tests are optional
i='$(TEST)'
fi
if [ "$dirs" = "" ]
then
dirs="$i"
else
dirs="$dirs $i"
fi
fi
done
if [ -f "$dirName".msg ]
then
# Message files to be built
message_file="${dirName}.msg"
message_hfile="${dirName}_Messages.h"
message_cfile="${dirName}_Messages.c"
elif [ "$cdir" != "" -a -f "$dirName".msg ]
then
# Message files to be built from common dir
message_file="${dirName}.msg"
message_hfile="${dirName}_Messages.h"
message_cfile="${dirName}_Messages.c"
else
message_file=""
message_hfile=""
message_cfile=""
fi
formatVariable DIRS.tmp 'DIRS =' "$dirs"
if [ "$cdir" != "" ]
then
file_dirs=". $full_module_dir/$cdir"
else
file_dirs="."
fi
formatFileList CFILES.tmp "$file_dirs" "" "$message_cfile" "CFILES =" c
formatFileList CCFILES.tmp "$file_dirs" "" "" "CCFILES =" cpp
formatFileList LFILES.tmp "$file_dirs" "" "" "LFILES =" lex
foundCode=$foundSource
formatFileList INCLUDE_TARGETS.tmp "$file_dirs" "\$(COMMON_SRCDIR)" "$message_hfile" "INCLUDE_TARGETS =" h hpp
formatVariable CLEAN_TARGETS_MISC.tmp 'CLEAN_TARGETS_MISC =' "$message_hfile $message_cfile"
if [ "$project" = "" ]
then
project="$dirName"
fi
if [ "$dirName" = "Test" ]
then
if [ "$mflag" = y ]
then
echo "Module makefiles cannot be Unit Test directories" 2>&1
Usage
fi
# Unit Test
parent=`dirname $pwd`
parent=`basename $parent`
project=${parent}_Test
libTarget=n
exeTarget=y
driverTarget=n
kextTarget=n
if [ "$uflag" = n ]
then
ds_subprojects="$parent Osa Gen Log Err Rai UiUtil UTest"
localdeplibs="$parent Osa Gen Log Err Rai UiUtil UTest"
fi
formatRule runtest.tmp 'include $(TL_DIR)/Makerules/Maketargets.runtest'
else
# TBD other tests, projectDir should be y for exe, check for a main?
# if we didn't find any real code files (just headers)
# we don't build a library nor executable
if [ "$foundCode" = y -a "$dflag" != y ]
then
libTarget=y
exeTarget=n
driverTarget=n
kextTarget=n
else
libTarget=n
exeTarget=n
driverTarget=n
kextTarget=n
fi
formatRule runtest.tmp '#include $(TL_DIR)/Makerules/Maketargets.runtest'
fi
# -x, -a and -s, -d override the above heuristics
if [ "$xflag" = y ]
then
exeTarget=y
libTarget=n
elif [ "$sflag" = y -o "$aflag" = y ]
then
exeTarget=n
libTarget=y
fi
if [ "$dflag" = y ]
then
driverTarget=y
fi
if [ "$kflag" = y ]
then
kextTarget=y
fi
arlib=""
shlib=""
driver=""
kext=""
if [ "$libTarget" = y ]
then
if [ "$sflag" = y ]
then
shlib='$(LIB_PREFIX)'"${project}"'$(SHLIB_VERSION_SUFFIX)'
if [ "$shlib_version" = "" ]
then
shlib_version="0.0"
fi
fi
if [ "$aflag" = y -o "$sflag" = n ]
then
arlib='$(LIB_PREFIX)'"${project}"'$(ARLIB_SUFFIX)'
fi
fi
if [ "$driverTarget" = y ]
then
driver="${project}"'$(KOBJ_SUFFIX)'
fi
if [ "$kextTarget" = y ]
then
kext="${project}"'$(KEXT_SUFFIX)'
fi
formatVariable LIB_TARGETS_ARLIB.tmp 'LIB_TARGETS_ARLIB =' "$arlib"
formatVariable SHLIB_VERSION.tmp 'SHLIB_VERSION =' "$shlib_version"
formatVariable CMD_TARGETS_SHLIB.tmp 'CMD_TARGETS_SHLIB =' "$shlib"
formatVariable CMD_TARGETS_DRIVER.tmp 'CMD_TARGETS_DRIVER =' "$driver"
formatVariable CMD_TARGETS_KEXT.tmp 'CMD_TARGETS_KEXT =' "$kext"
if [ "$exeTarget" = y ]
then
executable="${project}"'$(EXE_SUFFIX)'
else
executable='# '"${project}"'$(EXE_SUFFIX)'
fi
formatVariable EXECUTABLE.tmp 'EXECUTABLE =' "\$(BUILDDIR)/$executable"
formatVariable DS_SUBPROJECTS.tmp 'DS_SUBPROJECTS =' "$ds_subprojects"
formatVariable LOCALDEPLIBS.tmp 'LOCALDEPLIBS =' "$localdeplibs"
formatOptionalVariable CLOCAL.tmp 'CLOCAL =' "$clocal"
formatOptionalVariable CCLOCAL.tmp 'CCLOCAL =' "$cclocal"
formatOptionalVariable LOCAL_INCLUDE_DIRS.tmp 'LOCAL_INCLUDE_DIRS =' "$local_include_dirs"
formatVariable LIBFILES.tmp 'LIBFILES =' "$libfiles"
if [ "$module_dir" != "" ]
then
if [ "$cdir" != "" ]
then
cdir_def="\n\nCOMMON_SRCDIR = \$(MOD_DIR)/$cdir"
else
cdir_def=""
fi
formatRule rules.tmp "include \$(TL_DIR)/$module_dir/Makerules.module$cdir_def"
else
formatRule rules.tmp "include \$(TL_DIR)/\$(PROJ_FILE_DIR)/Makerules.project"
fi
if [ "$driverTarget" = y ]
then
formatOptionalVariable COPT.tmp 'COPT =' "# set by CKERNEL for drivers"
formatOptionalVariable CCOPT.tmp 'CCOPT =' "# set by CKERNEL for drivers"
else
formatOptionalVariable COPT.tmp 'COPT =' "$copt"
formatOptionalVariable CCOPT.tmp 'COPT =' "$ccopt"
fi
if [ "$projectDir" = y ]
then
# building a project level makefile
buildProjectMakefile
elif [ "$mflag" = y ]
then
# building a lower level module makefile
formatRule MOD_DIR.tmp "MOD_DIR=\$(TL_DIR)/$module_dir"
buildModuleMakefile
else
# building a lower level makefile
buildBasicMakefile
fi