text: #!/bin/bash
  
  # Copyright (c) 2011-2014 Benjamin Fleischer
  # All rights reserved.
  #
  # Redistribution  and  use  in  source  and  binary  forms,  with   or   without
  # modification, are permitted provided that the following conditions are met:
  #
  # 1. Redistributions of source code must retain the above copyright notice, this
  #    list of conditions and the following disclaimer.
  # 2. Redistributions in binary form must reproduce the above  copyright  notice,
  #    this list of conditions and the following disclaimer in  the  documentation
  #    and/or other materials provided with the distribution.
  # 3. Neither the name of osxfuse nor the names of its contributors may  be  used
  #    to endorse or promote products derived from this software without  specific
  #    prior written permission.
  #
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND  CONTRIBUTORS  "AS  IS"
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT  NOT  LIMITED  TO,  THE
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS  FOR  A  PARTICULAR  PURPOSE
  # ARE DISCLAIMED.  IN NO EVENT SHALL THE  COPYRIGHT  OWNER  OR  CONTRIBUTORS  BE
  # LIABLE  FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL,   SPECIAL,   EXEMPLARY,   OR
  # CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,   PROCUREMENT   OF
  # SUBSTITUTE GOODS OR SERVICES; LOSS OF  USE,  DATA,  OR  PROFITS;  OR  BUSINESS
  # INTERRUPTION) HOWEVER CAUSED AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN
  # CONTRACT, STRICT  LIABILITY,  OR  TORT  (INCLUDING  NEGLIGENCE  OR  OTHERWISE)
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN  IF  ADVISED  OF  THE
  # POSSIBILITY OF SUCH DAMAGE.
  
  
  declare -ra BUILD_TARGET_ACTIONS=("build" "clean" "install")
  
  declare -a  DISTRIBUTION_KEXT_TASKS=()
  declare -i  DISTRIBUTION_MACFUSE=0
  
  
  function distribution_create_stage_core
  {
      local stage_directory="${1}"
      common_assert "[[ -n `string_escape "${stage_directory}"` ]]"
  
      /bin/mkdir -p "${stage_directory}" \
                    "${stage_directory}/Library/Filesystems" \
                    "${stage_directory}/Library/Frameworks" \
                    "${stage_directory}/usr/local/include" \
                    "${stage_directory}/usr/local/lib" \
                    "${stage_directory}/usr/local/lib/pkgconfig" 1>&3 2>&4
  }
  
  function distribution_create_stage_prefpane
  {
      local stage_directory="${1}"
      common_assert "[[ -n `string_escape "${stage_directory}"` ]]"
  
      /bin/mkdir -p "${stage_directory}" \
                    "${stage_directory}/Library/PreferencePanes" 1>&3 2>&4
  }
  
  function distribution_create_stage_macfuse
  {
      local stage_directory="${1}"
      common_assert "[[ -n `string_escape "${stage_directory}"` ]]"
  
      /bin/mkdir -p "${stage_directory}" \
                    "${stage_directory}/Library/Frameworks" \
                    "${stage_directory}/usr/local/include" \
                    "${stage_directory}/usr/local/lib" \
                    "${stage_directory}/usr/local/lib/pkgconfig" 1>&3 2>&4
  }
  
  function distribution_build
  {
      function distribution_build_getopt_handler
      {
          case "${1}" in
              --kext)
                  DISTRIBUTION_KEXT_TASKS+=("${2}")
                  return 2
                  ;;
              --macfuse)
                  DISTRIBUTION_MACFUSE=1
                  return 1
                  ;;
              --no-macfuse)
                  DISTRIBUTION_MACFUSE=0
                  return 1
                  ;;
          esac
      }
  
      build_target_getopt -p build -s "kext:,macfuse,no-macfuse" -h distribution_build_getopt_handler -- "${@}"
      unset distribution_build_getopt_handler
  
      common_log_variable DISTRIBUTION_KEXT_TASKS
      common_log_variable DISTRIBUTION_MACFUSE
  
      common_log "Clean target"
      build_target_invoke "${BUILD_TARGET_NAME}" clean
      common_die_on_error "Failed to clean target"
  
      common_log "Build target for OS X ${BUILD_TARGET_OPTION_DEPLOYMENT_TARGET}"
  
      local -a default_build_options=("-s${BUILD_TARGET_OPTION_SDK}"
                                      "-x${BUILD_TARGET_OPTION_XCODE}"
                                      "${BUILD_TARGET_OPTION_ARCHITECTURES[@]/#/-a}"
                                      "-d${BUILD_TARGET_OPTION_DEPLOYMENT_TARGET}"
                                      "-c${BUILD_TARGET_OPTION_BUILD_CONFIGURATION}"
                                      "-bENABLE_MACFUSE_MODE=${DISTRIBUTION_MACFUSE}"
                                      "${BUILD_TARGET_OPTION_BUILD_SETTINGS[@]/#/-b}"
                                      "${BUILD_TARGET_OPTION_MACROS[@]/#/-m}"
                                      "--code-sign-identity=${BUILD_TARGET_OPTION_CODE_SIGN_IDENTITY}"
                                      "--product-sign-identity=${BUILD_TARGET_OPTION_PRODUCT_SIGN_IDENTITY}")
  
      local -a library_build_options=("-s${BUILD_TARGET_OPTION_SDK}"
                                      "-x${BUILD_TARGET_OPTION_XCODE}"
                                      "${BUILD_TARGET_OPTION_ARCHITECTURES[@]/#/-a}"
                                      "-d${BUILD_TARGET_OPTION_DEPLOYMENT_TARGET}"
                                      "${BUILD_TARGET_OPTION_MACROS[@]/#/-m}"
                                      "--code-sign-identity=${BUILD_TARGET_OPTION_CODE_SIGN_IDENTITY}"
                                      "--product-sign-identity=${BUILD_TARGET_OPTION_PRODUCT_SIGN_IDENTITY}")
  
      local stage_directory_core="${BUILD_TARGET_BUILD_DIRECTORY}/Core"
      local stage_directory_prefpane="${BUILD_TARGET_BUILD_DIRECTORY}/PrefPane"
      local debug_directory="${BUILD_TARGET_BUILD_DIRECTORY}/Debug"
      local packages_directory="${BUILD_TARGET_BUILD_DIRECTORY}/Packages"
  
      /bin/mkdir -p "${BUILD_TARGET_BUILD_DIRECTORY}" 1>&3 2>&4
      common_die_on_error "Failed to create build directory"
  
      distribution_create_stage_core "${stage_directory_core}"
      common_die_on_error "Failed to create core stage"
  
      distribution_create_stage_prefpane "${stage_directory_prefpane}"
      common_die_on_error "Failed to create preference pane stage"
  
      /bin/mkdir -p "${debug_directory}" 1>&3 2>&4
      common_die_on_error "Failed to create debug directory"
  
      /bin/mkdir -p "${packages_directory}" 1>&3 2>&4
      common_die_on_error "Failed to create packages directory"
  
      local -a component_packages=()
  
      # Build file system bundle
  
      build_target_invoke fsbundle build "${default_build_options[@]}" "${DISTRIBUTION_KEXT_TASKS[@]/#/--kext=}"
      common_die_on_error "Failed to build file system bundle"
  
      build_target_invoke fsbundle install --debug="${debug_directory}" -- "${stage_directory_core}/Library/Filesystems"
      common_die_on_error "Failed to install file system bundle"
  
      # Locate file system bundle
  
      local fsbundle_path=""
      fsbundle_path="`osxfuse_find "${stage_directory_core}/Library/Filesystems"/*.fs`"
      common_die_on_error "Failed to locate file system bundle"
  
      # Set kernel extension loader SUID bit
  
      local loader_path=""
      loader_path="`osxfuse_find "${fsbundle_path}/Contents/Resources"/load_*`"
      common_die_on_error "Failed to locate kernel extension loader"
  
      /bin/chmod u+s "${loader_path}"
      common_die_on_error "Failed to set SUID bit of kernel extension loader"
  
      # Add embedded uninstaller to file system bundle
  
      local uninstaller_path="${fsbundle_path}/Contents/Resources/uninstall_osxfuse.app"
  
      /bin/cp -R "${BUILD_SOURCE_DIRECTORY}/support/uninstall_osxfuse.app" "${uninstaller_path}" 1>&3 2>&4
      common_die_on_error "Failed to copy embedded uninstaller to file system bundle"
  
      build_target_codesign --deep "${uninstaller_path}"
      common_die_on_error "Failed to sign embedded uninstaller"
  
      # Sign file system bundle
  
      build_target_codesign "${fsbundle_path}"
      common_die_on_error "Failed to sign file system bundle"
  
      # Build library
  
      build_target_invoke library build "${library_build_options[@]}"
      common_die_on_error "Failed to build library"
  
      build_target_invoke library install --debug="${debug_directory}" -- "${stage_directory_core}"
      common_die_on_error "Failed to install library"
  
      /bin/ln -s "libosxfuse.2.dylib" "${stage_directory_core}/usr/local/lib/libosxfuse_i64.2.dylib" && \
      /bin/ln -s "libosxfuse.dylib" "${stage_directory_core}/usr/local/lib/libosxfuse_i64.dylib" && \
      /bin/ln -s "libosxfuse.la" "${stage_directory_core}/usr/local/lib/libosxfuse_i64.la" && \
      /bin/ln -s "osxfuse.pc" "${stage_directory_core}/usr/local/lib/pkgconfig/fuse.pc"
      common_die_on_error "Failed to create legacy library links"
  
      # Build framework
  
      build_target_invoke framework build "${default_build_options[@]}" --library-prefix="${stage_directory_core}/usr/local"
      common_die_on_error "Failed to build framework"
  
      build_target_invoke framework install --debug="${debug_directory}" -- "${stage_directory_core}/Library/Frameworks"
      common_die_on_error "Failed to install framework"
  
      # Build core component package
  
      common_log -v 3 "Build core component package"
  
      osxfuse_build_component_package -n Core -r "${stage_directory_core}" "${packages_directory}/Core.pkg"
      common_die_on_error "Failed to build core package"
      component_packages+=("${packages_directory}/Core.pkg")
  
      # Build preference pane
  
      build_target_invoke prefpane build "${default_build_options[@]}"
      common_die_on_error "Failed to build preference pane"
  
      build_target_invoke prefpane install -- "${stage_directory_prefpane}/Library/PreferencePanes"
      common_die_on_error "Failed to install preference pane"
  
      # Build preference pane component package
  
      common_log -v 3 "Build preference pane component package"
  
      osxfuse_build_component_package -n PrefPane -r "${stage_directory_prefpane}" "${packages_directory}/PrefPane.pkg"
      common_die_on_error "Failed to build preference pane package"
      component_packages+=("${packages_directory}/PrefPane.pkg")
  
      # MacFUSE
  
      if (( DISTRIBUTION_MACFUSE  != 0 ))
      then
          local stage_directory_macfuse="${BUILD_TARGET_BUILD_DIRECTORY}/MacFUSE"
  
          distribution_create_stage_macfuse "${stage_directory_macfuse}"
          common_die_on_error "Failed to create MacFUSE stage"
  
          # Build library
  
          build_target_invoke macfuse_library build "${library_build_options[@]}"
          common_die_on_error "Failed to build MacFUSE library"
  
          build_target_invoke macfuse_library install --debug="${debug_directory}" -- "${stage_directory_macfuse}"
          common_die_on_error "Failed to install MacFUSE library"
  
          /bin/ln -s "libfuse.dylib" "${stage_directory_macfuse}/usr/local/lib/libfuse.0.dylib" && \
          common_die_on_error "Failed to create MacFUSE legacy library links"
  
          # Build framework
  
          build_target_invoke macfuse_framework build "${default_build_options[@]}" --library-prefix="${stage_directory_macfuse}/usr/local"
          common_die_on_error "Failed to build MacFUSE framework"
  
          build_target_invoke macfuse_framework install --debug="${debug_directory}" -- "${stage_directory_macfuse}/Library/Frameworks"
          common_die_on_error "Failed to install MacFUSE framework"
  
          # Build MacFUSE component package
  
          common_log -v 3 "Build MacFUSE component package"
  
          osxfuse_build_component_package -n MacFUSE -r "${stage_directory_macfuse}" "${packages_directory}/MacFUSE.pkg"
          common_die_on_error "Failed to build MacFUSE package"
          component_packages+=("${packages_directory}/MacFUSE.pkg")
      fi
  
      # Build distribution package
  
      common_log -v 3 "Build distribution package"
  
      local distribution_package_path="${BUILD_TARGET_BUILD_DIRECTORY}/Distribution.pkg"
  
      local -a osx_versions_supported=()
      for task in "${DISTRIBUTION_KEXT_TASKS[@]}"
      do
          local osx_version="`expr "${task}" : '^\([[:digit:]]\{1,\}\(\.[[:digit:]]\{1,\}\)*\)'`"
          version_compare "${osx_version}" "${BUILD_TARGET_OPTION_DEPLOYMENT_TARGET}"
          if (( ${?} != 1 ))
          then
              osx_versions_supported+=("${osx_version}")
          fi
      done
  
      pushd "${BUILD_TARGET_BUILD_DIRECTORY}" > /dev/null 2>&1
      common_die_on_error "Build directory '${BUILD_TARGET_BUILD_DIRECTORY}' does not exist"
  
      osxfuse_build_distribution_package -p "${packages_directory}" \
                                         "${component_packages[@]/#/-c}" \
                                         "${osx_versions_supported[@]/#/-d}" \
                                         "${distribution_package_path}"
      common_die_on_error "Failed to build distribution package"
  
      popd > /dev/null 2>&1
  }
  
  function distribution_install
  {
      local -a arguments=()
      build_target_getopt -p install -o arguments -- "${@}"
  
      local target_directory="${arguments[0]}"
      if [[ ! -d "${target_directory}" ]]
      then
          common_die "Target directory '${target_directory}' does not exist"
      fi
  
      common_log "Install target"
  
      local distribution_source_path=""
      distribution_source_path="`osxfuse_find "${BUILD_TARGET_BUILD_DIRECTORY}/Distribution.pkg"`"
      common_die_on_error "Failed to locate distribution package"
  
      build_target_install "${distribution_source_path}" "${target_directory}"
      common_die_on_error "Failed to install target"
  
      if [[ -n "${BUILD_TARGET_OPTION_DEBUG_DIRECTORY}" ]]
      then
          build_target_install "${BUILD_TARGET_BUILD_DIRECTORY}/Debug/" "${BUILD_TARGET_OPTION_DEBUG_DIRECTORY}"
          common_die_on_error "Failed to Install debug files"
      fi
  }
  