diff options
author | Araq <rumpf_a@web.de> | 2012-02-17 02:16:50 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-02-17 02:16:50 +0100 |
commit | 547e8aa418ee9a851a876e109b483fc987bd87df (patch) | |
tree | a2b7dfe509beef289b83b933c51abbb8829b8541 | |
parent | 97366d44195a96075960749a0ea84ded582dce87 (diff) | |
parent | 6901a725d5718dc985243b93bd5bfc968f5b1521 (diff) | |
download | Nim-547e8aa418ee9a851a876e109b483fc987bd87df.tar.gz |
Merge branch 'master' of github.com:Araq/Nimrod
-rwxr-xr-x | compiler/nimrod.ini | 6 | ||||
-rwxr-xr-x | lib/pure/times.nim | 13 | ||||
-rw-r--r-- | tools/niminst/debcreation.nim | 227 | ||||
-rwxr-xr-x | tools/niminst/niminst.nim | 92 |
4 files changed, 336 insertions, 2 deletions
diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 4016328ae..b689ec1c4 100755 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -122,3 +122,9 @@ flags = "/Q" [C_Compiler] path = r"" flags = "-w" + +[deb] +buildDepends: "gcc (>= 4:4.3.2)" +pkgDepends: "gcc (>= 4:4.3.2)" +shortDesc: "The Nimrod Compiler" +licenses: "bin/nimrod,gpl2;lib/*,lgpl;" diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 2347557dc..98b91a33d 100755 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -377,4 +377,17 @@ proc getClockStr*(): string {.rtl, extern: "nt$1".} = result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) & ':' & intToStr(ti.second, 2) +proc `$`*(day: TWeekDay): string = + ## stingify operator for ``TWeekDay``. + let lookup: array[TWeekDay, string] = ["Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday"] + return lookup[day] + +proc `$`*(m: TMonth): string = + ## stingify operator for ``TMonth``. + let lookup: array[TMonth, string] = ["January", "February", "March", "April", + "May", "June", "July", "August", "September", "October", "November", + "December"] + return lookup[m] + {.pop.} diff --git a/tools/niminst/debcreation.nim b/tools/niminst/debcreation.nim new file mode 100644 index 000000000..287bd9a7b --- /dev/null +++ b/tools/niminst/debcreation.nim @@ -0,0 +1,227 @@ +import osproc, times, os, strutils + +# http://www.debian.org/doc/manuals/maint-guide/ + +# Required files for debhelper. +# -- control +# -- copyright +# -- changelog +# -- rules + +type + TDebOptions* = object + buildDepends*, pkgDepends*, shortDesc*: string + licenses*: seq[tuple[files, license: string]] + +template addN(r: string): expr = + result.add(r & "\n") + +proc createControl(pkgName, maintainer, shortDesc, desc: string, + buildDepends, pkgDepends: string = ""): string = + ## pkgName: Should be the package name, no spaces. + ## maintainer: firstName lastName <email> + ## shortDesc: short description of the application + ## desc: long description of the application + ## buildDepends: what the build depends on (compiling from source), + ## this needs to be in the format deb accepts. For example, + ## for gcc: ``gcc (>= 4:4.3.2)`` + ## Multiple dependencies should be separated by commas. + ## pkgDepends: Same as buildDepends except that this specifies the + ## dependencies that the compiled application depends on. + + + result = "" + + addN("Source: " & pkgName) + addN("Maintainer: " & maintainer) + addN("Section: misc") + addN("Priority: optional") + addN("Standards-Version: 3.9.2") + addN("Build-Depends: debhelper (>= 8)" & + (if buildDepends != "": ", " & buildDepends else: "")) + addN("\n") + addN("Package: " & pkgName) + addN("Architecture: any") + addN("Depends: ${shlibs:Depends}, ${misc:Depends}" & + (if pkgDepends != "": ", " & pkgDepends else: "")) + + var formattedDesc = "" + for line in splitLines(desc): + if line == "": + formattedDesc.add(" .\n") + else: + formattedDesc.add(" " & line & "\n") + + addN("Description: " & shortDesc & "\n" & formattedDesc) + +proc createCopyright(pkgName, mtnName, mtnEmail, version: string, + licenses: seq[tuple[files, license: string]]): string = + ## pkgName: Package name + ## mtnName: Maintainer name + ## mtnEmail: Maintainer email + ## version: package version + ## licenses: files: This specifies the files that the `license` covers, + ## for example, it might be ``lib/*`` to cover the whole ``lib`` dir + ## license: This specifies the license, for example gpl2, or lgpl. + + result = "" + addN("Maintainer name: " & mtnName) + addN("Email-Address: " & mtnEmail) + addN("Date: " & $getTime()) + addN("Package Name: " & pkgName) + addN("Version: " & version) + for f, license in items(licenses): + addN("Files: " & f) + addN("License: " & license) + +proc formatDateTime(t: TTimeInfo, timezone: string): string = + var day = ($t.weekday)[0..2] & ", " + + return "$1$2 $3 $4 $5:$6:$7 $8" % [day, intToStr(t.monthday, 2), + ($t.month)[0..2], $t.year, intToStr(t.hour, 2), intToStr(t.minute, 2), + intToStr(t.second, 2), timezone] + +proc createChangelog(pkgName, version, maintainer: string): string = + ## pkgName: package name + ## version: package version + ## maintainer: firstName lastName <email> + result = "" + addN(pkgName & " (" & version & "-1) unstable; urgency=low") + addN("") + addN(" * Initial release.") + addN("") + addN(" -- " & maintainer & " " & + formatDateTime(getGmTime(getTime()), "+0000")) + +proc createRules(): string = + ## Creates a nimrod application-agnostic rules file for building deb packages. + ## Please note: this assumes the c sources have been built and the + ## ``build.sh`` and ``install.sh`` files are available. + result = "" + addN("#!/usr/bin/make -f") + addN("%:") + addN("\tdh $@\n") + addN("dh_install:") + addN("\tdh_install --sourcedir=debian/tmp") + addN("override_dh_auto_clean:") + addN("\tfind . -name *.o -exec rm {} \\;") + addN("override_dh_auto_build:") + addN("\t./build.sh") + addN("override_dh_auto_install:") + addN("\t./install.sh debian/tmp") + +proc createIncludeBinaries(binaries: seq[string]): string = + return join(binaries, "\n") + +proc createDotInstall(pkgName: string, binaries, config, docs, + lib: seq[string]): string = + result = "" + for b in binaries: + addN(pkgName / b & " " & "usr/bin/") + for c in config: + addN(pkgName / c & " " & "etc/") + for d in docs: + addN(pkgName / d & " " & "usr/share/doc/nimrod/") + for l1 in lib: + addN(pkgName / l1 & " " & "usr/lib/nimrod") + +proc makeMtn(name, email: string): string = + return name & " <" & email & ">" + +proc assertSuccess(exitCode: int) = + doAssert(exitCode == QuitSuccess) + +proc prepDeb*(packName, version, mtnName, mtnEmail, shortDesc, desc: string, + licenses: seq[tuple[files, license: string]], binaries, + config, docs, lib: seq[string], + buildDepends, pkgDepends = "") = + ## binaries/config/docs/lib: files relative to nimrod's root, that need to + ## be installed. + + let pkgName = packName.toLower() + + var workingDir = getTempDir() / "niminst" / "deb" + var upstreamSource = (pkgName & "-" & version) + + echo("Making sure build.sh and install.sh are +x") + assertSuccess execCmd("chmod +x \"" & + (workingDir / upstreamSource / "build.sh") & "\"") + assertSuccess execCmd("chmod +x \"" & + (workingDir / upstreamSource / "install.sh") & "\"") + + var tarCmd = "tar pczf \"" & + (pkgName & "_" & version & ".orig.tar.gz") & + "\" \"" & upstreamSource & "\"" + echo(tarCmd) + assertSuccess execCmd("cd \"" & workingDir & "\" && " & tarCmd) + + echo("Creating necessary files in debian/") + createDir(workingDir / upstreamSource / "debian") + + template writeDebian(f, s: string): expr = + writeFile(workingDir / upstreamSource / "debian" / f, s) + + var controlFile = createControl(pkgName, makeMtn(mtnName, mtnEmail), + shortDesc, desc, buildDepends, pkgDepends) + echo("debian/control") + writeDebian("control", controlFile) + + var copyrightFile = createCopyright(pkgName, mtnName, mtnEmail, version, + licenses) + echo("debian/copyright") + writeDebian("copyright", copyrightFile) + + var changelogFile = createChangelog(pkgName, version, + makeMtn(mtnName, mtnEmail)) + echo("debian/changelog") + writeDebian("changelog", changelogFile) + + echo("debian/rules") + writeDebian("rules", createRules()) + + echo("debian/compat") + writeDebian("compat", "8") + + echo("debian/" & pkgName & ".install") + writeDebian(pkgName & ".install", + createDotInstall(pkgName, binaries, config, docs, lib)) + + # Other things.. + createDir(workingDir / upstreamSource / "debian" / "source") + echo("debian/source/format") + writeDebian("source" / "format", + "3.0 (quilt)") + echo("debian/source/include-binaries") + writeFile(workingDir / upstreamSource / "debian" / "source" / "include-binaries", + createIncludeBinaries(binaries)) + + echo("All done, you can now build.") + echo("Before you do however, make sure the files in " & + workingDir / upstreamSource / "debian" & " are correct.") + echo("Change your directory to: " & workingDir / upstreamSource) + echo("And execute `debuild -us -uc` to build the .deb") + +when isMainModule: + #var controlFile = createControl("nimrod", "Dominik Picheta <morfeusz8@gmail.com>", + # "The Nimrod compiler", "Compiler for the Nimrod programming language", "gcc (>= 4:4.3.2)", "gcc (>= 4:4.3.2)") + + #echo(controlFile) + + #var copyrightFile = createCopyright("nimrod", "Dominik Picheta", "morfeusz8@a.b", "0.8.14", + # @[("bin/nimrod", "gpl2"), ("lib/*", "lgpl")]) + + #echo copyrightFile + + #var changelogFile = createChangelog("nimrod", "0.8.14", "Dom P <m@b.c>") + #echo(changelogFile) + + #echo(createRules()) + + prepDeb("nimrod", "0.8.14", "Dominik Picheta", "morfeusz8@gmail.com", + "The Nimrod compiler", "Compiler for the Nimrod programming language", + @[("bin/nimrod", "gpl2"), ("lib/*", "lgpl")], + @["bin/nimrod"], @["config/*"], @["doc/*"], @["lib/*"], + "gcc (>= 4:4.3.2)", "gcc (>= 4:4.3.2)") + + + \ No newline at end of file diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index 8f73ae93a..207df0d32 100755 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -14,7 +14,7 @@ when haveZipLib: import zipfiles import - os, strutils, parseopt, parsecfg, strtabs, streams + os, strutils, parseopt, parsecfg, strtabs, streams, debcreation const maxOS = 20 # max number of OSes @@ -30,7 +30,8 @@ type actionNone, # action not yet known actionCSource # action: create C sources actionInno, # action: create Inno Setup installer - actionZip # action: create zip file + actionZip, # action: create zip file + actionDeb # action: prepare deb package TFileCategory = enum fcWinBin, # binaries for Windows @@ -56,6 +57,7 @@ type vars: PStringTable app: TAppType nimrodArgs: string + debOpts: TDebOptions const unixDirVars: array[fcConfig..fcLib, string] = [ @@ -86,6 +88,11 @@ proc initConfigData(c: var TConfigData) = c.uninstallScript = false c.vars = newStringTable(modeStyleInsensitive) + c.debOpts.buildDepends = "" + c.debOpts.pkgDepends = "" + c.debOpts.shortDesc = "" + c.debOpts.licenses = @[] + proc firstBinPath(c: TConfigData): string = if c.binPaths.len > 0: result = c.binPaths[0] else: result = "" @@ -121,6 +128,7 @@ Command: csource build C source code for source based installations zip build the ZIP file inno build the Inno Setup installer + deb create files for debhelper Options: -o, --output:dir set the output directory --var:name=value set the value of a variable @@ -145,6 +153,7 @@ proc parseCmdLine(c: var TConfigData) = of "csource": incl(c.actions, actionCSource) of "zip": incl(c.actions, actionZip) of "inno": incl(c.actions, actionInno) + of "deb": incl(c.actions, actionDeb) else: quit(Usage) else: c.infile = addFileExt(key.string, "ini") @@ -266,6 +275,36 @@ proc parseIniFile(c: var TConfigData) = of "innosetup": pathFlags(p, k.key, v, c.innoSetup) of "ccompiler": pathFlags(p, k.key, v, c.ccompiler) of "linker": pathFlags(p, k.key, v, c.linker) + of "deb": + case normalize(k.key) + of "builddepends": + c.debOpts.buildDepends = v + of "packagedepends", "pkgdepends": + c.debOpts.pkgDepends = v + of "shortdesc": + c.debOpts.shortDesc = v + of "licenses": + # file,license;file,license; + var i = 0 + var file = "" + var license = "" + var afterComma = false + while i < v.len(): + case v[i] + of ',': + afterComma = true + of ';': + if file == "" or license == "": + quit(errorStr(p, "Invalid `licenses` key.")) + c.debOpts.licenses.add((file, license)) + afterComma = false + file = "" + license = "" + else: + if afterComma: license.add(v[i]) + else: file.add(v[i]) + inc(i) + else: quit(errorStr(p, "unknown variable: " & k.key)) else: quit(errorStr(p, "invalid section: " & section)) of cfgOption: quit(errorStr(p, "syntax error")) @@ -415,6 +454,52 @@ when haveZipLib: else: quit("Cannot open for writing: " & n) +# -- prepare build files for .deb creation + +proc debDist(c: var TConfigData) = + if not existsFile("build.sh"): quit("No build.sh found.") + if not existsFile("install.sh"): quit("No install.sh found.") + + if c.debOpts.shortDesc == "": quit("shortDesc must be set in the .ini file.") + if c.debOpts.licenses.len == 0: + echo("[Warning] No licenses specified for .deb creation.") + + # -- Copy files into /tmp/.. + echo("Copying source to tmp/niminst/deb/") + var currentSource = getCurrentDir() + var workingDir = getTempDir() / "niminst" / "deb" + var upstreamSource = (c.name.toLower() & "-" & c.version) + + createDir(workingDir / upstreamSource) + + template copyNimDist(f, dest: string): stmt = + createDir((workingDir / upstreamSource / dest).splitFile.dir) + copyFile(currentSource / f, workingDir / upstreamSource / dest) + + # Don't copy all files, only the ones specified in the config: + copyNimDist(buildShFile, buildShFile) + copyNimDist(installShFile, installShFile) + createDir(workingDir / upstreamSource / "build") + for f in walkFiles(c.libpath / "lib/*.h"): + copyNimDist(f, "build" / extractFilename(f)) + for osA in 1..c.oses.len: + for cpuA in 1..c.cpus.len: + var dir = buildDir(osA, cpuA) + for k, f in walkDir(dir): + if k == pcFile: copyNimDist(f, dir / extractFilename(f)) + for cat in items({fcConfig..fcOther, fcUnix}): + for f in items(c.cat[cat]): copyNimDist(f, f) + + # -- Create necessary build files for debhelper. + + let mtnName = c.vars["mtnname"] + let mtnEmail = c.vars["mtnemail"] + + prepDeb(c.name, c.version, mtnName, mtnEmail, c.debOpts.shortDesc, + c.description, c.debOpts.licenses, c.cat[fcUnixBin], c.cat[fcConfig], + c.cat[fcDoc], c.cat[fcLib], c.debOpts.buildDepends, + c.debOpts.pkgDepends) + # ------------------- main ---------------------------------------------------- var c: TConfigData @@ -430,3 +515,6 @@ if actionZip in c.actions: zipdist(c) else: quit("libzip is not installed") +if actionDeb in c.actions: + debDist(c) + |