]> granicus.if.org Git - handbrake/commitdiff
BuildSystem: general, configure and Xcode updates.
authorkonablend <kona8lend@gmail.com>
Sun, 8 Mar 2009 22:50:57 +0000 (22:50 +0000)
committerkonablend <kona8lend@gmail.com>
Sun, 8 Mar 2009 22:50:57 +0000 (22:50 +0000)
*** NOTICE:
This changeset requires a clean build directory. Please issue 'make xclean' inside
build dir(s) after 'svn up'. This will help ensure there are no unexpected results.

*** GENERAL:
- renamed makevar PROJECT/ -> SRC/ for clarity.
- renamed makevar PREFIX.install/ -> PREFIX/ for clarity.
- split custom GNUmakefile overrides into defs/rules files.
- inserted optional level of make customization at SRC/ level; see docs.
- dropped HB.repo.wcversion (svnversion is no longer used).
- corrected several 'rm' usages to use -f flag which avoids some build errors.
- refreshed generated 00-Building.*.txt docs; work still in progress on the wiki front.

*** CONFIGURE:
- made configure more robust; configure may now be run outside of build directory!
- adding log recording of configure activities.
- improved readability of default options for configure
- added:

    --force             overwrite existing build config
    --src=DIR           specify top-level source dir [.]
    --build=DIR         specify build scratch/output dir [.]
    --prefix=DIR        specify install dir for products [/Applications]

- dropped --launch-force (replaced by --force)
- dropped --launch-dir (replaced by --build)
- dropped --launch-log

*** XCODE:
- renamed pbxproj definition EXTERNAL_PROJECT -> EXTERNAL_SRC for clarity.
- fixed all configurations to default to EXTERNAL_JOBS=1 .
- enabled Xcode internal parallelization (libhb, HandBrakeCLI and HandBrake benefit).
- make now tickles Xcode build files to cause Info.plist regeneration and posting to HandBrake.app output;
  ie: svn up; click build and HandBrake.app's about panel will reflect the new repository rev.

*** DARWIN:
- added support to build universal binaries; see docs.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2242 b64f7644-9d1e-0410-96f1-a4d463321fa5

34 files changed:
00-Building.cygwin.txt
00-Building.linux.txt
00-Building.osx.txt
configure
contrib/bzip2/module.defs
contrib/ffmpeg/module.defs
contrib/xvidcore/module.defs
doc/module.defs
doc/module.rules
doc/texi/Building.osx.texi
doc/texi/base/handbrake.texi.m4
doc/texi/building/chapter.quickstart.texi
doc/texi/building/chapter.via.terminal.texi
doc/texi/building/chapter.via.xcode.texi
doc/texi/building/command.texi
gtk/module.defs
gtk/module.rules
libhb/module.defs
libhb/module.rules
libhb/project.h.m4
macosx/HandBrake.xcodeproj/project.pbxproj
macosx/module.defs
macosx/module.rules
macosx/module.xcode
make/configure.py
make/include/contrib.defs
make/include/main.defs
make/include/main.rules
make/variant/darwin.defs
make/variant/darwin.rules
make/variant/freebsd.defs
make/xcodemake
test/module.defs
test/module.rules

index dca7d9064d5ac4343b31a65ce8323e2d5656fa28..70cbd53dd0134ddc9ad9207c661936ea690cffc1 100644 (file)
@@ -1,4 +1,4 @@
-Guide to Building HandBrake svn2213 (2009030301) on Cygwin
+Guide to Building HandBrake svn2241 (2009030801) on Cygwin
 **********************************************************
 
 Table of Contents
@@ -16,7 +16,8 @@ Table of Contents
     5.4.1 Global
     5.4.2 General Modules
     5.4.3 Contrib Modules
-    5.4.4 Contrib Aggregates
+    5.4.4 Contrib Touch and Untouch
+    5.4.5 Contrib Aggregates
   5.5 Customizing Make
 
 
@@ -81,14 +82,17 @@ recommended you use these versions or similar:
 ************
 
 This chapter is for building from a terminal/shell environment in as
-few commands as possible. If more flexibility is required you should
-skip this chapter and jump to *Note overview::.
+few commands as possible. Upon completion of the following commands you
+should have a fresh build of HandBrake. Further instructions are
+available beginning with *Note overview:: which describes procedures
+suitable for repeating builds. This chapter should be skipped by those
+seeking more than a minimalist build.
 
      svn checkout svn://svn.handbrake.fr/HandBrake/trunk hb-trunk
      cd hb-trunk
      ./configure --launch
 
-The special option `--launch' selected launch mode and performs the
+The special option `--launch' selects launch mode and performs the
 following steps:
 
    * assert scratch directory `build/' does not exist
@@ -99,10 +103,14 @@ following steps:
 
    * launch `make'
 
-   * capture build output to `build/log.txt'
+   * capture build output to `build/log/build.txt'
 
    * echo build output
 
+   * print elapsed time
+
+   * indicate if build ultimately succeeded or failed
+
 4 Overview
 **********
 
@@ -133,16 +141,14 @@ use Subversion 1.5.0 or higher. Lower versions should also work.
 
 Configure the build system.
 
-     rm -fr build/
-     mkdir build/
-     cd build/
-     ../configure
+     ./configure
 
-Create a scratch directory which will contain all files created during
-the build process. The directory name is arbitrary but we recommend
-something simple and descriptive. One directory is required for each
-distinctly configured build. We name our directory `build' for example
-purposes.
+Configure will automatically create a scratch build directory `build'
+unless you use GNU-style build procedures and first `cd' to a directory
+other than top-level source. Additionally you may specify use `--build'
+to specify the directory. The name of the directory is arbitrary but it
+is recommended to use something which indicates transient files which
+are not checked into the repository.
 
 The `configure' utility accepts many options. It is recommended that
 you specify `--help' for the complete list of options. The following
@@ -151,14 +157,26 @@ options are also documented here:
 `--help'
      List available options.
 
-`--prefix=PREFIX'
+`--src=DIR'
+     Specify top-level source directory for HandBrake sources.
+
+`--build=DIR'
+     Specify destination directory for final product install. The
+     default is to use either `build' if in the top-level source
+     directory, otherwise `.'
+
+`--prefix=DIR'
      Specify destination directory for final product install.  This
      defaults to a reasonable platform-specific value.
 
+`--launch'
+     All-in-one option which launches the build and logs output
+     automatically.  Useful for novices and quickstart procedures.
+
 `--disable-xcode'
-     Disable driving the build through Xcode. If this option is
-     disabled only `HandBrakeCLI' will be produced and Xcode will not
-     be invoked. Mac OS X only.
+     Disable shunting the build through Xcode. If this option is
+     applied, `HandBrakeCLI' will be produced in a similare fashion as
+     it is on other platforms; sans Xcode. Mac OS X only.
 
 `--disable-gtk'
      Disable building the GTK GUI on applicable platforms such as
@@ -179,10 +197,6 @@ options are also documented here:
      architectures. The available choices are hard-coded per platform
      and no sanity checks for the required tools are performed.
 
-`--gcc=EXE'
-     Specify the `gcc' executable to use where EXE is the executable
-     name which is either absolute or environment `PATH' is searched
-     accordingly.
 
 Clean-room procedures dictate that when certain factors change, old
 builds should be scrapped and new builds configured. This is the main
@@ -261,6 +275,14 @@ period.
      Build auto-generated project documentation. Various articles are
      produced and may be found in `build/doc/articles'.
 
+`make report.help'
+     Print list of available makefile vars report targets.  These
+     reports detail var definitions and expanded values used by the
+     build system.  For experts only.
+
+`make report.all'
+     Convenience target which aggregates all reports.  For experts only.
+
 5.4.2 General Modules
 ---------------------
 
@@ -313,7 +335,36 @@ Contrib modules such as `a52dec', `bzip2', `faac', `faad2', `ffmpeg',
      Extra clean module; first invokes uninstall then recursively
      removes the module build directory.
 
-5.4.4 Contrib Aggregates
+5.4.4 Contrib Touch and Untouch
+-------------------------------
+
+Also available are some very granular targets which help force builds
+from specific cycle points. The following targets are available to
+touch and untouch the respective module target; this will force the
+build system to treat the target as satisfied after a touch or
+unsatisfied after an untouch:
+
+   * make MODULE.extract.touch
+
+   * make MODULE.extract.untouch
+
+   * make MODULE.patch.touch
+
+   * make MODULE.patch.untouch
+
+   * make MODULE.configure.touch
+
+   * make MODULE.configure.untouch
+
+   * make MODULE.build.touch
+
+   * make MODULE.build.untouch
+
+   * make MODULE.install.touch
+
+   * make MODULE.install.untouch
+
+5.4.5 Contrib Aggregates
 ------------------------
 
 For convenience, the following targets aggregate the all contrib
@@ -341,15 +392,34 @@ modules' respective targets together:
 ====================
 
 If the need arises to override settings in the build system
-(essentially gnu-make variables) the recommended method is to
-create/edit the optional include file `build/GNUmakefile.custom' which
-sits adjacent to the top-level makefile. Do not check this file into
-the respository. The sole purpose is to allow a place to store local
-build settings for testing, tweaking, and experimenting with build
-configuration without losing your settings if `configure' is invoked;
-ie: `configure' would overwrite `GNUmakefile' and any customizations
-contained therein would be lost. Here is a short example of what the
-contents of `build/GNUmakefile.custom' might contain:
+(essentially gnu-make variables) the recommended method is to create
+optional include files which are automatically included if present and
+follow this naming convention; Do not check these files into the
+respository:
+
+`_SRC_/custom.defs'
+     Custom makevar definitions outside `build'. Suitable for settings
+     which apply across all builds for a particular checkout; or which
+     survives manual removal of `build'.
+
+`_SRC_/custom.rules'
+     Custom make rules outside `build'. Suitable for settings which
+     apply across all builds for a particular checkout; or which
+     survives manual removal of `build'.
+
+`_BUILD_/GNUmakefile.custom.defs'
+     Custom makevar definitions specific to a `build' directory.
+
+`_BUILD_/GNUmakefile.custom.rules'
+     Custom makevar rules specific to a `build' directory.
+
+
+The purpose is to allow a place to store local build settings for
+testing, tweaking, and experimenting with build configuration without
+losing your settings if `configure' is invoked; ie: `configure' would
+overwrite `GNUmakefile' and any customizations contained therein would
+be lost. Here is a short example of what the contents of
+`_SRC_/custom.defs' might contain:
 
      ## bump to gcc-4.2 in current path
      GCC.gcc = gcc-4.2
@@ -357,3 +427,6 @@ contents of `build/GNUmakefile.custom' might contain:
      ## replace optimize for 'speed' with more agressive settings
      GCC.args.O.speed = -O3 -fomit-frame-pointer -msse4.2
 
+See also `make report.help' which displays a set of reports used to
+dump makefile vars.
+
index ae6158e968c3564bea44b957fe8825f21743d6d4..955e4cd4aaa6c8e72236db1dac18cff7f023566c 100644 (file)
@@ -1,4 +1,4 @@
-Guide to Building HandBrake svn2213 (2009030301) on Linux
+Guide to Building HandBrake svn2241 (2009030801) on Linux
 *********************************************************
 
 Table of Contents
@@ -16,7 +16,8 @@ Table of Contents
     5.4.1 Global
     5.4.2 General Modules
     5.4.3 Contrib Modules
-    5.4.4 Contrib Aggregates
+    5.4.4 Contrib Touch and Untouch
+    5.4.5 Contrib Aggregates
   5.5 Customizing Make
 
 
@@ -147,14 +148,17 @@ To install these packages:
 ************
 
 This chapter is for building from a terminal/shell environment in as
-few commands as possible. If more flexibility is required you should
-skip this chapter and jump to *Note overview::.
+few commands as possible. Upon completion of the following commands you
+should have a fresh build of HandBrake. Further instructions are
+available beginning with *Note overview:: which describes procedures
+suitable for repeating builds. This chapter should be skipped by those
+seeking more than a minimalist build.
 
      svn checkout svn://svn.handbrake.fr/HandBrake/trunk hb-trunk
      cd hb-trunk
      ./configure --launch
 
-The special option `--launch' selected launch mode and performs the
+The special option `--launch' selects launch mode and performs the
 following steps:
 
    * assert scratch directory `build/' does not exist
@@ -165,10 +169,14 @@ following steps:
 
    * launch `make'
 
-   * capture build output to `build/log.txt'
+   * capture build output to `build/log/build.txt'
 
    * echo build output
 
+   * print elapsed time
+
+   * indicate if build ultimately succeeded or failed
+
 4 Overview
 **********
 
@@ -199,16 +207,14 @@ use Subversion 1.5.0 or higher. Lower versions should also work.
 
 Configure the build system.
 
-     rm -fr build/
-     mkdir build/
-     cd build/
-     ../configure
+     ./configure
 
-Create a scratch directory which will contain all files created during
-the build process. The directory name is arbitrary but we recommend
-something simple and descriptive. One directory is required for each
-distinctly configured build. We name our directory `build' for example
-purposes.
+Configure will automatically create a scratch build directory `build'
+unless you use GNU-style build procedures and first `cd' to a directory
+other than top-level source. Additionally you may specify use `--build'
+to specify the directory. The name of the directory is arbitrary but it
+is recommended to use something which indicates transient files which
+are not checked into the repository.
 
 The `configure' utility accepts many options. It is recommended that
 you specify `--help' for the complete list of options. The following
@@ -217,14 +223,26 @@ options are also documented here:
 `--help'
      List available options.
 
-`--prefix=PREFIX'
+`--src=DIR'
+     Specify top-level source directory for HandBrake sources.
+
+`--build=DIR'
+     Specify destination directory for final product install. The
+     default is to use either `build' if in the top-level source
+     directory, otherwise `.'
+
+`--prefix=DIR'
      Specify destination directory for final product install.  This
      defaults to a reasonable platform-specific value.
 
+`--launch'
+     All-in-one option which launches the build and logs output
+     automatically.  Useful for novices and quickstart procedures.
+
 `--disable-xcode'
-     Disable driving the build through Xcode. If this option is
-     disabled only `HandBrakeCLI' will be produced and Xcode will not
-     be invoked. Mac OS X only.
+     Disable shunting the build through Xcode. If this option is
+     applied, `HandBrakeCLI' will be produced in a similare fashion as
+     it is on other platforms; sans Xcode. Mac OS X only.
 
 `--disable-gtk'
      Disable building the GTK GUI on applicable platforms such as
@@ -245,10 +263,6 @@ options are also documented here:
      architectures. The available choices are hard-coded per platform
      and no sanity checks for the required tools are performed.
 
-`--gcc=EXE'
-     Specify the `gcc' executable to use where EXE is the executable
-     name which is either absolute or environment `PATH' is searched
-     accordingly.
 
 Clean-room procedures dictate that when certain factors change, old
 builds should be scrapped and new builds configured. This is the main
@@ -327,6 +341,14 @@ period.
      Build auto-generated project documentation. Various articles are
      produced and may be found in `build/doc/articles'.
 
+`make report.help'
+     Print list of available makefile vars report targets.  These
+     reports detail var definitions and expanded values used by the
+     build system.  For experts only.
+
+`make report.all'
+     Convenience target which aggregates all reports.  For experts only.
+
 5.4.2 General Modules
 ---------------------
 
@@ -379,7 +401,36 @@ Contrib modules such as `a52dec', `bzip2', `faac', `faad2', `ffmpeg',
      Extra clean module; first invokes uninstall then recursively
      removes the module build directory.
 
-5.4.4 Contrib Aggregates
+5.4.4 Contrib Touch and Untouch
+-------------------------------
+
+Also available are some very granular targets which help force builds
+from specific cycle points. The following targets are available to
+touch and untouch the respective module target; this will force the
+build system to treat the target as satisfied after a touch or
+unsatisfied after an untouch:
+
+   * make MODULE.extract.touch
+
+   * make MODULE.extract.untouch
+
+   * make MODULE.patch.touch
+
+   * make MODULE.patch.untouch
+
+   * make MODULE.configure.touch
+
+   * make MODULE.configure.untouch
+
+   * make MODULE.build.touch
+
+   * make MODULE.build.untouch
+
+   * make MODULE.install.touch
+
+   * make MODULE.install.untouch
+
+5.4.5 Contrib Aggregates
 ------------------------
 
 For convenience, the following targets aggregate the all contrib
@@ -407,15 +458,34 @@ modules' respective targets together:
 ====================
 
 If the need arises to override settings in the build system
-(essentially gnu-make variables) the recommended method is to
-create/edit the optional include file `build/GNUmakefile.custom' which
-sits adjacent to the top-level makefile. Do not check this file into
-the respository. The sole purpose is to allow a place to store local
-build settings for testing, tweaking, and experimenting with build
-configuration without losing your settings if `configure' is invoked;
-ie: `configure' would overwrite `GNUmakefile' and any customizations
-contained therein would be lost. Here is a short example of what the
-contents of `build/GNUmakefile.custom' might contain:
+(essentially gnu-make variables) the recommended method is to create
+optional include files which are automatically included if present and
+follow this naming convention; Do not check these files into the
+respository:
+
+`_SRC_/custom.defs'
+     Custom makevar definitions outside `build'. Suitable for settings
+     which apply across all builds for a particular checkout; or which
+     survives manual removal of `build'.
+
+`_SRC_/custom.rules'
+     Custom make rules outside `build'. Suitable for settings which
+     apply across all builds for a particular checkout; or which
+     survives manual removal of `build'.
+
+`_BUILD_/GNUmakefile.custom.defs'
+     Custom makevar definitions specific to a `build' directory.
+
+`_BUILD_/GNUmakefile.custom.rules'
+     Custom makevar rules specific to a `build' directory.
+
+
+The purpose is to allow a place to store local build settings for
+testing, tweaking, and experimenting with build configuration without
+losing your settings if `configure' is invoked; ie: `configure' would
+overwrite `GNUmakefile' and any customizations contained therein would
+be lost. Here is a short example of what the contents of
+`_SRC_/custom.defs' might contain:
 
      ## bump to gcc-4.2 in current path
      GCC.gcc = gcc-4.2
@@ -423,3 +493,6 @@ contents of `build/GNUmakefile.custom' might contain:
      ## replace optimize for 'speed' with more agressive settings
      GCC.args.O.speed = -O3 -fomit-frame-pointer -msse4.2
 
+See also `make report.help' which displays a set of reports used to
+dump makefile vars.
+
index 471ffda712c5e97dcb5963b0ff6c6ba45152a99a..0d91d75a8acfbef4426b8f9a8e531b36ac8f9240 100644 (file)
@@ -1,4 +1,4 @@
-Guide to Building HandBrake svn2213 (2009030301) on Mac OS X
+Guide to Building HandBrake svn2241 (2009030801) on Mac OS X
 ************************************************************
 
 Table of Contents
@@ -16,8 +16,10 @@ Table of Contents
     5.4.1 Global
     5.4.2 General Modules
     5.4.3 Contrib Modules
-    5.4.4 Contrib Aggregates
+    5.4.4 Contrib Touch and Untouch
+    5.4.5 Contrib Aggregates
   5.5 Customizing Make
+  5.6 Universal Binaries
 6 Building via Xcode
   6.1 Checkout Sources
   6.2 Build
@@ -80,14 +82,17 @@ recommended you use these versions or similar:
 ************
 
 This chapter is for building from a terminal/shell environment in as
-few commands as possible. If more flexibility is required you should
-skip this chapter and jump to *Note overview::.
+few commands as possible. Upon completion of the following commands you
+should have a fresh build of HandBrake. Further instructions are
+available beginning with *Note overview:: which describes procedures
+suitable for repeating builds. This chapter should be skipped by those
+seeking more than a minimalist build.
 
      svn checkout svn://svn.handbrake.fr/HandBrake/trunk hb-trunk
      cd hb-trunk
      ./configure --launch
 
-The special option `--launch' selected launch mode and performs the
+The special option `--launch' selects launch mode and performs the
 following steps:
 
    * assert scratch directory `build/' does not exist
@@ -98,10 +103,14 @@ following steps:
 
    * launch `make'
 
-   * capture build output to `build/log.txt'
+   * capture build output to `build/log/build.txt'
 
    * echo build output
 
+   * print elapsed time
+
+   * indicate if build ultimately succeeded or failed
+
 4 Overview
 **********
 
@@ -135,16 +144,14 @@ use Subversion 1.5.0 or higher. Lower versions should also work.
 
 Configure the build system.
 
-     rm -fr build/
-     mkdir build/
-     cd build/
-     ../configure
+     ./configure
 
-Create a scratch directory which will contain all files created during
-the build process. The directory name is arbitrary but we recommend
-something simple and descriptive. One directory is required for each
-distinctly configured build. We name our directory `build' for example
-purposes.
+Configure will automatically create a scratch build directory `build'
+unless you use GNU-style build procedures and first `cd' to a directory
+other than top-level source. Additionally you may specify use `--build'
+to specify the directory. The name of the directory is arbitrary but it
+is recommended to use something which indicates transient files which
+are not checked into the repository.
 
 The `configure' utility accepts many options. It is recommended that
 you specify `--help' for the complete list of options. The following
@@ -153,14 +160,26 @@ options are also documented here:
 `--help'
      List available options.
 
-`--prefix=PREFIX'
+`--src=DIR'
+     Specify top-level source directory for HandBrake sources.
+
+`--build=DIR'
+     Specify destination directory for final product install. The
+     default is to use either `build' if in the top-level source
+     directory, otherwise `.'
+
+`--prefix=DIR'
      Specify destination directory for final product install.  This
      defaults to a reasonable platform-specific value.
 
+`--launch'
+     All-in-one option which launches the build and logs output
+     automatically.  Useful for novices and quickstart procedures.
+
 `--disable-xcode'
-     Disable driving the build through Xcode. If this option is
-     disabled only `HandBrakeCLI' will be produced and Xcode will not
-     be invoked. Mac OS X only.
+     Disable shunting the build through Xcode. If this option is
+     applied, `HandBrakeCLI' will be produced in a similare fashion as
+     it is on other platforms; sans Xcode. Mac OS X only.
 
 `--disable-gtk'
      Disable building the GTK GUI on applicable platforms such as
@@ -181,10 +200,6 @@ options are also documented here:
      architectures. The available choices are hard-coded per platform
      and no sanity checks for the required tools are performed.
 
-`--gcc=EXE'
-     Specify the `gcc' executable to use where EXE is the executable
-     name which is either absolute or environment `PATH' is searched
-     accordingly.
 
 Clean-room procedures dictate that when certain factors change, old
 builds should be scrapped and new builds configured. This is the main
@@ -263,6 +278,14 @@ period.
      Build auto-generated project documentation. Various articles are
      produced and may be found in `build/doc/articles'.
 
+`make report.help'
+     Print list of available makefile vars report targets.  These
+     reports detail var definitions and expanded values used by the
+     build system.  For experts only.
+
+`make report.all'
+     Convenience target which aggregates all reports.  For experts only.
+
 5.4.2 General Modules
 ---------------------
 
@@ -315,7 +338,36 @@ Contrib modules such as `a52dec', `bzip2', `faac', `faad2', `ffmpeg',
      Extra clean module; first invokes uninstall then recursively
      removes the module build directory.
 
-5.4.4 Contrib Aggregates
+5.4.4 Contrib Touch and Untouch
+-------------------------------
+
+Also available are some very granular targets which help force builds
+from specific cycle points. The following targets are available to
+touch and untouch the respective module target; this will force the
+build system to treat the target as satisfied after a touch or
+unsatisfied after an untouch:
+
+   * make MODULE.extract.touch
+
+   * make MODULE.extract.untouch
+
+   * make MODULE.patch.touch
+
+   * make MODULE.patch.untouch
+
+   * make MODULE.configure.touch
+
+   * make MODULE.configure.untouch
+
+   * make MODULE.build.touch
+
+   * make MODULE.build.untouch
+
+   * make MODULE.install.touch
+
+   * make MODULE.install.untouch
+
+5.4.5 Contrib Aggregates
 ------------------------
 
 For convenience, the following targets aggregate the all contrib
@@ -343,15 +395,34 @@ modules' respective targets together:
 ====================
 
 If the need arises to override settings in the build system
-(essentially gnu-make variables) the recommended method is to
-create/edit the optional include file `build/GNUmakefile.custom' which
-sits adjacent to the top-level makefile. Do not check this file into
-the respository. The sole purpose is to allow a place to store local
-build settings for testing, tweaking, and experimenting with build
-configuration without losing your settings if `configure' is invoked;
-ie: `configure' would overwrite `GNUmakefile' and any customizations
-contained therein would be lost. Here is a short example of what the
-contents of `build/GNUmakefile.custom' might contain:
+(essentially gnu-make variables) the recommended method is to create
+optional include files which are automatically included if present and
+follow this naming convention; Do not check these files into the
+respository:
+
+`_SRC_/custom.defs'
+     Custom makevar definitions outside `build'. Suitable for settings
+     which apply across all builds for a particular checkout; or which
+     survives manual removal of `build'.
+
+`_SRC_/custom.rules'
+     Custom make rules outside `build'. Suitable for settings which
+     apply across all builds for a particular checkout; or which
+     survives manual removal of `build'.
+
+`_BUILD_/GNUmakefile.custom.defs'
+     Custom makevar definitions specific to a `build' directory.
+
+`_BUILD_/GNUmakefile.custom.rules'
+     Custom makevar rules specific to a `build' directory.
+
+
+The purpose is to allow a place to store local build settings for
+testing, tweaking, and experimenting with build configuration without
+losing your settings if `configure' is invoked; ie: `configure' would
+overwrite `GNUmakefile' and any customizations contained therein would
+be lost. Here is a short example of what the contents of
+`_SRC_/custom.defs' might contain:
 
      ## bump to gcc-4.2 in current path
      GCC.gcc = gcc-4.2
@@ -359,6 +430,36 @@ contents of `build/GNUmakefile.custom' might contain:
      ## replace optimize for 'speed' with more agressive settings
      GCC.args.O.speed = -O3 -fomit-frame-pointer -msse4.2
 
+See also `make report.help' which displays a set of reports used to
+dump makefile vars.
+
+5.6 Universal Binaries
+======================
+
+This section outlines convenience procedures for creating Universal
+Binaries for all the architectures.
+
+     Note: The dummy (container) build configuration uses
+     `--disable-xcode'; but the nested architecture builds will all
+     make full use of Xcode.
+
+Create a dummy (container) build configuration and use it to launch a
+nested-build for each architecture serially; optionally you may
+substitute `make ub.build.serial' for `make ub.build.parallel' if your
+machine has the horsepower:
+
+     ./configure --disable-xcode
+     cd build/
+     make ub.build.serial
+     make ub.combine
+
+To specify a subset of architectures to be built first create/edit
+`_SRC_/custom.defs' with the following override to build UB for `i386'
+and `x86_64' before invoking `make':
+
+     ## prefer i386 (order is important)
+     UB.archs = i386 x86_64
+
 6 Building via Xcode
 ********************
 
@@ -470,21 +571,21 @@ The following user defined settings are used in Xcode project for the
 external build system:
 
 `EXTERNAL_BUILD'
-     Specifies the build location for each configuration.  It is highly
-     recommended the locations always evaluate to a unique pathname
-     when factoring the configuration name.
+     Specifies the build (scratch) directory for each configuration.
 
 `EXTERNAL_JOBS'
      Specifies the concurrency factor for the external build system
-     when builds are launched from within Xcode.  This variable is
-     meant to be customized by the developer for faster builds if the
-     host supports it.
+     when builds are launched from within Xcode.  Modify for faster
+     external builds if your system has the horsepower and resources.
+     Specifying a value greater than the number of CPU cores (or
+     virtual cores) in your system is unlikely to produce gains and
+     will needlessly consume extra resources.
 
 `EXTERNAL_METHOD'
-     This variable is used for internal/external build coordination and
+     Do not modify; Used for internal/external build coordination and
      must always be `xcode'.
 
-`EXTERNAL_PROJECT'
-     Specifies the directory which is top of HandBrake source tree.
+`EXTERNAL_SRC'
+     Specifies the top-level source directory for HandBrake.
 
 
index 8ea57efbf9646fba5f8dbcf6176b5ac125dc3959..09c80b7fe194404f3cd01b8e692727eec45a9070 100755 (executable)
--- a/configure
+++ b/configure
@@ -13,7 +13,7 @@ inpath()
     return 1
 }
 
-for p in python2.6 python2.5 python2.4
+for p in python2.7 python2.6 python2.5 python2.4 python2 python
 do
     if ( inpath $p ); then
         exec $p `dirname $0`/make/configure.py "$@"
index bda2a132fb61275a6da47f569078f1ac7fc32e96..4384f83f7ae73e25c56b698945d4786707adb336 100644 (file)
@@ -19,7 +19,7 @@ define BZIP2.INSTALL
 endef
 
 define BZIP2.UNINSTALL
-    $(RM.exe) $(CONTRIB.build/)lib/libbz2.a
-    $(RM.exe) $(CONTRIB.build/)include/bzlib.h
+    $(RM.exe) -f $(CONTRIB.build/)lib/libbz2.a
+    $(RM.exe) -f $(CONTRIB.build/)include/bzlib.h
     $(RM.exe) -f $(BZIP2.INSTALL.target)
 endef
index b41291018343ca11135543c91b86400f9108ba8c..04b0609109e83ca81d8a8e622fad277585088cb8 100644 (file)
@@ -28,5 +28,5 @@ FFMPEG.CONFIGURE.extra = \
     --extra-ldflags="$(call fn.ARGS,FFMPEG.GCC,*archs) -L$(call fn.ABSOLUTE,$(CONTRIB.build/)lib)"
 
 ifeq ($(BUILD.cross),1)
-    FFMPEG.CONFIGURE.extra += --enable-cross-compile --arch=$(FFMPEG.GCC.archs)
+    FFMPEG.CONFIGURE.extra += --enable-cross-compile --arch=$(BUILD.machine)
 endif
index f25d89d7780533a295c53477a7b2c97da5d8abcb..dee8b3e452783c130830b621e4638991be53db49 100644 (file)
@@ -9,6 +9,8 @@ XVIDCORE.CONFIGURE.dir = $(XVIDCORE.EXTRACT.dir/)build/generic/
 XVIDCORE.BUILD.dir      = $(XVIDCORE.EXTRACT.dir/)build/generic/
 XVIDCORE.BUILD.ntargets = libxvidcore.a
 
+XVIDCORE.CLEAN.dir      = $(XVIDCORE.EXTRACT.dir/)build/generic/
+
 define XVIDCORE.INSTALL
     $(CP.exe) $(XVIDCORE.EXTRACT.dir/)build/generic/=build/libxvidcore.a $(CONTRIB.build/)lib/
     $(CP.exe) $(XVIDCORE.EXTRACT.dir/)src/xvid.h $(CONTRIB.build/)include/
@@ -16,7 +18,7 @@ define XVIDCORE.INSTALL
 endef
 
 define XVIDCORE.UNINSTALL
-    $(RM.exe) $(CONTRIB.build/)lib/libxvidcore.a
-    $(RM.exe) $(CONTRIB.build/)include/xvid.h
+    $(RM.exe) -f $(CONTRIB.build/)lib/libxvidcore.a
+    $(RM.exe) -f $(CONTRIB.build/)include/xvid.h
     $(RM.exe) -f $(XVIDCORE.INSTALL.target)
 endef
index 1697c9b695f7a7d363fbc67466db0ec5945f2f22..84d924ab7841417db4ef1195ca000a93843c4d7f 100644 (file)
@@ -1,6 +1,6 @@
 $(eval $(call import.MODULE.defs,DOC,doc))
 
-DOC.in/  = $(PROJECT/)doc/
+DOC.in/  = $(SRC/)doc/
 DOC.out/ = $(BUILD/)doc/
 
 DOC.out.api/      = $(DOC.out/)api/
index f86b66c09dfe6b5b674eb126d5a34d57530fae8a..54fec6dc7a43119d449cb8cbf52d2048ffba251d 100644 (file)
@@ -32,6 +32,8 @@ $(DOC.m4.out): $(DOC.M4.deps)
 $(DOC.m4.out): $(DOC.out/)%: $(DOC.in/)%.m4
        $(call DOC.M4,$@,$<)
 
+clean: doc.clean
+
 ###############################################################################
 
 #.PHONY: wiki.post wiki.sync wiki.rm wiki.add wiki.propset wiki.clean
index a554f7a0e4ce596e141d97fced868e2f248980e9..a02ec61316490a12f1164b664bdeaf7c7fc97b2d 100644 (file)
@@ -37,5 +37,33 @@ Building on @value{OS.osx} is well supported. It is the reference platform for @
 @chapter Overview
 The two general methods to build on @value{OS.osx} are building from @b{terminal} or @b{Xcode}. The preferred method for automated and repeatable builds is to use the terminal. Otherwise the choice is generally up to the individual. In essence, the terminal actually invokes @command{xcodebuild} to build the very same targets contained in the Xcode project.
 
+@c %**-------------------------------------------------------------------------
 @include building/chapter.via.terminal.texi
+
+@c %**-------------------------------------------------------------------------
+@anchor{terminal.ub}
+@section Universal Binaries
+This section outlines convenience procedures for creating Universal Binaries for all the architectures.
+
+@quotation Note
+The dummy (container) build configuration uses @command{--disable-xcode}; but the nested architecture builds will all make full use of Xcode.
+@end quotation
+
+Create a dummy (container) build configuration and use it to launch a nested-build for each architecture @i{serially}; optionally you may substitute @command{make ub.build.serial} for @command{make ub.build.parallel} if your machine has the horsepower:
+
+@example
+./configure --disable-xcode
+cd build/
+make ub.build.serial
+make ub.combine
+@end example
+
+To specify a subset of architectures to be built first create/edit @file{_SRC_/custom.defs} with the following override to build UB for @samp{i386} and @samp{x86_64} before invoking @command{make}:
+
+@example
+## prefer i386 (order is important)
+UB.archs = i386 x86_64
+@end example
+
+@c %**-------------------------------------------------------------------------
 @include building/chapter.via.xcode.texi
index efcfa8d823ee6220c26e267994b6dfd86ea2ff11..0466df77c80cf9d927adce66f96c6aa051170acb 100644 (file)
@@ -25,6 +25,5 @@ dnl
 @set HB.repo.uuid       __HB_repo_uuid
 @set HB.repo.rev        __HB_repo_rev
 @set HB.repo.date       __HB_repo_date
-@set HB.repo.wcversion  __HB_repo_wcversion
 @set HB.repo.official   __HB_repo_official
 @set HB.repo.type       __HB_repo_type
index 9e18db7564428936496ea1d9ecfa1f5acd768eda..6aee76b91b8a27311eb7af803d513f6578783c37 100644 (file)
@@ -5,7 +5,6 @@ This chapter is for building from a terminal/shell environment in as few command
 @example
 @COMMAND.checkout{}
 ./configure --launch
-cd build/
 @end example
 
 The special option @command{--launch} selects launch mode and performs the following steps:
@@ -15,6 +14,8 @@ The special option @command{--launch} selects launch mode and performs the follo
 @item create scratch directory @file{build/}
 @item change to directory @file{build/}
 @item launch @command{make}
-@item capture build output to @file{build/log.txt}
+@item capture build output to @file{build/log/build.txt}
 @item echo build output
+@item print elapsed time
+@item indicate if build ultimately succeeded or failed
 @end itemize
index 29014819e54ac42cb2c67b988b6d4922c783059b..56afb816899a466b031d2fe48ffa7eff8b1dbd5d 100644 (file)
 Configure the build system.
 
 @example
-rm -fr build/
-mkdir build/
-cd build/
-../configure
+./configure
 @end example
 
-Create a scratch directory which will contain all files created during the build process. The directory name is arbitrary but we recommend something simple and descriptive. One directory is required for each distinctly configured build. We name our directory @file{build} for example purposes.
+Configure will automatically create a scratch build directory @file{build} unless you use GNU-style build procedures and first @command{cd} to a directory other than top-level source. Additionally you may specify use @command{--build} to specify the directory. The name of the directory is arbitrary but it is recommended to use something which indicates transient files which are @b{not} checked into the repository.
 
 The @command{configure} utility accepts many options. It is recommended that you specify @command{--help} for the complete list of options. The following options are also documented here:
 
@@ -26,12 +23,22 @@ The @command{configure} utility accepts many options. It is recommended that you
 @item --help
 List available options.
 
-@item --prefix=PREFIX
+@item --src=DIR
+Specify top-level source directory for @value{HB.name} sources.
+
+@item --build=DIR
+Specify destination directory for final product install. The default is to use either @file{build} if in the top-level source directory, otherwise @file{.} 
+
+@item --prefix=DIR
 Specify destination directory for final product install.
 This defaults to a reasonable platform-specific value.
 
+@item --launch
+All-in-one option which launches the build and logs output automatically.
+Useful for novices and quickstart procedures.
+
 @item --disable-xcode
-Disable driving the build through Xcode. If this option is disabled only @command{HandBrakeCLI} will be produced and Xcode will not be invoked. @value{OS.osx} only.
+Disable shunting the build through Xcode. If this option is applied, @command{HandBrakeCLI} will be produced in a similare fashion as it is on other platforms; sans Xcode. @value{OS.osx} only.
 
 @item --disable-gtk
 Disable building the GTK GUI on applicable platforms such as @value{OS.linux}.
@@ -47,8 +54,6 @@ This generally maps to gcc options @samp{-g0}, @samp{-O0}, @samp{-O3}, @samp{-Os
 @item --arch=MODE
 Select build architecture. The available architectures vary by platform. Most platforms support exactly one architecture except @value{OS.osx} which has support for various universal binary architectures. The available choices are hard-coded per platform and no sanity checks for the required tools are performed.
 
-@item --gcc=EXE
-Specify the @command{gcc} executable to use where @b{EXE} is the executable name which is either absolute or environment @samp{PATH} is searched accordingly.
 @end table
 
 Clean-room procedures dictate that when certain factors change, old builds should be scrapped and new builds configured. This is the main reason for requiring a scratch directory; to promote consistent, reliable and clean software builds. The following is a short list of some of the reasons why someone may choose to scrap an existing build:
@@ -207,7 +212,24 @@ For convenience, the following targets aggregate the all contrib modules' respec
 @c %**-------------------------------------------------------------------------
 @anchor{terminal.customizing}
 @section Customizing Make
-If the need arises to override settings in the build system (essentially gnu-make variables) the recommended method is to create/edit the optional include file @file{build/GNUmakefile.custom} which sits adjacent to the top-level makefile. @b{Do not check this file into the respository}. The sole purpose is to allow a place to store local build settings for testing, tweaking, and experimenting with build configuration without losing your settings if @command{configure} is invoked; ie: @command{configure} would overwrite @file{GNUmakefile} and any customizations contained therein would be lost. Here is a short example of what the contents of @file{build/GNUmakefile.custom} might contain:
+If the need arises to override settings in the build system (essentially gnu-make variables) the recommended method is to create optional include files which are automatically included if present and follow this naming convention; @b{Do not check these files into the respository}:
+
+@table @file
+@item _SRC_/custom.defs
+Custom makevar definitions @i{outside} @file{build}. Suitable for settings which apply across all builds for a particular checkout; or which survives manual removal of @file{build}.
+
+@item _SRC_/custom.rules
+Custom make rules @i{outside} @file{build}. Suitable for settings which apply across all builds for a particular checkout; or which survives manual removal of @file{build}.
+
+@item _BUILD_/GNUmakefile.custom.defs
+Custom makevar definitions specific to a @file{build} directory.
+
+@item _BUILD_/GNUmakefile.custom.rules
+Custom makevar rules specific to a @file{build} directory.
+
+@end table
+
+The purpose is to allow a place to store local build settings for testing, tweaking, and experimenting with build configuration without losing your settings if @command{configure} is invoked; ie: @command{configure} would overwrite @file{GNUmakefile} and any customizations contained therein would be lost. Here is a short example of what the contents of @file{_SRC_/custom.defs} might contain:
 
 @example
 ## bump to gcc-4.2 in current path
index df42faca0c56f68a4b0c8939ef52e1e6fcb912b2..a78e0808de16c89137bba078f31fad76d69b538d 100644 (file)
@@ -72,17 +72,16 @@ The following user defined settings are used in Xcode project for the external b
 
 @table @samp
 @item EXTERNAL_BUILD
-Specifies the build location for each configuration.
-It is highly recommended the locations always evaluate to a unique pathname when factoring the configuration name.
+Specifies the build (scratch) directory for each configuration.
 
 @item EXTERNAL_JOBS
 Specifies the concurrency factor for the external build system when builds are launched from within Xcode.
-This variable is meant to be customized by the developer for faster builds if the host supports it.
+Modify for faster external builds if your system has the horsepower and resources. Specifying a value greater than the number of CPU cores (or virtual cores) in your system is unlikely to produce gains and will needlessly consume extra resources.
 
 @item EXTERNAL_METHOD
-This variable is used for internal/external build coordination and must always be @samp{xcode}.
+Do not modify; Used for internal/external build coordination and must always be @samp{xcode}.
 
-@item EXTERNAL_PROJECT
-Specifies the directory which is top of @value{HB.name} source tree.
+@item EXTERNAL_SRC
+Specifies the top-level source directory for @value{HB.name}.
 
 @end table
index 4c21e9892888555354a72e4e4b899a6571978480..3acddc3a09a26aebf0c672dafc35c9d16ee50326 100644 (file)
@@ -1,4 +1,4 @@
 @macro COMMAND.checkout{}
-svn checkout @value{HB.repo.url} @value{HB.acro.lower}@value{HB.repo.branch}
-cd @value{HB.acro.lower}@value{HB.repo.branch}
+svn checkout @value{HB.repo.url} @value{HB.acro.lower}-@value{HB.repo.branch}
+cd @value{HB.acro.lower}-@value{HB.repo.branch}
 @end macro
index ed46be53bdfbcb5d3f9f38a81d4c34253ab8b827..7550a82aed3399ce059a2cfdc0e4cd255591ef52 100644 (file)
@@ -1,7 +1,7 @@
 $(eval $(call import.MODULE.defs,GTK,gtk,LIBHB))
 $(eval $(call import.GCC,GTK))
 
-GTK.src/   = $(PROJECT/)gtk/
+GTK.src/   = $(SRC/)gtk/
 GTK.build/ = $(BUILD/)gtk/
 
 GTK.CONFIGURE.stamp = $(GTK.build/).stamp.configure
index f66bbbb60fda29734375a72a3595406ae02f4d4a..c2800785aeb14588cf3fe8cc898d898b930d4f1a 100644 (file)
@@ -14,7 +14,7 @@ $(GTK.CONFIGURE.stamp): | $(dir $(GTK.CONFIGURE.stamp))
                PKG_CONFIG_DIR=$(BUILD/)contrib/lib/pkgconfig \
            CFLAGS="$(call fn.ARGS,GTK.GCC,.g .O)" \
            LDFLAGS="$(call fn.ARGS,GTK.GCC,?strip .g .O)" \
-           --prefix=$(INSTALL.prefix) \
+           --prefix=$(PREFIX) \
            --with-hb=$(call fn.ABSOLUTE,$(BUILD/))
        $(TOUCH.exe) $@
 
index e36d1a8834ac7bc8e084ed5e6ba5f9f7bf59b181..9853a102708eedbb8cf6c48040feaffeab40464a 100644 (file)
@@ -1,14 +1,14 @@
 $(eval $(call import.MODULE.defs,LIBHB,libhb,A52DEC BZIP2 FAAC FAAD2 FFMPEG LAME LIBDCA LIBDVDREAD LIBMKV LIBMP4V2 LIBOGG LIBSAMPLERATE LIBTHEORA LIBVORBIS MPEG2DEC X264 XVIDCORE ZLIB LIBHB TEST DOC))
 $(eval $(call import.GCC,LIBHB))
 
-LIBHB.src/   = $(PROJECT/)libhb/
+LIBHB.src/   = $(SRC/)libhb/
 LIBHB.build/ = $(BUILD/)libhb/
 
 LIBHB.m4.in  = $(wildcard $(LIBHB.src/)*.m4)
 LIBHB.m4.out = $(patsubst $(LIBHB.src/)%.m4,$(LIBHB.build/)%,$(LIBHB.m4.in))
 
 LIBHB.c   = $(wildcard $(LIBHB.src/)*.c)
-LIBHB.c.o = $(patsubst $(PROJECT/)%.c,$(BUILD/)%.o,$(LIBHB.c))
+LIBHB.c.o = $(patsubst $(SRC/)%.c,$(BUILD/)%.o,$(LIBHB.c))
 LIBHB.d   = $(LIBHB.m4.out) $(LIBHB.h.out) \
     $(foreach n, \
     A52DEC BZIP2 FAAC FAAD2 FFMPEG LAME LIBDCA LIBDVDREAD LIBMKV LIBMP4V2 LIBOGG \
@@ -16,7 +16,7 @@ LIBHB.d   = $(LIBHB.m4.out) $(LIBHB.h.out) \
     $($n.INSTALL.target) )
 
 LIBHB.h.in  = $(wildcard $(LIBHB.src/)*.h)
-LIBHB.h.out = $(patsubst $(PROJECT/)%,$(BUILD/)%,$(LIBHB.h.in))
+LIBHB.h.out = $(patsubst $(SRC/)%,$(BUILD/)%,$(LIBHB.h.in))
 
 ###############################################################################
 
index 396deb09b85f06e99a25a0ea9ec2fb84dee3b564..7ac6e3f5a64dcbe06b93258f4abe428a65fc33f1 100644 (file)
@@ -8,7 +8,7 @@ $(LIBHB.a): $(LIBHB.c.o)
 
 $(LIBHB.c.o): $(LIBHB.d)
 $(LIBHB.c.o): | $(dir $(LIBHB.c.o))
-$(LIBHB.c.o): $(BUILD/)%.o: $(PROJECT/)%.c
+$(LIBHB.c.o): $(BUILD/)%.o: $(SRC/)%.c
        $(call LIBHB.GCC.C_O,$@,$<)
 
 $(LIBHB.m4.out): $(BUILD/)project/handbrake.m4
@@ -17,7 +17,7 @@ $(LIBHB.m4.out): $(LIBHB.build/)%: $(LIBHB.src/)%.m4
        $(M4.exe) -Iproject $< > $@
 
 $(LIBHB.h.out): | $(dir $(LIBHB.h.out))
-$(LIBHB.h.out): $(BUILD/)%: $(PROJECT/)%
+$(LIBHB.h.out): $(BUILD/)%: $(SRC/)%
        $(CP.exe) $< $@
 
 libhb.clean:
index 73388fd394f1c10bcf26892bdf0a552aba5e6537..a7baa221bd15f7560c8e64bd9804cc75c9086a4c 100644 (file)
@@ -25,7 +25,6 @@ dnl
 <<#>>define HB_PROJECT_REPO_UUID       "__HB_repo_uuid"
 <<#>>define HB_PROJECT_REPO_REV        __HB_repo_rev
 <<#>>define HB_PROJECT_REPO_DATE       "__HB_repo_date"
-<<#>>define HB_PROJECT_REPO_WCVERSION  "__HB_repo_wcversion"
 <<#>>define HB_PROJECT_REPO_OFFICIAL   __HB_repo_official
 <<#>>define HB_PROJECT_REPO_TYPE       "__HB_repo_type"
 
index 690e8b95b544087ab6a3bcc24cb2fb25058bdc6f..c93959cf5372dfa0484f59d1400439035c414538 100644 (file)
 /* Begin PBXLegacyTarget section */
                27F143770F5DF34F00A684FF /* external */ = {
                        isa = PBXLegacyTarget;
-                       buildArgumentsString = "\"$EXTERNAL_PROJECT/make/xcodemake";
+                       buildArgumentsString = "\"$EXTERNAL_SRC/make/xcodemake";
                        buildConfigurationList = 27F1438E0F5DF3EA00A684FF /* Build configuration list for PBXLegacyTarget "external" */;
                        buildPhases = (
                        );
                };
                27F1437E0F5DF36000A684FF /* contrib */ = {
                        isa = PBXLegacyTarget;
-                       buildArgumentsString = "\"$EXTERNAL_PROJECT/make/xcodemake";
+                       buildArgumentsString = "\"$EXTERNAL_SRC/make/xcodemake";
                        buildConfigurationList = 27F1438F0F5DF3EA00A684FF /* Build configuration list for PBXLegacyTarget "contrib" */;
                        buildPhases = (
                        );
                };
                27F143850F5DF37600A684FF /* libhb */ = {
                        isa = PBXLegacyTarget;
-                       buildArgumentsString = "\"$EXTERNAL_PROJECT/make/xcodemake";
+                       buildArgumentsString = "\"$EXTERNAL_SRC/make/xcodemake";
                        buildConfigurationList = 27F143900F5DF3EA00A684FF /* Build configuration list for PBXLegacyTarget "libhb" */;
                        buildPhases = (
                        );
 /* Begin PBXProject section */
                29B97313FDCFA39411CA2CEA /* Project object */ = {
                        isa = PBXProject;
+                       attributes = {
+                               BuildIndependentTargetsInParallel = YES;
+                       };
                        buildConfigurationList = 4D4E7BC4087804870051572B /* Build configuration list for PBXProject "HandBrake" */;
                        compatibilityVersion = "Xcode 3.1";
                        hasScannedForEncodings = 1;
                                ARCHS = i386;
                                CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)";
                                CONFIGURATION_TEMP_DIR = "$(SYMROOT)";
-                               EXTERNAL_BUILD = "$(EXTERNAL_PROJECT)/build.$(CONFIGURATION)";
-                               EXTERNAL_JOBS = 8;
+                               EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)";
+                               EXTERNAL_JOBS = 1;
                                EXTERNAL_METHOD = xcode;
-                               EXTERNAL_PROJECT = ..;
+                               EXTERNAL_SRC = ..;
                                GCC_DYNAMIC_NO_PIC = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
                                GCC_MODEL_TUNING = G5;
                                ARCHS = ppc;
                                CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)";
                                CONFIGURATION_TEMP_DIR = "$(SYMROOT)";
-                               EXTERNAL_BUILD = "$(EXTERNAL_PROJECT)/build.$(CONFIGURATION)";
-                               EXTERNAL_JOBS = 8;
+                               EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)";
+                               EXTERNAL_JOBS = 1;
                                EXTERNAL_METHOD = xcode;
-                               EXTERNAL_PROJECT = ..;
+                               EXTERNAL_SRC = ..;
                                GCC_DYNAMIC_NO_PIC = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
                                GCC_MODEL_TUNING = G5;
                                ARCHS = x86_64;
                                CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)";
                                CONFIGURATION_TEMP_DIR = "$(SYMROOT)";
-                               EXTERNAL_BUILD = "$(EXTERNAL_PROJECT)/build.$(CONFIGURATION)";
-                               EXTERNAL_JOBS = 8;
+                               EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)";
+                               EXTERNAL_JOBS = 1;
                                EXTERNAL_METHOD = xcode;
-                               EXTERNAL_PROJECT = ..;
+                               EXTERNAL_SRC = ..;
                                GCC_DYNAMIC_NO_PIC = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
                                GCC_MODEL_TUNING = G5;
                                ARCHS = ppc64;
                                CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)";
                                CONFIGURATION_TEMP_DIR = "$(SYMROOT)";
-                               EXTERNAL_BUILD = "$(EXTERNAL_PROJECT)/build.$(CONFIGURATION)";
-                               EXTERNAL_JOBS = 8;
+                               EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)";
+                               EXTERNAL_JOBS = 1;
                                EXTERNAL_METHOD = xcode;
-                               EXTERNAL_PROJECT = ..;
+                               EXTERNAL_SRC = ..;
                                GCC_DYNAMIC_NO_PIC = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
                                GCC_MODEL_TUNING = G5;
                                CONFIGURATION_TEMP_DIR = "$(SYMROOT)";
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = dwarf;
-                               EXTERNAL_BUILD = "$(EXTERNAL_PROJECT)/build.$(CONFIGURATION)";
-                               EXTERNAL_JOBS = 8;
+                               EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)";
+                               EXTERNAL_JOBS = 1;
                                EXTERNAL_METHOD = xcode;
-                               EXTERNAL_PROJECT = ..;
+                               EXTERNAL_SRC = ..;
                                GCC_DYNAMIC_NO_PIC = YES;
                                GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_OPTIMIZATION_LEVEL = 0;
                        buildSettings = {
                                CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)";
                                CONFIGURATION_TEMP_DIR = "$(SYMROOT)";
-                               EXTERNAL_BUILD = "$(EXTERNAL_PROJECT)/build.$(CONFIGURATION)";
+                               EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)";
                                EXTERNAL_JOBS = 1;
                                EXTERNAL_METHOD = xcode;
-                               EXTERNAL_PROJECT = ..;
+                               EXTERNAL_SRC = ..;
                                GCC_DYNAMIC_NO_PIC = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
                                GCC_MODEL_TUNING = G5;
index fec467db989698a0e8cc47bca44978ef30882a6d..75b9655ae9b9075b9c89f161bc3af20b98154419 100644 (file)
@@ -1,10 +1,13 @@
 $(eval $(call import.MODULE.defs,MACOSX,macosx))
 
-MACOSX.src/   = $(PROJECT/)macosx/
+MACOSX.src/   = $(SRC/)macosx/
 MACOSX.build/ = $(BUILD/)macosx/
 
 MACOSX.m4.in  = $(wildcard $(MACOSX.src/)*.m4)
-MACOSX.m4.out = $(patsubst $(MACOSX.src/)%.m4,$(MACOSX.build/)%,$(MACOSX.m4.in))
+MACOSX.m4.out = $(MACOSX.m4.in:$(MACOSX.src/)%.m4=$(MACOSX.build/)%)
+
+## optional special command to run post macro processing
+MACOSX.m4.post.Info.h = $(RM.exe) -f $(MACOSX.build/)HandBrake.build/Preprocessed-Info.plist
 
 MACOSX.targs = HandBrakeCLI HandBrake
 MACOSX.conf  = standard$(if $(filter 1,$(BUILD.cross)),.$(BUILD.arch))
@@ -12,6 +15,7 @@ MACOSX.conf  = standard$(if $(filter 1,$(BUILD.cross)),.$(BUILD.arch))
 ###############################################################################
 
 BUILD.out += $(MACOSX.m4.out)
+BUILD.out += $(MACOSX.m4.wc.out)
 
 ###############################################################################
 
@@ -30,10 +34,11 @@ MACOSX.XCODE = $(strip \
         -project $(MACOSX.XCODE.project) \
         -configuration $(MACOSX.conf) \
         $(foreach t,$(1),-target $t) \
-        EXTERNAL_BUILD='$(CURDIR)' \
+        EXTERNAL_SRC='$(XCODE.external.src)' \
+        EXTERNAL_BUILD='$(XCODE.external.build)' \
+        EXTERNAL_PREFIX='$(XCODE.external.prefix)' \
         EXTERNAL_JOBS='$(BUILD.jobs)' \
         EXTERNAL_METHOD='$(CONF.method)' \
-        EXTERNAL_PROJECT='$(PROJECT/)' \
         EXTERNAL_GOALS='$(3)' \
         EXTERNAL_VARS='$(-*-command-variables-*-)' \
         $(2) )
index 9873e90e644796a5f05a84ccda9a9fcb42f234a1..c6623649c516d3040fec008c055e893a60532401 100644 (file)
@@ -2,10 +2,14 @@ $(eval $(call import.MODULE.rules,MACOSX))
 
 macosx.build: $(MACOSX.m4.out)
 
+macosx.clean:
+       $(RM.exe) -f $(MACOSX.m4.out)
+
 $(MACOSX.m4.out): $(BUILD/)project/handbrake.m4
 $(MACOSX.m4.out): | $(dir $(MACOSX.m4.out))
 $(MACOSX.m4.out): $(MACOSX.build/)%: $(MACOSX.src/)%.m4
        $(M4.exe) -Iproject $< > $@
+       $(MACOSX.m4.post.$(notdir $@))
 
 ###############################################################################
 
index 81f661629bd8187e6f2326fc2dfd3799927e50d3..fc52b365ea2913411f9ef4f4793834c3bbae1e0c 100644 (file)
@@ -20,7 +20,7 @@ xclean: clean
 
 ###############################################################################
 
-MACOSX.goals = $(filter-out build clean install xclean,$(MAKECMDGOALS))
+MACOSX.goals = $(filter-out build clean install,$(MAKECMDGOALS))
 
 $(MACOSX.goals): __goals__
        @true
index ce288409301cef5bb293b87f3ba89019990d6e05..c984ccc3bd36f9dfd9b915edbc80b8c97a457fff 100644 (file)
@@ -1,3 +1,12 @@
+###############################################################################
+##
+## This script is coded for minimum version of Python 2.4 .
+## Pyhthon3 is incompatible.
+##
+## Authors: konablend
+##
+###############################################################################
+
 import fnmatch
 import optparse
 import os
@@ -13,408 +22,514 @@ from optparse import OptionParser
 from sys import stderr
 from sys import stdout
 
+class AbortError( Exception ):
+    def __init__( self, format, *args ):
+        self.value = format % args
+    def __str__( self ):
+        return self.value
+
 ###############################################################################
+##
+## Main configure object.
+##
+## dir = containing this configure script
+## cwd = current working dir at time of script launch
+##
+class Configure( object ):
+    OUT_QUIET   = 0
+    OUT_INFO    = 1
+    OUT_VERBOSE = 2
+
+    def __init__( self, verbose ):
+        self._log_info    = []
+        self._log_verbose = []
+        self._record      = False
+
+        self.verbose = verbose
+        self.dir = os.path.dirname( sys.argv[0] )
+        self.cwd = os.getcwd()
+
+        self.build_dir = '.'
+
+        ## compute src dir which is 2 dirs up from this script
+        self.src_dir = os.path.normpath( sys.argv[0] )
+        for i in range( 2 ):
+            self.src_dir = os.path.dirname( self.src_dir )
+        if len( self.src_dir ) == 0:
+            self.src_dir = os.curdir
+
+    def _final_dir( self, chdir, dir ):
+        dir = os.path.normpath( dir )
+        if not os.path.isabs( dir ):
+            if os.path.isabs( chdir ):
+                dir = os.path.normpath( os.path.abspath(dir ))
+            else:
+                dir = os.path.normpath( self.relpath( dir, chdir ))
+        return dir
+
+    ## output functions
+    def errln( self, format, *args ):
+        s = (format % args)
+        if re.match( '^.*[!?:;.]$', s ):
+            stderr.write( 'ERROR: %s configure stop.\n' % (s) )
+        else:
+            stderr.write( 'ERROR: %s; configure stop.\n' % (s) )
+        self.record_log()
+        sys.exit( 1 )
+    def infof( self, format, *args ):
+        line = format % args
+        self._log_verbose.append( line )
+        if cfg.verbose >= Configure.OUT_INFO:
+            self._log_info.append( line )
+            stdout.write( line )
+    def verbosef( self, format, *args ):
+        line = format % args
+        self._log_verbose.append( line )
+        if cfg.verbose >= Configure.OUT_VERBOSE:
+            stdout.write( line )
+
+    ## doc is ready to be populated
+    def doc_ready( self ):
+        ## compute final paths as they are after chdir into build
+        self.build_final  = os.curdir
+        self.src_final    = self._final_dir( self.build_dir, self.src_dir )
+        self.prefix_final = self._final_dir( self.build_dir, self.prefix_dir )
+
+        cfg.infof( 'compute: makevar SRC/    = %s\n', self.src_final )
+        cfg.infof( 'compute: makevar BUILD/  = %s\n', self.build_final )
+        cfg.infof( 'compute: makevar PREFIX/ = %s\n', self.prefix_final )
+
+        ## xcode does a chdir so we need appropriate values
+        macosx = os.path.join( self.src_dir, 'macosx' )
+        self.xcode_x_src    = self._final_dir( macosx, self.src_dir )
+        self.xcode_x_build  = self._final_dir( macosx, self.build_dir )
+        self.xcode_x_prefix = self._final_dir( macosx, self.prefix_dir )
+
+    ## perform chdir and enable log recording
+    def chdir( self ):
+        if os.path.abspath( self.build_dir ) == os.path.abspath( self.src_dir ):
+            cfg.errln( 'build (scratch) directory must not be the same as top-level source root!' )
+
+        if self.build_dir != os.curdir:
+            if os.path.exists( self.build_dir ):
+                if not options.force:
+                    self.errln( 'build directory already exists: %s (use --force to overwrite)', self.build_dir )
+            else:
+                self.mkdirs( self.build_dir )
+            self.infof( 'chdir: %s\n', self.build_dir )
+            os.chdir( self.build_dir )
+
+        ## enable logging
+        self._record = True
+
+    def mkdirs( self, dir ):
+        if len(dir) and not os.path.exists( dir ):
+            self.infof( 'mkdir: %s\n', dir )
+            os.makedirs( dir )
+
+    def open( self, *args ):
+        dir = os.path.dirname( args[0] )
+        if len(args) > 1 and args[1].find('w') != -1:
+            self.mkdirs( dir )
+        m = re.match( '^(.*)\.tmp$', args[0] )
+        if m:
+            self.infof( 'write: %s\n', m.group(1) )
+        else:
+            self.infof( 'write: %s\n', args[0] )
 
-def errf( format, *args ):
-    stderr.write( ('ERROR: ' + format + '\n') % args )
-    sys.exit( 1 )
+        try:
+            return open( *args )
+        except Exception, x:
+            cfg.errln( 'open failure: %s', x )
 
-def outf( format, *args ):
-    stdout.write( (format + '\n') % args )
+    def record_log( self ):
+        if not self._record:
+            return
+        self._record = False
+        self.verbose = Configure.OUT_QUIET
+        file = cfg.open( 'log/config.info.txt', 'w' )
+        for line in self._log_info:
+            file.write( line )
+        file.close()
+        file = cfg.open( 'log/config.verbose.txt', 'w' )
+        for line in self._log_verbose:
+            file.write( line )
+        file.close()
+
+    ## Find executable by searching path.
+    ## On success, returns full pathname of executable.
+    ## On fail, returns None.
+    def findExecutable( self, name ):
+        if len( os.path.split(name)[0] ):
+            if os.access( name, os.X_OK ):
+                return name
+            return None
+        
+        if not os.environ.has_key( 'PATH' ) or os.environ[ 'PATH' ] == '':
+            path = os.defpath
+        else:
+            path = os.environ['PATH']
+        
+        for dir in path.split( os.pathsep ):
+            f = os.path.join( dir, name )
+            if os.access( f, os.X_OK ):
+                return f
+        return None
+
+    ## taken from python2.6 -- we need it
+    def relpath( self, path, start=os.curdir ):
+        """Return a relative version of a path"""
+
+        if not path:
+            raise ValueError("no path specified")
+
+        start_list = os.path.abspath(start).split(os.sep)
+        path_list = os.path.abspath(path).split(os.sep)
+
+        # Work out how much of the filepath is shared by start and path.
+        i = len(os.path.commonprefix([start_list, path_list]))
+
+        rel_list = [os.pardir] * (len(start_list)-i) + path_list[i:]
+        if not rel_list:
+            return os.curdir
+        return os.path.join(*rel_list)
+
+    ## update with parsed cli options
+    def update_cli( self, options ):
+        self.src_dir    = os.path.normpath( options.src )
+        self.build_dir  = os.path.normpath( options.build )
+        self.prefix_dir = os.path.normpath( options.prefix )
+
+        ## special case if src == build: add build subdir
+        if os.path.abspath( self.src_dir ) == os.path.abspath( self.build_dir ):
+            self.build_dir = os.path.join( self.build_dir, 'build' )
 
 ###############################################################################
-
-## Expand values of iterable object into a decent string representation.
 ##
-def expandValues( obj ):
-    buf = ''
-    for v in obj:
-        buf += ', ' + v
-    return '{ ' + buf[2:] + ' }'
+## abstract action
+##
+## pretext = text which immediately follows 'probe:' output prefix
+## abort   = if true configure will exit on probe fail
+## head    = if true probe session is stripped of all but first line
+## session = output from command, including stderr
+## fail    = true if probe failed
+##
+class Action( object ):
+    actions = []
+
+    def __init__( self, category, pretext='unknown', abort=False, head=False ):
+        if self not in Action.actions:
+            Action.actions.append( self )
+
+        self.category = category
+        self.pretext  = pretext
+        self.abort    = abort
+        self.head     = head
+        self.session  = None
+
+        self.run_done = False
+        self.fail     = True
+        self.msg_fail = 'fail'
+        self.msg_pass = 'pass'
+        self.msg_end  = 'end'
+
+    def _actionBegin( self ):
+        cfg.infof( '%s: %s...', self.category, self.pretext )
+
+    def _actionEnd( self ):
+        if self.fail:
+            cfg.infof( '(%s) %s\n', self.msg_fail, self.msg_end )
+            if self.abort:
+                self._dumpSession( cfg.infof )
+                cfg.errln( 'unable to continue' )
+            self._dumpSession( cfg.verbosef )
+        else:
+            cfg.infof( '(%s) %s\n', self.msg_pass, self.msg_end )
+            self._dumpSession( cfg.verbosef )
 
-###############################################################################
+    def _dumpSession( self, printf ):
+        if self.session and len(self.session):
+            for line in self.session:
+                printf( '  : %s\n', line )
+        else:
+            printf( '  : <NO-OUTPUT>\n' )
+
+    def _parseSession( self ):
+        pass
+
+    def run( self ):
+        if self.run_done:
+            return
+        self.run_done = True
+        self._actionBegin()
+        self._action()
+        if not self.fail:
+            self._parseSession()
+        self._actionEnd()
 
-## Find executable by searching path.
-## On success, returns full pathname of executable.
-## On fail, returns None.
+###############################################################################
+##
+## base probe: anything which runs in shell.
+##
+## pretext = text which immediately follows 'probe:' output prefix
+## command = full command and arguments to pipe
+## abort   = if true configure will exit on probe fail
+## head    = if true probe session is stripped of all but first line
+## session = output from command, including stderr
+## fail    = true if probe failed
 ##
-def findExecutable( name ):
-    if len( os.path.split(name)[0] ):
-        return name if os.access( name, os.X_OK ) else None
+class ShellProbe( Action ):
+    def __init__( self, pretext, command, abort=False, head=False ):
+        super( ShellProbe, self ).__init__( 'probe', pretext, abort, head )
+        self.command = command
 
-    if not os.environ.has_key( 'PATH' ) or os.environ[ 'PATH' ] == '':
-        path = os.defpath
-    else:
-        path = os.environ['PATH']
+    def _action( self ):
+        ## pipe and redirect stderr to stdout; effects communicate result
+        pipe = subprocess.Popen( self.command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
 
-    for dir in path.split( os.pathsep ):
-        f = os.path.join( dir, name )
-        if os.access( f, os.X_OK ):
-            return f
-    return None
+        ## read data into memory buffers, only first element (stdout) data is used
+        data = pipe.communicate()
+        self.fail = pipe.returncode != 0
 
-###############################################################################
+        if data[0]:
+            self.session = data[0].splitlines()
+        else:
+            self.session = []
 
-def computeNumCPU():
-    ## good for darwin9.6.0 and linux
-    try:
-        n = os.sysconf( 'SC_NPROCESSORS_ONLN' )
-        if n < 1:
-            n = 1
-        return n
-    except:
-        pass
-    ## windows
-    try:
-        n = int( os.environ['NUMBER_OF_PROCESSORS'] )
-        if n < 1:
-            n = 1
-        return n
-    except:
-        pass
-    return 1
+        if pipe.returncode:
+            self.msg_end = 'code %d' % (pipe.returncode)
+
+    def _dumpSession( self, printf ):
+        printf( '  + %s\n', self.command )
+        super( ShellProbe, self )._dumpSession( printf )
 
 ###############################################################################
+##
+## GNU host tuple probe: determine canonical platform type
+##
+## example results from various platforms:
+##
+##   i386-apple-darwin9.6.0     (Mac OS X 10.5.6 Intel)
+##   powerpc-apple-darwin9.6.0  (Mac OS X 10.5.6 PPC)
+##   i686-pc-cygwin             (Cygwin, Microsoft Vista)
+##   x86_64-unknown-linux-gnu   (Linux, Fedora 10 x86_64)
+##
+class HostTupleProbe( ShellProbe, list ):
+    GNU_TUPLE_RX = '([^-]+)-([^-]+)-([^0-9-]+)([^-]*)-?([^-]*)'
+
+    def __init__( self ):
+        super( HostTupleProbe, self ).__init__( 'host tuple', '%s/config.guess' % (cfg.dir), abort=True, head=True )
 
-## taken from python2.6 -- we need it
-def relpath(path, start=os.path.curdir):
-    """Return a relative version of a path"""
+    def _parseSession( self ):
+        if len(self.session):
+            self.spec = self.session[0]
+        else:
+            self.spec = ''
 
-    if not path:
-        raise ValueError("no path specified")
+        ## grok GNU host tuples
+        m = re.match( HostTupleProbe.GNU_TUPLE_RX, self.spec )
+        if not m:
+            self.fail = True
+            self.msg_end = 'invalid host tuple: %s' % (self.spec)
+            return
 
-    start_list = os.path.abspath(start).split(os.sep)
-    path_list = os.path.abspath(path).split(os.sep)
+        self.msg_end = self.spec
 
-    # Work out how much of the filepath is shared by start and path.
-    i = len(os.path.commonprefix([start_list, path_list]))
+        ## assign tuple from regex
+        self[:] = m.groups()
 
-    rel_list = [os.pardir] * (len(start_list)-i) + path_list[i:]
-    if not rel_list:
-        return os.path.curdir
-    return os.path.join(*rel_list)
+        ## for clarity
+        self.machine = self[0]
+        self.vendor  = self[1]
+        self.system  = self[2]
+        self.release = self[3]
+        self.extra   = self[4]
 
-###############################################################################
+        ## nice formal name for 'system'
+        self.systemf = platform.system()
 
-# compute project dir which should be 2 dirs below this script
-build_dir = os.curdir
-project_dir = os.path.normpath( sys.argv[0] )
-for i in range( 2 ):
-    project_dir = os.path.dirname( project_dir )
-if len( project_dir ) == 0:
-    project_dir = os.curdir
-initial_project_dir = project_dir
+        if self.match( '*-*-cygwin*' ):
+            self.systemf = self[2][0].upper() + self[2][1:]
+            
+    ## glob-match against spec
+    def match( self, spec ):
+        return fnmatch.fnmatch( self.spec, spec )
 
 ###############################################################################
 
-## model gnu-autotools platform guess
+class BuildAction( Action, list ):
+    def __init__( self ):
+        super( BuildAction, self ).__init__( 'compute', 'build tuple', abort=True )
+
+    def _action( self ):
+        self.spec = arch.mode[arch.mode.mode]
+
+        ## grok GNU host tuples
+        m = re.match( HostTupleProbe.GNU_TUPLE_RX, self.spec )
+        if not m:
+            self.msg_end = 'invalid host tuple: %s' % (self.spec)
+            return
+
+        self.msg_end = self.spec
+
+        ## assign tuple from regex
+        self[:] = m.groups()
+
+        ## for clarity
+        self.machine = self[0]
+        self.vendor  = self[1]
+        self.system  = self[2]
+        self.release = self[3]
+        self.extra   = self[4]
+        self.systemf = host.systemf
+
+        self.fail = False
+
+###############################################################################
 ##
-## native format:
-##   (PROC)-(VENDOR)-(SYSTEM)(RELEASE)-(EXTRA)
+## platform conditional string; if specs do not match host:
 ##
-## examples:
-##   i386-apple-darwin9.6.0    (Mac OS X 10.5.6 Intel)
-##   powerpc-apple-darwin9.6.0 (Mac OS X 10.5.6 PPC)
-##   i686-pc-cygwin            (Cygwin, Microsoft Vista)
-##   x86_64-unknown-linux-gnu  (Linux, Fedora 10 x86_64)
+## - str value is blank
+## - evaluates to False
 ##
-class Guess:
-    def __init__( self ):
-        self.machine = 'unknown'
-        self.vendor  = 'unknown'
-        self.system  = 'unknown'
-        self.systemc = 'Unknown'
-        self.release = '0.0.0'
-        self.extra   = ''
-
-        p_system    = platform.system().lower()
-        p_systemc   = platform.system()
-        p_release   = platform.release().lower()
-        p_processor = platform.processor().lower()
-        p_machine   = platform.machine().lower()
-
-        if re.match( 'cygwin', p_system ):
-            self.machine = p_machine
-            self.vendor  = 'pc'
-            self.system  = 'cygwin'
-            self.systemc = 'Cygwin'
-            self.release = ''
-            self.extra   = ''
-        elif re.match( 'darwin', p_system ):
-            self.machine = p_processor
-            self.vendor  = 'apple'
-            self.system  = p_system
-            self.systemc = p_systemc
-            self.release = p_release
-            self.extra   = ''
-        elif re.match( 'linux', p_system ):
-            self.machine = p_machine
-            self.vendor  = 'unknown'
-            self.system  = p_system
-            self.systemc = p_systemc
-            self.release = ''
-            self.extra   = 'gnu'
-            self.title   = 'Linux %s' % (p_machine)
-        else:
-            errf( 'unrecognized host system: %s', p_system )
-
+class IfHost( object ):
+    def __init__( self, value, *specs ):
+        self.value = ''
+        for spec in specs:
+            if host.match( spec ):
+                self.value = value
+                break
+
+    def __nonzero__( self ):
+        return len(self.value) != 0
+        
     def __str__( self ):
-        if len(self.extra):
-            return '%s-%s-%s%s-%s' % (self.machine,self.vendor,self.system,self.release,self.extra)
-        else:
-            return '%s-%s-%s%s' % (self.machine,self.vendor,self.system,self.release)
+        return self.value
 
-    def match( self, spec ):
-        return fnmatch.fnmatch( str(self), spec )
+###############################################################################
+##
+## platform conditional value; loops through list of tuples comparing
+## to first host match and sets value accordingly; the first value is
+## always default.
+##
+class ForHost( object ):
+    def __init__( self, default, *tuples ):
+        self.value = default
+        for tuple in tuples:
+            if host.match( tuple[1] ):
+                self.value = tuple[0]
+                break
+
+    def __str__( self ):
+        return self.value
 
 ###############################################################################
 
-# a tool represents a command-line tool which may be searched for in PATH
-class Tool:
-    def __init__( self, parent, optional, var, *pool ):
-        self.name     = pool[0]
-        self.optional = optional
-        self.var      = var
-        self.pool     = pool
-        self.found    = None
-        if parent:
-            parent.register( self )
-
-    def addToConfig( self, config ):
-        config.add( self.var, self.found )
-
-    def addToGroup( self, group ):
-        group.add_option( '', '--' + self.name, help='specify %s location' % (self.name), default=None, metavar='EXE' )
-
-    def locate( self, options ):
-        spec = options.__dict__[self.name]
-        pool = self.pool if not spec else [spec]
-        for p in pool:
-            self.found = findExecutable( p )
-            if self.found:
-                outf( 'located %s: %s', self.name, self.found )
-                return
-        if self.optional:
-            outf( 'missing: %s (optional)', self.name )
+class ArchAction( Action ):
+    def __init__( self ):
+        super( ArchAction, self ).__init__( 'compute', 'available architectures', abort=True )
+        self.mode = SelectMode( 'architecture', (host.machine,host.spec) )
+
+    def _action( self ):
+        self.fail = False
+
+        ## some match on system should be made here; otherwise we signal a warning. 
+        if host.match( '*-*-cygwin*' ):
+            pass
+        elif host.match( '*-*-darwin*' ):
+            self.mode['i386']   = 'i386-apple-darwin%s'      % (host.release)
+            self.mode['x86_64'] = 'x86_64-apple-darwin%s'    % (host.release)
+            self.mode['ppc']    = 'powerpc-apple-darwin%s'   % (host.release)
+            self.mode['ppc64']  = 'powerpc64-apple-darwin%s' % (host.release)
+        elif host.match( '*-*-linux*' ):
+            pass
         else:
-            errf( 'unable to locate tool: %s', self.name )
-
-## a select tool picks first found from a list of tools
-class SelectTool( Tool ):
-    def __init__( self, parent, var, name, *pool ):
-        self.var     = var
-        self.name    = name
-        self.pool    = pool
-        self.found   = None
-
-        self.poolMap = {}
-        for p in self.pool:
-            self.poolMap[p.name] = p
-        if parent:
-            parent.register( self )
-
-    def addToConfig( self, config ):
-        config.add( self.var, self.found )
-
-    def addToGroup( self, group ):
-        group.add_option( '', '--' + self.name, help='select %s mode: %s' % (self.name,expandValues(self.poolMap)),
-            default=self.name, metavar='MODE' )
-
-    def locate( self, options ):
-        spec = options.__dict__[self.name]
-        if spec in self.poolMap:
-            self.found = spec
-            return
-        for p in self.pool:
-            if p.found:
-                self.found = p.name
-                outf( 'selected %s: %s', self.name, self.found )
-                return
-        errf( 'require at least one location of: %s', expandValues( self.poolMap ))
+            self.msg_pass = 'WARNING'
+
+        self.msg_end = self.mode.toString()
+
+    ## glob-match against spec
+    def match( self, spec ):
+        return fnmatch.fnmatch( self.spec, spec )
 
 ###############################################################################
 
-class ToolSet:
+class CoreProbe( Action ):
     def __init__( self ):
-        self.items = []
-        Tool( self, False, 'AR.exe',    'ar' )
-        Tool( self, False, 'CP.exe',    'cp' )
-        Tool( self, True,  'CURL.exe',  'curl' )
-        Tool( self, False, 'GCC.gcc',   'gcc', 'gcc-4' )
-        Tool( self, False, 'M4.exe',    'm4' )
-        Tool( self, False, 'MKDIR.exe', 'mkdir' )
-        Tool( self, False, 'PATCH.exe', 'patch' )
-        Tool( self, False, 'RM.exe',    'rm' )
-        Tool( self, False, 'TAR.exe',   'tar' )
-        Tool( self, True,  'WGET.exe',  'wget' )
-
-        SelectTool( self, 'FETCH.select', 'fetch', self.wget, self.curl )
-
-    def register( self, item ):
-        self.__dict__[item.name] = item
-        self.items.append( item )
+        super( CoreProbe, self ).__init__( 'probe', 'number of CPU cores' )
+        self.count = 1
 
-###############################################################################
+    def _action( self ):
+        if self.fail:
+            ## good for darwin9.6.0 and linux
+            try:
+                self.count = os.sysconf( 'SC_NPROCESSORS_ONLN' )
+                if self.count < 1:
+                    self.count = 1
+                self.fail = False
+            except:
+                pass
+
+        if self.fail:
+            ## windows
+            try:
+                self.count = int( os.environ['NUMBER_OF_PROCESSORS'] )
+                if self.count < 1:
+                    self.count = 1
+                self.fail = False
+            except:
+                pass
 
-class OptionMode( list ):
-    def __init__( self, default, *items ):
-        super( OptionMode, self ).__init__( items )
-        self.default = items[default]
-        self.mode = self.default
+        ## clamp
+        if self.count < 1:
+            self.count = 1
+        elif self.count > 32:
+            self.count = 32
 
-    def __str__( self ):
-        s = ''
-        for a in self:
-            if a == self.mode:
-                s += ' *' + a
+        if options.launch:
+            if options.launch_jobs == 0:
+                self.jobs = core.count
             else:
-                s += ' ' + a
-        return s[1:]
-
-    def addToGroup( self, group, option, name ):
-        group.add_option( '', option, help='select %s mode: %s' % (name,self), default=self.mode, metavar='MODE' )
+                self.jobs = options.launch_jobs
+        else:
+            self.jobs = core.count
 
-    def setFromOption( self, name, mode ):
-        if mode not in self:
-            errf( 'invalid %s mode: %s', name, mode )
-        self.mode = mode
+        self.msg_end = str(self.count)
 
 ###############################################################################
 
-## create singletons
-guessHost  = Guess()
-guessBuild = Guess()
-
-makeTool = Tool( None, False, 'CONF.make', 'gmake', 'make' )
-tools = ToolSet()
-
-debugMode    = OptionMode( 0, 'none', 'min', 'std', 'max' )
-optimizeMode = OptionMode( 1, 'none', 'speed', 'size' )
-
-## populate platform-specific architecture modes
-if guessHost.match( 'i386-*-darwin8.*' ):
-    archMode = OptionMode( 0, 'i386', 'ppc' )
-elif guessHost.match( 'powerpc-*-darwin8.*' ):
-    archMode = OptionMode( 1, 'i386', 'ppc' )
-elif guessHost.match( 'i386-*-darwin9.*' ):
-    archMode = OptionMode( 0, 'i386', 'x86_64', 'ppc', 'ppc64' )
-elif guessHost.match( 'powerpc-*-darwin9.*' ):
-    archMode = OptionMode( 2, 'i386', 'x86_64', 'ppc', 'ppc64' )
-else:
-    archMode = OptionMode( 0, guessHost.machine )
-
-if guessHost.match( '*-*-darwin*' ):
-    d_xcode = True
-    d_prefix = '/Applications'
-else: 
-    d_xcode = False
-    d_prefix = '/usr/local'
-
-## create parser
-parser = OptionParser( 'Usage: %prog' )
-
-## add hidden options
-parser.add_option( '', '--conf-method', default='terminal', action='store', help=optparse.SUPPRESS_HELP )
-
-## add install options
-group = OptionGroup( parser, 'Installation Options' )
-group.add_option( '', '--prefix', default=d_prefix, action='store',
-    help='specify destination for final products (%s)' % (d_prefix) )
-parser.add_option_group( group )
-
-group = OptionGroup( parser, 'Feature Options' )
-if d_xcode:
-    group.add_option( '', '--disable-xcode', default=False, action='store_true',
-        help='disable Xcode (Darwin only)' )
-group.add_option( '', '--disable-gtk', default=False, action='store_true',
-    help='disable GTK GUI (Linux only)' )
-parser.add_option_group( group )
-
-## add launch options
-group = OptionGroup( parser, 'Launch Options' )
-group.add_option( '', '--launch', default=False, action='store_true',
-    help='launch build, capture log and wait for completion' )
-group.add_option( '', '--launch-jobs', default=1, action='store', metavar='N',
-    help='allow N jobs at once; 0 to match CPU count (1)' )
-group.add_option( '', '--launch-args', default=None, action='store', metavar='ARGS',
-    help='specify additional ARGS for launch command' )
-group.add_option( '', '--launch-dir', default='build', action='store', metavar='DIR',
-    help='specify scratch DIR to use for build (build)' )
-group.add_option( '', '--launch-force', default=False, action='store_true',
-    help='force use of scratch directory even if exists' )
-group.add_option( '', '--launch-log', default='log.txt', action='store', metavar='FILE',
-    help='specify log FILE (log.txt)' )
-group.add_option( '', '--launch-quiet', default=False, action='store_true',
-    help='do not echo build output' )
-parser.add_option_group( group )
-
-## add compile options
-group = OptionGroup( parser, 'Compiler Options' )
-debugMode.addToGroup( group, '--debug', 'debug' )
-optimizeMode.addToGroup( group, '--optimize', 'optimize' )
-archMode.addToGroup( group, '--arch', 'architecutre' )
-parser.add_option_group( group )
-
-## add tool options
-group = OptionGroup( parser, 'Tool Options' )
-makeTool.addToGroup( group )
-for tool in tools.items:
-    tool.addToGroup( group )
-parser.add_option_group( group )
-
-(options,args) = parser.parse_args()
-
-exports = []
-for arg in args:
-    m = re.match( '([^=]+)=(.*)', arg )
-    if m:
-        exports.append( m.groups() )
-
-## recompute values when launch mode
-if options.launch:
-    options.launch_jobs = int(options.launch_jobs)
-    build_dir = options.launch_dir
-    if os.path.isabs( build_dir ):
-        project_dir = os.getcwd() 
-    else:
-        project_dir = os.path.normpath( relpath( project_dir, build_dir ))
-    if options.launch_jobs == 0:
-        options.launch_jobs = computeNumCPU()
-    if options.launch_jobs < 1:
-        options.launch_jobs = 1
-    elif options.launch_jobs > 8:
-        options.launch_jobs = 8
-
-## make sure configure does not run in source root
-if os.path.abspath( project_dir ) == os.path.abspath( build_dir ):
-    errf( 'scratch (build) directory must not be the same as source root' )
-
-## validate modes
-debugMode.setFromOption( 'debug', options.debug )
-optimizeMode.setFromOption( 'optimize', options.optimize )
-archMode.setFromOption( 'architecture', options.arch )
-
-## update guessBuild as per architecture mode
-if guessHost.match( '*-*-darwin*' ):
-    if archMode.mode == 'i386':
-        guessBuild.machine = 'i386'
-    elif archMode.mode == 'x86_64':
-        guessBuild.machine = 'x86_64'
-    elif archMode.mode == 'ppc':
-        guessBuild.machine = 'powerpc'
-    elif archMode.mode == 'ppc64':
-        guessBuild.machine = 'powerpc64'
-else:
-    guessBuild.machine = archMode.mode
-guessBuild.cross = 0 if archMode.default == archMode.mode else 1
-
-# locate tools
-makeTool.locate( options )
-for tool in tools.items:
-    tool.locate( options )
+class SelectMode( dict ):
+    def __init__( self, descr, *modes, **kwargs ):
+        super( SelectMode, self ).__init__( modes )
+        self.descr    = descr
+        self.modes    = modes
+        self.default  = kwargs.get('default',modes[0][0])
+        self.mode     = self.default
+
+    def cli_add_option( self, parser, option ):
+        parser.add_option( '', option, default=self.mode, metavar='MODE',
+            help='select %s mode: %s' % (self.descr,self.toString()),
+            action='callback', callback=self.cli_callback, type='str' )
+
+    def cli_callback( self, option, opt_str, value, parser, *args, **kwargs ):
+        if value not in self:
+            raise optparse.OptionValueError( 'invalid %s mode: %s (choose from %s)'
+                % (self.descr,value,self.toString( True )) )
+        self.mode = value
+
+    def toString( self, nodefault=False ):
+        keys = self.keys()
+        keys.sort()
+        if len(self) == 1:
+            value = self.mode
+        elif nodefault:
+            value = ' '.join( keys )
+        else:
+            value = '%s [%s]' % (' '.join( keys ), self.mode )
+        return value
 
 ###############################################################################
-
+##
 ## Repository object.
 ## Holds information gleaned from subversion working dir.
 ##
@@ -427,62 +542,48 @@ for tool in tools.items:
 ##  unofficial
 ##      all other builds
 ##
-class Repository:
+class RepoProbe( ShellProbe ):
     def __init__( self ):
+        super( RepoProbe, self ).__init__( 'svn info', 'svn info %s' % (cfg.src_dir) )
+
         self.url       = 'svn://nowhere.com/project/unknown'
         self.root      = 'svn://nowhere.com/project'
         self.branch    = 'unknown'
         self.uuid      = '00000000-0000-0000-0000-000000000000';
         self.rev       = 0
         self.date      = '0000-00-00 00:00:00 -0000'
-        self.wcversion = 'exported'
         self.official  = 0
         self.type      = 'unofficial'
 
-        # parse output: svnversion PROJECT_DIR
-        cmd = 'svnversion ' + initial_project_dir
-        print 'attempting to probe subversion: %s' % (cmd)
-        try:
-            p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE )
-            p.wait();
-            if p.returncode:
-                sys.exit( 1 )
-            self.wcversion = p.stdout.readline().rstrip()
-        except:
-            pass
+    def _parseSession( self ):
+        for line in self.session:
+            ## grok fields
+            m = re.match( '([^:]+):\\s+(.+)', line )
+            if not m:
+                continue
 
-        # parse output: svn info PROJECT_DIR
-        cmd = 'svn info ' + initial_project_dir
-        print 'attempting to probe subversion: %s' % (cmd)
-        try:
-            p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE )
-            p.wait();
-            if p.returncode:
-                sys.exit( 1 )
-            for line in p.stdout:
-                (name,value) = re.match( '([^:]+):\\s+(.+)', line.rstrip() ).groups()
-                if name == 'URL':
-                    self.url = value
-                elif name == 'Repository Root':
-                    self.root = value
-                elif name == 'Repository UUID':
-                    self.uuid = value
-                elif name == 'Revision':
-                    self.rev = int( value )
-                elif name == 'Last Changed Date':
-                    # strip chars in parens
-                    if value.find( ' (' ):
-                        self.date = value[0:value.find(' (')]
-                    else:
-                        self.date = value
-        except:
-            pass
+            (name,value) = m.groups()
+            if name == 'URL':
+                self.url = value
+            elif name == 'Repository Root':
+                self.root = value
+            elif name == 'Repository UUID':
+                self.uuid = value
+            elif name == 'Revision':
+                self.rev = int( value )
+            elif name == 'Last Changed Date':
+                # strip chars in parens
+                if value.find( ' (' ):
+                    self.date = value[0:value.find(' (')]
+                else:
+                    self.date = value
 
+        ## grok branch
         i = self.url.rfind( '/' )
         if i != -1 and i < len(self.url)-1:
             self.branch = self.url[i+1:]
 
-        # official UUID behavior
+        # type-classification via repository UUID
         if self.uuid == 'b64f7644-9d1e-0410-96f1-a4d463321fa5':
             self.official = 1
             m = re.match( '([^:]+)://([^/]+)/(.+)', self.url )
@@ -491,14 +592,19 @@ class Repository:
             else:
                 self.type = 'developer'
 
-###############################################################################
+        self.msg_end = self.url
 
-## Project object.
+###############################################################################
+##
+## project object.
+##
 ## Contains manually updated version numbers consistent with HB releases
 ## and other project metadata.
 ##
-class Project:
+class Project( Action ):
     def __init__( self ):
+        super( Project, self ).__init__( 'compute', 'project data' )
+
         self.name          = 'HandBrake'
         self.acro_lower    = 'hb'
         self.acro_upper    = 'HB'
@@ -513,6 +619,7 @@ class Project:
         self.vminor = 9
         self.vpoint = 4
 
+    def _action( self ):
         appcastfmt = 'http://handbrake.fr/appcast%s.xml'
 
         if repo.type == 'release':
@@ -527,48 +634,164 @@ class Project:
             self.title = '%s svn%d (%s)' % (self.name,repo.rev,self.build)
         else:
             self.version = 'svn%d' % (repo.rev)
-            self.version = '%d.%d.%d' % (self.vmajor,self.vminor,self.vpoint)
             self.url_appcast = appcastfmt % ('_unofficial')
             self.build = time.strftime('%Y%m%d') + '99'
             self.title = 'Unofficial svn%d (%s)' % (repo.rev,self.build)
 
+        self.msg_end = '%s (%s)' % (self.name,repo.type)
+        self.fail = False
+
 ###############################################################################
 
-## Config object used to output gnu-make or gnu-m4 output.
+class ToolProbe( Action ):
+    tools = []
+
+    def __init__( self, var, *names, **kwargs ):
+        super( ToolProbe, self ).__init__( 'find', abort=kwargs.get('abort',True) )
+        if not self in ToolProbe.tools:
+            ToolProbe.tools.append( self )
+        self.var    = var
+        self.names  = []
+        self.kwargs = kwargs
+        for name in names:
+            if name:
+                self.names.append( str(name) )
+        self.name = self.names[0]
+        self.pretext = self.name
+        self.pathname = self.names[0]
+
+    def _action( self ):
+        self.session = []
+        for i,name in enumerate(self.names):
+            self.session.append( 'name[%d] = %s' % (i,name) )
+        for name in self.names:
+            f = cfg.findExecutable( name )
+            if f:
+                self.pathname = f
+                self.fail = False
+                self.msg_end = f
+                break
+        if self.fail:
+            self.msg_end = 'not found'
+
+    def cli_add_option( self, parser ):
+        parser.add_option( '', '--'+self.name, metavar='PROG',
+            help='[%s]' % (self.pathname),
+            action='callback', callback=self.cli_callback, type='str' )
+
+    def cli_callback( self, option, opt_str, value, parser, *args, **kwargs ):
+        self.__init__( self.var, value, **self.kwargs )
+        self.run()
+
+    def doc_add( self, doc ):
+        doc.add( self.var, self.pathname )
+
+###############################################################################
+
+class SelectTool( Action ):
+    selects = []
+
+    def __init__( self, var, name, *pool, **kwargs ):
+        super( SelectTool, self ).__init__( 'select', abort=kwargs.get('abort',True) )
+        self.pretext = name
+        if not self in SelectTool.selects:
+            SelectTool.selects.append( self )
+        self.var      = var
+        self.name     = name
+        self.pool     = pool
+        self.kwargs   = kwargs
+
+    def _action( self ):
+        self.session = []
+        for i,(name,tool) in enumerate(self.pool):
+            self.session.append( 'tool[%d] = %s (%s)' % (i,name,tool.pathname) )
+        for (name,tool) in self.pool:
+            if not tool.fail:
+                self.selected = name
+                self.fail = False
+                self.msg_end = '%s (%s)' % (name,tool.pathname)
+                break
+        if self.fail:
+            self.msg_end = 'not found'
+
+    def cli_add_option( self, parser ):
+        parser.add_option( '', '--'+self.name, metavar='MODE',
+            help='select %s mode: %s' % (self.name,self.toString()),
+            action='callback', callback=self.cli_callback, type='str' )
+
+    def cli_callback( self, option, opt_str, value, parser, *args, **kwargs ):
+        found = False
+        for (name,tool) in self.pool:
+            if name == value:
+                found = True
+                self.__init__( self.var, self.name, [name,tool], **kwargs )
+                self.run()
+                break
+        if not found:
+            raise optparse.OptionValueError( 'invalid %s mode: %s (choose from %s)'
+                % (self.name,value,self.toString( True )) )
+
+    def doc_add( self, doc ):
+        doc.add( self.var, self.selected )
+
+    def toString( self, nodefault=False ):
+        if len(self.pool) == 1:
+            value = self.pool[0][0]
+        else:
+            s = ''
+            for key,value in self.pool:
+                s += ' ' + key
+            if nodefault:
+                value = s[1:]
+            else:
+                value = '%s [%s]' % (s[1:], self.selected )
+        return value
+
+###############################################################################
 ##
-## Use add() to add NAME/VALUE pairs suitable for both make/m4.
-## Use addBlank() to add a linefeed for both make/m4.
-## Use addMake() to add a make-specific line.
-## Use addM4() to add a m4-specific line.
+## config object used to output gnu-make or gnu-m4 output.
 ##
-class Config:
+## - add() to add NAME/VALUE pairs suitable for both make/m4.
+## - addBlank() to add a linefeed for both make/m4.
+## - addMake() to add a make-specific line.
+## - addM4() to add a m4-specific line.
+##
+class ConfigDocument:
     def __init__( self ):
-        self._items = []
+        self._elements = []
+
+    def _outputMake( self, file, namelen, name, value ):
+        file.write( '%-*s = %s\n' % (namelen, name, value ))
+
+    def _outputM4( self, file, namelen, name, value ):
+        namelen += 7
+        name = '<<__%s>>,' % name.replace( '.', '_' )
+        file.write( 'define(%-*s  <<%s>>)dnl\n' % (namelen, name, value ))
 
     def add( self, name, value ):
-        self._items.append( (name,value) )
+        self._elements.append( (name,value) )
 
     def addBlank( self ):
-        self._items.append( None )
+        self._elements.append( None )
 
     def addComment( self, format, *args ):
         self.addMake( '## ' + format % args )
         self.addM4( 'dnl ' + format % args )
 
     def addMake( self, line ):
-        self._items.append( ('?make',line) )
+        self._elements.append( ('?make',line) )
 
     def addM4( self, line ):
-        self._items.append( ('?m4',line) )
+        self._elements.append( ('?m4',line) )
 
     def output( self, file, type ):
         namelen = 0
-        for item in self._items:
+        for item in self._elements:
             if item == None or item[0].find( '?' ) == 0:
                 continue
             if len(item[0]) > namelen:
                 namelen = len(item[0])
-        for item in self._items:
+        for item in self._elements:
             if item == None:
                 if type == 'm4':
                     file.write( 'dnl\n' )
@@ -585,226 +808,445 @@ class Config:
             else:
                 self._outputMake( file, namelen, item[0], item[1] )
 
-    def _outputMake( self, file, namelen, name, value ):
-        file.write( '%-*s = %s\n' % (namelen, name, value ))
-
-    def _outputM4( self, file, namelen, name, value ):
-        namelen += 7
-        name = '<<__%s>>,' % name.replace( '.', '_' )
-        file.write( 'define(%-*s  <<%s>>)dnl\n' % (namelen, name, value ))
+    def write( self, type ):
+        if type == 'make':
+            fname = 'GNUmakefile'
+        elif type == 'm4':
+            fname = os.path.join( 'project', project.name_lower + '.m4' )
+        else:
+            raise ValueError, 'unknown file type: ' + type
 
-###############################################################################
+        ftmp  = fname + '.tmp'
+        try:
+            try:
+                file = cfg.open( ftmp, 'w' )
+                self.output( file, type )
+            finally:
+                try:
+                    file.close()
+                except:
+                    pass
+        except Exception, x:
+            try:
+                os.remove( ftmp )
+            except Exception, x:
+                pass
+            cfg.errln( 'failed writing to %s\n%s', ftmp, x )
 
-## create configure line, stripping arg --launch, quoting others
-configure = []
-for arg in sys.argv[1:]:
-    if arg == '--launch':
-        continue
-    configure.append( "'%s'" % (arg.replace("'", '%c%c%c%c%c' % (0x27,0x22,0x27,0x22,0x27))) )
-
-## create singletones
-repo = Repository()
-project = Project()
-config  = Config()
-
-config.addComment( 'generated by configure on %s', time.strftime( '%c' ))
-
-config.addBlank()
-config.add( 'CONF.args', ' '.join( configure ))
-
-config.addBlank()
-config.add( 'HB.title',         project.title )
-config.add( 'HB.name',          project.name )
-config.add( 'HB.name.lower',    project.name_lower )
-config.add( 'HB.name.upper',    project.name_upper )
-config.add( 'HB.acro.lower',    project.acro_lower )
-config.add( 'HB.acro.upper',    project.acro_upper )
-
-config.add( 'HB.url.website',   project.url_website )
-config.add( 'HB.url.community', project.url_community )
-config.add( 'HB.url.irc',       project.url_irc )
-config.add( 'HB.url.appcast',   project.url_appcast )
-
-config.add( 'HB.version.major',  project.vmajor )
-config.add( 'HB.version.minor',  project.vminor )
-config.add( 'HB.version.point',  project.vpoint )
-config.add( 'HB.version',        project.version )
-config.add( 'HB.version.hex',    '%04x%02x%02x%08x' % (project.vmajor,project.vminor,project.vpoint,repo.rev) )
-
-config.add( 'HB.build', project.build )
-
-config.add( 'HB.repo.url',       repo.url )
-config.add( 'HB.repo.root',      repo.root )
-config.add( 'HB.repo.branch',    repo.branch )
-config.add( 'HB.repo.uuid',      repo.uuid )
-config.add( 'HB.repo.rev',       repo.rev )
-config.add( 'HB.repo.date',      repo.date )
-config.add( 'HB.repo.wcversion', repo.wcversion )
-config.add( 'HB.repo.official',  repo.official )
-config.add( 'HB.repo.type',      repo.type )
-
-config.addBlank()
-config.add( 'HOST.spec',    guessHost )
-config.add( 'HOST.machine', guessHost.machine )
-config.add( 'HOST.vendor',  guessHost.vendor )
-config.add( 'HOST.system',  guessHost.system )
-config.add( 'HOST.systemc', guessHost.systemc )
-config.add( 'HOST.release', guessHost.release )
-config.add( 'HOST.title',   '%s %s' % (guessHost.systemc,archMode.default) )
-config.add( 'HOST.extra',   guessHost.extra )
-config.add( 'HOST.ncpu',    computeNumCPU() )
-
-config.addBlank()
-config.add( 'BUILD.spec',    guessBuild )
-config.add( 'BUILD.machine', guessBuild.machine )
-config.add( 'BUILD.vendor',  guessBuild.vendor )
-config.add( 'BUILD.system',  guessBuild.system )
-config.add( 'BUILD.systemc', guessBuild.systemc )
-config.add( 'BUILD.release', guessBuild.release )
-config.add( 'BUILD.title',   '%s %s' % (guessBuild.systemc,archMode.mode) )
-config.add( 'BUILD.extra',   guessBuild.extra )
-config.add( 'BUILD.method',  'terminal' )
-config.add( 'BUILD.cross',   guessBuild.cross )
-config.add( 'BUILD.date',    time.strftime('%c') )
-config.add( 'BUILD.arch',    archMode.mode )
-config.add( 'BUILD.jobs',    computeNumCPU() )
-
-config.addBlank()
-config.add( 'CONF.method', options.conf_method )
-
-config.addBlank()
-config.add( 'BUILD/',   os.curdir + os.sep )
-config.add( 'PROJECT/', project_dir + os.sep )
-
-config.addBlank()
-config.add( 'INSTALL.prefix', options.prefix )
-config.add( 'INSTALL.prefix/', '$(INSTALL.prefix)/' )
-
-config.addBlank()
-config.add( 'FEATURE.xcode', 0 if not hasattr(options, 'disable_xcode') or options.disable_xcode else 1 )
-config.add( 'FEATURE.gtk',   0 if options.disable_gtk   else 1 )
-
-config.addMake( '' )
-config.addMake( '## include main definitions' )
-config.addMake( 'include $(PROJECT/)make/include/main.defs' )
-
-config.addBlank()
-for tool in tools.items:
-    tool.addToConfig( config )
-
-config.addBlank()
-config.add( 'GCC.archs', archMode.mode if guessBuild.cross else '' )
-config.add( 'GCC.g', options.debug )
-config.add( 'GCC.O', options.optimize )
-
-if len(exports):
-    config.addBlank()
-    for nv in exports:
-        config.add( nv[0], nv[1] )
-
-config.addMake( '' )
-config.addMake( '## include (optional) customization file' )
-config.addMake( '-include $(BUID/)GNUmakefile.custom' )
-
-config.addMake( '' )
-config.addMake( '## include main rules' )
-config.addMake( 'include $(PROJECT/)make/include/main.rules' )
+        try:
+            os.rename( ftmp, fname )
+        except Exception, x:
+            cfg.errln( 'failed writing to %s\n%s', fname, x )
 
 ###############################################################################
+##
+## create cli parser
+##
+def createCLI():
+    cli = OptionParser( 'usage: %prog [OPTIONS...] [TARGETS...]' )
+
+    cli.description = ''
+    cli.description += 'Configure %s build system.' % (project.name)
+
+    ## add hidden options
+    cli.add_option( '', '--conf-method', default='terminal', action='store', help=optparse.SUPPRESS_HELP )
+    cli.add_option( '', '--force', default=False, action='store_true', help='overwrite existing build config' )
+    cli.add_option( '', '--verbose', default=False, action='store_true', help='increase verbosity' )
+
+    ## add install options
+    grp = OptionGroup( cli, 'Directory Locations' )
+    grp.add_option( '', '--src', default=cfg.src_dir, action='store', metavar='DIR',
+        help='specify top-level source dir [%s]' % (cfg.src_dir) )
+    grp.add_option( '', '--build', default=cfg.build_dir, action='store', metavar='DIR',
+        help='specify build scratch/output dir [%s]' % (cfg.build_dir) )
+    grp.add_option( '', '--prefix', default=cfg.prefix_dir, action='store', metavar='DIR',
+        help='specify install dir for products [%s]' % (cfg.prefix_dir) )
+    cli.add_option_group( grp )
+
+    ## add feature options
+    grp = OptionGroup( cli, 'Feature Options' )
+    h = ForHost( optparse.SUPPRESS_HELP, ['disable Xcode (Darwin only)','*-*-darwin*'] ).value
+    grp.add_option( '', '--disable-xcode', default=False, action='store_true', help=h )
+    h = ForHost( optparse.SUPPRESS_HELP, ['disable GTK GUI (Linux only)','*-*-linux*'] ).value
+    grp.add_option( '', '--disable-gtk', default=False, action='store_true', help=h )
+    cli.add_option_group( grp )
+
+    ## add launch options
+    grp = OptionGroup( cli, 'Launch Options' )
+    grp.add_option( '', '--launch', default=False, action='store_true',
+        help='launch build, capture log and wait for completion' )
+    grp.add_option( '', '--launch-jobs', default=1, action='store', metavar='N', type='int',
+        help='allow N jobs at once; 0 to match CPU count [1]' )
+    grp.add_option( '', '--launch-args', default=None, action='store', metavar='ARGS',
+        help='specify additional ARGS for launch command' )
+    grp.add_option( '', '--launch-quiet', default=False, action='store_true',
+        help='do not echo build output' )
+    cli.add_option_group( grp )
+
+    ## add compile options
+    grp = OptionGroup( cli, 'Compiler Options' )
+    debugMode.cli_add_option( grp, '--debug' )
+    optimizeMode.cli_add_option( grp, '--optimize' )
+    arch.mode.cli_add_option( grp, '--arch' )
+    cli.add_option_group( grp )
+
+    ## add tool locations
+    grp = OptionGroup( cli, 'Tool Basenames and Locations' )
+    for tool in ToolProbe.tools:
+        tool.cli_add_option( grp )
+    cli.add_option_group( grp )
+
+    ## add tool modes
+    grp = OptionGroup( cli, 'Tool Options' )
+    for select in SelectTool.selects:
+        select.cli_add_option( grp )
+    cli.add_option_group( grp )
+    return cli
 
-# generate make or m4 file
-def generate( type ):
-    if type == 'make':
-        fname = 'GNUmakefile'
-    elif type == 'm4':
-        fname = os.path.join( 'project', project.name_lower + '.m4' )
-    else:
-        raise ValueError, 'unknown file type: ' + type
-
-    ftmp  = fname + '.tmp'
-
-    pdir = os.path.dirname( fname )
-    if pdir:
-        if not os.path.exists( pdir ):
-            os.makedirs( pdir )
+###############################################################################
+##
+## launcher - used for QuickStart method; launch; build and capture log.
+##
+class Launcher:
+    def __init__( self, targets ):
+        # open build logfile
+        self._file = cfg.open( 'log/build.txt', 'w' )
+
+        cmd = '%s -j%d' % (Tools.gmake.pathname,core.jobs)
+        if options.launch_args:
+            cmd += ' ' + options.launch_args
+        if len(targets):
+            cmd += ' ' + ' '.join(targets)
+
+        ## record begin
+        timeBegin = time.time()
+        self.infof( 'time begin: %s\n', time.asctime() )
+        self.infof( 'launch: %s\n', cmd )
+        if options.launch_quiet:
+            stdout.write( 'building to %s ...\n' % (os.path.abspath( cfg.build_final )))
+        else:
+            stdout.write( '%s\n' % ('-' * 79) )
 
-    try:
+        ## launch/pipe
         try:
-            outf( 'generating %s', fname )
-            file = open( ftmp, 'w' )
-            config.output( file, type )
-        finally:
-            try:
-                file.close()
-            except:
-                pass
-    except Exception, x:
-        try:
-            os.remove( ftmp )
+            pipe = subprocess.Popen( cmd, shell=True, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
         except Exception, x:
-            pass
-        errf( 'failed writing to %s\n%s', ftmp, x )
+            cfg.errln( 'launch failure: %s', x )
+        for line in pipe.stdout:
+            self.echof( '%s', line )
+        pipe.wait()
 
-    try:
-        os.rename( ftmp, fname )
-    except Exception, x:
-        errf( 'failed writing to %s\n%s', fname, x )
+        ## record end
+        timeEnd = time.time()
+        elapsed = timeEnd - timeBegin
 
-###############################################################################
+        if pipe.returncode:
+            result = 'FAILURE (code %d)' % pipe.returncode
+        else:
+            result = 'SUCCESS'
+
+        ## present duration in decent format
+        seconds = elapsed
+        hours = int(seconds / 3600)
+        seconds -= hours * 3600
+        minutes = int(seconds / 60)
+        seconds -= minutes * 60
+
+        segs = []
+        duration = ''
+
+        if hours == 1:
+            segs.append( '%d hour' % hours )
+        elif hours > 1:
+            segs.append( '%d hours' % hours )
+
+        if len(segs) or minutes == 1:
+            segs.append( '%d minute' % minutes )
+        elif len(segs) or  minutes > 1:
+            segs.append( '%d minutes' % minutes )
+
+        if seconds == 1:
+            segs.append( '%d second' % seconds )
+        else:
+            segs.append( '%d seconds' % seconds )
 
-if not options.launch:
-    generate( 'make' )
-    generate( 'm4' )
-    sys.exit( 0 )
+        if not options.launch_quiet:
+            stdout.write( '%s\n' % ('-' * 79) )
+        self.infof( 'time end: %s\n', time.asctime() )
+        self.infof( 'duration: %s (%.2fs)\n', ', '.join(segs), elapsed )
+        self.infof( 'result: %s\n', result )
 
-###############################################################################
+        ## cleanup
+        self._file.close()
 
-if os.path.exists( options.launch_dir ):
-    if not options.launch_force:
-        errf( 'scratch directory already exists: %s', options.launch_dir )
-else:
-    outf( 'creating %s', options.launch_dir )
-    os.makedirs( options.launch_dir )    
+    def echof( self, format, *args ):
+        line = format % args
+        self._file.write( line )
+        if not options.launch_quiet:
+            stdout.write( '  : %s' % line )
+            stdout.flush()
 
-outf( 'chdir %s', options.launch_dir )
-os.chdir( options.launch_dir )
-generate( 'make' )
-generate( 'm4' )
+    def infof( self, format, *args ):
+        line = format % args
+        self._file.write( line )
+        cfg.infof( '%s', line )
 
-outf( 'opening %s', options.launch_log )
+###############################################################################
+##
+## main program
+##
 try:
-    log = open( options.launch_log, 'w' )
-except Exception, x:
-    errf( 'open failure: %s', x )
+    ## we need to pre-check argv for -h or --help or --verbose to deal with
+    ## initializing Configure correctly.
+    verbose = Configure.OUT_INFO
+    for arg in sys.argv:
+        if arg == '-h' or arg == '--help':
+            verbose = Configure.OUT_QUIET
+            break
+        if arg == '--verbose':
+            verbose = Configure.OUT_VERBOSE
+
+    ## create main objects; actions/probes run() is delayed.
+    ## if any actions must be run earlier (eg: for configure --help purposes)
+    ## then run() must be invoked earlier. subequent run() invocations
+    ## are ignored.
+    cfg   = Configure( verbose )
+    host  = HostTupleProbe(); host.run()
+
+    cfg.prefix_dir = ForHost( '/usr/local', ['/Applications','*-*-darwin*'] ).value
+
+    build = BuildAction()
+    arch  = ArchAction(); arch.run()
+
+    ## create remaining main objects
+    core    = CoreProbe()
+    repo    = RepoProbe()
+    project = Project()
+
+    ## create tools in a scope
+    class Tools:
+        ar    = ToolProbe( 'AR.exe',    'ar' )
+        cp    = ToolProbe( 'CP.exe',    'cp' )
+        curl  = ToolProbe( 'CURL.exe',  'curl', abort=False )
+        gcc   = ToolProbe( 'GCC.gcc',   'gcc', IfHost('gcc-4','*-*-cygwin*') )
+
+        if host.match( '*-*-darwin*' ):
+            gmake = ToolProbe( 'GMAKE.exe', 'make', 'gmake' )
+        else:
+            gmake = ToolProbe( 'GMAKE.exe', 'gmake', 'make' )
+
+        m4    = ToolProbe( 'M4.exe',    'm4' )
+        mkdir = ToolProbe( 'MKDIR.exe', 'mkdir' )
+        patch = ToolProbe( 'PATCH.exe', 'gpatch', 'patch' )
+        rm    = ToolProbe( 'RM.exe',    'rm' )
+        tar   = ToolProbe( 'TAR.exe',   'gtar', 'tar' )
+        wget  = ToolProbe( 'WGET.exe',  'wget', abort=False )
+
+        xcodebuild = ToolProbe( 'XCODEBUILD.exe', 'xcodebuild', abort=False )
+        lipo       = ToolProbe( 'LIPO.exe',       'lipo', abort=False )
+
+        fetch = SelectTool( 'FETCH.select', 'fetch', ['wget',wget], ['curl',curl] )
+
+    ## run tool probes
+    for tool in ToolProbe.tools:
+        tool.run()
+    for select in SelectTool.selects:
+        select.run()
+
+    debugMode = SelectMode( 'debug', ('none','none'), ('min','min'), ('std','std'), ('max','max') )
+    optimizeMode = SelectMode( 'optimize', ('none','none'), ('speed','speed'), ('size','size'), default='speed' )
+
+    ## create CLI and parse
+    cli = createCLI()
+    (options,args) = cli.parse_args()
+
+    ## update cfg with cli directory locations
+    cfg.update_cli( options )
+
+    ## prepare list of targets and NAME=VALUE args to pass to make
+    targets = []
+    exports = []
+    rx_exports = re.compile( '([^=]+)=(.*)' )
+    for arg in args:
+        m = rx_exports.match( arg )
+        if m:
+            exports.append( m.groups() )
+        else:
+            targets.append( arg )
+
+    ## run delayed actions
+    for action in Action.actions:
+        action.run()
+
+    ## cfg hook before doc prep
+    cfg.doc_ready()
+
+    ## create document object
+    doc = ConfigDocument()
+    doc.addComment( 'generated by configure on %s', time.strftime( '%c' ))
+
+    ## add configure line for reconfigure purposes
+    doc.addBlank()
+    args = []
+    for arg in sys.argv[1:]:
+        if arg == '--launch':
+            continue
+        args.append( "'%s'" % (arg.replace("'", '%c%c%c%c%c' % (0x27,0x22,0x27,0x22,0x27))) )
+    doc.add( 'CONF.args', ' '.join( args ))
+
+    doc.addBlank()
+    doc.add( 'HB.title',         project.title )
+    doc.add( 'HB.name',          project.name )
+    doc.add( 'HB.name.lower',    project.name_lower )
+    doc.add( 'HB.name.upper',    project.name_upper )
+    doc.add( 'HB.acro.lower',    project.acro_lower )
+    doc.add( 'HB.acro.upper',    project.acro_upper )
+
+    doc.add( 'HB.url.website',   project.url_website )
+    doc.add( 'HB.url.community', project.url_community )
+    doc.add( 'HB.url.irc',       project.url_irc )
+    doc.add( 'HB.url.appcast',   project.url_appcast )
+
+    doc.add( 'HB.version.major',  project.vmajor )
+    doc.add( 'HB.version.minor',  project.vminor )
+    doc.add( 'HB.version.point',  project.vpoint )
+    doc.add( 'HB.version',        project.version )
+    doc.add( 'HB.version.hex',    '%04x%02x%02x%08x' % (project.vmajor,project.vminor,project.vpoint,repo.rev) )
+
+    doc.add( 'HB.build', project.build )
+
+    doc.add( 'HB.repo.url',       repo.url )
+    doc.add( 'HB.repo.root',      repo.root )
+    doc.add( 'HB.repo.branch',    repo.branch )
+    doc.add( 'HB.repo.uuid',      repo.uuid )
+    doc.add( 'HB.repo.rev',       repo.rev )
+    doc.add( 'HB.repo.date',      repo.date )
+    doc.add( 'HB.repo.official',  repo.official )
+    doc.add( 'HB.repo.type',      repo.type )
+
+    doc.addBlank()
+    doc.add( 'HOST.spec',    host.spec )
+    doc.add( 'HOST.machine', host.machine )
+    doc.add( 'HOST.vendor',  host.vendor )
+    doc.add( 'HOST.system',  host.system )
+    doc.add( 'HOST.systemf', host.systemf )
+    doc.add( 'HOST.release', host.release )
+    doc.add( 'HOST.extra',   host.extra )
+    doc.add( 'HOST.title',   '%s %s' % (host.systemf,arch.mode.default) )
+    doc.add( 'HOST.ncpu',    core.count )
+
+    doc.addBlank()
+    doc.add( 'BUILD.spec',    build.spec )
+    doc.add( 'BUILD.machine', build.machine )
+    doc.add( 'BUILD.vendor',  build.vendor )
+    doc.add( 'BUILD.system',  build.system )
+    doc.add( 'BUILD.systemf', build.systemf )
+    doc.add( 'BUILD.release', build.release )
+    doc.add( 'BUILD.extra',   build.extra )
+    doc.add( 'BUILD.title',   '%s %s' % (build.systemf,arch.mode.mode) )
+    doc.add( 'BUILD.ncpu',    core.count )
+    doc.add( 'BUILD.jobs',    core.jobs )
+
+    doc.add( 'BUILD.cross',   int(arch.mode.mode != arch.mode.default) )
+    doc.add( 'BUILD.method',  'terminal' )
+    doc.add( 'BUILD.date',    time.strftime('%c') )
+    doc.add( 'BUILD.arch',    arch.mode.mode )
+
+    doc.addBlank()
+    doc.add( 'CONF.method', options.conf_method )
+
+    doc.addBlank()
+    doc.add( 'SRC',     cfg.src_final )
+    doc.add( 'SRC/',    cfg.src_final + os.sep )
+    doc.add( 'BUILD',   cfg.build_final )
+    doc.add( 'BUILD/',  cfg.build_final + os.sep )
+    doc.add( 'PREFIX',  cfg.prefix_final )
+    doc.add( 'PREFIX/', cfg.prefix_final + os.sep )
+    
+    doc.addBlank()
+    doc.add( 'FEATURE.xcode', int( not (Tools.xcodebuild.fail or options.disable_xcode) ))
+    doc.add( 'FEATURE.gtk',   int( not options.disable_gtk ))
+
+    if not Tools.xcodebuild.fail and not options.disable_xcode:
+        doc.addBlank()
+        doc.add( 'XCODE.external.src',    cfg.xcode_x_src )
+        doc.add( 'XCODE.external.build',  cfg.xcode_x_build )
+        doc.add( 'XCODE.external.prefix', cfg.xcode_x_prefix )
+
+    doc.addMake( '' )
+    doc.addMake( '## include definitions' )
+    doc.addMake( 'include $(SRC/)make/include/main.defs' )
+
+    doc.addBlank()
+    for tool in ToolProbe.tools:
+        tool.doc_add( doc )
+
+    doc.addBlank()
+    for select in SelectTool.selects:
+        select.doc_add( doc )
+
+    doc.addBlank()
+    if arch.mode.mode != arch.mode.default:
+        doc.add( 'GCC.archs', arch.mode.mode )
+    else:
+        doc.add( 'GCC.archs', '' )
+    doc.add( 'GCC.g', debugMode.mode )
+    doc.add( 'GCC.O', optimizeMode.mode )
+
+    ## add exports to make
+    if len(exports):
+        doc.addBlank()
+        doc.addComment( 'overrides via VARIABLE=VALUE on command-line' )
+        for nv in exports:
+            doc.add( nv[0], nv[1] )
+
+    doc.addMake( '' )
+    doc.addMake( '## include custom definitions' )
+    doc.addMake( '-include $(SRC/)custom.defs' )
+    doc.addMake( '-include $(BUILD/)GNUmakefile.custom.defs' )
+
+    doc.addMake( '' )
+    doc.addMake( '## include rules' )
+    doc.addMake( 'include $(SRC/)make/include/main.rules' )
+    doc.addMake( '-include $(SRC/)custom.rules' )
+    doc.addMake( '-include $(BUILD/)GNUmakefile.custom.rules' )
+
+    ## chdir
+    cfg.chdir()
+
+    ## perform
+    doc.write( 'make' )
+    doc.write( 'm4' )
+    if options.launch:
+        Launcher( targets )
+
+    cfg.record_log()
+
+    if os.path.normpath( cfg.build_dir ) == os.curdir:
+        nocd = True
+    else:
+        nocd = False
 
-cmd = '%s -j%d' % (makeTool.found,options.launch_jobs)
-if options.launch_args:
-    cmd += ' ' + options.launch_args
+    stdout.write( '%s\n' % ('-' * 79) )
+    if options.launch:
+        stdout.write( 'Build is finished!\n' )
+        if nocd:
+            stdout.write( 'You may now examine the output.\n' )
+        else:
+            stdout.write( 'You may now cd into %s and examine the output.\n' % (cfg.build_dir) )
+    else:
+        stdout.write( 'Build is configured!\n' )
+        if nocd:
+            stdout.write( 'You may now run make (%s).\n' % (Tools.gmake.pathname) )
+        else:
+            stdout.write( 'You may now cd into %s and run make (%s).\n' % (cfg.build_dir,Tools.gmake.pathname) )
 
-## record begin
-timeBegin = time.time()
-s = '###\n### TIME: %s\n### launch: %s\n###\n' % (time.asctime(),cmd)
-stdout.write( s ); stdout.flush()
-log.write( s ); log.flush()
+except AbortError, x:
+    stderr.write( 'ERROR: %s\n' % (x) )
+    try:
+        cfg.record_log()
+    except:
+        pass        
+    sys.exit( 1 )    
 
-## launch/pipe
-try:
-    pipe = subprocess.Popen( cmd, shell=True, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
-except Exception, x:
-    errf( 'launch failure: %s', x )
-for line in pipe.stdout:
-    if not options.launch_quiet:
-        stdout.write( line ); stdout.flush()
-    log.write( line ); log.flush()
-pipe.wait()
-
-## record end
-timeEnd = time.time()
-elapsed = timeEnd - timeBegin
-result = '%s (exit code %d)' % ('success' if pipe.returncode == 0 else 'failed',pipe.returncode)
-s = '###\n### TIME: %s\n### finished: %.2f seconds\n### %s\n###\n' % (time.asctime(),elapsed,result)
-stdout.write( s ); stdout.flush()
-log.write( s ); log.flush()
-
-log.close()
 sys.exit( 0 )
index 3cd80303e09d97027131bc35c7974965fc25a94e..5f1f9e54b766cd3938e27938aa47c521d3170fe1 100644 (file)
@@ -1,5 +1,5 @@
 CONTRIB.build/    = $(BUILD/)contrib/
-CONTRIB.download/ = $(PROJECT/)download/
+CONTRIB.download/ = $(SRC/)download/
 CONTRIB.host      = $(if $(filter 1,$(BUILD.cross)),$(BUILD.spec))
 
 ###############################################################################
@@ -17,7 +17,7 @@ define import.CONTRIB.defs
     ##
     ## common values useful across targets
     ##
-    $(1).src/   = $$(PROJECT/)contrib/$($(1).name)/
+    $(1).src/   = $$(SRC/)contrib/$($(1).name)/
     $(1).build/ = $$(CONTRIB.build/)$($(1).name)/
     $(1).deps   = $$(foreach n,$($(1).prerequisites),$$($$n.INSTALL.target))
 
@@ -209,7 +209,7 @@ $($(1).name).extract.touch:
        $$(TOUCH.exe) $$($(1).EXTRACT.target)
 
 $($(1).name).extract.untouch:
-       $$(RM.exe) $$($(1).EXTRACT.target)
+       $$(RM.exe) -f $$($(1).EXTRACT.target)
 
 ##
 ## target: patch
@@ -224,7 +224,7 @@ $($(1).name).patch.touch:
        $$(TOUCH.exe) $$($(1).PATCH.target)
 
 $($(1).name).patch.untouch:
-       $$(RM.exe) $$($(1).PATCH.target)
+       $$(RM.exe) -f $$($(1).PATCH.target)
 
 ##
 ## target: configure
@@ -240,7 +240,7 @@ $($(1).name).configure.touch:
        $$(TOUCH.exe) $$($(1).CONFIGURE.target)
 
 $($(1).name).configure.untouch:
-       $$(RM.exe) $$($(1).CONFIGURE.target)
+       $$(RM.exe) -f $$($(1).CONFIGURE.target)
 
 ##
 ## target: build
@@ -256,7 +256,7 @@ $($(1).name).build.touch:
        $$(TOUCH.exe) $$($(1).BUILD.target)
 
 $($(1).name).build.untouch:
-       $$(RM.exe) $$($(1).BUILD.target)
+       $$(RM.exe) -f $$($(1).BUILD.target)
 
 ##
 ## target: install
@@ -271,7 +271,7 @@ $($(1).name).install.touch:
        $$(TOUCH.exe) $$($(1).INSTALL.target)
 
 $($(1).name).install.untouch:
-       $$(RM.exe) $$($(1).INSTALL.target)
+       $$(RM.exe) -f $$($(1).INSTALL.target)
 
 ##
 ## target: uninstall
index 93271a36550c8ff0f4d600081d20950bab28f4d9..f07678b79cb5b02ee8e9d6441891d34e53837c0f 100644 (file)
@@ -1,10 +1,10 @@
-include $(PROJECT/)make/include/base.defs
-include $(PROJECT/)make/include/contrib.defs
-include $(PROJECT/)make/include/function.defs
-include $(PROJECT/)make/include/gcc.defs
-include $(PROJECT/)make/include/select.defs
-include $(PROJECT/)make/include/target.defs
-include $(PROJECT/)make/include/tool.defs
+include $(SRC/)make/include/base.defs
+include $(SRC/)make/include/contrib.defs
+include $(SRC/)make/include/function.defs
+include $(SRC/)make/include/gcc.defs
+include $(SRC/)make/include/select.defs
+include $(SRC/)make/include/target.defs
+include $(SRC/)make/include/tool.defs
 
 ###############################################################################
 
@@ -62,6 +62,6 @@ MODULES += doc
 
 ###############################################################################
 
-include $(MODULES:%=$(PROJECT/)%/module.defs)
-include $(PROJECT/)make/variant/$(HOST.system).defs
--include $(PROJECT/)make/variant/$(HOST.system).$(BUILD.machine).defs
+include $(MODULES:%=$(SRC/)%/module.defs)
+include $(SRC/)make/variant/$(HOST.system).defs
+-include $(SRC/)make/variant/$(HOST.system).$(BUILD.machine).defs
index 4625ae9db490ddafa776a3bf56d44af96adfc7a7..51460a35d84ad14a108b5f0488c6170130d4c19a 100644 (file)
@@ -5,12 +5,12 @@
 
 ## file-wide conditional to use xcode rules if xcode=1 method=terminal
 ifeq ($(FEATURE.xcode):$(BUILD.method),1:terminal)
-    include $(PROJECT/)macosx/module.xcode
+    include $(SRC/)macosx/module.xcode
 else
 
 ## only included using special report targets
 ifneq (,$(REPORT))
-    include $(PROJECT/)make/include/report.defs
+    include $(SRC/)make/include/report.defs
 endif
 
 ###############################################################################
@@ -30,22 +30,22 @@ mrproper: xclean
 
 ###############################################################################
 
-include $(PROJECT/)make/include/base.rules
+include $(SRC/)make/include/base.rules
 
-include $(MODULES:%=$(PROJECT/)%/module.rules)
--include $(PROJECT/)make/variant/$(HOST.system).rules
--include $(PROJECT/)make/variant/$(HOST.system).$(BUILD.machine).rules
+include $(MODULES:%=$(SRC/)%/module.rules)
+-include $(SRC/)make/variant/$(HOST.system).rules
+-include $(SRC/)make/variant/$(HOST.system).$(BUILD.machine).rules
 
 ###############################################################################
 
 ## target which causes re-configure if project-root is svn update'd
-$(BUILD/)GNUmakefile: $(wildcard $(PROJECT/).svn/entries)
-       $(PROJECT/)configure $(CONF.args)
+$(BUILD/)GNUmakefile: $(wildcard $(SRC/).svn/entries)
+       $(SRC/)configure $(CONF.args)
 
 ## target useful to force reconfigure; only helpful for build-system development
 .PHONY: reconfigure
 reconfigure:
-       $(PROJECT/)configure $(CONF.args)
+       $(SRC/)configure $(CONF.args)
 
 ###############################################################################
 
index 6f8f6729dd2b338ff1ed5281043a9ab71e9f8e43..baffda595b384c5f5380c59df77e61814211590c 100644 (file)
@@ -1,40 +1,9 @@
-## UB build support
-##
-## PROCEDURE:
-##
-##  1. Perform a build (let us call it arch-X).
-##  2. cd into arch-X's build/ driectory.
-##  3. Launch builds of the remaining architectures.
-##     We compute $(UB.archs.other) to be the remaining archs to build.
-##     The entire list is defined $(UB.archs) .
-##  4. Combine other architectures into arch-X's binaries.
-##
-## EXAMPLE: serial method, archs: i386,x86_64,ppc,ppc64
-##
-##  ./configure --launch
-##  cd build/
-##  make ub.build.serial
-##  make ub.combine
-##
-## EXAMPLE: parallel method, archs: i386,x86_64,ppc,ppc64
-##
-##  ./configure --launch
-##  cd build/
-##  make ub.build.parallel
-##  make ub.combine
-##
-## EXAMPLE: serial, archs: i386,x86_64 (assuming i386 is native)
-##
-##  ./configure --launch
-##  cd build/
-##  make ub.build.parallel UB.archs="i386 x86_64"
-##  make ub.combine UB.archs="i386 x86_64"
-##
-UB.archs       = i386 x86_64 ppc ppc64
-UB.archs.other = $(filter-out $(BUILD.arch),$(UB.archs))
-UB.builds      = $(wildcard $(foreach n,$(UB.archs.other),$(PROJECT/)build.$n))
+UB.archs  = i386 x86_64 ppc ppc64
+UB.builds = $(wildcard $(foreach n,$(UB.archs),$(SRC/)build.$n))
+UB.first  = $(word 1,$(UB.archs))
+UB.other  = $(wordlist 2,999,$(UB.archs))
 
-UB.BUILD = $(PROJECT/)configure --launch --launch-dir=ub.$(1) --arch=$(1)
+UB.BUILD = $(SRC/)configure --build=ub.$(1) --arch=$(1) --launch --launch-quiet
 
 ## linefeed is important
 define UB.BUILD.item
@@ -43,19 +12,21 @@ define UB.BUILD.item
 endef
 
 define UB.BUILD.SERIAL
-       $(foreach n,$(UB.archs.other),$(call UB.BUILD.item,$n))
+       $(foreach n,$(UB.archs),$(call UB.BUILD.item,$n))
 endef
 
 define UB.BUILD.PARALLEL
-       $(call UB.BUILD,$(1)) 2>&1 > ub.$(1).log
+       $(call UB.BUILD,$(1)) >/dev/null 2>&1
 endef
 
 define UB.COMBINE
        $(RM.exe) -fr ub.combine
        $(MKDIR.exe) -p ub.combine
-       $(CP.exe) -R HandBrake.app ub.combine/.
-       lipo $(1) $(foreach n,$(UB.archs.other),ub.$n/$(1)) -create -output ub.combine/$(1)
+       $(CP.exe) -R ub.$(UB.first)/HandBrake.app ub.combine/.
+       $(LIPO.exe) $(foreach n,$(UB.archs),ub.$n/$(1)) -create -output ub.combine/$(1)
+       @lipo -info ub.combine/$(1)
+       @sync
        @echo ""
-       @sync; lipo -info ub.combine/$(1)
-       @du -sh ub.combine/$(1)
+       @echo "$@: { $(UB.archs) } combined -> ub.combine/HandBrake.app"
+       @echo "$@: UB executable size: `du -sh ub.combine/$(1) | awk '{ print $$1 }'`"
 endef
index c4f4f97a414814563f8e5dbbb138600dd7912913..d59a222b4d1f2f2a69e9110216469bd6ccfad42a 100644 (file)
@@ -5,7 +5,7 @@ ub.build.serial:
 
 ub.build.parallel:
        @set -e; \
-       for arch in $(UB.archs.other); do \
+       for arch in $(UB.archs); do \
            $(call UB.BUILD.PARALLEL,$$arch) & \
            children="$$children $$!"; \
            echo "pid $$!: $(call UB.BUILD.PARALLEL,$$arch)"; \
index c58706ba178d1bff3516ab8870185ffd22124d2a..9a807b8d4a50138df58ecc69c143c16232360408 100644 (file)
@@ -2,3 +2,8 @@ TARGET.dylib.ext = .so
 
 GCC.args.dylib = -shared
 GCC.args.pic   = 1
+
+GCC.args.g.none    = -g0
+GCC.args.g.min     = -g1
+GCC.args.g.default = -g2
+GCC.args.g.max     = -g3
index a75cd3ed6d59712b203834619b75c67581576e90..fde684cdf4c24fbc93c4128178ddcdd28fcc29d1 100755 (executable)
@@ -12,8 +12,6 @@ set -e
 MAKEFLAGS=
 MFLAGS=
 
-cd $EXTERNAL_BUILD
-
 ## re/configure if not configured by Xcode or if missing top-makefile
 if [ $EXTERNAL_METHOD != 'xcode' -o ! -f $EXTERNAL_BUILD/GNUmakefile ]; then
     ## compute --arch value based on Xcode configuration naming convention
@@ -36,7 +34,7 @@ if [ $EXTERNAL_METHOD != 'xcode' -o ! -f $EXTERNAL_BUILD/GNUmakefile ]; then
     esac
 
     ## invoke configure with (hidden) option which indicates conf performed by xcode
-    $EXTERNAL_PROJECT/configure PATH=$PATH --conf-method=xcode $args
+    $EXTERNAL_SRC/configure --force --build=$EXTERNAL_BUILD --conf-method=xcode PATH=$PATH $args
 fi
 
 ## safeguard against passing blank value which would result in unlimited jobs
index af42f13c747aacfdc11a250e1ce3f7e64db602cb..234cb1dcfe8f3e16cfce7be9cf83ab21498c2dbc 100644 (file)
@@ -1,11 +1,11 @@
 $(eval $(call import.MODULE.defs,TEST,test,LIBHB))
 $(eval $(call import.GCC,TEST))
 
-TEST.src/   = $(PROJECT/)test/
+TEST.src/   = $(SRC/)test/
 TEST.build/ = $(BUILD/)test/
 
 TEST.c   = $(wildcard $(TEST.src/)*.c)
-TEST.c.o = $(patsubst $(PROJECT/)%.c,$(BUILD/)%.o,$(TEST.c))
+TEST.c.o = $(patsubst $(SRC/)%.c,$(BUILD/)%.o,$(TEST.c))
 
 TEST.exe = $(BUILD/)$(call TARGET.exe,$(HB.name)CLI)
 
@@ -14,7 +14,7 @@ TEST.libs = $(LIBHB.a) $(foreach n, \
         ogg samplerate swscale theora vorbis vorbisenc x264 xvidcore, \
         $(CONTRIB.build/)lib/lib$(n).a )
 
-TEST.install.exe = $(INSTALL.prefix/)bin/$(notdir $(TEST.exe))
+TEST.install.exe = $(PREFIX/)bin/$(notdir $(TEST.exe))
 
 ## add libs from optional modules
 ifeq (1,$(BZIP2.enabled))
index 9a47aa172c3ca26fe746038eae8942ac741f0ce8..c51068901d3edbc22b14f33bfbd309d553899f72 100644 (file)
@@ -8,7 +8,7 @@ $(TEST.exe): $(TEST.c.o)
 
 $(TEST.c.o): $(LIBHB.a)
 $(TEST.c.o): | $(dir $(TEST.c.o))
-$(TEST.c.o): $(BUILD/)%.o: $(PROJECT/)%.c
+$(TEST.c.o): $(BUILD/)%.o: $(SRC/)%.c
        $(call TEST.GCC.C_O,$@,$<)
 
 test.clean: