modbuild.in 11.5 KB
Newer Older
gsell's avatar
gsell committed
1
#!/usr/bin/env bash
2 3 4 5 6 7
#
# The following build specific variables are set and used in libpbuild.bash:
#       ARGS
#       BUILD_SCRIPT
#       BUILDBLOCK_DIR
#
8
#.............................................................................
9 10 11

declare VERSION='@PMODULES_VERSION@'

12 13 14
# get absolute path of script
declare	    mydir=$(dirname "$0")
declare -r  mydir=$(cd ${mydir} && pwd -P)
gsell's avatar
gsell committed
15

16 17 18
# initialize PATH,
# add library installation directories to the PATH,
# so 'source' is able find them
gsell's avatar
gsell committed
19 20 21 22 23 24 25

if [[ $(uname -s) == 'Darwin' ]]; then
        PATH='/usr/local/bin:'
else
        PATH=''
fi
PATH+='/usr/bin:/bin:/usr/sbin:/sbin'
26 27
PATH+=":${mydir}"
PATH+=":${mydir}/../lib:${mydir}/../config"
28

29
source libstd.bash    || {
gsell's avatar
gsell committed
30
        echo "Oops: cannot source library -- '$_'" 1>&2; exit 3;
31
}
gsell's avatar
gsell committed
32

gsell's avatar
gsell committed
33 34 35 36
# can be set in the configuration file
declare         PMODULES_DISTFILESDIR=''
declare         PMODULES_TMPDIR=''

37
source libpbuild.bash    || \
gsell's avatar
gsell committed
38
        std::die 3 "Oops: cannot source library -- '$_'"
39

40
# save arguments, (still) required for building dependencies
41 42
declare -r ARGS="$@"

gsell's avatar
gsell committed
43 44 45
##############################################################################
#
usage() {
gsell's avatar
gsell committed
46
	std::error "
gsell's avatar
gsell committed
47 48
USAGE:
        $0 [options..] [build_script] version
gsell's avatar
gsell committed
49

gsell's avatar
gsell committed
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
MANDATORY ARGUMENTS:

version
        Variant of module to build.

SELECT VARIANT TO BUILD:

--system
        Specify the system for selecting a variants. Defaults to the
	output of 'uname -s'.

--with=P/V
        Select variant to compile. Use multiple '--with' arguments
	to make the selected variant unique.

BUILD-STEPS OPTIONS:

--prep
	Prepare sources: unpack sources and apply patches only.

--configure
	Prepare and configure sources.

--compile
	Prepare, configure and compile everything.

--install
	Prepare, configure and compile everything. Finally run install
	step. Do not cleanup build and source directory.

--all
	Run throu all steps including cleanup.

--update-modulefiles
	Only install the modulefile and set the release.

MISCELLANEOUS OPTIONS:
gsell's avatar
gsell committed
87 88

-? | -h | --help
89 90 91 92
        Print usage.

-V | --version )
        Print version.
gsell's avatar
gsell committed
93 94

-v | --verbose )
95
        Verbose output.
gsell's avatar
gsell committed
96 97

-j N | --jobs=N
98
        Run N parallel make jobs.
gsell's avatar
gsell committed
99 100 101 102

-f | --force-rebuild
        Force rebuild of module.

gsell's avatar
gsell committed
103 104 105
--dry-run
	Dry run.

gsell's avatar
gsell committed
106
--disable-cleanup-build
gsell's avatar
gsell committed
107
--enable-cleanup-build
gsell's avatar
gsell committed
108 109
	Cleanup files in the build directory. Default is to remove.
      	all files in the build-directory.
gsell's avatar
gsell committed
110

gsell's avatar
gsell committed
111
--disable-cleanup-src
gsell's avatar
gsell committed
112
--enable-cleanup-src
gsell's avatar
gsell committed
113 114
	Cleanup files in the source directory. Default is to
	remove all files in the source directory.
gsell's avatar
gsell committed
115 116

--disable-cleanup
gsell's avatar
gsell committed
117
--enable-cleanup
118
	Cleanup all files in temporary directory. Default is to
gsell's avatar
gsell committed
119
	remove all files created during building.
gsell's avatar
gsell committed
120

gsell's avatar
gsell committed
121 122
--distdir
	Directory wwhere to store and lookup downloaded files.
gsell's avatar
gsell committed
123

gsell's avatar
gsell committed
124 125
--tmpdir
        Directory used for building a module.
gsell's avatar
gsell committed
126

gsell's avatar
gsell committed
127 128 129 130
"
	exit 1
}

131
##############################################################################
gsell's avatar
gsell committed
132
#
133 134
# parse options and arguments
#
gsell's avatar
gsell committed
135 136 137
# command line arguments are taken first
# then configuration file
# last default
138

gsell's avatar
gsell committed
139
# versions to be build, '.*' or none means all
140 141
declare -a      versions=()
declare         opt_bootstrap='no'
gsell's avatar
gsell committed
142 143 144 145 146 147
declare 	opt_build_config='modbuild.conf'
declare         opt_build_target='all'
declare         opt_dry_run='no'
declare         opt_enable_cleanup_build='yes'
declare         opt_enable_cleanup_src='yes'
declare         opt_force_rebuild='no'
148
declare -i      opt_jobs=0
gsell's avatar
gsell committed
149 150 151
declare         opt_update_modulefiles='no'
declare         opt_system=''
declare         opt_verbose='no'
152 153
# array collecting all modules specified on the command line via '--with=module'
declare -a      opt_with_modules=()
154

155 156 157 158
parse_args() {
	while (( $# > 0 )); do
		case $1 in
		-j )
gsell's avatar
gsell committed
159
                        opt_jobs="$2"
160 161 162
			shift
			;;
		--jobs=[0-9]* )
gsell's avatar
gsell committed
163
			opt_jobs="${1/--jobs=}"
164 165 166
			;;
		-v | --verbose )
			trap 'echo "$BASH_COMMAND"' DEBUG
gsell's avatar
gsell committed
167
                        opt_verbose='yes'
168 169 170 171 172
			;;
		--debug )
			set -x
			;;
		-f | --force-rebuild )
gsell's avatar
gsell committed
173
                        opt_force_rebuild='yes'
174 175 176 177
			;;
		-\? | -h | --help )
			usage
			;;
178 179 180
                -V | --version )
                        std::die 0  "\nPmodules version ${VERSION}\nCopyright GNU GPL v2\n"
                        ;;
181
		--dry-run )
gsell's avatar
gsell committed
182
			opt_dry_run='yes'
183
			;;
184
		--config )
gsell's avatar
gsell committed
185
			opt_build_config="$2"
186 187 188
			shift 1
			;;
		--config=* )
gsell's avatar
gsell committed
189
			opt_build_config="${1#*=}"
190
			;;
191
		--enable-cleanup )
gsell's avatar
gsell committed
192 193
			opt_enable_cleanup_build='yes'
			opt_enable_cleanup_src='yes'
194
			;;
195
		--disable-cleanup )
gsell's avatar
gsell committed
196 197
			opt_enable_cleanup_build='no'
			opt_enable_cleanup_src='no'
198 199
			;;
		--enable-cleanup-build )
gsell's avatar
gsell committed
200
			opt_enable_cleanup_build='yes'
201 202
			;;
		--disable-cleanup-build )
gsell's avatar
gsell committed
203
			opt_enable_cleanup_build='no'
204 205
			;;
		--enable-cleanup-src )
gsell's avatar
gsell committed
206
			opt_enable_cleanup_src='yes'
207 208
			;;
		--disable-cleanup-src )
gsell's avatar
gsell committed
209
			opt_enable_cleanup_src='no'
210 211
			;;
		--distdir )
gsell's avatar
gsell committed
212
			PMODULES_DISTFILESDIR="$2"
213 214 215
			shift
			;;
		--distdir=* )
gsell's avatar
gsell committed
216
			PMODULES_DISTFILESDIR="${1/--distdir=}"
217 218
			;;
		--tmpdir )
gsell's avatar
gsell committed
219
                        PMODULES_TMPDIR="$2"
220 221 222
			shift
			;;
		--tmpdir=* )
gsell's avatar
gsell committed
223
			PMODULES_TMPDIR="${1/--tmpdir=}"
224
			;;
gsell's avatar
gsell committed
225
		--system )
gsell's avatar
gsell committed
226
			opt_system="$2"
227 228
			shift
			;;
gsell's avatar
gsell committed
229
		--system=* )
gsell's avatar
gsell committed
230
			opt_system="${1/*=}"
231 232
			;;
		--with )
233
			opt_with_modules+=( "$2" )
234 235 236 237
			shift
			;;
		--with=*/* )
			m="${1/--with=}"
238
			opt_with_modules+=( ${m} )
239 240
			;;
		--prep | --configure | --compile | --install | --all )
gsell's avatar
gsell committed
241
			opt_build_target=${1:2}
242 243
			;;
		--bootstrap )
244
			opt_bootstrap='yes'
245
			;;
gsell's avatar
gsell committed
246
		--update-modulefiles )
gsell's avatar
gsell committed
247
			opt_update_modulefiles='yes'
248
			;;
249 250 251
                -- )
                        :
                        ;;
252
		-* )
253
			std::die 1 "Invalid option -- '$1'"
254
			;;
255
		[=0-9]* | '.*' )
256
			versions+=( "$1" )
257
			;;
258 259 260
		'')	
			:
			;;
261 262
		* )
			[[ -z "${BUILD_SCRIPT}" ]] || \
263
				std::die 1 "%s "\
264 265
					 "Build script already set to" \
					 "'${BUILD_SCRIPT}' -- '$1'"
266 267
		        BUILD_SCRIPT=$(std::get_abspath "$1")
			test -r ${BUILD_SCRIPT} || \
268
				std::die 1 "%s " \
269 270
					 "Build script does not exist" \
					 "or is not readable -- '$_'"
271 272 273 274 275
			BUILDBLOCK_DIR=$(dirname "${BUILD_SCRIPT}")
			;;
		esac
		shift
	done	
276
	[[ -n ${BUILD_SCRIPT} ]] || std::die 1 "No build-block specified!"
gsell's avatar
gsell committed
277
	(( ${#versions[@]} > 0)) || versions+=( '.*' )
gsell's avatar
gsell committed
278
}
279

280
shopt -s nocaseglob
281
find_variants_files(){
282 283 284
        shopt -q nullglob || :
        local -i nullglob_set=$?
        shopt -s nullglob
285
        local files=( "${BUILDBLOCK_DIR}"/*/variants\.${opt_system} )
gsell's avatar
gsell committed
286
        files+=( "${BUILDBLOCK_DIR}"/*/variants.$(uname -s) )
287 288
        local f
	for f in "${BUILDBLOCK_DIR}"/*/variants; do
gsell's avatar
gsell committed
289 290 291
		[[ -e "${f}.${opt_system}" ]] \
                        || [[ -e "${f}.$(uname -s)" ]] \
                        || files+=( "$f" )
292
	done
293
        (( nullglob_set == 1 )) && shopt -u nullglob
294
	std::upvar "$1" "${files[@]}"
295 296
}

297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
shopt -s extglob
expand_variants_file(){
	expand_deps(){
		local text="$1"
                shift
		local deps=( "${@}" )
                echo "${deps[@]}"
                if (( ${#deps[@]} == 0 )); then
                        echo ${text}
		else
                        local list
		        eval list=( ${deps[0]} )
			for dep in ${list[*]}; do
				expand_deps "${text} ${dep}" "${deps[@]:1}"
			done
		fi
	}

	local -r input="$1"
	while read -a toks; do
		# skip empty and comment lines
		[[ -z ${toks} ]] && continue
		[[ ${toke:0:1} == '#' ]] && continue

		deps=( ${toks[*]:2} )
		expand_deps "${toks[0]} ${toks[1]}" "${deps[@]}"
	done < "${input}"
}

326 327 328 329 330 331 332 333 334 335 336 337
build_modules() {
        local name="$1"
        local version="$2"
        local exact_match='no'
        if [[ "${version:0:1}" == "=" ]]; then
                exact_match='yes'
                version="${version:1}"
        fi
        shift 2
        local with_modules=( $* )
        local files
        find_variants_files files
338 339 340 341 342

        # if we have to build a dependency, we might have less dependencies
        # on it. Or in other words: the list of "with modules" might be
        # overdetermined. In the loop below we check, which dependencies
        # specified with '--with' are required.
343 344
        local m
	local pattern="/^${name}\/${version}[[:blank:]]/"
345
	for m in "${with_modules[@]}"; do
346
                if [[ -n $(awk "/${m%/*}[\/ ]/" "${files[@]}") ]]; then
347 348
		        pattern+=" && /${m//\//\\/}/"
                fi
349
	done
350 351

        
352 353 354
        local variants=()
        local variants_files=()
        for f in "${files[@]}"; do
355
                local line=''
356
                while read line; do
357
                        variants+=( "${line}" )
358
                        variants_files+=( "$f" )
359
                done < <(expand_variants_file "${f}" | awk "${pattern}")
360 361 362
                # here we should add a check, whether the version of the
                # found variants are in the right variants files. Example:
                # a variant for hdf5/1.10.4 is not allowed in a variants file
363 364
                # for version 1.8. For this we need the mapping of a variant
                # to the variants file in array 'variants_files'
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
        done
        if (( ${#variants[@]} == 0 )); then
		std::info "%s " \
			 "${name}/${version}:" \
			 "no suitable variant found!"
                std::die 10 "Aborting..."
        elif (( ${#variants[@]} > 1 )) && [[ ${exact_match} == 'yes' ]]; then
		std::info "%s " \
			 "Multiple variants found:"
                for variant in "${variants[@]}"; do
                        std::info "${variant}"
                done
                std::die 10 "Aborting..."
        fi
        local -i i=0
        local -i num_variants=${#variants[@]}
        for ((i = 0; i < num_variants; i++)); do
                local tokens=( ${variants[i]} )
                local name="${tokens[0]%/*}"
                version="${tokens[0]#*/}"
                release="${tokens[1]}"
                with_modules=( "${tokens[@]:2}" )
                pbuild.build_module \
                        "${name}" "${version}" \
                        "${release}" "${with_modules[@]}"
        done
391 392 393 394
}

#.............................................................................
# main
395

396 397
parse_args "$@"

gsell's avatar
gsell committed
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
if [[ -z "${opt_system}" ]]; then
        opt_system=$(std::get_os_release)
fi

pbuild.jobs "${opt_jobs}"
pbuild.force_rebuild "${opt_force_rebuild}"
pbuild.build_target "${opt_build_target}"
pbuild.dry_run "${opt_dry_run}"
pbuild.enable_cleanup_build "${opt_enable_cleanup_build}"
pbuild.enable_cleanup_src "${opt_enable_cleanup_src}"
pbuild.update_modulefiles "${opt_update_modulefiles}"
pbuild.system "${opt_system}"
pbuild.verbose "${opt_verbose}"

source libpbuild_dyn.bash    || \
        std::die 3 "Oops: cannot source library -- '$_'"

415 416 417
# source build configuration,
# must be done before sourcing libpbuild!
if [[ "${opt_bootstrap}" == 'yes' ]]; then
gsell's avatar
gsell committed
418
        test -d "${BUILDBLOCK_DIR}/../../config" && PATH+=":$_"
419
else
gsell's avatar
gsell committed
420 421 422 423 424 425
        # Please note: if we trap DEBUG a statement like
        #              test -d ... && PATH+=$_
        #              does not work (at least on macOS with bash 4 and 5)
        if [[ -d "${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}" ]]; then
                PATH+=":${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}"
        fi
426
fi
gsell's avatar
gsell committed
427 428
source "${opt_build_config}" || \
        std::die 3 "Oops: Cannot source configuration file -- '$_'"
429

gsell's avatar
gsell committed
430 431 432
: ${PMODULES_DISTFILESDIR:=${PMODULES_ROOT}/var/distfiles}
: ${PMODULES_TMPDIR:=/var/tmp/${USER}}

433 434
declare -r BUILD_SCRIPT
declare -r BUILDBLOCK_DIR
435

436
# the module name is defined by the directory the build script is in
437 438
IFS=/ read -r -a fname <<< "${BUILD_SCRIPT:1}"
module_name=${fname[${#fname[@]}-2]}
Achim Gsell's avatar
Achim Gsell committed
439

440
#
441
# are we bootstrapping? If yes, go for it...
442
#
443 444
if [[ "${opt_bootstrap}" == 'yes' ]]; then
	pbuild.bootstrap "${module_name}"  "${versions[0]}" 'stable'
445 446
        exit $?
fi
gsell's avatar
gsell committed
447

448
#
449
# else
450
#
451
for version in "${versions[@]}"; do
452
        build_modules "${module_name}" "${version}" "${opt_with_modules[@]}"
453
done
gsell's avatar
gsell committed
454

gsell's avatar
gsell committed
455 456 457 458 459
# Local Variables:
# mode: sh
# sh-basic-offset: 8
# tab-width: 8
# End: