1#!/bin/bash 2# 3# Execute this tool to setup the environment and build binary releases 4# for xtrabackup starting from a fresh tree. 5# 6# Usage: build-binary.sh [target dir] 7# The default target directory is the current directory. If it is not 8# supplied and the current directory is not empty, it will issue an error in 9# order to avoid polluting the current directory after a test run. 10# 11 12# Bail out on errors, be strict 13set -ue 14 15# Examine parameters 16TARGET="$(uname -m)" 17TARGET_CFLAGS='' 18 19# Some programs that may be overriden 20TAR=${TAR:-tar} 21 22# Check if we have a functional getopt(1) 23if ! getopt --test 24then 25 go_out="$(getopt --options="i" --longoptions=i686 \ 26 --name="$(basename "$0")" -- "$@")" 27 test $? -eq 0 || exit 1 28 eval set -- $go_out 29fi 30 31for arg 32do 33 case "$arg" in 34 -- ) shift; break;; 35 -i | --i686 ) 36 shift 37 TARGET="i686" 38 TARGET_CFLAGS="-m32 -march=i686" 39 ;; 40 esac 41done 42 43# Working directory 44if test "$#" -eq 0 45then 46 WORKDIR="$(readlink -f $(dirname $0)/../../../../)" 47 48 # Check that the current directory is not empty 49 if test "x$(echo *)" != "x*" 50 then 51 echo >&2 \ 52 "Current directory is not empty. Use $0 . to force build in ." 53 exit 1 54 fi 55 56 WORKDIR_ABS="$(cd "$WORKDIR"; pwd)" 57 58elif test "$#" -eq 1 59then 60 WORKDIR="$1" 61 62 # Check that the provided directory exists and is a directory 63 if ! test -d "$WORKDIR" 64 then 65 echo >&2 "$WORKDIR is not a directory" 66 exit 1 67 fi 68 69 WORKDIR_ABS="$(cd "$WORKDIR"; pwd)" 70 71else 72 echo >&2 "Usage: $0 [target dir]" 73 exit 1 74 75fi 76 77SOURCEDIR="$(cd $(dirname "$0"); cd ../../../../; pwd)" 78test -e "$SOURCEDIR/XB_VERSION" || exit 2 79 80# Read version info from the XB_VERSION file 81. $SOURCEDIR/XB_VERSION 82 83XTRABACKUP_VERSION="${XB_VERSION_MAJOR}.${XB_VERSION_MINOR}.${XB_VERSION_PATCH}${XB_VERSION_EXTRA}" 84 85# Compilation flags 86export CC=${CC:-gcc} 87export CXX=${CXX:-g++} 88export CFLAGS=${CFLAGS:-} 89export CXXFLAGS=${CXXFLAGS:-} 90export MAKE_JFLAG=-j4 91 92# Create a temporary working directory 93PRODUCT_FULL="percona-xtrabackup-$XTRABACKUP_VERSION-$(uname -s)-$(uname -m)$GLIBC_VER" 94BASEINSTALLDIR="$(cd "$WORKDIR" && TMPDIR="$WORKDIR_ABS" mktemp -d xtrabackup-build.XXXXXX)" 95INSTALLDIR="$WORKDIR_ABS/$BASEINSTALLDIR/$PRODUCT_FULL" # Make it absolute 96 97mkdir "$INSTALLDIR" 98 99# Build 100( 101 cd "$WORKDIR" 102 103 # Build proper 104 ( 105 cd $SOURCEDIR 106 107 # Install the files 108 mkdir -p "$INSTALLDIR" 109 cmake -DBUILD_CONFIG=xtrabackup_release -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" \ 110 -DINSTALL_MYSQLTESTDIR=percona-xtrabackup-${XB_VERSION_MAJOR}.${XB_VERSION_MINOR}-test -DINSTALL_MANDIR=${INSTALLDIR}/man \ 111 -DDOWNLOAD_BOOST=1 -DWITH_BOOST=${WORKDIR_ABS}/libboost \ 112 -DMYSQL_UNIX_ADDR=/var/run/mysqld/mysqld.sock . 113 make $MAKE_JFLAG 114 make install 115 116 ) 117 exit_value=$? 118 119 if test "x$exit_value" = "x0" 120 then 121 cd $INSTALLDIR 122 123 LIBLIST="libgcrypt.so libcrypto.so libssl.so libsasl2.so libssl3.so libsmime3.so libnss3.so libnssutil3.so libplds4.so libplc4.so libnspr4.so" 124 DIRLIST="bin lib/private lib/plugin" 125 126 LIBPATH="" 127 128 function gather_libs { 129 local elf_path=$1 130 for lib in ${LIBLIST}; do 131 for elf in $(find ${elf_path} -maxdepth 1 -exec file {} \; | grep 'ELF ' | cut -d':' -f1); do 132 IFS=$'\n' 133 for libfromelf in $(ldd ${elf} | grep ${lib} | awk '{print $3}'); do 134 lib_realpath="$(readlink -f ${libfromelf})" 135 lib_realpath_basename="$(basename $(readlink -f ${libfromelf}))" 136 lib_without_version_suffix=$(echo ${lib_realpath_basename} | awk -F"." 'BEGIN { OFS = "." }{ print $1, $2}') 137 138 if [ ! -f "lib/private/${lib_realpath_basename}" ] && [ ! -L "lib/private/${lib_without_version_suffix}" ]; then 139 140 echo "Copying lib ${lib_realpath_basename}" 141 cp ${lib_realpath} lib/private 142 143 if [ ${lib_realpath_basename} != ${lib_without_version_suffix} ]; then 144 echo "Symlinking lib from ${lib_realpath_basename} to ${lib_without_version_suffix}" 145 cd lib/private 146 ln -s ${lib_realpath_basename} ${lib_without_version_suffix} 147 cd - 148 fi 149 150 patchelf --set-soname ${lib_without_version_suffix} lib/private/${lib_realpath_basename} 151 152 LIBPATH+=" $(echo ${libfromelf} | grep -v $(pwd))" 153 fi 154 done 155 unset IFS 156 done 157 done 158 } 159 160 function set_runpath { 161 # Set proper runpath for bins but check before doing anything 162 local elf_path=$1 163 local r_path=$2 164 for elf in $(find ${elf_path} -maxdepth 1 -exec file {} \; | grep 'ELF ' | cut -d':' -f1); do 165 echo "Checking LD_RUNPATH for ${elf}" 166 if [ -z $(patchelf --print-rpath ${elf}) ]; then 167 echo "Changing RUNPATH for ${elf}" 168 patchelf --set-rpath ${r_path} ${elf} 169 fi 170 done 171 } 172 173 function replace_libs { 174 local elf_path=$1 175 for libpath_sorted in ${LIBPATH}; do 176 for elf in $(find ${elf_path} -maxdepth 1 -exec file {} \; | grep 'ELF ' | cut -d':' -f1); do 177 LDD=$(ldd ${elf} | grep ${libpath_sorted}|head -n1|awk '{print $1}') 178 lib_realpath_basename="$(basename $(readlink -f ${libpath_sorted}))" 179 lib_without_version_suffix="$(echo ${lib_realpath_basename} | awk -F"." 'BEGIN { OFS = "." }{ print $1, $2}')" 180 if [[ ! -z $LDD ]]; then 181 echo "Replacing lib ${lib_realpath_basename} to ${lib_without_version_suffix} for ${elf}" 182 patchelf --replace-needed ${LDD} ${lib_without_version_suffix} ${elf} 183 fi 184 done 185 done 186 } 187 188 function check_libs { 189 local elf_path=$1 190 for elf in $(find ${elf_path} -maxdepth 1 -exec file {} \; | grep 'ELF ' | cut -d':' -f1); do 191 if ! ldd ${elf}; then 192 exit 1 193 fi 194 done 195 } 196 197 function link { 198 if [ ! -d lib/private ]; then 199 mkdir -p lib/private 200 fi 201 # Gather libs 202 for DIR in ${DIRLIST}; do 203 gather_libs ${DIR} 204 done 205 206 # Set proper runpath 207 set_runpath bin '$ORIGIN/../lib/private/' 208 set_runpath lib '$ORIGIN/private/' 209 set_runpath lib/plugin '$ORIGIN/../private/' 210 set_runpath lib/private '$ORIGIN' 211 212 # Replace libs 213 for DIR in ${DIRLIST}; do 214 replace_libs ${DIR} 215 done 216 217 # Make final check in order to determine any error after linkage 218 for DIR in ${DIRLIST}; do 219 check_libs ${DIR} 220 done 221 } 222 223 cd "$WORKDIR" 224 225 mkdir "$WORKDIR_ABS/$BASEINSTALLDIR/minimal" 226 cp -r "$WORKDIR_ABS/$BASEINSTALLDIR/$PRODUCT_FULL" "$WORKDIR_ABS/$BASEINSTALLDIR/minimal/$PRODUCT_FULL-minimal" 227 228 # NORMAL TARBALL 229 cd "$INSTALLDIR" 230 link 231 232 cd "$WORKDIR_ABS/$BASEINSTALLDIR/minimal/$PRODUCT_FULL-minimal" 233 rm -rf percona-xtrabackup-2.4-test 2> /dev/null 234 find . -type f -exec file '{}' \; | grep ': ELF ' | cut -d':' -f1 | xargs strip --strip-unneeded 235 link 236 237 cd "$WORKDIR" 238 $TAR czf "percona-xtrabackup-$XTRABACKUP_VERSION-$(uname -s)-$(uname -m)$GLIBC_VER.tar.gz" \ 239 --owner=0 --group=0 -C "$INSTALLDIR/../" \ 240 "percona-xtrabackup-$XTRABACKUP_VERSION-$(uname -s)-$(uname -m)$GLIBC_VER" 241 242 $TAR czf "percona-xtrabackup-$XTRABACKUP_VERSION-$(uname -s)-$(uname -m)$GLIBC_VER-minimal.tar.gz" \ 243 --owner=0 --group=0 -C "$INSTALLDIR/../minimal/" \ 244 "percona-xtrabackup-$XTRABACKUP_VERSION-$(uname -s)-$(uname -m)$GLIBC_VER-minimal" 245 fi 246 247 # Clean up build dir 248 rm -rf "percona-xtrabackup-$XTRABACKUP_VERSION-$(uname -s)-$(uname -m)$GLIBC_VER" 249 250 exit $exit_value 251 252) 253exit_value=$? 254 255# Clean up 256rm -rf "$WORKDIR_ABS/$BASEINSTALLDIR" 257 258exit $exit_value 259 260