#!/usr/bin/env python3 import os.path import re import sys WINDOWS = [ # --------------------- ----------------- # # Runtime ID Platform # # --------------------- ----------------- # ("win-x64", "x64"), ("win-x86", "Win32"), # --------------------- ----------------- # ] MACOS = [ # --------------------- ----------------- # # Runtime ID Codename # # --------------------- ----------------- # ("osx-x64", "mojave"), # --------------------- ----------------- # ] LINUX = [ # --------------------- ----------------- # # Runtime ID Docker Image # # --------------------- ----------------- # ("linux-x64", "debian:stretch"), # --------------------- ----------------- # ] EXTRAS = ["LICENSE", "AUTHORS", "ChangeLog"] PROPSFILE = "libsodium.props" MAKEFILE = "Makefile" BUILDDIR = "build" CACHEDIR = "cache" TEMPDIR = "temp" PACKAGE = "libsodium" LIBRARY = "libsodium" DOCKER = "sudo docker" class Version: def __init__(self, libsodium_version, package_version): self.libsodium_version = libsodium_version self.package_version = package_version self.builddir = os.path.join(BUILDDIR, libsodium_version) self.tempdir = os.path.join(TEMPDIR, libsodium_version) self.projfile = os.path.join( self.builddir, "{0}.{1}.pkgproj".format(PACKAGE, package_version) ) self.propsfile = os.path.join(self.builddir, "{0}.props".format(PACKAGE)) self.pkgfile = os.path.join( BUILDDIR, "{0}.{1}.nupkg".format(PACKAGE, package_version) ) class WindowsItem: def __init__(self, version, rid, platform): self.url = "https://download.libsodium.org/libsodium/releases/libsodium-{0}-stable-msvc.zip".format( version.libsodium_version ) self.cachefile = os.path.join(CACHEDIR, re.sub(r"[^A-Za-z0-9.]", "-", self.url)) self.packfile = os.path.join( version.builddir, "runtimes", rid, "native", LIBRARY + ".dll" ) self.itemfile = "{0}/Release/v140/dynamic/libsodium.dll".format(platform) self.tempdir = os.path.join(version.tempdir, rid) self.tempfile = os.path.join(self.tempdir, os.path.normpath(self.itemfile)) def make(self, f): f.write("\n") f.write("{0}: {1}\n".format(self.packfile, self.tempfile)) f.write("\t@mkdir -p $(dir $@)\n") f.write("\tcp -f $< $@\n") f.write("\n") f.write("{0}: {1}\n".format(self.tempfile, self.cachefile)) f.write("\t@mkdir -p $(dir $@)\n") f.write( "\tcd {0} && unzip -q -DD -o {1} '{2}'\n".format( self.tempdir, os.path.relpath(self.cachefile, self.tempdir), self.itemfile, ) ) class MacOSItem: def __init__(self, version, rid, codename): self.url = "https://bintray.com/homebrew/bottles/download_file?file_path=libsodium-{0}.{1}.bottle.tar.gz".format( version.libsodium_version, codename ) self.cachefile = os.path.join(CACHEDIR, re.sub(r"[^A-Za-z0-9.]", "-", self.url)) self.packfile = os.path.join( version.builddir, "runtimes", rid, "native", LIBRARY + ".dylib" ) self.itemfile = "libsodium/{0}/lib/libsodium.dylib".format( version.libsodium_version ) self.tempdir = os.path.join(version.tempdir, rid) self.tempfile = os.path.join(self.tempdir, os.path.normpath(self.itemfile)) def make(self, f): f.write("\n") f.write("{0}: {1}\n".format(self.packfile, self.tempfile)) f.write("\t@mkdir -p $(dir $@)\n") f.write("\tcp -f $< $@\n") f.write("\n") f.write("{0}: {1}\n".format(self.tempfile, self.cachefile)) f.write("\t@mkdir -p $(dir $@)\n") f.write( "\tcd {0} && tar xzmf {1} '{2}'\n".format( self.tempdir, os.path.relpath(self.cachefile, self.tempdir), os.path.dirname(self.itemfile), ) ) class LinuxItem: def __init__(self, version, rid, docker_image): self.url = "https://download.libsodium.org/libsodium/releases/libsodium-{0}.tar.gz".format( version.libsodium_version ) self.cachefile = os.path.join(CACHEDIR, re.sub(r"[^A-Za-z0-9.]", "-", self.url)) self.packfile = os.path.join( version.builddir, "runtimes", rid, "native", LIBRARY + ".so" ) self.tempdir = os.path.join(version.tempdir, rid) self.tempfile = os.path.join(self.tempdir, "libsodium.so") self.docker_image = docker_image self.recipe = rid def make(self, f): recipe = self.recipe while not os.path.exists(os.path.join("recipes", recipe)): m = re.fullmatch(r"([^.-]+)((([.][^.-]+)*)[.][^.-]+)?([-].*)?", recipe) if m.group(5) is None: recipe = "build" break elif m.group(2) is None: recipe = m.group(1) else: recipe = m.group(1) + m.group(3) + m.group(5) f.write("\n") f.write("{0}: {1}\n".format(self.packfile, self.tempfile)) f.write("\t@mkdir -p $(dir $@)\n") f.write("\tcp -f $< $@\n") f.write("\n") f.write("{0}: {1}\n".format(self.tempfile, self.cachefile)) f.write("\t@mkdir -p $(dir $@)\n") f.write( "\t{0} run --rm ".format(DOCKER) + "-v $(abspath recipes):/io/recipes " + "-v $(abspath $<):/io/libsodium.tar.gz " + "-v $(abspath $(dir $@)):/io/output " + "{0} sh -x -e /io/recipes/{1}\n".format(self.docker_image, recipe) ) class ExtraItem: def __init__(self, version, filename): self.url = "https://download.libsodium.org/libsodium/releases/libsodium-{0}.tar.gz".format( version.libsodium_version ) self.cachefile = os.path.join(CACHEDIR, re.sub(r"[^A-Za-z0-9.]", "-", self.url)) self.packfile = os.path.join(version.builddir, filename) self.itemfile = "libsodium-{0}/{1}".format(version.libsodium_version, filename) self.tempdir = os.path.join(version.tempdir, "extras") self.tempfile = os.path.join(self.tempdir, os.path.normpath(self.itemfile)) def make(self, f): f.write("\n") f.write("{0}: {1}\n".format(self.packfile, self.tempfile)) f.write("\t@mkdir -p $(dir $@)\n") f.write("\tcp -f $< $@\n") f.write("\n") f.write("{0}: {1}\n".format(self.tempfile, self.cachefile)) f.write("\t@mkdir -p $(dir $@)\n") f.write( "\tcd {0} && tar xzmf {1} '{2}'\n".format( self.tempdir, os.path.relpath(self.cachefile, self.tempdir), self.itemfile, ) ) def main(args): m = ( re.fullmatch(r"((\d+\.\d+\.\d+)(\.\d+)?)(?:-(\w+(?:[_.-]\w+)*))?", args[1]) if len(args) == 2 else None ) if m is None: print("Usage:") print(" python3 prepare.py ") print() print("Examples:") print(" python3 prepare.py 1.0.17-preview-01") print(" python3 prepare.py 1.0.17-preview-02") print(" python3 prepare.py 1.0.17-preview-03") print(" python3 prepare.py 1.0.17") print(" python3 prepare.py 1.0.17.1-preview-01") print(" python3 prepare.py 1.0.17.1") print(" python3 prepare.py 1.0.17.2") return 1 version = Version(m.group(2), m.group(0)) items = ( [WindowsItem(version, rid, platform) for (rid, platform) in WINDOWS] + [MacOSItem(version, rid, codename) for (rid, codename) in MACOS] + [LinuxItem(version, rid, docker_image) for (rid, docker_image) in LINUX] + [ExtraItem(version, filename) for filename in EXTRAS] ) downloads = {item.cachefile: item.url for item in items} with open(MAKEFILE, "w") as f: f.write("all: {0}\n".format(version.pkgfile)) for download in sorted(downloads): f.write("\n") f.write("{0}:\n".format(download)) f.write("\t@mkdir -p $(dir $@)\n") f.write("\tcurl -f#Lo $@ '{0}'\n".format(downloads[download])) for item in items: item.make(f) f.write("\n") f.write("{0}: {1}\n".format(version.propsfile, PROPSFILE)) f.write("\t@mkdir -p $(dir $@)\n") f.write("\tcp -f $< $@\n") f.write("\n") f.write("{0}: {1}\n".format(version.projfile, version.propsfile)) f.write("\t@mkdir -p $(dir $@)\n") f.write( "\techo '" + '' + ''.format( os.path.relpath(version.propsfile, os.path.dirname(version.projfile)) ) + "" + "{0}".format(version.package_version) + "" + "' > $@\n" ) f.write("\n") f.write("{0}:".format(version.pkgfile)) f.write(" \\\n\t\t{0}".format(version.projfile)) f.write(" \\\n\t\t{0}".format(version.propsfile)) for item in items: f.write(" \\\n\t\t{0}".format(item.packfile)) f.write("\n") f.write("\t@mkdir -p $(dir $@)\n") f.write( "\t{0} run --rm ".format(DOCKER) + "-v $(abspath recipes):/io/recipes " + "-v $(abspath $(dir $<)):/io/input " + "-v $(abspath $(dir $@)):/io/output " + "{0} sh -x -e /io/recipes/{1} {2}\n".format( "microsoft/dotnet:2.0-sdk", "pack", os.path.relpath(version.projfile, version.builddir), ) ) f.write("\n") f.write("test: {0}\n".format(version.pkgfile)) f.write( "\t{0} run --rm ".format(DOCKER) + "-v $(abspath recipes):/io/recipes " + "-v $(abspath $(dir $<)):/io/packages " + '{0} sh -x -e /io/recipes/{1} "{2}"\n'.format( "microsoft/dotnet:2.0-sdk", "test", version.package_version ) ) print( "prepared", MAKEFILE, "to make", version.pkgfile, "for libsodium", version.libsodium_version, ) return 0 if __name__ == "__main__": sys.exit(main(sys.argv))