def main(): from functools import partial as func_partial from argparse import ArgumentParser, SUPPRESS parser = ArgumentParser() addarg = parser.add_argument addflag = func_partial(addarg, action="store_true") addarg("version", metavar="VERSION", nargs=1, help="the version to be released") addflag("-s", "--dsymbols", dest="debug_symbols", help="generate debug symbols for debug builds") addflag("-d", "--docs", dest="docs", help="generate documentation") addflag("-n", "--no-bin", dest="no_binaries", help="don't compile code") addflag("--7z", dest="_7z", help="create a 7z archive") addflag("--gz", dest="tar_gz", help="create a tar.gz archive") addflag("--bz2", dest="tar_bz2", help="create a tar.bz2 archive") addflag("--zip", dest="zip", help="create a zip archive") addflag("--deb", dest="deb", help="create deb files") addflag("--pdf", dest="pdf", help="create a PDF document") addflag("--chm", dest="chm", help=SUPPRESS) # "create a CHM file" addflag("-m", dest="copy_modified", help="copy modified files from the (git) working directory") addflag("--ldc", dest="ldc", help="use ldc instead of dmd") addarg("--src", dest="src", metavar="SRC", help="use SRC folder instead of checking out code with git") addarg("--cmp-exe", dest="cmp_exe", metavar="EXE_PATH", help="specify EXE_PATH if dmd/ldc is not in your PATH") addarg("--builddir", dest="builddir", metavar="DIR", help="where to build the release and archives (default is build/)") addarg( "--winpath", dest="winpath", metavar="P", help="permanently append P to PATH in the Windows (or wine's) registry. " "Exits the script.") addarg("--debm", dest="deb_mntnr", metavar="MTR", help=SUPPRESS) # Sets the maintainer info of the package. addarg("--debnum", dest="deb_num", metavar="NUM", default=1, help=SUPPRESS) # Sets the package number. options = args = parser.parse_args(sys.uargv[1:]) if options.winpath != None: from env_path import append2PATH append2PATH(options.winpath) return change_cwd(__file__) # Validate the version argument. m = re.match(r"^((\d)\.(\d{3})(?:-(\w+))?)(?:\+(\w+))?$", args.version) if not m: parser.error("invalid VERSION format: /\d.\d\d\d(-\w+)?/ E.g.: 1.123") # The version of DIL to be built. class Version(unicode): def __new__(cls, parts): v = unicode.__new__(cls, parts[0]) v.MAJ, v.MIN, SFX, BSFX = parts[1:] v.SFX = SFX or '' v.BINSFX = BSFX or '' return v VERSION = Version(m.groups()) # Pick a compiler for compiling DIL. CmdClass = (DMDCommand, LDCCommand)[options.ldc] COMPILER = Path(options.cmp_exe or CmdClass.exe) COMPILER.CmdClass = CmdClass if not COMPILER.exists and not locate_command(COMPILER): parser.error("The executable '%s' could not be located." % COMPILER) # Path to DIL's root folder. DIL = dil_path() # Build folder. BUILDROOT = Path(options.builddir or "build") / ("dil_" + VERSION) # Destination of distributable files. DEST = dil_path(BUILDROOT / "dil", dilconf=False) DEST.DOC = doc_path(DEST.DOC) # Temporary directory, deleted in the end. TMP = BUILDROOT / "tmp" # The list of module files (with info) that have been processed. MODLIST = TMP / "modules.txt" # The source files that need to be compiled and documentation generated for. FILES = [] # The folders and files which were produced by a build. PRODUCED = [] sw, sw_all = StopWatch(), StopWatch() # Check out a new working copy. BUILDROOT.rm().mkdir() # First remove the whole folder and recreate it. if options.src != None: # Use the source folder specified by the user. src = Path(options.src) if not src.exists: parser.error("the given SRC path (%s) doesn't exist" % src) #if src.ext in ('zip', 'gz', 'bz2'): # TODO: src.copy(DEST) else: if not locate_command('git'): parser.error("'git' is not in your PATH; specify --src instead") if not locate_command('tar'): parser.error("program 'tar' is not in your PATH") # Use git to checkout a clean copy. DEST.mkdir() TARFILE = DEST / "dil.tar" call_proc("git", "archive", "-o", TARFILE, "HEAD") call_proc("tar", "-xf", TARFILE.name, cwd=DEST) TARFILE.rm() if options.copy_modified: modified_files = call_read("git", "ls-files", "-m")[:-1] if modified_files != "": for f in modified_files.split("\n"): Path(f).copy(DEST / f) # Create other directories not available in a clean checkout. DOC = DEST.DOC Paths(DOC.HTMLSRC, DOC.CSS, DOC.IMG, DOC.JS, TMP).mkdirs() # Rebuild the path object for kandil. (Images are globbed.) DEST.KANDIL = kandil_path(DEST / "kandil") print("== Copying files ==") copy_files(DEST) # Find the source code files. FILES = find_dil_source_files(DEST.SRC) # Update the version info. update_VERSION(DEST.SRC / "dil" / "Version.d", VERSION) write_VERSION(VERSION, DEST) if options.docs: build_dil_if_inexistant(DIL.EXE) print("== Generating documentation ==") DOC_FILES = DEST.DATA / ("macros_dil.ddoc", "dilconf.d") + FILES versions = ["DDoc"] generate_docs(DIL.EXE, DEST.DOC, MODLIST, DOC_FILES, versions, options=['-v', '-i', '-hl', '--kandil']) if options.pdf: write_PDF(DEST, DEST.DOC, VERSION, TMP) #if options.chm: #write_CHM(DEST, DEST.DOC, VERSION, TMP) TARGETS = [Targets[n] for n in ("Lin32", "Lin64", "Win32")] if not options.no_binaries: BINS = build_binaries(TARGETS, COMPILER, VERSION.MAJ, FILES, DEST) for bin in BINS: (DIL.DATA / "dilconf.d").copy(bin.folder) PRODUCED += [(DEST.abspath, sw.stop())] # Remove unneeded directories. options.docs or DEST.DOC.rm() # Build archives. assert DEST[-1] != Path.sep create_archives(options, DEST.name, DEST.name, DEST.folder) if options.deb and not options.no_binaries: MTR = get_MAINTAINER(options.deb_mntnr) NUM = int(options.deb_num) # Make an archive for each architecture. SRC = Path(DEST) SRC.DATA = DEST.DATA SRC.DOC = DEST.DOC LINUX_BINS = [bin for bin in BINS if bin.target.islin] for arch in ("i386", "amd64"): # Gather the binaries that belong to arch. SRC.BINS = [bin for bin in LINUX_BINS if bin.target.arch == arch] sw.start() DEB = make_deb_package(SRC, DEST.folder, VERSION, arch, DEST, MTR, NUM) PRODUCED += [(DEB.abspath, sw.stop())] if not options.no_binaries: # Make an arch-independent folder. NOARCH = TMP / "dil_noarch" DEST.copy(NOARCH) (NOARCH / ("linux", "windows")).rm() # Linux: for bits in (32, 64): BIN = DEST / "linux" / "bin%d" % bits if not BIN.exists: continue SRC = (TMP / "dil_" + VERSION).rm() # Clear if necessary. NOARCH.copy(SRC) BIN.copy(SRC / "bin") write_modified_dilconf(SRC / "data" / "dilconf.d", SRC / "bin" / "dilconf.d", Path("${BINDIR}") / ".." / "data") NAME = BUILDROOT.abspath / "dil_%s_linux%s" % (VERSION, bits) for ext in (".7z", ".tar.xz"): sw.start() make_archive(SRC, NAME + ext) PRODUCED += [(NAME + ext, sw.stop())] SRC.rm() # Windows: for bits in (32, 64): if bits != 32: continue # Only 32bit supported atm. BIN = DEST / "windows" / "bin%d" % bits if not BIN.exists: continue SRC = (TMP / "dil_" + VERSION).rm() # Clear if necessary. NOARCH.copy(SRC) BIN.copy(SRC / "bin") write_modified_dilconf(SRC / "data" / "dilconf.d", SRC / "bin" / "dilconf.d", Path("${BINDIR}") / ".." / "data") NAME = BUILDROOT.abspath / "dil_%s_win%s" % (VERSION, bits) for ext in (".7z", ".zip"): sw.start() make_archive(SRC, NAME + ext) PRODUCED += [(NAME + ext, sw.stop())] SRC.rm() NOARCH.rm() # All platforms: NAME = BUILDROOT.abspath / "dil_%s_all" % VERSION for ext in (".7z", ".zip", ".tar.xz"): sw.start() make_archive(DEST, NAME + ext) PRODUCED += [(NAME + ext, sw.stop())] TMP.rm() if PRODUCED: print("\nProduced files/folders:") for x, sec in PRODUCED: if Path(x).exists: print(x + " (%.2fs)" % sec) print() print("Finished in %.2fs!" % sw_all.stop())
def main(): from functools import partial as func_partial from argparse import ArgumentParser, SUPPRESS parser = ArgumentParser() addarg = parser.add_argument addflag = func_partial(addarg, action="store_true") addarg("version", metavar="VERSION", nargs=1, help="the version to be released") addflag("-s", "--dsymbols", dest="debug_symbols", help="generate debug symbols for debug builds") addflag("-d", "--docs", dest="docs", help="generate documentation") addflag("-n", "--no-bin", dest="no_binaries", help="don't compile code") addflag("--7z", dest="_7z", help="create a 7z archive") addflag("--gz", dest="tar_gz", help="create a tar.gz archive") addflag("--bz2", dest="tar_bz2", help="create a tar.bz2 archive") addflag("--zip", dest="zip", help="create a zip archive") addflag("--deb", dest="deb", help="create deb files") addflag("--pdf", dest="pdf", help="create a PDF document") addflag("--chm", dest="chm", help=SUPPRESS) # "create a CHM file" addflag("-m", dest="copy_modified", help="copy modified files from the (git) working directory") addflag("--ldc", dest="ldc", help="use ldc instead of dmd") addarg("--src", dest="src", metavar="SRC", help="use SRC folder instead of checking out code with git") addarg("--cmp-exe", dest="cmp_exe", metavar="EXE_PATH", help="specify EXE_PATH if dmd/ldc is not in your PATH") addarg("--builddir", dest="builddir", metavar="DIR", help="where to build the release and archives (default is build/)") addarg("--winpath", dest="winpath", metavar="P", help="permanently append P to PATH in the Windows (or wine's) registry. " "Exits the script.") addarg("--debm", dest="deb_mntnr", metavar="MTR", help=SUPPRESS) # Sets the maintainer info of the package. addarg("--debnum", dest="deb_num", metavar="NUM", default=1, help=SUPPRESS) # Sets the package number. options = args = parser.parse_args(sys.uargv[1:]) if options.winpath != None: from env_path import append2PATH append2PATH(options.winpath) return change_cwd(__file__) # Validate the version argument. m = re.match(r"^((\d)\.(\d{3})(?:-(\w+))?)(?:\+(\w+))?$", args.version) if not m: parser.error("invalid VERSION format: /\d.\d\d\d(-\w+)?/ E.g.: 1.123") # The version of DIL to be built. class Version(unicode): def __new__(cls, parts): v = unicode.__new__(cls, parts[0]) v.MAJ, v.MIN, SFX, BSFX = parts[1:] v.SFX = SFX or '' v.BINSFX = BSFX or '' return v VERSION = Version(m.groups()) # Pick a compiler for compiling DIL. CmdClass = (DMDCommand, LDCCommand)[options.ldc] COMPILER = Path(options.cmp_exe or CmdClass.exe) COMPILER.CmdClass = CmdClass if not COMPILER.exists and not locate_command(COMPILER): parser.error("The executable '%s' could not be located." % COMPILER) # Path to DIL's root folder. DIL = dil_path() # Build folder. BUILDROOT = Path(options.builddir or "build")/("dil_"+VERSION) # Destination of distributable files. DEST = dil_path(BUILDROOT/"dil", dilconf=False) DEST.DOC = doc_path(DEST.DOC) # Temporary directory, deleted in the end. TMP = BUILDROOT/"tmp" # The list of module files (with info) that have been processed. MODLIST = TMP/"modules.txt" # The source files that need to be compiled and documentation generated for. FILES = [] # The folders and files which were produced by a build. PRODUCED = [] sw, sw_all = StopWatch(), StopWatch() # Check out a new working copy. BUILDROOT.rm().mkdir() # First remove the whole folder and recreate it. if options.src != None: # Use the source folder specified by the user. src = Path(options.src) if not src.exists: parser.error("the given SRC path (%s) doesn't exist" % src) #if src.ext in ('zip', 'gz', 'bz2'): # TODO: src.copy(DEST) else: if not locate_command('git'): parser.error("'git' is not in your PATH; specify --src instead") if not locate_command('tar'): parser.error("program 'tar' is not in your PATH") # Use git to checkout a clean copy. DEST.mkdir() TARFILE = DEST/"dil.tar" call_proc("git", "archive", "-o", TARFILE, "HEAD") call_proc("tar", "-xf", TARFILE.name, cwd=DEST) TARFILE.rm() if options.copy_modified: modified_files = call_read("git", "ls-files", "-m")[:-1] if modified_files != "": for f in modified_files.split("\n"): Path(f).copy(DEST/f) # Create other directories not available in a clean checkout. DOC = DEST.DOC Paths(DOC.HTMLSRC, DOC.CSS, DOC.IMG, DOC.JS, TMP).mkdirs() # Rebuild the path object for kandil. (Images are globbed.) DEST.KANDIL = kandil_path(DEST/"kandil") print("== Copying files ==") copy_files(DEST) # Find the source code files. FILES = find_dil_source_files(DEST.SRC) # Update the version info. update_VERSION(DEST.SRC/"dil"/"Version.d", VERSION) write_VERSION(VERSION, DEST) if options.docs: build_dil_if_inexistant(DIL.EXE) print("== Generating documentation ==") DOC_FILES = DEST.DATA/("macros_dil.ddoc", "dilconf.d") + FILES versions = ["DDoc"] generate_docs(DIL.EXE, DEST.DOC, MODLIST, DOC_FILES, versions, options=['-v', '-i', '-hl', '--kandil']) if options.pdf: write_PDF(DEST, DEST.DOC, VERSION, TMP) #if options.chm: #write_CHM(DEST, DEST.DOC, VERSION, TMP) TARGETS = [Targets[n] for n in ("Lin32", "Lin64", "Win32")] if not options.no_binaries: BINS = build_binaries(TARGETS, COMPILER, VERSION.MAJ, FILES, DEST) for bin in BINS: (DIL.DATA/"dilconf.d").copy(bin.folder) PRODUCED += [(DEST.abspath, sw.stop())] # Remove unneeded directories. options.docs or DEST.DOC.rm() # Build archives. assert DEST[-1] != Path.sep create_archives(options, DEST.name, DEST.name, DEST.folder) if options.deb and not options.no_binaries: MTR = get_MAINTAINER(options.deb_mntnr) NUM = int(options.deb_num) # Make an archive for each architecture. SRC = Path(DEST) SRC.DATA = DEST.DATA SRC.DOC = DEST.DOC LINUX_BINS = [bin for bin in BINS if bin.target.islin] for arch in ("i386", "amd64"): # Gather the binaries that belong to arch. SRC.BINS = [bin for bin in LINUX_BINS if bin.target.arch == arch] sw.start() DEB = make_deb_package(SRC, DEST.folder, VERSION, arch, DEST, MTR, NUM) PRODUCED += [(DEB.abspath, sw.stop())] if not options.no_binaries: # Make an arch-independent folder. NOARCH = TMP/"dil_noarch" DEST.copy(NOARCH) (NOARCH/("linux", "windows")).rm() # Linux: for bits in (32, 64): BIN = DEST/"linux"/"bin%d"%bits if not BIN.exists: continue SRC = (TMP/"dil_"+VERSION).rm() # Clear if necessary. NOARCH.copy(SRC) BIN.copy(SRC/"bin") write_modified_dilconf(SRC/"data"/"dilconf.d", SRC/"bin"/"dilconf.d", Path("${BINDIR}")/".."/"data") NAME = BUILDROOT.abspath/"dil_%s_linux%s" % (VERSION, bits) for ext in (".7z", ".tar.xz"): sw.start() make_archive(SRC, NAME+ext) PRODUCED += [(NAME+ext, sw.stop())] SRC.rm() # Windows: for bits in (32, 64): if bits != 32: continue # Only 32bit supported atm. BIN = DEST/"windows"/"bin%d"%bits if not BIN.exists: continue SRC = (TMP/"dil_"+VERSION).rm() # Clear if necessary. NOARCH.copy(SRC) BIN.copy(SRC/"bin") write_modified_dilconf(SRC/"data"/"dilconf.d", SRC/"bin"/"dilconf.d", Path("${BINDIR}")/".."/"data") NAME = BUILDROOT.abspath/"dil_%s_win%s" % (VERSION, bits) for ext in (".7z", ".zip"): sw.start() make_archive(SRC, NAME+ext) PRODUCED += [(NAME+ext, sw.stop())] SRC.rm() NOARCH.rm() # All platforms: NAME = BUILDROOT.abspath/"dil_%s_all" % VERSION for ext in (".7z", ".zip", ".tar.xz"): sw.start() make_archive(DEST, NAME+ext) PRODUCED += [(NAME+ext, sw.stop())] TMP.rm() if PRODUCED: print("\nProduced files/folders:") for x, sec in PRODUCED: if Path(x).exists: print(x+" (%.2fs)"%sec) print() print("Finished in %.2fs!" % sw_all.stop())
def main(): from functools import partial as func_partial from optparse import OptionParser usage = "Usage: scripts/release.py VERSION [Options]" parser = OptionParser(usage=usage) add_option = func_partial(parser.add_option, action="store_true", default=False) add_option("-s", "--dsymbols", dest="debug_symbols", help="generate debug symbols for debug builds") add_option("-d", "--docs", dest="docs", help="generate documentation") add_option("-n", "--no-bin", dest="no_binaries", help="don't compile code") add_option("--7z", dest="_7z", help="create a 7z archive") add_option("--gz", dest="tar_gz", help="create a tar.gz archive") add_option("--bz2", dest="tar_bz2", help="create a tar.bz2 archive") add_option("--zip", dest="zip", help="create a zip archive") add_option("--pdf", dest="pdf", help="create a PDF document") add_option("-m", dest="copy_modified", help="copy modified files from the (git) working directory") parser.add_option("--src", dest="src", metavar="SRC", default=None, help="use SRC folder instead of checking out code with git") parser.add_option("--dmd-exe", dest="dmd_exe", metavar="EXE_PATH", default="dmd", help="specify EXE_PATH if dmd is not in your PATH") parser.add_option("--builddir", dest="builddir", metavar="DIR", default=None, help="where to build the release and archives (default is build/)") parser.add_option("--winpath", dest="winpath", metavar="P", default=None, help="permanently append P to PATH in the Windows (or wine's) registry. " "Exits the script.") (options, args) = parser.parse_args() if options.winpath != None: from env_path import append2PATH append2PATH(options.winpath, Path("")) return if len(args) < 1: return parser.print_help() if len(args) > 1: print "Warning! Arguments ignored: " + " ".join(args[1:]) change_cwd(__file__) # Validate the version argument. m = re.match(r"((\d)\.(\d\d\d)(-\w+)?)", args[0]) if not m: parser.error("invalid VERSION; format: /\d.\d\d\d(-\w+)?/ E.g.: 1.123") matched = m.groups() if not Path(options.dmd_exe).exists and not locate_command(options.dmd_exe): parser.error("The executable '%s' couldn't be located or does not exist." % options.dmd_exe) # Path to dil's root folder. DIL = dil_path() # Name or path to the executable of dmd. DMD_EXE = Path(options.dmd_exe) # The version of dil to be built. VERSION, V_MAJOR = matched[:2] V_MINOR, V_SUFFIX = (matched[2], firstof(str, matched[3], '')) # Build folder. BUILD_DIR = Path(firstof(str, options.builddir, "build")) # Destination of distributable files. DEST = dil_path(BUILD_DIR/("dil."+VERSION), dilconf=False) BIN = DEST.BIN # Shortcut to the bin/ folder. DEST.DOC = doc_path(DEST.DOC) # Temporary directory, deleted in the end. TMP = DEST/"tmp" # The list of module files (with info) that have been processed. MODLIST = TMP/"modules.txt" # The files to generate documentation for. FILES = [] # Create the build directory. BUILD_DIR.makedirs() # Check out a new working copy. DEST.rmtree() # First remove the tree. if options.src != None: # Use the source folder specified by the user. src = Path(options.src) if not src.exists: parser.error("the given SRC path (%s) doesn't exist" % src) #if src.ext in ('.zip', '.gz', 'bz2'): # TODO: src.copytree(DEST) elif locate_command('git'): # Use git to checkout a clean copy. os.system("git clone ./ '%s'" % DEST) (DEST/".git").rmtree() # Remove the .git folder. if options.copy_modified: modified_files = os.popen("git ls-files -m").read()[:-1] if modified_files != "": for f in modified_files.split("\n"): Path(f).copy(DEST/f) else: parser.error("git is not in your PATH; specify --src instead") # Create other directories not available in a clean checkout. DOC = DEST.DOC map(Path.mkdir, (DEST.BIN, DOC, DOC.HTMLSRC, DOC.CSS, DOC.IMG, DOC.JS, TMP)) # Rebuild the path object for kandil. (Images are globbed.) DEST.KANDIL = kandil_path(DEST/"kandil") # Find the source code files. FILES = find_dil_source_files(DEST.SRC) # Update the version info. VERSION_FILE = DEST.SRC/"dil"/"Version.d" update_version(VERSION_FILE, V_MAJOR, V_MINOR, V_SUFFIX) if options.docs: build_dil_if_inexistant(DIL.EXE) DOC_FILES = [DEST.KANDIL.ddoc] + \ DEST.DATA//("macros_dil.ddoc", "dilconf.d") + FILES print "***** Generating documentation *****" versions = ["DDoc"] generate_docs(DIL.EXE, DEST.DOC, MODLIST, DOC_FILES, versions, options=['-v', '-i', '-hl', '--kandil']) if options.pdf: write_PDF(DEST, DEST.DOC, VERSION, TMP) DMD_EXE.use_wine = False use_wine = False if platform is 'win32': build_linux_binaries = False build_windows_binaries = True else: build_linux_binaries = True build_windows_binaries = locate_command("wine") != None class BINPath(Path): def __div__(self, name): """ Converts a Unix path to a Windows path. """ name = Path.__div__(self, name) return name if name.ext != '.exe' else name.replace("/", r"\\") BIN = BINPath(BIN) use_wine = True # Use wine on Linux to build Windows binaries. if not build_windows_binaries: print "Error: can't build windows binaries: "\ "wine is not installed or not in PATH." if options.no_binaries: build_linux_binaries = build_windows_binaries = False # Create partial functions with common parameters. # Note: the -inline switch makes the binaries significantly larger on Linux. build_dil_rls = func_partial(build_dil, DMD_EXE, FILES, release=True, optimize=True, inline=True) build_dil_dbg = func_partial(build_dil, DMD_EXE, FILES, debug_info=options.debug_symbols) if build_linux_binaries: print "***** Building Linux binaries *****" # Linux Debug Binaries build_dil_dbg(BIN/"dil_d") build_dil_dbg(BIN/"dil2_d", versions=["D2"]) # Linux Release Binaries build_dil_rls(BIN/"dil") build_dil_rls(BIN/"dil2", versions=["D2"]) if build_windows_binaries: print "***** Building Windows binaries *****" DMD_EXE.use_wine = use_wine # Windows Debug Binaries build_dil_dbg(BIN/"dil_d.exe") build_dil_dbg(BIN/"dil2_d.exe", versions=["D2"]) # Windows Release Binaries build_dil_rls(BIN/"dil.exe") build_dil_rls(BIN/"dil2.exe", versions=["D2"]) print "***** Copying files *****" copy_files(DEST) options.docs or DEST.DOC.rmtree() TMP.rmtree() # Build archives. assert DEST[-1] != Path.sep opt = options for exec_cmd, cmd in zip((opt.tar_gz, opt.tar_bz2, opt.zip, opt._7z), ("tar --owner root --group root -czf %(name)s.tar.gz %(src)s", "tar --owner root --group root --bzip2 -cf %(name)s.tar.bz2 %(src)s", "zip -q -9 -r %(name)s.zip %(src)s", "7zr a %(name)s.7z %(src)s")): if not exec_cmd: continue if locate_command(cmd): print "Error: the utility '%s' is not in your PATH." % cmd continue cmd = cmd % dict(locals(), name=DEST, src=DEST) print cmd os.system(cmd)
def main(): from functools import partial as func_partial from optparse import OptionParser usage = "Usage: %s VERSION [Options]" % __file__ parser = OptionParser(usage=usage) add_option = func_partial(parser.add_option, action="store_true", default=False) add_option("-s", "--dsymbols", dest="debug_symbols", help="generate debug symbols for debug builds") add_option("-d", "--docs", dest="docs", help="generate documentation") add_option("-n", "--no-bin", dest="no_binaries", help="don't compile code") add_option("--7z", dest="_7z", help="create a 7z archive") add_option("--gz", dest="tar_gz", help="create a tar.gz archive") add_option("--bz2", dest="tar_bz2", help="create a tar.bz2 archive") add_option("--zip", dest="zip", help="create a zip archive") add_option("--pdf", dest="pdf", help="create a PDF document") #add_option("--chm", dest="chm", help="create a CHM file") add_option("-m", dest="copy_modified", help="copy modified files from the (git) working directory") parser.add_option("--src", dest="src", metavar="SRC", default=None, help="use SRC folder instead of checking out code with git") parser.add_option("--cmp-exe", dest="cmp_exe", metavar="EXE_PATH", help="specify EXE_PATH if dmd/ldc is not in your PATH") add_option("--ldc", dest="ldc", help="use ldc instead of dmd") parser.add_option("--builddir", dest="builddir", metavar="DIR", default=None, help="where to build the release and archives (default is build/)") parser.add_option("--winpath", dest="winpath", metavar="P", default=None, help="permanently append P to PATH in the Windows (or wine's) registry. " "Exits the script.") (options, args) = parser.parse_args(sys.uargv[1:]) if options.winpath != None: from env_path import append2PATH append2PATH(options.winpath, Path("")) return if len(args) < 1: return parser.print_help() if len(args) > 1: print("Warning! Arguments ignored: " + " ".join(args[1:])) change_cwd(__file__) # Validate the version argument. m = re.match(r"((\d)\.(\d\d\d)(-\w+)?)", args[0]) if not m: parser.error("invalid VERSION; format: /\d.\d\d\d(-\w+)?/ E.g.: 1.123") # The version of DIL to be built. VERSION, V_MAJOR, V_MINOR, V_SUFFIX = m.groups() V_SUFFIX = V_SUFFIX or '' # Pick a compiler for compiling DIL. CmdClass = (DMDCommand, LDCCommand)[options.ldc] COMPILER = Path(options.cmp_exe if options.cmp_exe else CmdClass.cmd) COMPILER.cmd = CmdClass if not COMPILER.exists and not locate_command(COMPILER): parser.error("The executable '%s' couldn't be located or does not exist." % COMPILER) # Path to DIL's root folder. DIL = dil_path() # Build folder. BUILD_DIR = Path(options.builddir or "build") # Destination of distributable files. DEST = dil_path(BUILD_DIR/("dil."+VERSION), dilconf=False) BIN = DEST.BIN # Shortcut to the bin/ folder. DEST.DOC = doc_path(DEST.DOC) # Temporary directory, deleted in the end. TMP = DEST/"tmp" # The list of module files (with info) that have been processed. MODLIST = TMP/"modules.txt" # The files to generate documentation for. FILES = [] # Create the build directory. BUILD_DIR.makedirs() # Check out a new working copy. DEST.rmtree() # First remove the tree. if options.src != None: # Use the source folder specified by the user. src = Path(options.src) if not src.exists: parser.error("the given SRC path (%s) doesn't exist" % src) #if src.ext in ('.zip', '.gz', 'bz2'): # TODO: src.copytree(DEST) elif locate_command('git'): # Use git to checkout a clean copy. DEST.mkdir() TARFILE = DEST/"dil.tar" subprocess.call(["git", "archive", "-o", TARFILE, "HEAD"]) subprocess.call(["tar", "-xf", TARFILE.name], cwd=DEST) TARFILE.rm() if options.copy_modified: modified_files = call_read(["git", "ls-files", "-m"])[:-1] if modified_files != "": for f in modified_files.split("\n"): Path(f).copy(DEST/f) else: parser.error("git is not in your PATH; specify --src instead") # Create other directories not available in a clean checkout. DOC = DEST.DOC map(Path.mkdir, (DEST.BIN, DOC, DOC.HTMLSRC, DOC.CSS, DOC.IMG, DOC.JS, TMP)) # Rebuild the path object for kandil. (Images are globbed.) DEST.KANDIL = kandil_path(DEST/"kandil") print("***** Copying files *****") copy_files(DEST) # Find the source code files. FILES = find_dil_source_files(DEST.SRC) # Update the version info. VERSION_FILE = DEST.SRC/"dil"/"Version.d" update_version(VERSION_FILE, V_MAJOR, V_MINOR, V_SUFFIX) if options.docs: build_dil_if_inexistant(DIL.EXE) print("***** Generating documentation *****") DOC_FILES = DEST.DATA//("macros_dil.ddoc", "dilconf.d") + FILES versions = ["DDoc"] generate_docs(DIL.EXE, DEST.DOC, MODLIST, DOC_FILES, versions, options=['-v', '-i', '-hl', '--kandil']) if options.pdf: write_PDF(DEST, DEST.DOC, VERSION, TMP) #if options.chm: #write_CHM(DEST, DEST.DOC, VERSION, TMP) COMPILER.use_wine = False use_wine = False if is_win32: build_linux_binaries = False build_windows_binaries = True else: build_linux_binaries = True build_windows_binaries = locate_command("wine") != None class BINPath(Path): def __div__(self, name): """ Converts a Unix path to a Windows path. """ name = Path.__div__(self, name) return name if name.ext != '.exe' else name.replace("/", r"\\") BIN = BINPath(BIN) use_wine = True # Use wine on Linux to build Windows binaries. if not build_windows_binaries: print("Error: can't build windows binaries: " "wine is not installed or not in PATH.") if options.no_binaries: build_linux_binaries = build_windows_binaries = False # Create partial functions with common parameters (aka. currying). # Note: the -inline switch makes the binaries significantly larger on Linux. linker_args = [None] build_dil_rls = func_partial(build_dil, COMPILER, FILES, release=True, optimize=True, inline=True, lnk_args=linker_args) build_dil_dbg = func_partial(build_dil, COMPILER, FILES, debug_info=options.debug_symbols, lnk_args=linker_args) if build_linux_binaries: print("\n***** Building Linux binaries *****\n") linker_args[0] = "-lmpfr" # Linux Debug Binaries build_dil_dbg(BIN/"dil_d") build_dil_dbg(BIN/"dil2_d", versions=["D2"]) # Linux Release Binaries build_dil_rls(BIN/"dil") build_dil_rls(BIN/"dil2", versions=["D2"]) if build_windows_binaries: print("\n***** Building Windows binaries *****\n") COMPILER.use_wine = use_wine linker_args[0] = "+mpfr.lib" # Windows Debug Binaries build_dil_dbg(BIN/"dil_d.exe") build_dil_dbg(BIN/"dil2_d.exe", versions=["D2"]) # Windows Release Binaries build_dil_rls(BIN/"dil.exe") build_dil_rls(BIN/"dil2.exe", versions=["D2"]) options.docs or DEST.DOC.rmtree() TMP.rmtree() # Build archives. assert DEST[-1] != Path.sep create_archives(options, DEST.name, DEST.name, DEST.folder)
def main(): from functools import partial as func_partial from optparse import OptionParser usage = "Usage: scripts/release.py VERSION [Options]" parser = OptionParser(usage=usage) add_option = func_partial(parser.add_option, action="store_true", default=False) add_option("-s", "--dsymbols", dest="debug_symbols", help="generate debug symbols for debug builds") add_option("-d", "--docs", dest="docs", help="generate documentation") add_option("--7z", dest="_7z", help="create a 7z archive") add_option("--gz", dest="tar_gz", help="create a tar.gz archive") add_option("--bz2", dest="tar_bz2", help="create a tar.bz2 archive") add_option("--zip", dest="zip", help="create a zip archive") add_option("--git", dest="git", help="use git to check out a clean copy (default is hg)") parser.add_option("--src", dest="src", metavar="SRC", default=None, help="use SRC folder instead of checking out code using hg or git") parser.add_option("--dmd-exe", dest="dmd_exe", metavar="EXE_PATH", default="dmd", help="specify EXE_PATH if dmd is not in your PATH") parser.add_option("--builddir", dest="builddir", metavar="DIR", default=None, help="where to build the release and archives (default is build/)") parser.add_option("--winpath", dest="winpath", metavar="P", default=None, help="permanently append P to PATH in the Windows (or wine's) registry. " "Exits the script.") (options, args) = parser.parse_args() if options.winpath != None: from env_path import append2PATH append2PATH(options.winpath, Path("")) return if len(args) < 1: return parser.print_help() if len(args) > 1: print "Warning! Arguments ignored: " + " ".join(args[1:]) # Validate the version argument. m = re.match(r"((\d)\.(\d\d\d)(-\w+)?)", args[0]) if not m: parser.error("invalid VERSION; format: /\d.\d\d\d(-\w+)?/ E.g.: 1.123") matched = m.groups() if not Path(options.dmd_exe).exists and not locate_command(options.dmd_exe): print "The executable '%s' couldn't be located or does not exist." % \ options.dmd_exe return notNone = max # Path of the executable of dil. DIL_EXE = Path("bin")/"dil" # Name or path to the executable of dmd. DMD_EXE = options.dmd_exe DMD_EXE_W = DMD_EXE # Executable to use for Windows builds. # The version of dil to be built. VERSION, V_MAJOR = matched[:2] V_MINOR, V_SUFFIX = (matched[2], notNone(matched[3], '')) # Build folder. BUILD_DIR = Path(notNone("build", options.builddir)) # Destination of distributable files. DEST = BUILD_DIR/("dil."+VERSION) # The destination of the binaries. DEST.BIN = DEST/"bin" BIN = DEST.BIN # Shortcut to the bin/ folder. # The source code folder of dil. DEST.SRC = DEST/"src" # Documentation folder of dil. DEST.DOC = DEST/"doc" # The JavaScript, CSS and image folders. DEST.JS, DEST.CSS, DEST.IMG = DEST.DOC//("js", "css", "img") # Destination of syntax highlighted source files. DEST.HTMLSRC = DEST.DOC/"htmlsrc" # Dil's data/ directory. DEST.DATA = DEST/'data' # Dil's fancy documentation format. DEST.KANDIL = DEST/"kandil" # Temporary directory, deleted in the end. TMP = DEST/"tmp" # The list of module files (with info) that have been processed. MODLIST = TMP/"modules.txt" # The files to generate documentation for. FILES = [] # Create the build directory. BUILD_DIR.makedirs() # Check out a new working copy. DEST.rmtree() # First remove the tree. if options.src != None: Path(options.src).copytree(DEST) elif options.git: if locate_command('git'): os.system("git clone ./ %(DEST)s && cd %(DEST)s && git checkout"%locals()) (DEST/".git").rmtree() # Remove the .git folder. else: raise Exception("git is not in your PATH") elif locate_command('hg'): os.system("hg archive -r tip -t files " + DEST) else: raise Exception("hg is not in your PATH; specify SRC or use git") # Create other directories not available in a clean checkout. map(Path.mkdir, (DEST.BIN, DEST.DOC, DEST.HTMLSRC, DEST.CSS, DEST.IMG, DEST.JS, TMP)) # Find the source code files. FILES = find_dil_source_files(DEST.SRC) # Make a backup of the original. VERSION_D = DEST.SRC/"dil"/"Version.d" VERSION_D.copy(TMP/"Version.d") # Update the version info. update_version(VERSION_D, V_MAJOR, V_MINOR) # Restore the original at the end of the build process. if options.docs: build_dil_if_inexistant(DIL_EXE) DOC_FILES = [DEST.KANDIL/"kandil.ddoc"] + \ DEST.DATA//("macros_dil.ddoc", "dilconf.d") + FILES versions = ["DDoc"] print "***** Generating documentation *****" generate_docs(DIL_EXE, DEST.DOC, MODLIST, DOC_FILES, versions, options='-v') modlist = read_modules_list(MODLIST) generate_modules_js(modlist, DEST.JS/"modules.js") print "***** Generating syntax highlighted HTML files *****" for args in generate_shl_files2(DIL_EXE, DEST.HTMLSRC, modlist): print "hl %s > %s" % args; download_jquery(DEST.JS/"jquery.js") if platform is 'win32': build_linux_binaries = False build_windows_binaries = True else: build_linux_binaries = True build_windows_binaries = locate_command("wine") != None class BINPath(Path): def __div__(self, name): """ Converts a Unix path to a Windows path. """ name = Path.__div__(self, name) return name if name.ext != '.exe' else name.replace("/", r"\\") BIN = BINPath(BIN) DMD_EXE_W = "wine dmd.exe" # Use wine on Linux to build Windows binaries. if not build_windows_binaries: print "Error: can't build windows binaries: "\ "wine is not installed or not in PATH." # Create partial functions with common parameters. # Note: the -inline switch makes the binaries significantly larger on Linux. build_dil_rls = func_partial(build_dil, FILES, dmd_exe=DMD_EXE, release=True, optimize=True, inline=True) build_dil_dbg = func_partial(build_dil, FILES, dmd_exe=DMD_EXE, debug_info=options.debug_symbols) if build_linux_binaries: print "***** Building Linux binaries *****" # Linux Debug Binaries build_dil_dbg(BIN/"dil_d") build_dil_dbg(BIN/"dil2_d", versions=["D2"]) # Linux Release Binaries build_dil_rls(BIN/"dil") build_dil_rls(BIN/"dil2", versions=["D2"]) if build_windows_binaries: print "***** Building Windows binaries *****" build_dil_dbg.keywords['dmd_exe'] = DMD_EXE_W build_dil_rls.keywords['dmd_exe'] = DMD_EXE_W # Windows Debug Binaries build_dil_dbg(BIN/"dil_d.exe") build_dil_dbg(BIN/"dil2_d.exe", versions=["D2"]) # Windows Release Binaries build_dil_rls(BIN/"dil.exe") build_dil_rls(BIN/"dil2.exe", versions=["D2"]) print "***** Copying files *****" copy_files(DEST) # Restore the original. NOTE: is this a good idea? (TMP/"Version.d").move(VERSION_D) if not options.docs: DEST.DOC.rmtree() TMP.rmtree() # Build archives. assert DEST[-1] != Path.sep opt = options for exec_cmd, cmd in zip((opt.tar_gz, opt.tar_bz2, opt.zip, opt._7z), ("tar --owner root --group root -czf %(name)s.tar.gz %(src)s", "tar --owner root --group root --bzip2 -cf %(name)s.tar.bz2 %(src)s", "zip -q -9 -r %(name)s.zip %(src)s", "7zr a %(name)s.7z %(src)s")): if not exec_cmd: continue if locate_command(cmd): print "Error: the utility '%s' is not in your PATH." % cmd continue cmd = cmd % dict(locals(), name=DEST, src=DEST) print cmd os.system(cmd)