Difference between revisions of "Code/build-experimental-X"
|  (Mesa has moved from CVS to Git) |  (Put script in <pre> block.) | ||
| (3 intermediate revisions by one other user not shown) | |||
| Line 1: | Line 1: | ||
| + | <pre> | ||
| #!/bin/bash | #!/bin/bash | ||
| − | # Script to fetch and build X.org, DRI, Mesa | + | # Script to fetch and build X.org (incl. XCB and pixman), DRI, Mesa and | 
| − | + | # xkeyboard-config from CVS and GIT, and save full git snapshots of their | |
| − | #  | + | # source and installation. | 
| + | # | ||
| + | # Default action: | ||
| + | # - Create/update a git repository for each module, under $HOME/3d-pit. | ||
| + | # - Install all modules, under $HOME/3d-pit/install | ||
| + | # - Make $HOME/3d-pit/install a git repository to track the installed binaries | ||
| + | # - Make $HOME/3d-pit a git super-repository which tracks all of the above | ||
| + | #   using the submodule mechanism of git >= 1.5.3. | ||
| + | # | ||
| + | # Each of these can be disabled via command line (see the code table below). | ||
| + | # | ||
| # Source: http://thinkwiki.org/wiki/How_to_compile_an_experimental_X_server | # Source: http://thinkwiki.org/wiki/How_to_compile_an_experimental_X_server | ||
| # See also: | # See also: | ||
| Line 9: | Line 20: | ||
| #   http://gitweb.freedesktop.org | #   http://gitweb.freedesktop.org | ||
| #   http://dri.freedesktop.org/wiki/Building | #   http://dri.freedesktop.org/wiki/Building | ||
| − | #   http://www.mesa3d.org/ | + | #   http://www.mesa3d.org/repository.html | 
| #   http://www.mesa3d.org/install.html | #   http://www.mesa3d.org/install.html | ||
| #   http://web.telia.com/~u89404340/touchpad | #   http://web.telia.com/~u89404340/touchpad | ||
| #   http://www.freedesktop.org/wiki/Software_2fXKeyboardConfig | #   http://www.freedesktop.org/wiki/Software_2fXKeyboardConfig | ||
| #   http://gitweb.freedesktop.org/?p=xorg/util/modular.git;a=blob;f=build.sh | #   http://gitweb.freedesktop.org/?p=xorg/util/modular.git;a=blob;f=build.sh | ||
| + | |||
| + | ############################################# | ||
| + | # X.org setup | ||
| + | # This is a list of modules that are in flux and likely to be related to | ||
| + | # whatever you're testing (or are required for the build), sorted by | ||
| + | # build order (see util/modular/build.sh for dependencies). | ||
| + | # Check CVS and the above URLs for other modules. | ||
| + | # For exhaustive list, see  | ||
| + | # get -qO - http://gitweb.freedesktop.org/ \ | ||
| + | # | perl -ne 'print "$1\n" if m!<a href="/\?p=([^;]+);a=summary">!' \ | ||
| + | # | egrep '^xcb/|^xorg/|^pixman/' | ||
| + | |||
| + | XORG_MODULES=( | ||
| + |   xorg/util/macros | ||
| + |   xorg/proto/{bigreqs,composite,fixes,damage,gl,input,kb,pm,randr,resource,xext,xcmisc}proto | ||
| + |   xorg/proto/{fontcache,fonts,kb}proto | ||
| + |   xorg/proto/{render,scrnsaver,video}proto | ||
| + |   xorg/proto/{x11,xf86bigfont,xf86dga,xf86dri,xf86misc,xf86vidmode,xinerama}proto | ||
| + |   xcb/proto | ||
| + |   xorg/lib/lib{xtrans,Xau,Xdmcp} | ||
| + |   xcb/libxcb | ||
| + |   xorg/lib/lib{X11,ICE,SM,Xt,Xmu,Xcomposite,Xrender,Xdamage,Xcursor,Xi,Xinerama} | ||
| + |   xorg/lib/lib{Xfont,Xfontcache,Xft} | ||
| + |   xorg/lib/lib{xkbui,Xrandr,Xv,XvMC,Xxf86dga,Xxf86misc,Xxf86vm,pciaccess} | ||
| + |   pixman | ||
| + |   xorg/xserver | ||
| + |   xorg/driver/xf86-video-ati | ||
| + |   xorg/driver/xf86-input-{mouse,keyboard,joystick,evdev} | ||
| + |   xorg/app/{xkbutils,xkbcomp,setxkbmap,xrandr,xsetpointer,xbacklight} | ||
| + | ) | ||
| ############################################# | ############################################# | ||
| # Init | # Init | ||
| + | |||
| + | FETCH=true | ||
| + | BUILD=true | ||
| + | RECONFIGURE=false       # Reconfigure everything even if unchanged from last run | ||
| + | MAKE_CLEAN=false        # If true, run "make clean" before building. | ||
| + | GIT_CLEAN=false         # Use "git clean" to delete all non-source files before building. | ||
| + | SUPERMODULE=true        # Take meta-snapshots using Git super/submodule | ||
| + | |||
| + | for OPT in "$@"; do | ||
| + | 	case "$OPT" in | ||
| + | 		(--no-fetch)       FETCH=false ;; | ||
| + | 		(--no-build)       BUILD=false ;; | ||
| + | 		(--no-supermodule) SUPERMODULE=false ;; | ||
| + | 		(--reconfigure)    RECONFIGURE=true ;; | ||
| + | 		(--make-clean)     MAKE_CLEAN=true ;; | ||
| + | 		(--git-clean)      GIT_CLEAN=true ;; | ||
| + | 		(*) echo "Unknown option" >&2; exit 1 ;; | ||
| + | 	esac | ||
| + | done | ||
| PIT=$HOME/3d-pit       # Download and build here | PIT=$HOME/3d-pit       # Download and build here | ||
| − | + | DEST_SUBDIR=install    # Install in this subdirectory of $PIT | |
| + | USE_XCB=false          # Use XCB? | ||
| FLAGS='-O2 -g -march=pentium-m' | FLAGS='-O2 -g -march=pentium-m' | ||
| − | + | ||
| − | + | DEST=$PIT/$DEST_SUBDIR | |
| − | |||
| − | |||
| trap "echo Aborting.; exit 1" ERR | trap "echo Aborting.; exit 1" ERR | ||
| set -E | set -E | ||
| + | |||
| + | ############################################# | ||
| + | # Support functions | ||
| die() { | die() { | ||
| Line 33: | Line 95: | ||
|    exit 1 |    exit 1 | ||
| } | } | ||
| + | |||
| run() { | run() { | ||
| − |    echo "@ $@" | + |    echo "@`pwd`:  $@" | 
|    "$@" || { echo "ERROR: Command \"$*\" failed in `pwd`"; exit 1; } |    "$@" || { echo "ERROR: Command \"$*\" failed in `pwd`"; exit 1; } | ||
| + | } | ||
| + | |||
| + | nothing_to_commit() { | ||
| + |   git status > /dev/null   # Force check of files for which only the timestamp changed. | ||
| + |   git diff --quiet HEAD > /dev/null | ||
| } | } | ||
| Line 43: | Line 111: | ||
|    MODULE="$3" |    MODULE="$3" | ||
|    DIR="${4:-$MODULE}" |    DIR="${4:-$MODULE}" | ||
| − |    if [ -d "$ | + |   FULLDIR="$PARENT_DIR/$DIR" | 
| − | + |   RELDIR="${FULLDIR#$PIT/}" | |
| + |    if [ -d "$FULLDIR" ]; then   | ||
| + |      cd "$FULLDIR" | ||
| + |     ORIG_HEAD=`git rev-parse HEAD` | ||
|      run git pull |      run git pull | ||
| + |     NEW_HEAD=`git rev-parse HEAD` | ||
| + |     [[ "$ORIG_HEAD" == "$NEW_HEAD" ]] || run git shortlog ORIG_HEAD..HEAD | cat | ||
|    else |    else | ||
|      run cd "$PARENT_DIR" |      run cd "$PARENT_DIR" | ||
|      run git clone "$GIT_REP/$MODULE" "$DIR" |      run git clone "$GIT_REP/$MODULE" "$DIR" | ||
|      cd "$DIR" |      cd "$DIR" | ||
| − |      git  | + |      git gc | 
| + |   fi | ||
| + | |||
| + |   add_to_supermodule "$RELDIR" | ||
| + | } | ||
| + | |||
| + | fetch_from_cvs() { | ||
| + |   CVS_SERVER="$1" | ||
| + |   DIR="$2" | ||
| + |   GITIGNORES="$3" | ||
| + | |||
| + |   run cd $PIT | ||
| + |   if [ ! -d $DIR ]; then | ||
| + |     grep -qF $CVS_SERVER ~/.cvspass || run cvs -d $CVS_SERVER login | ||
| + |     run cvs -z3 -d $CVS_SERVER co $DIR | ||
| + | |||
| + |     cd $PIT/$DIR | ||
| + |     run git init | ||
|    fi |    fi | ||
| + | |||
| + |   cd $PIT/$DIR | ||
| + |   run cvs -z3 update -ACPd -I .gitignore -I .git | ||
| + |   find . -name .cvsignore | while read X; do cp "$X" "${X%/.cvsignore}/.gitignore"; done | ||
| + |   echo -e "$GITIGNORES" >> .gitignore | ||
| + |   run git add . | ||
| + |   nothing_to_commit || run git commit -a -m "`date +'Fetched at %Y-%m-%d %H:%M:%S'`" | ||
| + | |||
| + | # We could use git-cvsimport instead, but that's way too slow: | ||
| + | #  mkdir -p $PIT/$DIR | ||
| + | #  cd $PIT/$DIR | ||
| + | #  git-cvsimport -v -d "$CVS_SERVER" -r origin | ||
| + | |||
| + |   add_to_supermodule "$DIR" | ||
| } | } | ||
| − | LAST_HASH=last_dir_hash | + | ############################################# | 
| + | # Handing git super/submodules | ||
| + | |||
| + | if $SUPERMODULE; then | ||
| + |   which git-submodule >&/dev/null || \ | ||
| + |     die "Error: git >= 1.3.5 required for submodule support. Try --no-supermodule." | ||
| + | |||
| + |   run mkdir -p $PIT | ||
| + |   cd $PIT | ||
| + |   if [ ! -d .git ]; then | ||
| + |      run git init | ||
| + |      echo -e 'xorg/autoconf.cache' > .gitignore | ||
| + |      run git add .gitignore | ||
| + |      run git commit -m 'initial' | ||
| + |   fi | ||
| + | |||
| + |   # Add new submodule's repository to the supermodule's .gitmodules | ||
| + |   add_to_supermodule_gitmodules() { | ||
| + |     SUBDIR="$1" | ||
| + |     GIT_CONFIG=$PIT/.gitmodules git config "submodule.$SUBDIR.path" "$SUBDIR" | ||
| + |     GIT_CONFIG=$PIT/.gitmodules git config "submodule.$SUBDIR.url" "$SUBDIR" | ||
| + |   } | ||
| + | |||
| + |   add_to_supermodule() { | ||
| + |     cd $PIT | ||
| + |     # add_to_supermodule_alternates "$1" | ||
| + |     add_to_supermodule_gitmodules "$1" | ||
| + |     run git add "$1" | ||
| + |   } | ||
| + | else | ||
| + |   add_to_supermodule() { true; } | ||
| + | fi | ||
| + | |||
| + | |||
| + | ############################################# | ||
| + | # Directory hashes for change detection | ||
| + | |||
| + | LAST_HASH=.last_dir_hash | ||
| + | |||
| dir_hash() { | dir_hash() { | ||
|    find . \( -name $LAST_HASH -o -path ./.git -prune \) -o -type f -ls | sort | md5sum |    find . \( -name $LAST_HASH -o -path ./.git -prune \) -o -type f -ls | sort | md5sum | ||
| } | } | ||
| + | |||
| dir_hash_changed() { | dir_hash_changed() { | ||
|    $RECONFIGURE || [ ! -f $LAST_HASH ] || [ "`dir_hash`" != "`cat $LAST_HASH`" ] |    $RECONFIGURE || [ ! -f $LAST_HASH ] || [ "`dir_hash`" != "`cat $LAST_HASH`" ] | ||
| } | } | ||
| + | |||
| save_dir_hash() { | save_dir_hash() { | ||
|    dir_hash > $LAST_HASH |    dir_hash > $LAST_HASH | ||
| Line 77: | Line 221: | ||
|    echo "########### Build libdrm ###########" |    echo "########### Build libdrm ###########" | ||
|    run cd $PIT/drm |    run cd $PIT/drm | ||
| + |   ! $GIT_CLEAN  || run git clean -x -d | ||
|    if dir_hash_changed; then |    if dir_hash_changed; then | ||
|      run ./autogen.sh |      run ./autogen.sh | ||
| Line 92: | Line 237: | ||
|    echo "########### Build DRM kernel modules ###########" |    echo "########### Build DRM kernel modules ###########" | ||
|    run cd $PIT/drm/linux-core |    run cd $PIT/drm/linux-core | ||
| + |   ! $GIT_CLEAN  || run git clean -x -d | ||
|    ! $MAKE_CLEAN || run make clean |    ! $MAKE_CLEAN || run make clean | ||
|    run make DRM_MODULES="radeon" |    run make DRM_MODULES="radeon" | ||
| Line 127: | Line 273: | ||
|    export PATH="$DEST/bin:$PATH" |    export PATH="$DEST/bin:$PATH" | ||
|    run mkdir -p $DRI_DRIVER_INSTALL_DIR |    run mkdir -p $DRI_DRIVER_INSTALL_DIR | ||
| + |   ! $GIT_CLEAN  || run git clean -x -d | ||
|    ! $MAKE_CLEAN || run make clean |    ! $MAKE_CLEAN || run make clean | ||
|    if [ -e configs/current ]; then |    if [ -e configs/current ]; then | ||
| Line 136: | Line 283: | ||
|    run cp -v lib/*_dri.so $DRI_DRIVER_INSTALL_DIR |    run cp -v lib/*_dri.so $DRI_DRIVER_INSTALL_DIR | ||
| ) } | ) } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| ############################################# | ############################################# | ||
| Line 173: | Line 291: | ||
|    XORG_GIT=git://anongit.freedesktop.org/git |    XORG_GIT=git://anongit.freedesktop.org/git | ||
|    run mkdir -p $PIT/xorg |    run mkdir -p $PIT/xorg | ||
| − |    for D in "${ | + |    for D in "${XORG_MODULES[@]}"; do | 
|      if [[ $D == xcb/* ]] && ! $USE_XCB; then continue; fi |      if [[ $D == xcb/* ]] && ! $USE_XCB; then continue; fi | ||
|      fetch_from_git $PIT/xorg "$XORG_GIT" "$D" "${D#xorg/}" |      fetch_from_git $PIT/xorg "$XORG_GIT" "$D" "${D#xorg/}" | ||
| Line 190: | Line 308: | ||
|    export ACLOCAL="${AC_LOCAL:-aclocal} -I $DEST/share/aclocal" |    export ACLOCAL="${AC_LOCAL:-aclocal} -I $DEST/share/aclocal" | ||
|    export LD_LIBRARY_PATH="$DEST/lib:$LD_LIBRARY_PATH" |    export LD_LIBRARY_PATH="$DEST/lib:$LD_LIBRARY_PATH" | ||
| + | |||
|    if [ $D == "xserver" ]; then |    if [ $D == "xserver" ]; then | ||
| − |      CONF_OPT="--with-mesa-source=$PIT/mesa --enable-xorg --disable-dmx --disable-xvfb --disable-xnest --disable-xprint" | + |      CONF_OPT="--with-mesa-source=$PIT/mesa --enable-xorg --disable-dmx --disable-xvfb --disable-xnest --disable-xprint --disable-freetype --disable-xselinux" | 
|    elif [ $D == "lib/libX11" ] && ! $USE_XCB; then |    elif [ $D == "lib/libX11" ] && ! $USE_XCB; then | ||
|      CONF_OPT="--with-xcb=no" |      CONF_OPT="--with-xcb=no" | ||
| Line 197: | Line 316: | ||
|      CONF_OPT= |      CONF_OPT= | ||
|    fi |    fi | ||
| + | |||
|    run cd $PIT/xorg/$D |    run cd $PIT/xorg/$D | ||
| + |   ! $GIT_CLEAN  || run git clean -x -d | ||
|    if dir_hash_changed; then |    if dir_hash_changed; then | ||
| − |      CFLAGS="$FLAGS" run sh autogen.sh --prefix=$DEST --quiet --cache-file=$PIT/xorg/autoconf.cache  | + |      CFLAGS="$FLAGS" run sh autogen.sh --prefix=$DEST --quiet $CONF_OPT | 
| + |       # --cache-file=$PIT/xorg/autoconf.cache   | ||
|      save_dir_hash |      save_dir_hash | ||
|    fi |    fi | ||
| Line 207: | Line 329: | ||
|    run make install |    run make install | ||
|    save_dir_hash |    save_dir_hash | ||
| + | |||
| + |   if [ $D == "pixman" ]; then # as of 2007-08-07 pixman needs this hack: | ||
| + |     [ -e $DEST/include/pixman.h ] || run ln -fs pixman-1/pixman.h $DEST/include/pixman.h | ||
| + |   fi | ||
| ) } | ) } | ||
| Line 213: | Line 339: | ||
|    run mkdir -p $DEST/share/aclocal |    run mkdir -p $DEST/share/aclocal | ||
|    run mkdir -p $DEST/var/log |    run mkdir -p $DEST/var/log | ||
| − |    for D in "${ | + |    for D in "${XORG_MODULES[@]}"; do | 
|      if [[ $D == xcb/* ]] && ! $USE_XCB; then continue; fi |      if [[ $D == xcb/* ]] && ! $USE_XCB; then continue; fi | ||
|      build_x_module $D || return 1 |      build_x_module $D || return 1 | ||
| Line 226: | Line 352: | ||
| fetch_xkeyboard_config() { | fetch_xkeyboard_config() { | ||
|    echo "########### Fetching xkeyboard-config ###########" |    echo "########### Fetching xkeyboard-config ###########" | ||
| − |    XKBC_CVS=:pserver:anoncvs@cvs.freedesktop.org:2401/cvs/xkeyboard-config | + |    XKBC_CVS=":pserver:anoncvs@cvs.freedesktop.org:2401/cvs/xkeyboard-config" | 
| − | + |    XKBC_DIR=xkeyboard-config | |
| − | + |    XKBC_GITIGNORES='install-sh\nmissing\npo/stamp-it' | |
| − | + |    fetch_from_cvs "$XKBC_CVS" "$XKBC_DIR" "$XKBC_GITIGNORES" | |
| − | |||
| − | |||
| } | } | ||
| Line 264: | Line 388: | ||
|    export PKG_CONFIG_PATH="$DEST/lib/pkgconfig:$PKG_CONFIG_PATH" |    export PKG_CONFIG_PATH="$DEST/lib/pkgconfig:$PKG_CONFIG_PATH" | ||
|    export PATH="$DEST/bin:$PATH" |    export PATH="$DEST/bin:$PATH" | ||
| + |   export CPATH="$DEST/include:$CPATH" | ||
| + |   ! $GIT_CLEAN  || run git clean -x -d | ||
|    ! $MAKE_CLEAN || run make clean |    ! $MAKE_CLEAN || run make clean | ||
|    run make |    run make | ||
| − |    run cp -v synaptics_drv.so $DEST/lib/xorg/modules/input/ | + |    run make install PREFIX="$DEST" MANDIR="$DEST/share/man" | 
| + |   #run cp -v synaptics_drv.so $DEST/lib/xorg/modules/input/ | ||
| ) } | ) } | ||
| Line 273: | Line 400: | ||
| create_xsetenv() { | create_xsetenv() { | ||
| + |   echo "Creating $DEST/bin/xsetenv" | ||
|    cat <<EOF > $DEST/bin/xsetenv || die "Can't create $DEST/bin/xsetenv" |    cat <<EOF > $DEST/bin/xsetenv || die "Can't create $DEST/bin/xsetenv" | ||
| export PATH="$DEST/bin:$PATH"   | export PATH="$DEST/bin:$PATH"   | ||
| Line 278: | Line 406: | ||
| export LIBGL_DRIVERS_PATH=$DEST/lib/dri | export LIBGL_DRIVERS_PATH=$DEST/lib/dri | ||
| EOF | EOF | ||
| − | |||
| } | } | ||
| ############################################# | ############################################# | ||
| − | #  | + | # Actual fetching and building: | 
| − | |||
| − | |||
| − | |||
| if $FETCH; then | if $FETCH; then | ||
| Line 304: | Line 428: | ||
| fi | fi | ||
| − | echo 'Done.' | + | ############################################# | 
| + | # Saving install and super state to git commits: | ||
| + | |||
| + | if $BUILD; then | ||
| + |   echo "########### Record installation dir commit ###########" | ||
| + |   cd $DEST | ||
| + |   if [ ! -d .git ]; then | ||
| + |     run git init | ||
| + |     echo '/var/log' > .gitignore | ||
| + |     run git add .gitignore | ||
| + |     run git commit -a -m "initial" | ||
| + |   fi | ||
| + |   run git add . | ||
| + |   if ! nothing_to_commit; then | ||
| + |     run git commit -a -m "`date +'Installed at %Y-%m-%d %H:%M:%S'`" | ||
| + |     run git gc | ||
| + |   fi | ||
| + |   add_to_supermodule "$DEST_SUBDIR" | ||
| + | fi | ||
| + | |||
| + | if $SUPERMODULE; then | ||
| + |   echo "########### Record supermodule commit ###########" | ||
| + |   cd $PIT | ||
| + |   nothing_to_commit || run git commit -m "`date +'Snapshot at %Y-%m-%d %H:%M:%S'` `$FETCH && echo fetch` `$BUILD && echo build`" | ||
| + | fi | ||
| + | |||
| + | ############################################# | ||
| + | |||
| + | echo | ||
| + | echo "Done." | ||
| + | ! $FETCH || echo "Run '. $DEST/bin/xsetenv' to point env vars to this installation." | ||
| + | </pre> | ||
Latest revision as of 08:27, 11 April 2025
#!/bin/bash
# Script to fetch and build X.org (incl. XCB and pixman), DRI, Mesa and
# xkeyboard-config from CVS and GIT, and save full git snapshots of their
# source and installation.
#
# Default action:
# - Create/update a git repository for each module, under $HOME/3d-pit.
# - Install all modules, under $HOME/3d-pit/install
# - Make $HOME/3d-pit/install a git repository to track the installed binaries
# - Make $HOME/3d-pit a git super-repository which tracks all of the above
#   using the submodule mechanism of git >= 1.5.3.
#
# Each of these can be disabled via command line (see the code table below).
#
# Source: http://thinkwiki.org/wiki/How_to_compile_an_experimental_X_server
# See also:
#   http://wiki.x.org/wiki/ModularDevelopersGuide
#   http://wiki.x.org/wiki/GitPage
#   http://gitweb.freedesktop.org
#   http://dri.freedesktop.org/wiki/Building
#   http://www.mesa3d.org/repository.html
#   http://www.mesa3d.org/install.html
#   http://web.telia.com/~u89404340/touchpad
#   http://www.freedesktop.org/wiki/Software_2fXKeyboardConfig
#   http://gitweb.freedesktop.org/?p=xorg/util/modular.git;a=blob;f=build.sh
#############################################
# X.org setup
# This is a list of modules that are in flux and likely to be related to
# whatever you're testing (or are required for the build), sorted by
# build order (see util/modular/build.sh for dependencies).
# Check CVS and the above URLs for other modules.
# For exhaustive list, see 
# get -qO - http://gitweb.freedesktop.org/ \
# | perl -ne 'print "$1\n" if m!<a href="/\?p=([^;]+);a=summary">!' \
# | egrep '^xcb/|^xorg/|^pixman/'
XORG_MODULES=(
  xorg/util/macros
  xorg/proto/{bigreqs,composite,fixes,damage,gl,input,kb,pm,randr,resource,xext,xcmisc}proto
  xorg/proto/{fontcache,fonts,kb}proto
  xorg/proto/{render,scrnsaver,video}proto
  xorg/proto/{x11,xf86bigfont,xf86dga,xf86dri,xf86misc,xf86vidmode,xinerama}proto
  xcb/proto
  xorg/lib/lib{xtrans,Xau,Xdmcp}
  xcb/libxcb
  xorg/lib/lib{X11,ICE,SM,Xt,Xmu,Xcomposite,Xrender,Xdamage,Xcursor,Xi,Xinerama}
  xorg/lib/lib{Xfont,Xfontcache,Xft}
  xorg/lib/lib{xkbui,Xrandr,Xv,XvMC,Xxf86dga,Xxf86misc,Xxf86vm,pciaccess}
  pixman
  xorg/xserver
  xorg/driver/xf86-video-ati
  xorg/driver/xf86-input-{mouse,keyboard,joystick,evdev}
  xorg/app/{xkbutils,xkbcomp,setxkbmap,xrandr,xsetpointer,xbacklight}
)
#############################################
# Init
FETCH=true
BUILD=true
RECONFIGURE=false       # Reconfigure everything even if unchanged from last run
MAKE_CLEAN=false        # If true, run "make clean" before building.
GIT_CLEAN=false         # Use "git clean" to delete all non-source files before building.
SUPERMODULE=true        # Take meta-snapshots using Git super/submodule
for OPT in "$@"; do
	case "$OPT" in
		(--no-fetch)       FETCH=false ;;
		(--no-build)       BUILD=false ;;
		(--no-supermodule) SUPERMODULE=false ;;
		(--reconfigure)    RECONFIGURE=true ;;
		(--make-clean)     MAKE_CLEAN=true ;;
		(--git-clean)      GIT_CLEAN=true ;;
		(*) echo "Unknown option" >&2; exit 1 ;;
	esac
done
PIT=$HOME/3d-pit       # Download and build here
DEST_SUBDIR=install    # Install in this subdirectory of $PIT
USE_XCB=false          # Use XCB?
FLAGS='-O2 -g -march=pentium-m'
DEST=$PIT/$DEST_SUBDIR
trap "echo Aborting.; exit 1" ERR
set -E
#############################################
# Support functions
die() {
  echo "$*"
  exit 1
}
run() {
  echo "@`pwd`:  $@"
  "$@" || { echo "ERROR: Command \"$*\" failed in `pwd`"; exit 1; }
}
nothing_to_commit() {
  git status > /dev/null   # Force check of files for which only the timestamp changed.
  git diff --quiet HEAD > /dev/null
}
fetch_from_git() {
  PARENT_DIR="$1"
  GIT_REP="$2"
  MODULE="$3"
  DIR="${4:-$MODULE}"
  FULLDIR="$PARENT_DIR/$DIR"
  RELDIR="${FULLDIR#$PIT/}"
  if [ -d "$FULLDIR" ]; then 
    cd "$FULLDIR"
    ORIG_HEAD=`git rev-parse HEAD`
    run git pull
    NEW_HEAD=`git rev-parse HEAD`
    [[ "$ORIG_HEAD" == "$NEW_HEAD" ]] || run git shortlog ORIG_HEAD..HEAD | cat
  else
    run cd "$PARENT_DIR"
    run git clone "$GIT_REP/$MODULE" "$DIR"
    cd "$DIR"
    git gc
  fi
  add_to_supermodule "$RELDIR"
}
fetch_from_cvs() {
  CVS_SERVER="$1"
  DIR="$2"
  GITIGNORES="$3"
  run cd $PIT
  if [ ! -d $DIR ]; then
    grep -qF $CVS_SERVER ~/.cvspass || run cvs -d $CVS_SERVER login
    run cvs -z3 -d $CVS_SERVER co $DIR
    cd $PIT/$DIR
    run git init
  fi
  cd $PIT/$DIR
  run cvs -z3 update -ACPd -I .gitignore -I .git
  find . -name .cvsignore | while read X; do cp "$X" "${X%/.cvsignore}/.gitignore"; done
  echo -e "$GITIGNORES" >> .gitignore
  run git add .
  nothing_to_commit || run git commit -a -m "`date +'Fetched at %Y-%m-%d %H:%M:%S'`"
# We could use git-cvsimport instead, but that's way too slow:
#  mkdir -p $PIT/$DIR
#  cd $PIT/$DIR
#  git-cvsimport -v -d "$CVS_SERVER" -r origin
  add_to_supermodule "$DIR"
}
#############################################
# Handing git super/submodules
if $SUPERMODULE; then
  which git-submodule >&/dev/null || \
    die "Error: git >= 1.3.5 required for submodule support. Try --no-supermodule."
  run mkdir -p $PIT
  cd $PIT
  if [ ! -d .git ]; then
     run git init
     echo -e 'xorg/autoconf.cache' > .gitignore
     run git add .gitignore
     run git commit -m 'initial'
  fi
  # Add new submodule's repository to the supermodule's .gitmodules
  add_to_supermodule_gitmodules() {
    SUBDIR="$1"
    GIT_CONFIG=$PIT/.gitmodules git config "submodule.$SUBDIR.path" "$SUBDIR"
    GIT_CONFIG=$PIT/.gitmodules git config "submodule.$SUBDIR.url" "$SUBDIR"
  }
  add_to_supermodule() {
    cd $PIT
    # add_to_supermodule_alternates "$1"
    add_to_supermodule_gitmodules "$1"
    run git add "$1"
  }
else
  add_to_supermodule() { true; }
fi
#############################################
# Directory hashes for change detection
LAST_HASH=.last_dir_hash
dir_hash() {
  find . \( -name $LAST_HASH -o -path ./.git -prune \) -o -type f -ls | sort | md5sum
}
dir_hash_changed() {
  $RECONFIGURE || [ ! -f $LAST_HASH ] || [ "`dir_hash`" != "`cat $LAST_HASH`" ]
}
save_dir_hash() {
  dir_hash > $LAST_HASH
}
#############################################
# Fetching and building libDRM and DRM kernel drivers
fetch_drm() {
  echo "########### Fetch DRM ###########"
  DRM_GIT=git://anongit.freedesktop.org/git/mesa
  fetch_from_git "$PIT" "$DRM_GIT" drm
}
build_libdrm() {
  echo "########### Build libdrm ###########"
  run cd $PIT/drm
  ! $GIT_CLEAN  || run git clean -x -d
  if dir_hash_changed; then
    run ./autogen.sh
    CFLAGS="$FLAGS" run ./configure --prefix=$DEST --quiet
    save_dir_hash
  fi
  ! $MAKE_CLEAN || run make clean
  run make
  save_dir_hash
  run make install
  save_dir_hash
}
build_drm_modules() {
  echo "########### Build DRM kernel modules ###########"
  run cd $PIT/drm/linux-core
  ! $GIT_CLEAN  || run git clean -x -d
  ! $MAKE_CLEAN || run make clean
  run make DRM_MODULES="radeon"
  run sudo sh -c \
    'rm -fv /lib/modules/`uname -r`/kernel/drivers/char/drm/*.ko; \
     cp -v *.ko /lib/modules/`uname -r`/extra/; \
     /sbin/depmod -a'
}
#############################################
# Fetching Mesa
fetch_mesa() {
  echo "########### Fetching Mesa ###########"
  MESA_GIT=git://anongit.freedesktop.org/git/mesa
  run mkdir -p $PIT
  run cd $PIT
  fetch_from_git "$PIT" "$MESA_GIT" mesa
}
#############################################
# Building Mesa (do this after installing base X.org libraries
build_mesa() { (
  echo "########### Building Mesa ###########"
  # This uses both old-style and new-style vars, to support older Mesa snapshots.
  run cd $PIT/mesa
  export DRM_SOURCE_PATH=$PIT/drm
  export PKG_CONFIG_PATH="$DEST/lib/pkgconfig:$PKG_CONFIG_PATH"
  export DRM_SOURCE_PATH="$PIT/drm"
  export DESTDIR=$DEST  INSTALL_DIR=$DEST
  export DRI_DRIVER_INSTALL_DIR=$DEST/lib/dri
  export DRI_DIRS='r300 r200 r128 radeon'
  export OPT_FLAGS="$FLAGS"
  export PATH="$DEST/bin:$PATH"
  run mkdir -p $DRI_DRIVER_INSTALL_DIR
  ! $GIT_CLEAN  || run git clean -x -d
  ! $MAKE_CLEAN || run make clean
  if [ -e configs/current ]; then
    run make -e
  else
    run make -e linux-dri-x86
  fi
  run make -e install
  run cp -v lib/*_dri.so $DRI_DRIVER_INSTALL_DIR
) }
#############################################
# Fetching X.org
fetch_xorg() {
  echo "########### Fetching (selected) X.org modules ###########"
  XORG_GIT=git://anongit.freedesktop.org/git
  run mkdir -p $PIT/xorg
  for D in "${XORG_MODULES[@]}"; do
    if [[ $D == xcb/* ]] && ! $USE_XCB; then continue; fi
    fetch_from_git $PIT/xorg "$XORG_GIT" "$D" "${D#xorg/}"
  done
}
#############################################
# Building and installing X.org
# (On repeated runs we avoid rerunning autotools if nothing changed.)
build_x_module() { (
  D="${1#xorg/}"
  echo "########### Building xorg/$D ###########"
  export PATH="$DEST/bin:$PATH"
  export PKG_CONFIG_PATH="$DEST/lib/pkgconfig:$PKG_CONFIG_PATH"
  export ACLOCAL="${AC_LOCAL:-aclocal} -I $DEST/share/aclocal"
  export LD_LIBRARY_PATH="$DEST/lib:$LD_LIBRARY_PATH"
  if [ $D == "xserver" ]; then
    CONF_OPT="--with-mesa-source=$PIT/mesa --enable-xorg --disable-dmx --disable-xvfb --disable-xnest --disable-xprint --disable-freetype --disable-xselinux"
  elif [ $D == "lib/libX11" ] && ! $USE_XCB; then
    CONF_OPT="--with-xcb=no"
  else
    CONF_OPT=
  fi
  run cd $PIT/xorg/$D
  ! $GIT_CLEAN  || run git clean -x -d
  if dir_hash_changed; then
    CFLAGS="$FLAGS" run sh autogen.sh --prefix=$DEST --quiet $CONF_OPT
      # --cache-file=$PIT/xorg/autoconf.cache 
    save_dir_hash
  fi
  ! $MAKE_CLEAN || run make clean
  run make
  save_dir_hash
  run make install
  save_dir_hash
  if [ $D == "pixman" ]; then # as of 2007-08-07 pixman needs this hack:
    [ -e $DEST/include/pixman.h ] || run ln -fs pixman-1/pixman.h $DEST/include/pixman.h
  fi
) }
build_xorg() {
  run cd $PIT/xorg
  run mkdir -p $DEST/share/aclocal
  run mkdir -p $DEST/var/log
  for D in "${XORG_MODULES[@]}"; do
    if [[ $D == xcb/* ]] && ! $USE_XCB; then continue; fi
    build_x_module $D || return 1
  done
  run sudo sh -c "chown -v root $DEST/bin/Xorg; \
                  chmod -v 4750 $DEST/bin/Xorg"
}
#############################################
# Fetching and building xkeyboard-config
fetch_xkeyboard_config() {
  echo "########### Fetching xkeyboard-config ###########"
  XKBC_CVS=":pserver:anoncvs@cvs.freedesktop.org:2401/cvs/xkeyboard-config"
  XKBC_DIR=xkeyboard-config
  XKBC_GITIGNORES='install-sh\nmissing\npo/stamp-it'
  fetch_from_cvs "$XKBC_CVS" "$XKBC_DIR" "$XKBC_GITIGNORES"
}
build_xkeyboard_config() { (
  echo "########### Building xkeyboard-config ###########"
  run cd $PIT/xkeyboard-config
  run ./autogen.sh
  export PKG_CONFIG_PATH="$DEST/lib/pkgconfig:$PKG_CONFIG_PATH"
  export PATH="$DEST/bin:$PATH"
  CFLAGS="$FLAGS" run ./configure --quiet --prefix=$DEST \
    --with-xkb-base=$DEST/share/X11/xkb --with-xkb-rules-symlink=xorg
  run make
  # "make install" replaces share/X11/xkb/compiled.tmp with a junk symlink, so override it:
  mv $DEST/share/X11/xkb/compiled $DEST/share/X11/xkb/compiled.tmp
  run make install
  rm -f $DEST/share/X11/xkb/compiled
  mv $DEST/share/X11/xkb/compiled.tmp $DEST/share/X11/xkb/compiled
) }
#############################################
# Fetching and building the synaptics driver
fetch_synaptics() {
  echo "########### Fetch synaptics ###########"
  SYN_GIT=http://web.telia.com/~u89404340/touchpad/synaptics/.git
  fetch_from_git "$PIT" "$SYN_GIT" '' synaptics
}
build_synaptics() { (
  echo "########### Build synaptics ###########"
  run cd $PIT/synaptics
  export PKG_CONFIG_PATH="$DEST/lib/pkgconfig:$PKG_CONFIG_PATH"
  export PATH="$DEST/bin:$PATH"
  export CPATH="$DEST/include:$CPATH"
  ! $GIT_CLEAN  || run git clean -x -d
  ! $MAKE_CLEAN || run make clean
  run make
  run make install PREFIX="$DEST" MANDIR="$DEST/share/man"
  #run cp -v synaptics_drv.so $DEST/lib/xorg/modules/input/
) }
#############################################
# Creating a script which sets env vars
create_xsetenv() {
  echo "Creating $DEST/bin/xsetenv"
  cat <<EOF > $DEST/bin/xsetenv || die "Can't create $DEST/bin/xsetenv"
export PATH="$DEST/bin:$PATH" 
export LD_LIBRARY_PATH="$DEST/lib:$LD_LIBRARY_PATH"
export LIBGL_DRIVERS_PATH=$DEST/lib/dri
EOF
}
#############################################
# Actual fetching and building:
if $FETCH; then
   fetch_drm
   fetch_mesa
   fetch_xorg
   fetch_xkeyboard_config
   fetch_synaptics
fi
if $BUILD; then
   build_libdrm
   build_drm_modules
   build_xorg
   build_mesa
   build_xkeyboard_config
   build_synaptics
   create_xsetenv
fi
#############################################
# Saving install and super state to git commits:
if $BUILD; then
  echo "########### Record installation dir commit ###########"
  cd $DEST
  if [ ! -d .git ]; then
    run git init
    echo '/var/log' > .gitignore
    run git add .gitignore
    run git commit -a -m "initial"
  fi
  run git add .
  if ! nothing_to_commit; then
    run git commit -a -m "`date +'Installed at %Y-%m-%d %H:%M:%S'`"
    run git gc
  fi
  add_to_supermodule "$DEST_SUBDIR"
fi
if $SUPERMODULE; then
  echo "########### Record supermodule commit ###########"
  cd $PIT
  nothing_to_commit || run git commit -m "`date +'Snapshot at %Y-%m-%d %H:%M:%S'` `$FETCH && echo fetch` `$BUILD && echo build`"
fi
#############################################
echo
echo "Done."
! $FETCH || echo "Run '. $DEST/bin/xsetenv' to point env vars to this installation."
