diff options
34 files changed, 1586 insertions, 859 deletions
diff --git a/00-Building.cygwin.txt b/00-Building.cygwin.txt index dca7d9064..70cbd53dd 100644 --- a/00-Building.cygwin.txt +++ b/00-Building.cygwin.txt @@ -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. + diff --git a/00-Building.linux.txt b/00-Building.linux.txt index ae6158e96..955e4cd4a 100644 --- a/00-Building.linux.txt +++ b/00-Building.linux.txt @@ -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. + diff --git a/00-Building.osx.txt b/00-Building.osx.txt index 471ffda71..0d91d75a8 100644 --- a/00-Building.osx.txt +++ b/00-Building.osx.txt @@ -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. @@ -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 "$@" diff --git a/contrib/bzip2/module.defs b/contrib/bzip2/module.defs index bda2a132f..4384f83f7 100644 --- a/contrib/bzip2/module.defs +++ b/contrib/bzip2/module.defs @@ -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 diff --git a/contrib/ffmpeg/module.defs b/contrib/ffmpeg/module.defs index b41291018..04b060910 100644 --- a/contrib/ffmpeg/module.defs +++ b/contrib/ffmpeg/module.defs @@ -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 diff --git a/contrib/xvidcore/module.defs b/contrib/xvidcore/module.defs index f25d89d77..dee8b3e45 100644 --- a/contrib/xvidcore/module.defs +++ b/contrib/xvidcore/module.defs @@ -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 diff --git a/doc/module.defs b/doc/module.defs index 1697c9b69..84d924ab7 100644 --- a/doc/module.defs +++ b/doc/module.defs @@ -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/ diff --git a/doc/module.rules b/doc/module.rules index f86b66c09..54fec6dc7 100644 --- a/doc/module.rules +++ b/doc/module.rules @@ -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 diff --git a/doc/texi/Building.osx.texi b/doc/texi/Building.osx.texi index a554f7a0e..a02ec6131 100644 --- a/doc/texi/Building.osx.texi +++ b/doc/texi/Building.osx.texi @@ -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 diff --git a/doc/texi/base/handbrake.texi.m4 b/doc/texi/base/handbrake.texi.m4 index efcfa8d82..0466df77c 100644 --- a/doc/texi/base/handbrake.texi.m4 +++ b/doc/texi/base/handbrake.texi.m4 @@ -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 diff --git a/doc/texi/building/chapter.quickstart.texi b/doc/texi/building/chapter.quickstart.texi index 9e18db756..6aee76b91 100644 --- a/doc/texi/building/chapter.quickstart.texi +++ b/doc/texi/building/chapter.quickstart.texi @@ -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 diff --git a/doc/texi/building/chapter.via.terminal.texi b/doc/texi/building/chapter.via.terminal.texi index 29014819e..56afb8168 100644 --- a/doc/texi/building/chapter.via.terminal.texi +++ b/doc/texi/building/chapter.via.terminal.texi @@ -12,13 +12,10 @@ 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 diff --git a/doc/texi/building/chapter.via.xcode.texi b/doc/texi/building/chapter.via.xcode.texi index df42faca0..a78e0808d 100644 --- a/doc/texi/building/chapter.via.xcode.texi +++ b/doc/texi/building/chapter.via.xcode.texi @@ -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 diff --git a/doc/texi/building/command.texi b/doc/texi/building/command.texi index 4c21e9892..3acddc3a0 100644 --- a/doc/texi/building/command.texi +++ b/doc/texi/building/command.texi @@ -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 diff --git a/gtk/module.defs b/gtk/module.defs index ed46be53b..7550a82ae 100644 --- a/gtk/module.defs +++ b/gtk/module.defs @@ -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 diff --git a/gtk/module.rules b/gtk/module.rules index f66bbbb60..c2800785a 100644 --- a/gtk/module.rules +++ b/gtk/module.rules @@ -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) $@ diff --git a/libhb/module.defs b/libhb/module.defs index e36d1a883..9853a1027 100644 --- a/libhb/module.defs +++ b/libhb/module.defs @@ -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)) ############################################################################### diff --git a/libhb/module.rules b/libhb/module.rules index 396deb09b..7ac6e3f5a 100644 --- a/libhb/module.rules +++ b/libhb/module.rules @@ -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: diff --git a/libhb/project.h.m4 b/libhb/project.h.m4 index 73388fd39..a7baa221b 100644 --- a/libhb/project.h.m4 +++ b/libhb/project.h.m4 @@ -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" diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj index 690e8b95b..c93959cf5 100644 --- a/macosx/HandBrake.xcodeproj/project.pbxproj +++ b/macosx/HandBrake.xcodeproj/project.pbxproj @@ -400,7 +400,7 @@ /* 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 = ( ); @@ -413,7 +413,7 @@ }; 27F1437E0F5DF36000A684FF /* contrib */ = { isa = PBXLegacyTarget; - buildArgumentsString = "\"$EXTERNAL_PROJECT/make/xcodemake"; + buildArgumentsString = "\"$EXTERNAL_SRC/make/xcodemake"; buildConfigurationList = 27F1438F0F5DF3EA00A684FF /* Build configuration list for PBXLegacyTarget "contrib" */; buildPhases = ( ); @@ -426,7 +426,7 @@ }; 27F143850F5DF37600A684FF /* libhb */ = { isa = PBXLegacyTarget; - buildArgumentsString = "\"$EXTERNAL_PROJECT/make/xcodemake"; + buildArgumentsString = "\"$EXTERNAL_SRC/make/xcodemake"; buildConfigurationList = 27F143900F5DF3EA00A684FF /* Build configuration list for PBXLegacyTarget "libhb" */; buildPhases = ( ); @@ -482,6 +482,9 @@ /* 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; @@ -735,10 +738,10 @@ 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; @@ -844,10 +847,10 @@ 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; @@ -953,10 +956,10 @@ 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; @@ -1062,10 +1065,10 @@ 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; @@ -1403,10 +1406,10 @@ 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; @@ -1427,10 +1430,10 @@ 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; diff --git a/macosx/module.defs b/macosx/module.defs index fec467db9..75b9655ae 100644 --- a/macosx/module.defs +++ b/macosx/module.defs @@ -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) ) diff --git a/macosx/module.rules b/macosx/module.rules index 9873e90e6..c6623649c 100644 --- a/macosx/module.rules +++ b/macosx/module.rules @@ -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 $@)) ############################################################################### diff --git a/macosx/module.xcode b/macosx/module.xcode index 81f661629..fc52b365e 100644 --- a/macosx/module.xcode +++ b/macosx/module.xcode @@ -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 diff --git a/make/configure.py b/make/configure.py index ce2884093..c984ccc3b 100644 --- a/make/configure.py +++ b/make/configure.py @@ -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 ) diff --git a/make/include/contrib.defs b/make/include/contrib.defs index 3cd80303e..5f1f9e54b 100644 --- a/make/include/contrib.defs +++ b/make/include/contrib.defs @@ -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 diff --git a/make/include/main.defs b/make/include/main.defs index 93271a365..f07678b79 100644 --- a/make/include/main.defs +++ b/make/include/main.defs @@ -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 diff --git a/make/include/main.rules b/make/include/main.rules index 4625ae9db..51460a35d 100644 --- a/make/include/main.rules +++ b/make/include/main.rules @@ -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) ############################################################################### diff --git a/make/variant/darwin.defs b/make/variant/darwin.defs index 6f8f6729d..baffda595 100644 --- a/make/variant/darwin.defs +++ b/make/variant/darwin.defs @@ -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 diff --git a/make/variant/darwin.rules b/make/variant/darwin.rules index c4f4f97a4..d59a222b4 100644 --- a/make/variant/darwin.rules +++ b/make/variant/darwin.rules @@ -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)"; \ diff --git a/make/variant/freebsd.defs b/make/variant/freebsd.defs index c58706ba1..9a807b8d4 100644 --- a/make/variant/freebsd.defs +++ b/make/variant/freebsd.defs @@ -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 diff --git a/make/xcodemake b/make/xcodemake index a75cd3ed6..fde684cdf 100755 --- a/make/xcodemake +++ b/make/xcodemake @@ -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 diff --git a/test/module.defs b/test/module.defs index af42f13c7..234cb1dcf 100644 --- a/test/module.defs +++ b/test/module.defs @@ -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)) diff --git a/test/module.rules b/test/module.rules index 9a47aa172..c51068901 100644 --- a/test/module.rules +++ b/test/module.rules @@ -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: |