Isoraqathedh

sbcl-build

Apr 14th, 2016
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 9.75 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. readonly SBCL_REPO="git://sbcl.git.sourceforge.net/gitroot/sbcl/sbcl.git"
  4. readonly BASE_DIR="/tmp/sbcl-git-build"
  5. readonly SOURCE_DIR="$BASE_DIR/src"
  6. readonly BUILD_DIR="$BASE_DIR/build"
  7. readonly CROSS_COMPILE_HOST="sbcl --disable-debugger --no-userinit --no-sysinit"
  8.  
  9. ########################################################################
  10. ## SCRIPT
  11. readonly PROGNAME=$(basename $0)
  12. readonly PROGDIR=$(readlink -m $(dirname $0))
  13. readonly ARGS="$@"
  14.  
  15. readonly DEFAULT_ACTIONS=(download prepare build install install-sources);
  16. readonly DEFAULT_ENABLED_FEATURES=":sb-thread :sb-safepoint :sb-thruption :sb-wtimer :sb-core-compression"
  17. readonly DEFAULT_DISABLED_FEATURES=":largefile :sb-ldb"
  18. readonly DEFAULT_DYNAMIC_SPACE_SIZE="1Gb"
  19. readonly DEFAULT_INSTALL_TARGET="/usr/local"
  20.  
  21. usage() {
  22.     cat <<- EOF
  23. usage: $PROGNAME options
  24.  
  25. Easily build and install SBCL from source.
  26.  
  27. Sources are downloaded to $SOURCE_DIR
  28. fetching them from        $SBCL_REPO
  29. and building them in      $BUILD_DIR
  30.  
  31. OPTIONS:
  32.     -a --actions     Specify the actions to perform, should be a
  33.                      space delimited string of the following choices:
  34.                        download prepare build test build-docs install install-sources cleanup
  35.                      Defaults to "${DEFAULT_ACTIONS[@]}"
  36.                      if -a, -b, and -i are not specified.
  37.     -b --build       Adds "download prepare build" to the actions.
  38.     -d --disable     Disable certain SBCL features.
  39.                      Defaults to "$DEFAULT_DISABLED_FEATURES"
  40.     -e --enable      Enable certain SBCL features.
  41.                      Defaults to "$DEFAULT_ENABLED_FEATURES"
  42.     -i --install     Adds "install install-sources" to the actions.
  43.     -t --target      Specify the directory to install SBCL to.
  44.                      Defaults to "$DEFAULT_INSTALL_TARGET"
  45.     -h --help        Display this help.
  46.  
  47. EOF
  48. }
  49.  
  50. contains_element() {
  51.     local e
  52.     for e in "${@:2}"; do
  53.         [ "$e" = "$1" ] && return 0;
  54.     done
  55.     return 1
  56. }
  57.  
  58. status() {
  59.     echo -e "\n\e[0;33m>> \e[0;32m" $@ "\e[0m"
  60.     sleep 1
  61. }
  62.  
  63. eexit() {
  64.     echo -e "\n\e[0;33m>> \e[0;31mError: " $@ "\e[0m"
  65.     exit 1
  66. }
  67.  
  68. try_run() {
  69.     echo "$1" | bash \
  70.         || eexit "$2"
  71. }
  72.  
  73. try_run_sudo() {
  74.     echo "$1" | sudo bash \
  75.         || eexit "$2"
  76. }
  77.  
  78. is_downloaded() {
  79.     return [ -d "$SOURCE_DIR" ]
  80. }
  81.  
  82. is_prepared() {
  83.     return [ -d "$BUILD_DIR" ]
  84. }
  85.  
  86. is_built() {
  87.     return [ -d "$BUILD_DIR/output" ]
  88. }
  89.  
  90. check_downloaded() {
  91.     [ ! is_downloaded ] \
  92.         && eexit "Sources are not available! Run `$PROGNAME -a download` first."
  93. }
  94.  
  95. check_prepared() {
  96.     [ ! is_prepared ] \
  97.          && eexit "Build directory is not available! Run `$PROGNAME -a prepare` first."
  98. }
  99.  
  100. check_built() {
  101.     [ ! is_built ] \
  102.         && eexit "SBCL has not been built yet! Run `$PROGNAME -a \"build\"` first."
  103. }
  104.  
  105. download_source() {
  106.     status "Downloading source..."
  107.     mkdir -p "$SOURCE_DIR"
  108.     if [ -d "$SOURCE_DIR/.git" ]; then
  109.         cd "$SOURCE_DIR"
  110.         git pull \
  111.             || eexit "Failed to download source."
  112.     else
  113.         git clone "$SBCL_REPO" "$SOURCE_DIR" \
  114.             || eexit "Failed to download source."
  115.     fi
  116. }
  117.  
  118. prepare_build() {
  119.     status "Preparing build..."
  120.     check_downloaded
  121.     [ -d "$BUILD_DIR" ] \
  122.         && cleanup_build
  123.     git clone "$SOURCE_DIR" "$BUILD_DIR" \
  124.         || eexit "Failed to prepare build."
  125.     cd "$BUILD_DIR"
  126.     cat >customize-target-features.lisp <<EOF
  127. (lambda (features)
  128.   (flet ((enable (x) (pushnew x features))
  129.          (disable (x) (setf features (remove x features))))
  130.     (dolist (feature '($ENABLED_FEATURES))
  131.       (enable feature))
  132.     (dolist (feature '($DISABLED_FEATURES))
  133.       (disable feature)))
  134.   features)
  135. EOF
  136. }
  137.  
  138. build_sbcl() {
  139.     status "Building SBCL..."
  140.     check_prepared
  141.     cd "$BUILD_DIR"
  142.     export CFLAGS="${CFLAGS} -fno-omit-frame-pointer -D_GNU_SOURCE"
  143.     sh make.sh --dynamic-space-size=$DYNAMIC_SPACE_SIZE \
  144.        || eexit "SBCL build failed."
  145. }
  146. test_sbcl() {
  147.     status "Testing SBCL..."
  148.     check_built
  149.     cd "$BUILD_DIR/tests"
  150.     sh ./run-tests.sh \
  151.        || eexit "SBCL tests failed."
  152. }
  153.  
  154. build_sbcl_docs() {
  155.     status "Building SBCL docs..."
  156.     check_built
  157.     cd "$BUILD_DIR/doc/manual"
  158.     make \
  159.         || eexit "Failed to build SBCL docs."
  160. }
  161.  
  162. install_sbcl() {
  163.     local command
  164.     status "Installing SBCL..."
  165.     check_built
  166.     cd "$BUILD_DIR"
  167.     unset SBCL_HOME
  168.     command="INSTALL_ROOT=\"$INSTALL_TARGET\" sh install.sh"
  169.  
  170.     # Attempt to create directory always, suppressing errors
  171.     # This way the -w test will truly check for permissions.
  172.     [ ! -d "$INSTALL_TARGET" ] \
  173.         && mkdir -p "$INSTALL_TARGET" &>/dev/null
  174.    
  175.     if [ -w "$INSTALL_TARGET" ]; then
  176.         try_run "$command" "SBCL install failed."
  177.     else
  178.         status "Super User privileges required to install to $INSTALL_TARGET"
  179.         try_run_sudo "$command" "SBCL install failed."
  180.     fi
  181. }
  182.  
  183. install_sources() {
  184.     local sources_dir="$INSTALL_TARGET/share/sbcl-source"
  185.     local copy_command="cp -R -t \"$sources_dir\" \"$BUILD_DIR/src\" \"$BUILD_DIR/contrib\""
  186.     local clean_command="find \"$sources_dir\" \
  187.                              -name \"*.fasl\" -or \
  188.                              -name \"*.o\" -or \
  189.                              -name \"*.log\" -or \
  190.                              -name \"*.so\" -or \
  191.                              -name \"a.out\" -delete"
  192.     local core_command="mv \"$BUILD_DIR/sbcl-sources.core\" \"$INSTALL_TARGET/lib/sbcl/sbcl.core\""
  193.     status "Installing sources..."
  194.     check_built
  195.    
  196.     cd "$BUILD_DIR"
  197.     cat >setup-sources.lisp <<EOF
  198. (in-package #:cl-user)
  199. (let* ((parent (parse-namestring "$sources_dir/")))
  200.   (setf (logical-pathname-translations "SYS")
  201.     \`(("SYS:SRC;**;*.*.*" ,(merge-pathnames "src/" parent))
  202.           ("SYS:CONTRIB;**;*.*.*" ,(merge-pathnames "contrib/" parent)))))
  203.  
  204. (ignore-errors
  205.  (sb-ext:gc :full t)
  206.  (sb-ext:enable-debugger)
  207.  (sb-ext:save-lisp-and-die "$BUILD_DIR/sbcl-sources.core"))
  208. EOF
  209.  
  210.     status "Creating proper core..."
  211.     src/runtime/sbcl --core output/sbcl.core --no-userinit --no-sysinit --script "$BUILD_DIR/setup-sources.lisp"
  212.  
  213.     status "Copying..."
  214.     [ ! -d "$sources_dir" ] \
  215.         && mkdir -p "$sources_dir" &>/dev/null
  216.  
  217.     if [ -w "$sources_dir" ]; then
  218.         try_run "$copy_command" "Source copying failed."
  219.         try_run "$clean_command" "Source cleaning failed."
  220.         try_run "$core_command" "Core copying failed."
  221.     else
  222.         status "Super User privileges required to install sources to $sources_dir"
  223.         try_run_sudo "mkdir -p \"$sources_dir\"" "Failed to create sources dir."
  224.         try_run_sudo "$copy_command" "Source copying failed."
  225.         try_run_sudo "$clean_command" "Source cleaning failed."
  226.         try_run_sudo "$core_command" "Core copying failed."
  227.     fi
  228. }
  229.  
  230. cleanup_build() {
  231.     status "Cleaning up build..."
  232.     rm -rf "$BUILD_DIR"
  233. }
  234.  
  235. perform_actions(){
  236.     local a=("${@}")
  237.     status "Performing actions: ${a[@]}"
  238.    
  239.     contains_element download "${a[@]}" \
  240.         && download_source
  241.    
  242.     contains_element prepare "${a[@]}" \
  243.         && prepare_build
  244.    
  245.     contains_element build "${a[@]}" \
  246.         && build_sbcl
  247.    
  248.     contains_element test "${a[@]}" \
  249.         && test_sbcl
  250.    
  251.     contains_element build-docs "${a[@]}" \
  252.         && build_sbcl_docs
  253.    
  254.     contains_element install "${a[@]}" \
  255.         && install_sbcl
  256.    
  257.     contains_element install-sources "${a[@]}" \
  258.         && install_sources
  259.    
  260.     contains_element cleanup "${a[@]}" \
  261.         && cleanup_build
  262.  
  263.     status "All done."
  264. }
  265.  
  266. cmdline() {
  267.     local arg=
  268.     for arg; do
  269.         local delim=""
  270.         case "$arg" in
  271.             --actions)  args="${args}-a ";;
  272.             --build)    args="${args}-b ";;
  273.             --disable)  args="${args}-d ";;
  274.             --enable)   args="${args}-e ";;
  275.             --help)     args="${args}-h ";;
  276.             --install)  args="${args}-i ";;
  277.             --target)   args="${args}-t ";;
  278.             # Pass through anything else
  279.             *) [[ "${arg:0:1}" == "-" ]] || delim="\""
  280.                args="${args}${delim}${arg}${delim} ";;
  281.         esac
  282.     done
  283.  
  284.     eval set -- $args
  285.    
  286.     local current_actions=()
  287.     while getopts "a:be:d:hit:" OPTION; do
  288.         case $OPTION in
  289.             a)
  290.                 current_actions=($OPTARG)
  291.                 ;;
  292.             b)
  293.                 current_actions+=(download prepare build)
  294.                 ;;
  295.             d)
  296.                 readonly DISABLED_FEATURES="$OPTARG"
  297.                 ;;
  298.             e)
  299.                 readonly ENABLED_FEATURES="$OPTARG"
  300.                 ;;
  301.             h)
  302.                 usage
  303.                 exit 0
  304.                 ;;
  305.             i)
  306.                 current_actions+=(install install-sources)
  307.                 ;;
  308.             t)
  309.                 readonly INSTALL_TARGET="$OPTARG"
  310.                 ;;
  311.             *)
  312.                 eexit "Unknown option given"
  313.                 ;;
  314.         esac
  315.     done
  316.  
  317.     ## Defaulting & Setting
  318.     [ ${#current_actions[@]} -eq 0 ] \
  319.         && readonly ACTIONS=("${DEFAULT_ACTIONS[@]}") \
  320.         || readonly ACTIONS=("${current_actions[@]}")
  321.  
  322.     [ -z ${ENABLED_FEATURES+x} ] \
  323.         && readonly ENABLED_FEATURES="$DEFAULT_ENABLED_FEATURES"
  324.    
  325.     [ -z ${DISABLED_FEATURES+x} ] \
  326.         && readonly DISABLED_FEATURES="$DEFAULT_DISABLED_FEATURES"
  327.  
  328.     [ -z ${INSTALL_TARGET+x} ] \
  329.         && readonly INSTALL_TARGET="$DEFAULT_INSTALL_TARGET"
  330.  
  331.     [ -z ${DYNAMIC_SPACE_SIZE+x} ] \
  332.         && readonly DYNAMIC_SPACE_SIZE="$DEFAULT_DYNAMIC_SPACE_SIZE"
  333.    
  334.     perform_actions "${ACTIONS[@]}"
  335. }
  336.  
  337. main() {
  338.     cmdline $ARGS
  339.     exit 0
  340. }
  341.  
  342. main
Advertisement
Add Comment
Please, Sign In to add comment