\r
To build a binary version of NVDA:\r
* Py2Exe (for Python 2.7), version 0.6.9 or later: http://www.sourceforge.net/projects/py2exe/\r
+ * SCons, version 2.0.0 or later: http://www.scons.org/\r
+\r
+To build a portable archive:\r
+ * 7-Zip: http://www.7-zip.org/\r
\r
To build an installer:\r
* Nulsoft Install System, version 2.42 or later: http://nsis.sourceforge.net/\r
== Running the Source Code ==\r
To start NVDA from source code, run nvda.pyw located in the source directory.\r
\r
-== Building a Standalone Binary Version of NVDA ==\r
-You can use py2exe to make a binary build of NVDA which can be run on a system without Python and all of NVDA's other dependencies installed (as we do for snapshots and releases).\r
+== Building NVDA ==\r
+A binary build of NVDA can be run on a system without Python and all of NVDA's other dependencies installed (as we do for snapshots and releases).\r
+\r
+Binary archives and bundles can be created using scons from the root of the NVDA source distribution/checkout. To build any of the following, open a command prompt and change to this directory.\r
+\r
+To make a non-archived binary build (equivalent to an extracted portable archive), type:\r
+scons dist\r
+The build will be created in the dist directory.\r
+\r
+To create a portable archive, type:\r
+scons portable\r
+The archive will be placed in the current directory.\r
\r
-Assuming py2exe is installed, open a command prompt, change to the NVDA source directory and type:\r
-setup.py py2exe\r
+To build an installer, type:\r
+scons installer\r
+The installer will be placed in the current directory.\r
\r
-== Building an NVDA Installer ==\r
-To build an NVDA installer:\r
- 1. First build a standalone binary version as described in the previous section.\r
- 2. Using Windows Explorer, locate nvda.nsi in the installer directory.\r
- 3. Press the applications key and choose "Compile NSIS Script".\r
-The installer will be built and placed in the installer directory.\r
+Optionally, the build can be customised by providing variables on the command line:\r
+ * version: The version of this build.\r
+ * isRelease: Whether this is a release version.\r
+ * publisher: The publisher of this build.\r
+ * certFile: The certificate file with which to sign executables.\r
+For example, to build an installer with a specific version, you might type:\r
+scons installer version=test1\r
--- /dev/null
+###\r
+#This file is a part of the NVDA project.\r
+#URL: http://www.nvda-project.org/\r
+#Copyright 2010 James Teh <jamie@jantrid.net>.\r
+#This program is free software: you can redistribute it and/or modify\r
+#it under the terms of the GNU General Public License version 2.0, as published by\r
+#the Free Software Foundation.\r
+#This program is distributed in the hope that it will be useful,\r
+#but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
+#This license can be found at:\r
+#http://www.gnu.org/licenses/old-licenses/gpl-2.0.html\r
+###\r
+\r
+import sys\r
+import os\r
+import _winreg\r
+\r
+# Import NVDA's versionInfo module.\r
+import gettext\r
+gettext.install("nvda", unicode=True)\r
+sys.path.append("source")\r
+import versionInfo\r
+del sys.path[-1]\r
+\r
+# Get the path to signtool.\r
+try:\r
+ with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Microsoft SDKs\Windows") as sdksKey:\r
+ signtool = os.path.join(_winreg.QueryValueEx(sdksKey, "CurrentInstallFolder")[0], "Bin", "signtool.exe")\r
+except WindowsError:\r
+ signtool = "signtool"\r
+\r
+# Get the path to 7z.\r
+try:\r
+ szKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\7-Zip", 0, _winreg.KEY_READ)\r
+except WindowsError:\r
+ try:\r
+ szKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\7-Zip", 0, _winreg.KEY_WOW64_64KEY | _winreg.KEY_READ)\r
+ except WindowsError:\r
+ szKey = None\r
+if szKey:\r
+ with szKey:\r
+ sz = os.path.join(_winreg.QueryValueEx(szKey, "Path")[0], "7z.exe")\r
+else:\r
+ sz = "7z"\r
+\r
+# Get the path to makensis.\r
+try:\r
+ with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\NSIS") as nsisKey:\r
+ makensis = os.path.join(_winreg.QueryValueEx(nsisKey, None)[0], "makensis.exe")\r
+except WindowsError:\r
+ makensis = "makensis"\r
+\r
+# Get the path to pygettext.\r
+pygettext = os.path.join(sys.exec_prefix, "Tools", "i18n", "pygettext.py")\r
+\r
+vars = Variables()\r
+vars.Add("version", "The version of this build", versionInfo.version)\r
+vars.Add(BoolVariable("isRelease", "Whether this is a release version", False))\r
+vars.Add("publisher", "The publisher of this build", "unknown")\r
+vars.Add(PathVariable("certFile", "The certificate file with which to sign executables", "",\r
+ lambda key, val, env: not val or PathVariable.PathIsFile(key, val, env)))\r
+\r
+env = Environment(variables=vars, tools=["textfile", "default"])\r
+version = env["version"]\r
+isRelease = env["isRelease"]\r
+certFile = env["certFile"]\r
+sourceDir = Dir("source")\r
+buildDir = Dir("build")\r
+outFilePrefix = "nvda{type}_{version}".format(type="" if isRelease else "_snapshot", version=version)\r
+\r
+# A builder to generate an NVDA distribution.\r
+def NVDADistGenerator(target, source, env, for_signature):\r
+ buildCmd = ["cd", source[0].path, "&&",\r
+ sys.executable]\r
+ if isRelease:\r
+ buildCmd.append("-O")\r
+ buildCmd.extend(("setup.py", "build", "--build-base", buildDir.abspath,\r
+ "py2exe", "--dist-dir", target[0].abspath))\r
+ if isRelease:\r
+ buildCmd.append("-O1")\r
+ action = [buildCmd]\r
+ if env.get("uiAccess"):\r
+ buildCmd.append("--enable-uiAccess")\r
+ for prog in "nvda", "nvda_slave", "nvda_service":\r
+ action.append(signExec[:-1] + [target[0].File("%s.exe" % prog)])\r
+ return action\r
+env["BUILDERS"]["NVDADist"] = Builder(generator=NVDADistGenerator, source_scanner=DirScanner, target_factory=Dir)\r
+\r
+# A builder to generate a 7-Zip self-extracting archive.\r
+def SzSfxGenerator(target, source, env, for_signature):\r
+ cmd = []\r
+ relativeToSourceDir = env.get("relativeToSourceDir", False)\r
+ if relativeToSourceDir:\r
+ cmd.extend(("cd", source[0], "&&"))\r
+ cmd.extend((sz, "a", "-mx=9", "-sfx7z.sfx", target[0].abspath, "." if relativeToSourceDir else "$SOURCES"))\r
+ return [cmd]\r
+env["BUILDERS"]["SzSfx"] = Builder(generator=SzSfxGenerator)\r
+\r
+# An action to sign an executable with certFile.\r
+signExec = [signtool, "sign", "/f", certFile, "$TARGET"]\r
+\r
+# Make the NVDA build use the specified version.\r
+buildVersionFile = env.Textfile(sourceDir.File("_buildVersion.py"), ['version = "$version"'])\r
+env.Depends(sourceDir, buildVersionFile)\r
+\r
+portableDist = env.NVDADist("dist", sourceDir, uiAccess=False)\r
+if certFile:\r
+ # If uiAccess is to be enabled, it must only be enabled on the installer.\r
+ # Therefore, a separate distribution is needed.\r
+ installerDist = env.NVDADist("dist_installer", sourceDir, uiAccess=True)\r
+else:\r
+ installerDist = portableDist\r
+# portableDist and installerDist don't get rebuilt even if sourceDir changes, so force them to always be built.\r
+#env.AlwaysBuild(portableDist, installerDist)\r
+# Dir node targets don't get cleaned, so cleaning of the dist nodes has to be explicitly specified.\r
+env.Clean(portableDist, portableDist)\r
+env.Clean(installerDist, installerDist)\r
+# Clean the intermediate build directory.\r
+env.Clean([portableDist, installerDist], buildDir)\r
+\r
+portableArchive = env.SzSfx("%s_portable.exe" % outFilePrefix, portableDist, relativeToSourceDir=True)\r
+if certFile:\r
+ env.AddPostAction(portableArchive, [signExec])\r
+env.Alias("portable", portableArchive)\r
+\r
+installer = env.Command("%s_installer.exe" % outFilePrefix, ["installer/nvda.nsi", installerDist],\r
+ [[makensis, "/V2",\r
+ "/DVERSION=$version", "/DPUBLISHER=$publisher",\r
+ "/DNVDASourceDir=${SOURCES[1].abspath}", "/XOutFile ${TARGET.abspath}",\r
+ "$SOURCE"]])\r
+if certFile:\r
+ env.AddPostAction(installer, [signExec])\r
+env.Alias("installer", installer)\r
+\r
+nvdaHelperArchive = env.SzSfx("%s_nvdaHelper.exe" % outFilePrefix,\r
+ env.Glob(r"source\lib\[nV]*.dll") + env.Glob(r"source\lib64\[nV]*.[de][lx][le]"))\r
+env.Alias("nvdaHelperArchive", nvdaHelperArchive)\r
+\r
+def makePot(target, source, env):\r
+ # Generate the pot.\r
+ if env.Execute([["cd", source[0], "&&",\r
+ pygettext, "-o", target[0].abspath, "*.py", r"*\*.py", r"*\*\*.py"]]) != 0:\r
+ raise RuntimeError("pygettext failed")\r
+\r
+ # Tweak the headers.\r
+ potFn = str(target[0])\r
+ tmpFn = "%s.tmp" % potFn\r
+ with file(potFn, "rt") as inp, file(tmpFn, "wt") as out:\r
+ for lineNum, line in enumerate(inp):\r
+ if lineNum == 1:\r
+ line = line.replace("YEAR ORGANIZATION", "2006-2010 NVDA Contributors")\r
+ elif lineNum == 2:\r
+ # Delete line.\r
+ continue\r
+ elif lineNum == 6:\r
+ line = line.replace("PACKAGE VERSION", version)\r
+ elif lineNum == 12:\r
+ line = line.replace("CHARSET", "UTF-8")\r
+ elif lineNum == 13:\r
+ line = line.replace("ENCODING", "8bit")\r
+ out.write(line)\r
+ os.remove(potFn)\r
+ os.rename(tmpFn, potFn)\r
+\r
+pot = env.Command("%s.pot" % outFilePrefix, sourceDir, makePot)\r
+env.Alias("pot", pot)\r
+\r
+env.Default(portableDist)\r