1 #!/bin/bash
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License, Version 1.0 only
7 # (the "License"). You may not use this file except in compliance
8 # with the License.
9 #
10 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 # or http://www.opensolaris.org/os/licensing.
12 # See the License for the specific language governing permissions
13 # and limitations under the License.
14 #
15 # When distributing Covered Code, include this CDDL HEADER in each
16 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 # If applicable, add the following below this CDDL HEADER, with the
18 # fields enclosed by brackets "[]" replaced with your own identifying
19 # information: Portions Copyright [yyyy] [name of copyright owner]
20 #
21 # CDDL HEADER END
22 #
23 #
24 # Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
25 # Use is subject to license terms.
26 #
27
28 umask 022
29
30 #############################################################################
31 # functions.sh
32 #############################################################################
33 # Helper functions for building packages that should be common to all build
34 # scripts
35 #############################################################################
36
37 #############################################################################
38 # Process command line options
39 #############################################################################
40 process_opts() {
41 SCREENOUT=
42 FLAVOR=
43 OLDFLAVOR=
44 BUILDARCH=both
45 OLDBUILDARCH=
46 BATCH=
47 DEPVER=
48 while getopts "bpf:ha:d:" opt; do
49 case $opt in
50 h)
51 show_usage
52 exit
53 ;;
54 \?)
55 show_usage
56 exit 2
57 ;;
58 p)
59 SCREENOUT=1
60 ;;
61 b)
62 BATCH=1 # Batch mode - exit on error
63 ;;
64 f)
65 FLAVOR=$OPTARG
66 OLDFLAVOR=$OPTARG # Used to see if the script overrides the
67 # flavor
68 ;;
69 a)
70 BUILDARCH=$OPTARG
71 OLDBUILDARCH=$OPTARG # Used to see if the script overrides the
72 # BUILDARCH variable
73 if [[ "$BUILDARCH" != "32" && "$BUILDARCH" != "64" &&
74 "$BUILDARCH" != "both" ]]; then
75 echo "Invalid build architecture specified: $BUILDARCH"
76 show_usage
77 exit 2
78 fi
79 ;;
80 d)
81 DEPVER=$OPTARG
82 ;;
83 esac
84 done
85 }
86
87 #############################################################################
88 # Show usage information
89 #############################################################################
90 show_usage() {
91 echo "Usage: $0 [-b] [-p] [-f FLAVOR] [-h] [-a 32|64|both] [-d DEPVER]"
92 echo " -b : batch mode (exit on errors without asking)"
93 echo " -p : output all commands to the screen as well as log file"
94 echo " -f FLAVOR : build a specific package flavor"
95 echo " -h : print this help text"
96 echo " -a ARCH : build 32/64 bit only, or both (default: both)"
97 echo " -d DEPVER : specify an extra dependency version (no default)"
98 }
99
100 #############################################################################
101 # Log output of a command to a file
102 #############################################################################
103 logcmd() {
104 if [[ -z "$SCREENOUT" ]]; then
105 echo Running: "$@" >> $LOGFILE
106 "$@" >> $LOGFILE 2>&1
107 else
108 echo Running: "$@" | tee $LOGFILE
109 "$@" | tee $LOGFILE 2>&1
110 fi
111 }
112 logmsg() {
113 echo "$@" >> $LOGFILE
114 echo "$@"
115 }
116 logerr() {
117 # Print an error message and ask the user if they wish to continue
118 logmsg $@
119 if [[ -z $BATCH ]]; then
120 ask_to_continue "An Error occured in the build. "
121 else
122 exit 1
123 fi
124 }
125 ask_to_continue() {
126 # Ask the user if they want to continue or quit
127 echo -n "${1}Do you wish to continue anyway? (y/n) "
128 read
129 while [[ ! "$REPLY" =~ [yYnN] ]]; do
130 echo -n "continue? (y/n) "
131 read
132 done
133 if [[ "$REPLY" == "n" || "$REPLY" == "N" ]]; then
134 logmsg "===== Build aborted ====="
135 exit 1
136 fi
137 logmsg "===== User elected to continue after prompt. ====="
138 }
139
140 #############################################################################
141 # URL encoding for package names, at least
142 #############################################################################
143 # This isn't real URL encoding, just a couple of common substitutions
144 url_encode() {
145 [ $# -lt 1 ] && logerr "Not enough arguments to url_encode(). Expecting a string to encode."
146 local encoded="$1";
147 encoded=`echo $encoded | sed -e 's!/!%2F!g' -e 's!+!%2B!g'`
148 encoded=`echo $encoded | sed -e 's/%../_/g;'`
149 echo $encoded
150 }
151
152 #############################################################################
153 # Some initialization
154 #############################################################################
155 # Set the LANG to C as the assembler will freak out on unicode in headers
156 LANG=C
157 export LANG
158 # Determine what release we're running as that affects some versions of things
159 RELEASE=$(head -1 /etc/release | awk '{ print $3 }')
160 # Set the path - This can be overriden/extended in the build script
161 PATH="/usr/ccs/bin:/usr/bin:/usr/sbin:/usr/gnu/bin:/usr/sfw/bin"
162 case ${RELEASE:1} in
163 151004)
164 PATH="/opt/gcc-4.6.3/bin:$PATH"
165 GCC_CMD="/opt/gcc-4.6.3/bin/gcc"
166 GCC_PKG="developer/gcc46"
167 ;;
168 151006)
169 PATH="/opt/gcc-4.7.2/bin:$PATH"
170 GCC_CMD="/opt/gcc-4.7.2/bin/gcc"
171 GCC_PKG="developer/gcc47"
172 ;;
173 151008|151010|151012|151014)
174 PATH="/opt/gcc-4.8.1/bin:$PATH"
175 GCC_CMD="/opt/gcc-4.8.1/bin/gcc"
176 GCC_PKG="developer/gcc48"
177 ;;
178 151016)
179 PATH="/opt/gcc-5.1.0/bin:$PATH"
180 GCC_CMD="/opt/gcc-5.1.0/bin/gcc"
181 GCC_PKG="developer/gcc51"
182 ;;
183 *)
184 logerr "Release $RELEASE not supported for omniti-ms"
185 ;;
186 esac
187 export PATH
188 # The dir where this file is located - used for sourcing further files
189 MYDIR=$PWD/`dirname $BASH_SOURCE[0]`
190 # The dir where this file was sourced from - this will be the directory of the
191 # build script
192 SRCDIR=$PWD/`dirname $0`
193
194 #############################################################################
195 # Load configuration options
196 #############################################################################
197 . $MYDIR/config.sh
198 . $MYDIR/site.sh
199
200 # Platform information
201 SUNOSVER=`uname -r` # e.g. 5.11
202
203 if [[ -f $LOGFILE ]]; then
204 mv $LOGFILE $LOGFILE.1
205 fi
206 process_opts $@
207
208 BasicRequirements(){
209 local needed=""
210 [[ -x $GCC_CMD ]] || needed+=" $GCC_PKG"
211 [[ -x /usr/bin/ar ]] || needed+=" developer/object-file"
212 [[ -x /usr/bin/ld ]] || needed+=" developer/linker"
213 [[ -f /usr/lib/crt1.o ]] || needed+=" developer/library/lint"
214 [[ -x /usr/bin/gmake ]] || needed+=" developer/build/gnu-make"
215 [[ -f /usr/include/sys/types.h ]] || needed+=" system/header"
216 [[ -f /usr/include/math.h ]] || needed+=" system/library/math/header-math"
217 [[ -x /usr/bin/rsync ]] || needed+=" network/rsync"
218 if [[ -n "$needed" ]]; then
219 logmsg "You appear to be missing some basic build requirements."
220 logmsg "To fix this run:"
221 logmsg " "
222 logmsg " sudo pkg install$needed"
223 logerr
224 fi
225 }
226 BasicRequirements
227
228 #############################################################################
229 # Running as root is not safe
230 #############################################################################
231 if [[ "$UID" = "0" ]]; then
232 logerr "--- You cannot run this as root"
233 fi
234
235 #############################################################################
236 # Print startup message
237 #############################################################################
238 [[ -z "$NOBANNER" ]] && logmsg "===== Build started at `date` ====="
239 #############################################################################
240 # Initialization function
241 #############################################################################
242 init() {
243 # Print out current settings
244 logmsg "Package name: $PKG"
245
246 # In the ms.omniti.com repo, we want all pkg FMRIs to start with "omniti/"
247 FMRI_PREFIX=${PKG:0:7}
248 if [[ ! $FMRI_PREFIX = "omniti/" ]]; then
249 logerr "Package name should begin with \"omniti/\". Please change the value of PKG in the build script."
250 fi
251
252 # Selected flavor
253 if [[ -z "$FLAVOR" ]]; then
254 logmsg "Selected flavor: None (use -f to specify a flavor)"
255 else
256 logmsg "Selected Flavor: $FLAVOR"
257 fi
258 if [[ -n "$OLDFLAVOR" && "$OLDFLAVOR" != "$FLAVOR" ]]; then
259 logmsg "NOTICE - The flavor was overridden by the build script."
260 logmsg "The flavor specified on the command line was: $OLDFLAVOR"
261 fi
262 # Build arch
263 logmsg "Selected build arch: $BUILDARCH"
264 if [[ -n "$OLDBUILDARCH" && "$OLDBUILDARCH" != "$BUILDARCH" ]]; then
265 logmsg "NOTICE - The build arch was overridden by the build script."
266 logmsg "The build arch specified on the command line was: $OLDFLAVOR"
267 fi
268 # Extra dependency version
269 if [[ -z "$DEPVER" ]]; then
270 logmsg "Extra dependency: None (use -d to specify a version)"
271 else
272 logmsg "Extra dependency: $DEPVER"
273 fi
274 # Ensure SUMMARY and DESC are non-empty
275 if [[ -z "$SUMMARY" ]]; then
276 logerr "SUMMARY may not be empty. Please update your build script"
277 elif [[ -z "$DESC" ]]; then
278 logerr "DESC may not be empty. Please update your build script"
279 fi
280
281 # BUILDDIR can be used to manually specify what directory the program is
282 # built in (i.e. what the tarball extracts to). This defaults to the name
283 # and version of the program, which works in most cases.
284 if [[ -z $BUILDDIR ]]; then
285 BUILDDIR=$PROG-$VER
286 fi
287
288 RPATH=`echo $PKGSRVR | sed -e 's/^file:\/*/\//'`
289 if [[ "$RPATH" != "$PKGSRVR" ]]; then
290 if [[ ! -d $RPATH ]]; then
291 pkgrepo create $RPATH || \
292 logerr "Could not local repo"
293 pkgrepo add-publisher -s $RPATH $PKGPUBLISHER || \
294 logerr "Could not set publisher on repo"
295 fi
296 fi
297 pkgrepo get -s $PKGSRVR > /dev/null 2>&1 || \
298 logerr "The PKGSRVR ($PKGSRVR) isn't available. All is doomed."
299 verify_depends
300 }
301
302 #############################################################################
303 # Verify any dependencies
304 #############################################################################
305 verify_depends() {
306 logmsg "Verifying build dependencies"
307 [[ -z "$BUILD_DEPENDS_IPS" ]] && BUILD_DEPENDS_IPS=$BUILD_DEPENDS
308 for i in $BUILD_DEPENDS_IPS; do
309 # Trim indicators to get the true name (see make_package for details)
310 case ${i:0:1} in
311 \=|\?)
312 i=${i:1}
313 ;;
314 \-)
315 # If it's an exclude, we should error if it's installed rather than missing
316 i=${i:1}
317 pkg info $i > /dev/null 2<&1 &&
318 logerr "--- Excluded dependency $i cannot be installed with this package."
319 continue
320 ;;
321 esac
322 pkg info $i > /dev/null 2<&1 ||
323 logerr "--- Build dependency $i not found"
324 done
325 }
326
327 #############################################################################
328 # People that need this should call it explicitly
329 #############################################################################
330 run_autoconf() {
331 logmsg "Running autoconf"
332 pushd $TMPDIR/$BUILDDIR > /dev/null
333 logcmd autoconf || logerr "Failed to run autoconf"
334 popd > /dev/null
335 }
336
337 run_autogen() {
338 logmsg "Running autogen.sh"
339 pushd $TMPDIR/$BUILDDIR > /dev/null
340 CFLAGS="$CFLAGS32 $CFLAGS" \
341 CXXFLAGS="$CXXFLAGS32 $CXXFLAGS" \
342 CPPFLAGS="$CPPFLAGS32 $CPPFLAGS" \
343 LDFLAGS="$LDFLAGS32 $LDFLAGS" \
344 CC=$CC CXX=$CXX \
345 logcmd ./autogen.sh $CONFIGURE_OPTS_32 $CONFIGURE_OPTS_64 $CONFIGURE_OPTS || \
346 logerr "Failed to run autogen.sh"
347 popd > /dev/null
348 }
349
350 #############################################################################
351 # Stuff that needs to be done/set before we start building
352 #############################################################################
353 prep_build() {
354 logmsg "Preparing for build"
355
356 # Get the current date/time for the package timestamp
357 DATETIME=`TZ=UTC /usr/bin/date +"%Y%m%dT%H%M%SZ"`
358
359 logmsg "--- Creating temporary install dir"
360 # We might need to encode some special chars
361 PKGE=$(url_encode $PKG)
362 # For DESTDIR the '%' can cause problems for some install scripts
363 PKGD=${PKGE//%/_}
364 DESTDIR=$DTMPDIR/${PKGD}_pkg
365 if [[ -z $DONT_REMOVE_INSTALL_DIR ]]; then
366 logcmd chmod -R u+w $DESTDIR > /dev/null 2>&1
367 logcmd rm -rf $DESTDIR || \
368 logerr "Failed to remove old temporary install dir"
369 mkdir -p $DESTDIR || \
370 logerr "Failed to create temporary install dir"
371 fi
372 }
373
374 #############################################################################
375 # Applies patches contained in $PATCHDIR (default patches/)
376 #############################################################################
377 check_for_patches() {
378 if [[ -z $1 ]]; then
379 logmsg "Checking for patches in $PATCHDIR/"
380 else
381 logmsg "Checking for patches in $PATCHDIR/ ($1)"
382 fi
383 if [[ ! -d $SRCDIR/$PATCHDIR ]]; then
384 logmsg "--- No patches directory found"
385 return 1
386 fi
387 if [[ ! -f $SRCDIR/$PATCHDIR/series ]]; then
388 logmsg "--- No series file (list of patches) found"
389 return 1
390 fi
391 return 0
392 }
393
394 patch_source() {
395 if ! check_for_patches "in order to apply them"; then
396 logmsg "--- Not applying any patches"
397 else
398 logmsg "Applying patches"
399 # Read the series file for patch filenames
400 exec 3<"$SRCDIR/$PATCHDIR/series" # Open the series file with handle 3
401 pushd $TMPDIR/$BUILDDIR > /dev/null
402 while read LINE <&3 ; do
403 # Split Line into filename+args
404 patch_file $LINE
405 done
406 popd > /dev/null
407 exec 3<&- # Close the file
408 fi
409 }
410
411 patch_file() {
412 FILENAME=$1
413 shift
414 ARGS=$@
415 if [[ ! -f $SRCDIR/$PATCHDIR/$FILENAME ]]; then
416 logmsg "--- Patch file $FILENAME not found. Skipping patch."
417 return
418 fi
419 # Note - if -p is specified more than once, then the last one takes
420 # precedence, so we can specify -p1 at the beginning to default to -p1.
421 # -t - don't ask questions
422 # -N - don't try to apply a reverse patch
423 if ! logcmd $PATCH -p1 -t -N $ARGS < $SRCDIR/$PATCHDIR/$FILENAME; then
424 logerr "--- Patch $FILENAME failed"
425 else
426 logmsg "--- Applied patch $FILENAME"
427 fi
428 }
429
430 #############################################################################
431 # Download source from git
432 #############################################################################
433 # Parameters
434 # $1 - repos
435 # $2 - branch
436 # $3 - commit
437 # $4 - version
438 #
439 # E.g.
440 # download_git https://github.com/omniti-labs/nab master HEAD
441 download_git() {
442 local REPOS=$1
443 local BRANCH=$2
444 local COMMIT=$3
445 local VERSION=$4
446 if [ -n "$BRANCH" ]; then
447 BRANCH="master"
448 fi
449 if [ -n "$COMMIT" ]; then
450 COMMIT="HEAD"
451 fi
452 pushd $TMPDIR > /dev/null
453 logmsg "Checking for source directory"
454 if [ -d $BUILDDIR ]; then
455 logmsg "--- removing previous source checkout"
456 logcmd rm -rf $BUILDDIR
457 fi
458 logmsg "Checking code out from git repo"
459 logcmd $GIT clone $REPOS $BUILDDIR
460 pushd $BUILDDIR > /dev/null
461 if [ -n "$COMMIT" ]; then
462 logcmd $GIT checkout $COMMIT
463 fi
464 if [ -n "$VERSION" ]; then
465 VER=$VERSION
466 VERHUMAN=$VER
467 else
468 REV=`$GIT log -1 --format=format:%at`
469 REVDATE=`echo $REV | gawk '{ print strftime("%c %Z",$1) }'`
470 VER=0.1.$REV
471 VERHUMAN="checkout from $REVDATE"
472 fi
473 popd > /dev/null
474 popd > /dev/null
475 }
476
477 #############################################################################
478 # Download source tarball if needed and extract it
479 #############################################################################
480 # Parameters
481 # $1 - directory name on the server
482 # $2 - program name
483 # $3 - program version
484 # $4 - target directory
485 #
486 # E.g.
487 # download_source myprog myprog 1.2.3 will try:
488 # http://mirrors.omniti.com/myprog/myprog-1.2.3.tar.gz
489 download_source() {
490 local DLDIR=$1
491 local PROG=$2
492 local VER=$3
493 local TARGETDIR=$4
494 if [[ -z $VER ]]; then
495 local ARCHIVEPREFIX=$PROG
496 else
497 local ARCHIVEPREFIX=$PROG-$VER
498 fi
499 if [[ -z $TARGETDIR ]]; then
500 # Default to $TMPDIR if no output dir specified
501 TARGETDIR=$TMPDIR
502 fi
503 # Create TARGETDIR if it doesn't exist
504 if [[ ! -d $TARGETDIR ]]; then
505 logmsg "Specified target directory $TARGETDIR does not exist. Creating it now."
506 logcmd mkdir -p $TARGETDIR
507 fi
508 pushd $TARGETDIR > /dev/null
509 logmsg "Checking for source directory"
510 if [ -d $BUILDDIR ]; then
511 logmsg "--- Source directory found"
512 if check_for_patches "to see if we need to remove the source dir"; then
513 logmsg "--- Patches are present, removing source directory"
514 logcmd rm -rf $BUILDDIR || \
515 logerr "Failed to remove source directory"
516 else
517 logmsg "--- Patches are not present, keeping source directory"
518 popd > /dev/null
519 return
520 fi
521 else
522 logmsg "--- Source directory not found"
523 fi
524
525 # If we reach this point, the source directory was either not found, or it
526 # was removed due to patches being present.
527 logmsg "Checking for $PROG source archive"
528 find_archive $ARCHIVEPREFIX FILENAME
529 if [[ "$FILENAME" == "" ]]; then
530 # Try all possible archive names
531 logmsg "--- Archive not found."
532 logmsg "Downloading archive"
533 URLPREFIX=http://$MIRROR/$DLDIR/$ARCHIVEPREFIX
534 $WGET -a $LOGFILE $URLPREFIX.tar.gz || \
535 $WGET -a $LOGFILE $URLPREFIX.tar.bz2 || \
536 $WGET -a $LOGFILE $URLPREFIX.tar.xz || \
537 $WGET -a $LOGFILE $URLPREFIX.tgz || \
538 $WGET -a $LOGFILE $URLPREFIX.tbz || \
539 $WGET -a $LOGFILE $URLPREFIX.tar || \
540 logerr "--- Failed to download file"
541 find_archive $ARCHIVEPREFIX FILENAME
542 if [[ "$FILENAME" == "" ]]; then
543 logerr "Unable to find downloaded file."
544 fi
545 else
546 logmsg "--- $PROG source archive found"
547 fi
548 # Extract the archive
549 logmsg "Extracting archive: $FILENAME"
550 if ! logcmd extract_archive $FILENAME; then
551 logerr "--- Unable to extract archive."
552 fi
553 # Make sure the archive actually extracted some source where we expect
554 if [[ ! -d $BUILDDIR ]]; then
555 logerr "--- Extracted source is not in the expected location" \
556 " ($BUILDDIR)"
557 fi
558 popd > /dev/null
559 }
560
561 # Finds an existing archive and stores its value in a variable whose name
562 # is passed as a second parameter
563 # Example: find_archive myprog-1.2.3 FILENAME
564 # Stores myprog-1.2.3.tar.gz in $FILENAME
565 find_archive() {
566 FILES=`ls $1.{tar.bz2,tar.gz,tar.xz,tgz,tbz,tar} 2>/dev/null`
567 FILES=${FILES%% *} # Take only the first filename returned
568 # This dereferences the second parameter passed
569 eval "$2=\"$FILES\""
570 }
571
572 # Extracts an archive regardless of its extension
573 extract_archive() {
574 if [[ ${1: -7} == ".tar.gz" || ${1: -4} == ".tgz" ]]; then
575 $GZIP -dc $1 | $TAR xvf -
576 elif [[ ${1: -8} == ".tar.bz2" || ${1: -4} == ".tbz" ]]; then
577 $BUNZIP2 -dc $1 | $TAR xvf -
578 elif [[ ${1: -7} == ".tar.xz" ]]; then
579 $XZCAT $1 | $TAR xvf -
580 elif [[ ${1: -4} == ".tar" ]]; then
581 $TAR xvf $1
582 else
583 return 1
584 fi
585 }
586
587 #############################################################################
588 # Make the package
589 #############################################################################
590 make_package() {
591 logmsg "Making package"
592 PKGSEND=/usr/bin/pkgsend
593 PKGDEPEND=/usr/bin/pkgdepend
594 PKGMOGRIFY=/usr/bin/pkgmogrify
595 PKGFMT=/usr/bin/pkgfmt
596 P5M_INT=$TMPDIR/${PKGE}.p5m.int
597 P5M_FINAL=$TMPDIR/${PKGE}.p5m
598 GLOBAL_MOG_FILE=$MYDIR/global-transforms.mog
599 MY_MOG_FILE=$TMPDIR/${PKGE}.mog
600
601 ## Strip leading zeros in version components.
602 VER=`echo $VER | sed -e 's/\.0*\([1-9]\)/.\1/g;'`
603 FMRI="${PKG}@${VER},${SUNOSVER}-${PVER}"
604 if [[ -n "$DESTDIR" ]]; then
605 logmsg "--- Generating package manifest from $DESTDIR"
606 logmsg "------ Running: $PKGSEND generate $DESTDIR > $P5M_INT"
607 $PKGSEND generate $DESTDIR > $P5M_INT || \
608 logerr "------ Failed to generate manifest"
609 else
610 logmsg "--- Looks like a meta-package. Creating empty manifest"
611 logcmd touch $P5M_INT || \
612 logerr "------ Failed to create empty manifest"
613 fi
614 logmsg "--- Generating package metadata"
615 echo "set name=pkg.fmri value=$FMRI" > $MY_MOG_FILE
616 # Set human-readable version, if it exists
617 if [[ -n "$VERHUMAN" ]]; then
618 logmsg "------ Setting human-readable version"
619 echo "set name=pkg.human-version value=\"$VERHUMAN\"" >> $MY_MOG_FILE
620 fi
621 echo "set name=pkg.summary value=\"$SUMMARY\"" >> $MY_MOG_FILE
622 echo "set name=pkg.descr value=\"$DESC\"" >> $MY_MOG_FILE
623 echo "set name=publisher value=\"sa@omniti.com\"" >> $MY_MOG_FILE
624 if [[ -n "$DEPENDS_IPS" ]]; then
625 logmsg "------ Adding dependencies"
626 for i in $DEPENDS_IPS; do
627 # IPS dependencies have multiple types, of which we care about four:
628 # require, optional, incorporate, exclude
629 # For backward compatibility, assume no indicator means type=require
630 # FMRI attributes are implicitly rooted so we don't have to prefix
631 # 'pkg:/' or worry about ambiguities in names
632 local DEPTYPE="require"
633 case ${i:0:1} in
634 \=)
635 DEPTYPE="incorporate"
636 i=${i:1}
637 ;;
638 \?)
639 DEPTYPE="optional"
640 i=${i:1}
641 ;;
642 \-)
643 DEPTYPE="exclude"
644 i=${i:1}
645 ;;
646 esac
647 echo "depend type=$DEPTYPE fmri=${i}" >> $MY_MOG_FILE
648 done
649 fi
650 if [[ -f $SRCDIR/local.mog ]]; then
651 LOCAL_MOG_FILE=$SRCDIR/local.mog
652 fi
653 logmsg "--- Applying transforms"
654 $PKGMOGRIFY $P5M_INT $MY_MOG_FILE $GLOBAL_MOG_FILE $LOCAL_MOG_FILE $* > $P5M_INT.stage1
655 if [[ -z "$NO_AUTO_DEPENDS" ]]; then
656 $PKGDEPEND generate -d $DESTDIR $P5M_INT.stage1 > $P5M_INT.dep
657 $PKGDEPEND resolve $P5M_INT.dep
658 cat $P5M_INT.dep.res >> $P5M_INT.stage1
659 # Use a "require" dependency on the 'entire' metapackage so that
660 # we don't let a later version for an unsupported early OmniOS install.
661 # For example:
662 # foo@1.9-0.151006 exists.
663 # We update it to:
664 # foo@1.10-0.151014
665 # and in both cases make it *require* entire@11-0.151XXX as appropriate.
666 # So foo@1.10 won't install on any OmniOS older than r151014.
667 # This used to be *incorporate* but that put both a floor AND a ceiling
668 # on the revision of OmniOS, and having just a floor is sufficient
669 # thanks to illumos's versioned libraries and backward compatibility.
670 echo "depend fmri=pkg:/entire@11-$PVER type=require" >> $P5M_INT.stage1
671 fi
672 $PKGFMT -u < $P5M_INT.stage1 > $P5M_FINAL
673 logmsg "--- Publishing package to $PKGSRVR"
674 if [[ -z "$BATCH" ]]; then
675 ask_to_continue "Last chance to sanity-check before publication! "
676 fi
677 if [[ -n "$DESTDIR" ]]; then
678 logcmd $PKGSEND -s $PKGSRVR publish -d $DESTDIR -d $TMPDIR/$BUILDDIR \
679 -d $SRCDIR -T \*.py $P5M_FINAL || \
680 logerr "------ Failed to publish package"
681 else
682 # If we're a metapackage (no DESTDIR) then there are no directories to check
683 logcmd $PKGSEND -s $PKGSRVR publish $P5M_FINAL || \
684 logerr "------ Failed to publish package"
685 fi
686 logmsg "--- Published $FMRI"
687 }
688
689 #############################################################################
690 # Make isaexec stub binaries
691 #############################################################################
692 make_isa_stub() {
693 logmsg "Making isaexec stub binaries"
694 [[ -z $ISAEXEC_DIRS ]] && ISAEXEC_DIRS="bin sbin"
695 for DIR in $ISAEXEC_DIRS; do
696 if [[ -d $DESTDIR$PREFIX/$DIR ]]; then
697 logmsg "--- $DIR"
698 pushd $DESTDIR$PREFIX/$DIR > /dev/null
699 make_isaexec_stub_arch $ISAPART
700 make_isaexec_stub_arch $ISAPART64
701 popd > /dev/null
702 fi
703 done
704 }
705
706 make_isaexec_stub_arch() {
707 for file in $1/*; do
708 [[ -f $file ]] || continue # Deals with empty dirs & non-files
709 # Check to make sure we don't have a script
710 read -n 5 < $file
711 file=`echo $file | sed -e "s/$1\///;"`
712 # Skip if we already made a stub for this file
713 [[ -f $file ]] && continue
714 # Only copy non-binaries if we set NOSCRIPTSTUB
715 if [[ $REPLY != $'\177'ELF && -n "$NOSCRIPTSTUB" ]]; then
716 logmsg "------ Non-binary file: $file - copying instead"
717 cp $1/$file .
718 chmod +x $file
719 continue
720 fi
721 logmsg "------ $file"
722 # Run the makeisa.sh script
723 CC=$CC \
724 logcmd $MYDIR/makeisa.sh $PREFIX/$DIR $file || \
725 logerr "--- Failed to make isaexec stub for $DIR/$file"
726 done
727 }
728
729 #############################################################################
730 # Build commands
731 #############################################################################
732 # Notes:
733 # - These methods are designed to work in the general case.
734 # - You can set CFLAGS/LDFLAGS (and CFLAGS32/CFLAGS64 for arch specific flags)
735 # - Configure flags are set in CONFIGURE_OPTS_32 and CONFIGURE_OPTS_64 with
736 # defaults set in config.sh. You can append to these variables or replace
737 # them if the defaults don't work for you.
738 # - In the normal case, where you just want to add --enable-feature, set
739 # CONFIGURE_OPTS. This will be appended to the end of CONFIGURE_CMD
740 # for both 32 and 64 bit builds.
741 # - Any of these functions can be overriden in your build script, so if
742 # anything here doesn't apply to the build process for your application,
743 # just override that function with whatever code you need. The build
744 # function itself can be overriden if the build process doesn't fit into a
745 # configure, make, make install pattern.
746 #############################################################################
747 make_clean() {
748 logmsg "--- make (dist)clean"
749 logcmd $MAKE distclean || \
750 logcmd $MAKE clean || \
751 logmsg "--- *** WARNING *** make (dist)clean Failed"
752 }
753
754 configure32() {
755 logmsg "--- configure (32-bit)"
756 CFLAGS="$CFLAGS32 $CFLAGS" \
757 CXXFLAGS="$CXXFLAGS32 $CXXFLAGS" \
758 CPPFLAGS="$CPPFLAGS32 $CPPFLAGS" \
759 LDFLAGS="$LDFLAGS32 $LDFLAGS" \
760 CC=$CC CXX=$CXX \
761 logcmd $CONFIGURE_CMD $CONFIGURE_OPTS_32 \
762 $CONFIGURE_OPTS || \
763 logerr "--- Configure failed"
764 }
765
766 configure64() {
767 logmsg "--- configure (64-bit)"
768 CFLAGS="$CFLAGS64 $CFLAGS" \
769 CXXFLAGS="$CXXFLAGS64 $CXXFLAGS" \
770 CPPFLAGS="$CPPFLAGS64 $CPPFLAGS" \
771 LDFLAGS="$LDFLAGS64 $LDFLAGS" \
772 CC=$CC CXX=$CXX \
773 logcmd $CONFIGURE_CMD $CONFIGURE_OPTS_64 \
774 $CONFIGURE_OPTS || \
775 logerr "--- Configure failed"
776 }
777
778 make_prog() {
779 [[ -n $NO_PARALLEL_MAKE ]] && MAKE_JOBS=""
780 logmsg "--- make"
781 logcmd $MAKE $MAKE_JOBS || \
782 logerr "--- Make failed"
783 }
784
785 make_prog32() {
786 make_prog
787 }
788
789 make_prog64() {
790 make_prog
791 }
792
793 make_install() {
794 logmsg "--- make install"
795 logcmd $MAKE DESTDIR=${DESTDIR} install || \
796 logerr "--- Make install failed"
797 }
798
799 make_install32() {
800 make_install
801 }
802
803 make_install64() {
804 make_install
805 }
806
807 make_pure_install() {
808 # Make pure_install for perl modules so they don't touch perllocal.pod
809 logmsg "--- make install (pure)"
810 logcmd $MAKE DESTDIR=${DESTDIR} pure_install || \
811 logerr "--- Make pure_install failed"
812 }
813
814 make_param() {
815 logmsg "--- make $@"
816 logcmd $MAKE "$@" || \
817 logerr "--- $MAKE $1 failed"
818 }
819
820 # Helper function that can be called by build scripts to make in a specific dir
821 make_in() {
822 [[ -z $1 ]] && logerr "------ Make in dir failed - no dir specified"
823 [[ -n $NO_PARALLEL_MAKE ]] && MAKE_JOBS=""
824 logmsg "------ make in $1"
825 logcmd $MAKE $MAKE_JOBS -C $1 || \
826 logerr "------ Make in $1 failed"
827 }
828
829 # Helper function that can be called by build scripts to install in a specific
830 # dir
831 make_install_in() {
832 [[ -z $1 ]] && logerr "--- Make install in dir failed - no dir specified"
833 logmsg "------ make install in $1"
834 logcmd $MAKE -C $1 DESTDIR=${DESTDIR} install || \
835 logerr "------ Make install in $1 failed"
836 }
837
838 build() {
839 if [[ $BUILDARCH == "32" || $BUILDARCH == "both" ]]; then
840 build32
841 fi
842 if [[ $BUILDARCH == "64" || $BUILDARCH == "both" ]]; then
843 build64
844 fi
845 }
846
847 build32() {
848 pushd $TMPDIR/$BUILDDIR > /dev/null
849 logmsg "Building 32-bit"
850 export ISALIST="$ISAPART"
851 make_clean
852 configure32
853 make_prog32
854 make_install32
855 popd > /dev/null
856 unset ISALIST
857 export ISALIST
858 }
859
860 build64() {
861 pushd $TMPDIR/$BUILDDIR > /dev/null
862 logmsg "Building 64-bit"
863 make_clean
864 configure64
865 make_prog64
866 make_install64
867 popd > /dev/null
868 }
869
870 #############################################################################
871 # Build function for python programs
872 #############################################################################
873 pre_python_32() {
874 logmsg "prepping 32bit python build"
875 }
876 pre_python_64() {
877 logmsg "prepping 64bit python build"
878 }
879 python_build() {
880 if [[ -z "$PYTHON" ]]; then logerr "PYTHON not set"; fi
881 if [[ -z "$PYTHONPATH" ]]; then logerr "PYTHONPATH not set"; fi
882 if [[ -z "$PYTHONLIB" ]]; then logerr "PYTHONLIB not set"; fi
883 logmsg "Building using python setup.py"
884 pushd $TMPDIR/$BUILDDIR > /dev/null
885
886 if [[ $BUILDARCH == "32" || $BUILDARCH == "both" ]]; then
887 buildpython32
888 fi
889 if [[ $BUILDARCH == "64" || $BUILDARCH == "both" ]]; then
890 buildpython64
891 fi
892 popd > /dev/null
893 }
894
895 buildpython32() {
896 ISALIST=i386
897 export ISALIST
898 pre_python_32
899 logmsg "--- setup.py (32) build"
900 CFLAGS="$CFLAGS32 $CFLAGS" \
901 CXXFLAGS="$CXXFLAGS32 $CXXFLAGS" \
902 CPPFLAGS="$CPPFLAGS32 $CPPFLAGS" \
903 LDFLAGS="$LDFLAGS32 $LDFLAGS" \
904 CC=$CC CXX=$CXX \
905 logcmd $PYTHON ./setup.py build ||
906 logerr "--- build failed"
907 logmsg "--- setup.py (32) install"
908 logcmd $PYTHON \
909 ./setup.py install --root=$DESTDIR ||
910 logerr "--- install failed"
911 }
912
913 buildpython64(){
914 ISALIST="amd64 i386"
915 export ISALIST
916 pre_python_64
917 logmsg "--- setup.py (64) build"
918 CFLAGS="$CFLAGS64 $CFLAGS" \
919 CXXFLAGS="$CXXFLAGS64 $CXXFLAGS" \
920 CPPFLAGS="$CPPFLAGS64 $CPPFLAGS" \
921 LDFLAGS="$LDFLAGS64 $LDFLAGS" \
922 CC=$CC CXX=$CXX \
923 logcmd $PYTHON ./setup.py build ||
924 logerr "--- build failed"
925 logmsg "--- setup.py (64) install"
926 logcmd $PYTHON \
927 ./setup.py install --root=$DESTDIR ||
928 logerr "--- install failed"
929 }
930
931 #############################################################################
932 # Build/test function for perl modules
933 #############################################################################
934 # Detects whether to use Build.PL or Makefile.PL
935 # Note: Build.PL probably needs Module::Build installed
936 #############################################################################
937 vendorizeperl() {
938 logcmd mv $DESTDIR/usr/perl5/lib/site_perl $DESTDIR/usr/perl5/vendor_perl || logerr "can't move to vendor_perl"
939 logcmd mkdir -p $DESTDIR/usr/perl5/${DEPVER}
940 logcmd mv $DESTDIR/usr/perl5/man $DESTDIR/usr/perl5/${DEPVER}/man || logerr "can't move perl man"
941 }
942
943 buildperl() {
944 if [[ -f $SRCDIR/${PROG}-${VER}.env ]]; then
945 logmsg "Sourcing environment file: $SRCDIR/${PROG}-${VER}.env"
946 source $SRCDIR/${PROG}-${VER}.env
947 fi
948 if [[ $BUILDARCH == "32" || $BUILDARCH == "both" ]]; then
949 buildperl32
950 fi
951 if [[ $BUILDARCH == "64" || $BUILDARCH == "both" ]]; then
952 buildperl64
953 fi
954 }
955
956 buildperl32() {
957 if [[ -f $SRCDIR/${PROG}-${VER}.env32 ]]; then
958 logmsg "Sourcing environment file: $SRCDIR/${PROG}-${VER}.env32"
959 source $SRCDIR/${PROG}-${VER}.env32
960 fi
961 pushd $TMPDIR/$BUILDDIR > /dev/null
962 logmsg "Building 32-bit"
963 export ISALIST="$ISAPART"
964 local OPTS
965 OPTS=${MAKEFILE_OPTS//_ARCH_/}
966 OPTS=${OPTS//_ARCHBIN_/$ISAPART}
967 if [[ -f Makefile.PL ]]; then
968 make_clean
969 makefilepl32 $OPTS
970 make_prog
971 [[ -n $PERL_MAKE_TEST ]] && make_param test
972 make_pure_install
973 elif [[ -f Build.PL ]]; then
974 build_clean
975 buildpl32 $OPTS
976 build_prog
977 [[ -n $PERL_MAKE_TEST ]] && build_test
978 build_install
979 fi
980 popd > /dev/null
981 unset ISALIST
982 export ISALIST
983 }
984
985 buildperl64() {
986 if [[ -f $SRCDIR/${PROG}-${VER}.env64 ]]; then
987 logmsg "Sourcing environment file: $SRCDIR/${PROG}-${VER}.env64"
988 source $SRCDIR/${PROG}-${VER}.env64
989 fi
990 pushd $TMPDIR/$BUILDDIR > /dev/null
991 logmsg "Building 64-bit"
992 local OPTS
993 OPTS=${MAKEFILE_OPTS//_ARCH_/$ISAPART64}
994 OPTS=${OPTS//_ARCHBIN_/$ISAPART64}
995 if [[ -f Makefile.PL ]]; then
996 make_clean
997 makefilepl64 $OPTS
998 make_prog
999 [[ -n $PERL_MAKE_TEST ]] && make_param test
1000 make_pure_install
1001 elif [[ -f Build.PL ]]; then
1002 build_clean
1003 buildpl64 $OPTS
1004 build_prog
1005 [[ -n $PERL_MAKE_TEST ]] && build_test
1006 build_install
1007 fi
1008 popd > /dev/null
1009 }
1010
1011 makefilepl32() {
1012 logmsg "--- Makefile.PL 32-bit"
1013 logcmd $PERL32 Makefile.PL PREFIX=$PREFIX $@ ||
1014 logerr "Failed to run Makefile.PL"
1015 }
1016
1017 makefilepl64() {
1018 logmsg "--- Makefile.PL 64-bit"
1019 logcmd $PERL64 Makefile.PL PREFIX=$PREFIX $@ ||
1020 logerr "Failed to run Makefile.PL"
1021 }
1022
1023 buildpl32() {
1024 logmsg "--- Build.PL 32-bit"
1025 logcmd $PERL32 Build.PL prefix=$PREFIX $@ ||
1026 logerr "Failed to run Build.PL"
1027 }
1028
1029 buildpl64() {
1030 logmsg "--- Build.PL 64-bit"
1031 logcmd $PERL64 Build.PL prefix=$PREFIX $@ ||
1032 logerr "Failed to run Build.PL"
1033 }
1034
1035 build_clean() {
1036 logmsg "--- Build (dist)clean"
1037 logcmd ./Build distclean || \
1038 logcmd ./Build clean || \
1039 logmsg "--- *** WARNING *** make (dist)clean Failed"
1040 }
1041
1042 build_prog() {
1043 logmsg "--- Build"
1044 logcmd ./Build ||
1045 logerr "Build failed"
1046 }
1047
1048 build_test() {
1049 logmsg "--- Build test"
1050 logcmd ./Build test ||
1051 logerr "Build test failed"
1052 }
1053
1054 build_install() {
1055 logmsg "--- Build install"
1056 logcmd ./Build pure_install --destdir=$DESTDIR || \
1057 logmsg "Build install failed"
1058 }
1059
1060 test_if_core() {
1061 logmsg "Testing whether $MODNAME is in core"
1062 logmsg "--- Ensuring ${PKG} is not installed"
1063 if logcmd pkg info ${PKG}; then
1064 logerr "------ Package ${PKG} appears to be installed. Please uninstall it."
1065 else
1066 logmsg "------ Not installed, good."
1067 fi
1068 if logcmd $PERL32 -M$MODNAME -e '1'; then
1069 # Module is in core, don't create a package
1070 logmsg "--- Module is in core for Perl $DEPVER. Not creating a package."
1071 exit 0
1072 else
1073 logmsg "--- Module is not in core for Perl $DEPVER. Continuing with build."
1074 fi
1075 }
1076
1077 #############################################################################
1078 # NPM build for node.js modules
1079 #############################################################################
1080 build_npm() {
1081 logmsg "Building module with npm"
1082 [[ -n "$NPM" ]] || NPM=/opt/omni/bin/npm
1083 pushd $TMPDIR > /dev/null
1084 if [[ -d node_modules ]]; then
1085 logcmd rm -rf node_modules
1086 fi
1087 logcmd $NPM install ${PROG}@${VER} --ws:verbose || \
1088 logerr "--- npm build failed"
1089 logmsg "Installing module into $DESTDIR"
1090 logcmd mkdir -p $DESTDIR$PREFIX/lib/node || \
1091 logerr "--- Unable to create destination directory"
1092 logcmd rsync -a node_modules/ $DESTDIR$PREFIX/lib/node/ || \
1093 logerr "--- Unable to copy files to destination directory"
1094 popd > /dev/null
1095 }
1096
1097 #############################################################################
1098 # Scan the destination install and strip the non-stipped ELF objects
1099 #############################################################################
1100 strip_install() {
1101 logmsg "Stripping installation"
1102 pushd $DESTDIR > /dev/null || logerr "Cannot change to installation directory"
1103 while read file
1104 do
1105 if [[ "$1" = "-x" ]]; then
1106 ACTION=$(file $file | grep ELF | egrep -v "(, stripped|debugging)")
1107 else
1108 ACTION=$(file $file | grep ELF | grep "not stripped")
1109 fi
1110 if [[ -n "$ACTION" ]]; then
1111 logmsg "------ stripping $file"
1112 MODE=$(stat -c %a "$file")
1113 logcmd chmod 644 "$file" || logerr "chmod failed: $file"
1114 logcmd strip $* "$file" || logerr "strip failed: $file"
1115 logcmd chmod $MODE "$file" || logerr "chmod failed: $file"
1116 fi
1117 done < <(find . -depth -type f)
1118 popd > /dev/null
1119 }
1120
1121 #############################################################################
1122 # Clean up and print Done message
1123 #############################################################################
1124 clean_up() {
1125 logmsg "Cleaning up"
1126 if [[ -z $DONT_REMOVE_INSTALL_DIR ]]; then
1127 logmsg "--- Removing temporary install directory $DESTDIR"
1128 logcmd chmod -R u+w $DESTDIR > /dev/null 2>&1
1129 logcmd rm -rf $DESTDIR || \
1130 logerr "Failed to remove temporary install directory"
1131 logmsg "--- Cleaning up temporary manifest and transform files"
1132 logcmd rm -f $P5M_INT $P5M_FINAL $MY_MOG_FILE || \
1133 logerr "Failed to remove temporary manifest and transform files"
1134 logmsg "Done."
1135 fi
1136 }
1137
1138 #############################################################################
1139 # Helper function that will let you save a predefined function so you can
1140 # override it and call it later
1141 #############################################################################
1142 save_function() {
1143 local ORIG_FUNC=$(declare -f $1)
1144 local NEWNAME_FUNC="$2${ORIG_FUNC#$1}"
1145 eval "$NEWNAME_FUNC"
1146 }
1147
1148 # Vim hints
1149 # vim:ts=4:sw=4:et: