Of course, that's not the Solaris main goals by nowadays as currently advertised. Nevertheless, against the vision one should get another system as a front-end to Solaris, I still prefer to also use Solaris as my front-end system because I also very much appreciate all the potential that Solaris has to offer in this area as well. But for that purpose I have to manually update several software to more current versions in order to keep pace with the modern world and natural evolution. It's true that Solaris 11.4 is promising a somewhat better catch-up with this, but still it doesn't seem to be among its main goals, of course! Solaris is huge and specially fitted to big-iron SPARC systems and I totally agree with this while I'm greatly delighted I still could enjoy it on my low-end toy x86_64 system.
SAFE HARBOUR / DISCLAMER
Please, note that I mean no Licenses, Rights or Copyright infringement at all in what I post here. It's just that I appreciate so much Solaris that I'd dream of (as if it were possible) having the best of many worlds merged on a single system. For instance, I would dream of something called GNU/Solaris somewhat as presented on Linux & GNU and somewhat in the sense of GNU's What's in a Name.Back to my manual additions and/or updates to Solaris 11.3 GA, I see that a great deal of GNU software is here and there. Even the standard distribution of Solaris 11 provides a dedicated /usr/gnu file-system (or directory) and a lot of IPS packages for that. In pursuing these manual additions and/or updates I set to a sort of building lab which I "creatively" ;-) called Stage Building.
At first, to play it safe, I was trying to keep a very strong separation for the artifacts I was attempting to build, by putting them under the /opt file-system (or directory), more specifically under /opt/gnu as well as keeping other non-GNU such stuff at /opt/usr. I've imagined these locations in a clear contrast to the usual GNU/Linux practice of adopting /usr/local as described on the Filesystem Hierarchy Standard. But with the development of my lab I have realized it should be fine and even more attractive to follow the /usr/local convention (and as a separate dedicated ZFS file-system on my building machine) as a replacement for both /opt/gnu and /opt/usr as I was using until then.
/opt/gnu/opt/usr
- /usr/local
Furthermore, I was also adopting a whole building work-space hierarchy under /stage from which I may just reconsider the source subdirectory in favor of /usr/local/src (as a separated dedicated ZFS file-system in all cases) as follows:
$ l /stage
total 31
drwxrwxrwt 4 root root ... build
drwxrwxrwt 10 root root ... package
drwxrwxrwt 4 root root ... prototype
drwxrwxrwt 6 root root ...
drwxrwxrwt 3 root root ... test
One last minor revision I make is that I was initially providing both 32-bits and 64-bits ZFS file-systems for each kind of build. But it seems that, in practice, most often one is going to build just one of these bitness targets. Hence, I slightly tweak my script in order to just the required ZFS file-systems instead of always providing for both possibilities. For instance, if I set to build zlib 1.2.11, the script will have the option to create just the 32 (or 64) of the following:
$ l /stage/{build/zlib,prototype/zlib/1.2.11}
/stage/build/zlib:
total 16K
-rw-r--r-- 1 ... NOTES
-rw-r--r-- 1 ... setenv-1.2.11
-rw-r--r-- 1 ... unsetenv
drwxr-xr-x 14 ... zlib-1.2.11
drwxr-xr-x 14 ... zlib-1.2.11-32
/stage/prototype/zlib/1.2.11:
total 3.0K
drwxr-xr-x 2 ... 32
To summarize the reasons for these revisions:
- It seems to exist no negative impacts.
- It seems better integrated to the rest of the system.
- It seems better separated from the original /opt purpose.
- It's definitely more aligned with third-party software & tools.
- Simplification and standardization.
NOTE
The remaining assumptions from the outdated previous post Staged Building stay unchanged. For instance, at least the following delegated datasets must exist: /stage/build and /stage/prototype. At this point, /stage/package (for later IPS package creation) and specially /stage/test are optional.
My new gnu-build-preparation helper script will become:
#!/bin/bash -
################################################################
if [[ -z "$1" ]];
then
echo
echo "Usage: $0 <tarball> [<bit-target>]"
echo
exit 1
else
if ! [[ -f "$1" ]];
then
echo
echo "$1 not found."
echo
exit 1
fi
fi
if [[ -z "$2" ]];
then
echo "Preparing for both 32-bits and 64-bits."
echo "Otherwise, use: $0 \"$1\" <32 or 64>"
echo
else
if [[ "$2" -ne 32 ]] && [[ "$2" -ne 64 ]];
then
echo "Valid bit-targets: 32 or 64."
exit 1
fi
fi
################################################################
# This can be potentially better suited elsewhere
# as long as it doesn't break previous assumptions.
DS_BASE=rpool
DS_STAGE=${DS_BASE:+$DS_BASE/}stage
DS_BUILD=build
DS_PROTOTYPE=prototype
################################################################
#
# legacy gnu-coreutils IPS package lacks realpath
# TAR=$(realpath "$1")
#
TAR=$(readlink -f "$1")
A=$(basename $1 |\
sed 's/\(\w\+\([-.]\w\+\)*\)-.*/\1/')
V=$(basename $1 |\
sed 's/\w\+\([-.]\w\+\)*-\([0-9]\+\([_.-][0-9]\+\)*[a-z]*\).*/\2/')
BITNESS=$2
echo
echo Processing $TAR
echo
echo ------------------------------------
echo "App: $A"
echo "Ver: $V"
echo ------------------------------------
echo
echo In the process, the following ZFS datasets will be created:
echo
echo " $DS_STAGE/$DS_BUILD/$A"
echo " $DS_STAGE/$DS_BUILD/$A/$A-$V"
if [[ -z $BITNESS ]]; then
echo " $DS_STAGE/$DS_BUILD/$A/$A-$V-32"
echo " $DS_STAGE/$DS_BUILD/$A/$A-$V-64"
else
echo " $DS_STAGE/$DS_BUILD/$A/$A-$V-$BITNESS"
fi
echo
echo " $DS_STAGE/$DS_PROTOTYPE/$A"
echo " $DS_STAGE/$DS_PROTOTYPE/$A/$A-$V"
if [[ -z $BITNESS ]]; then
echo " $DS_STAGE/$DS_PROTOTYPE/$A/$A-$V/32"
echo " $DS_STAGE/$DS_PROTOTYPE/$A/$A-$V/64"
else
echo " $DS_STAGE/$DS_PROTOTYPE/$A/$A-$V/$BITNESS"
fi
echo
read -p "Enter \"y\" to proceed: " -r
if ! [[ "$REPLY" = "y" ]] && ! [[ "$REPLY" = "Y" ]];
then
echo "Exiting..."
exit 1
fi
################################################################
function dataset-exists()
{
zfs list -H "$1" >/dev/null 2>&1
local rv=$?
echo $rv
}
################################################################
function get-mountpoint()
{
echo $(zfs get -H -o value mountpoint "$1" 2>/dev/null)
}
################################################################
function dataset-assert-mounted()
{
if [[ -z $(get-mountpoint "$1") ]]; then
echo "Unexpected: \"$1\" doesn't seem to be mounted."
exit 1
fi
}
dataset-assert-mounted "$DS_STAGE"
dataset-assert-mounted "$DS_STAGE/$DS_BUILD"
dataset-assert-mounted "$DS_STAGE/$DS_PROTOTYPE"
################################################################
function create-source-area()
{
if [[ $(dataset-exists "$1") -eq 1 ]]; then
echo "Creating $1..."
zfs create "$1"
else
local MP=$(get-mountpoint "$1")
if [[ $(basename "$MP") == "$A" ]]; then
echo "No need to create $1."
else
echo
echo "$1 mounted as $MP."
echo "No further action can be safely taken."
echo "Exiting..."
exit 1
fi
fi
}
echo
create-source-area "$DS_STAGE/$DS_BUILD/$A"
create-source-area "$DS_STAGE/$DS_BUILD/$A/$A-$V"
################################################################
echo
DS_SOURCE="$DS_STAGE/$DS_BUILD/$A"
MP_SOURCE=$(get-mountpoint "$DS_SOURCE")
DS_SOURCE_VERSION="$DS_SOURCE/$A-$V"
MP_SOURCE_VERSION=$(get-mountpoint "$DS_SOURCE_VERSION")
if [[ $(ls -A "$MP_SOURCE_VERSION" 2>/dev/null) ]]; then
echo
echo "Directory $MP_SOURCE_VERSION not empty!"
echo "No further action can be safely taken."
echo "Exiting..."
exit 1
fi
(cd "$MP_SOURCE_VERSION/.."; gtar xf "$TAR")
if ! [[ $(ls -A "$MP_SOURCE_VERSION" 2>/dev/null) ]]; then
echo
echo "Directory $MP_SOURCE_VERSION shouldn't be empty!"
echo "No further action can be safely taken."
echo "Exiting..."
exit 1
fi
zfs snapshot "$DS_SOURCE_VERSION@source"
zfs set readonly=on "$DS_SOURCE_VERSION"
################################################################
function set-target()
{
local T=$1
# This may be inappropriate in some cases.
# Some "packages" require/prefer just an empty dataset.
zfs clone "$DS_SOURCE_VERSION"@source \
"$DS_SOURCE_VERSION-$T"
# This may be too soon.
# The "package" may need some manual fix before @start
zfs snapshot "$DS_SOURCE_VERSION-$T"@start
}
if [[ -z $BITNESS ]]; then
set-target 32
set-target 64
else
set-target $BITNESS
fi
################################################################
zfs list -H -r -t all -o name "$DS_SOURCE"
################################################################
#
# Create the final resting place of the results.
# Use an independent ZFS pool/dataset, not rpool/VARSHARE.
# At end consider snapshoting, just in case.
# Could be a staging area for packaging.
#
DS_ARTIFACT="$DS_STAGE/$DS_PROTOTYPE/$A"
DS_ARTIFACT_VERSION="$DS_ARTIFACT/$V"
echo
echo "Creating "$DS_ARTIFACT" subtree."
echo
function create-staging-area()
{
if [[ $(dataset-exists "$1") -eq 1 ]]; then
zfs create -p "$1"
fi
}
create-staging-area "$DS_ARTIFACT_VERSION"
if [[ -z $BITNESS ]]; then
create-staging-area "$DS_ARTIFACT_VERSION/32"
create-staging-area "$DS_ARTIFACT_VERSION/64"
else
create-staging-area "$DS_ARTIFACT_VERSION/$BITNESS"
fi
zfs list -H -r -t all -o name "$DS_ARTIFACT"
MP_PROTOTYPE=$(get-mountpoint "$DS_STAGE/$DS_PROTOTYPE")
################################################################
echo
echo "Creating pre-configuration script."
cat > "$MP_SOURCE/setenv-$V" <
#
# HOSTTYPE=$HOSTTYPE
# OSTYPE=$OSTYPE
# MACHTYPE=$MACHTYPE
#
# Up to Solaris 11.3 the default is 32-bits.
# MACHTYPE is typically i386-pc-solaris2.11
#
# Since Solaris 11.4 Beta the default is 64-bits.
# MACHTYPE is x86_64-pc-solaris2.11
#
# It's advisable not to override the above env vars
# buy you experiment with the --build or --target options
# to the standard GNU's configuration script: configure.
# (they are important to properly organize the built artifacts)
#
# Bottom line it seems that the -m option to the flags
# CFLAGS, CXXFLAGS and LDFLAGS always prevail after all.
# (in terms of the actual bitness of the built artifacts)
#
if [[ -z "\$1" ]];
then
echo "Usage: source setenv
return 1
else
if [[ "\$1" -ne 32 ]] && [[ "\$1" -ne 64 ]];
then
echo "Valid bit-targets: 32 or 64."
return 1
fi
fi
# Despite setting bitness as shown next
# DON'T override HOSTTYPE and MACHTYPE
# Just remind the proper --build option
BITS=\$1
echo
function add-path()
{
local COMPONENT="\$1"
if [[ -d "\$COMPONENT" ]] ;
then
! [[ "\$PATH" =~ "\$COMPONENT" ]] && \
export PATH="\$COMPONENT:\$PATH"
fi
}
function add-pkgconfig-path()
{
local COMPONENT="\$1"
local TAIL="\${PKG_CONFIG_PATH:+:\$PKG_CONFIG_PATH}"
if [[ -d "\$COMPONENT" ]] ;
then
! [[ "\$TAIL" =~ "\$COMPONENT" ]] && \
export PKG_CONFIG_PATH="\$COMPONENT\$TAIL"
fi
}
function extend-env()
{
# In this revision I'm only focusing on 64-bits.
# Hence, I'm omitting the bitness subfolder.
# local BASE="\$1/\$BITS"
local BASE="\$1"
add-path "\$BASE/bin"
add-pkgconfig-path "\$BASE/lib/pkgconfig"
}
add-path /usr/gnu/bin
#
# Other PATH and PKG_CONFIG_PATH settings.
# Put entries in reverse order of dependency.
# (following my PATH building suggestion)
# The samples below are pre-Solaris 11.4 Beta.
#
# ...
# extend-env /opt/...
# extend-env /usr/local
#
# RLE configuration
#
LIBBITS=\$([[ \$BITS -eq 32 ]] && echo "" || echo "/64")
RLEBITS=\$([[ \$BITS -eq 32 ]] && echo "" || echo "-64")
RLECFG="$MP_SOURCE/ld.config-\$BITS"
#
# /usr/local/lib is fixed for simplificity
# but could mimic the system /usr/gnu/lib and /usr/lib
# with a trailing /64 for 64-bits although this would complicate
# the 64-bits building with special prefixes for bin and lib.
#
crle \$RLEBITS \\
-c "\$RLECFG" \\
-l /usr/local/lib \\
-l /lib\$LIBBITS:/usr/lib\$LIBBITS
crle \$RLEBITS -c "\$RLECFG"
export LD_CONFIG_\$BITS="\$RLECFG"
echo LD_CONFIG_\$BITS="\$RLECFG"
echo
# In general, not a good idea; evaluate.
# export CONFIG_SHELL=/bin/bash
echo CONFIG_SHELL=\$CONFIG_SHELL
echo
#
# The following compilers and linker overrides
# may be troublesome, specially the -m and -std options
# as it may be very source dependent; evaluate.
# The -std bar minimums on Solaris 11 Express is gnu89 and gnu++98.
# The -std bar minimums on Solaris 11.3 is gnu89 and gnu++03.
# On Solaris 11.4 Beta gnu11 and gnu++11 seem Ok.
#
FLAGS="-m\$BITS -march=core2 -mtune=core2"
export CC=/usr/bin/gcc
export CFLAGS="\$FLAGS -std=gnu89"
echo CC=\$CC CFLAGS=\$CFLAGS
echo
export CXX=/usr/bin/g++
export CXXFLAGS="\$FLAGS -std=gnu++03"
echo CXX=\$CXX CXXFLAGS=\$CXXFLAGS
echo
export LD=/usr/bin/ld
export LDFLAGS="\$FLAGS"
echo LD=\$LD LDFLAGS=\$LDFLAGS
echo
echo PATH=\$PATH
echo
echo PKG_CONFIG_PATH=\$PKG_CONFIG_PATH
unset FLAGS
unset LIBBITS
unset RLEBITS
unset RLECFG
function get-target()
{
case \$BITS in
32)
echo i386-pc-solaris2.11
;;
64)
echo x86_64-pc-solaris2.11
;;
esac
}
echo
echo Suggested build sequence:
echo
echo Fine-tune/fix/tweak/hack source...
echo
echo \$ ./configure \\\\
echo " "--build=\$(get-target \$BITS) \\\\
echo " "--prefix=/usr/local \\\\
echo " "...
echo
echo \$ gmake -j\$(( \$(psrinfo |wc -l) - 1 ))
echo
echo \$ su
echo \# source ../setenv-$V \$BITS
echo
echo For IPS package:
echo
echo \# gmake DESTDIR=$MP_PROTOTYPE/$A/$V/\$BITS install
echo
echo For immediate use:
echo
echo \# gmake install
echo \# zfs snapshot -r .../usr/local@$A-$V
EOF
cat > "$MP_SOURCE/unsetenv-$V" <
function cleanup-env()
{
[[ -f "\$LD_CONFIG_32" ]] && rm "\$LD_CONFIG_32"
unset LD_CONFIG_32
[[ -f "\$LD_CONFIG_64" ]] && rm "\$LD_CONFIG_64"
unset LD_CONFIG_64
unset CONFIG_SHELL
unset CC
unset CFLAGS
unset CXX
unset CXXFLAGS
unset LD
unset LDFLAGS
unset PKG_CONFIG_PATH
export PATH=/usr/bin:/usr/sbin
unset -f add-path
unset -f add-pkgconfig-path
unset -f extend-env
unset -f cleanup-env
}
cleanup-env
EOF
touch "$MP_SOURCE/NOTES"
And this is certainly not the end of the story.