diff options
Diffstat (limited to 'tools/niminst.nim')
-rwxr-xr-x | tools/niminst.nim | 389 |
1 files changed, 0 insertions, 389 deletions
diff --git a/tools/niminst.nim b/tools/niminst.nim deleted file mode 100755 index b1de0964c..000000000 --- a/tools/niminst.nim +++ /dev/null @@ -1,389 +0,0 @@ -# -# -# The Nimrod Installation Generator -# (c) Copyright 2009 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -const - haveZipLib = defined(unix) - -when haveZipLib: - import zipfiles - -import - os, strutils, parseopt, parsecfg, strtabs, streams - -const - maxOS = 20 # max number of OSes - maxCPU = 10 # max number of CPUs - buildShFile = "build.sh" - installShFile = "install.sh" - deinstallShFile = "deinstall.sh" - -type - TAppType = enum appConsole, appGUI - TAction = enum - actionNone, # action not yet known - actionCSource # action: create C sources - actionInno, # action: create Inno Setup installer - actionZip # action: create zip file - - TFileCategory = enum - fcWinBin, # binaries for Windows - fcConfig, # configuration files - fcData, # data files - fcDoc, # documentation files - fcLib, # library files - fcOther, # other files; will not be copied on UNIX - fcWindows, # files only for Windows - fcUnix, # files only for Unix; must be after ``fcWindows`` - fcUnixBin # binaries for Unix - - TConfigData = object of TObject - actions: set[TAction] - cat: array[TFileCategory, seq[string]] - binPaths, authors, oses, cpus: seq[string] - cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]] - ccompiler, innosetup: tuple[path, flags: string] - name, version, description, license, infile, outdir: string - innoSetupFlag, installScript, uninstallScript: bool - vars: PStringTable - app: TAppType - nimrodArgs: string - -const - unixDirVars: array[fcConfig..fcLib, string] = [ - "$configdir", "$datadir", "$docdir", "$libdir" - ] - -proc initConfigData(c: var TConfigData) = - c.actions = {} - for i in low(TFileCategory)..high(TFileCategory): c.cat[i] = @[] - c.binPaths = @[] - c.authors = @[] - c.oses = @[] - c.cpus = @[] - c.ccompiler = ("", "") - c.innosetup = ("", "") - c.name = "" - c.version = "" - c.description = "" - c.license = "" - c.infile = "" - c.outdir = "" - c.nimrodArgs = "" - c.innoSetupFlag = false - c.installScript = false - c.uninstallScript = false - c.vars = newStringTable(modeStyleInsensitive) - -proc skipRoot(f: string): string = - var i = 0 - result = "" - for component in split(f, {dirsep, altsep}): - if i > 0: result = result / component - inc i - if result.len == 0: result = f - -include "inno.tmpl" -include "build.tmpl" -include "install.tmpl" -include "deinstall.tmpl" - -# ------------------------- configuration file ------------------------------- - -const - Version = "0.7" - Usage = "niminst - Nimrod Installation Generator Version " & version & """ - - (c) 2009 Andreas Rumpf -Usage: - niminst [options] command[;command2...] ini-file[.ini] [compile_options] -Command: - csource build C source code for source based installations - zip build the ZIP file - inno build the Inno Setup installer -Options: - -o, --output:dir set the output directory - --var:name=value set the value of a variable - -h, --help shows this help - -v, --version shows the version -Compile_options: - will be passed to the Nimrod compiler -""" - -proc parseCmdLine(c: var TConfigData) = - var p = initOptParser() - while true: - next(p) - var kind = p.kind - var key = p.key - var val = p.val - case kind - of cmdArgument: - if c.actions == {}: - for a in split(normalize(key), {';', ','}): - case a - of "csource": incl(c.actions, actionCSource) - of "zip": incl(c.actions, actionZip) - of "inno": incl(c.actions, actionInno) - else: quit(Usage) - else: - c.infile = addFileExt(key, "ini") - c.nimrodArgs = cmdLineRest(p) - break - of cmdLongOption, cmdShortOption: - case normalize(key) - of "help", "h": write(stdout, Usage) - of "version", "v": writeln(stdout, Version) - of "o", "output": c.outdir = val - of "var": - var idx = val.find('=') - if idx < 0: quit("invalid command line") - c.vars[copy(val, 0, idx-1)] = copy(val, idx+1) - else: quit(Usage) - of cmdEnd: break - if c.infile.len == 0: quit(Usage) - -proc walkDirRecursively(s: var seq[string], root: string) = - for k, f in walkDir(root): - case k - of pcFile, pcLinkToFile: add(s, UnixToNativePath(f)) - of pcDirectory: walkDirRecursively(s, f) - of pcLinkToDirectory: nil - -proc addFiles(s: var seq[string], patterns: seq[string]) = - for p in items(patterns): - if existsDir(p): - walkDirRecursively(s, p) - else: - var i = 0 - for f in walkFiles(p): - add(s, UnixToNativePath(f)) - inc(i) - if i == 0: echo("[Warning] No file found that matches: " & p) - -proc pathFlags(p: var TCfgParser, k, v: string, - t: var tuple[path, flags: string]) = - case normalize(k) - of "path": t.path = v - of "flags": t.flags = v - else: quit(errorStr(p, "unknown variable: " & k)) - -proc filesOnly(p: var TCfgParser, k, v: string, dest: var seq[string]) = - case normalize(k) - of "files": addFiles(dest, split(v, {';'})) - else: quit(errorStr(p, "unknown variable: " & k)) - -proc yesno(p: var TCfgParser, v: string): bool = - case normalize(v) - of "yes", "y", "on", "true": - result = true - of "no", "n", "off", "false": - result = false - else: quit(errorStr(p, "unknown value; use: yes|no")) - -proc parseIniFile(c: var TConfigData) = - var - p: TCfgParser - section: string # current section - var input = newFileStream(c.infile, fmRead) - if input != nil: - open(p, input, c.infile) - while true: - var k = next(p) - case k.kind - of cfgEof: break - of cfgSectionStart: - section = normalize(k.section) - of cfgKeyValuePair: - var v = k.value % c.vars - c.vars[k.key] = v - - case section - of "project": - case normalize(k.key) - of "name": c.name = v - of "version": c.version = v - of "os": c.oses = split(v, {';'}) - of "cpu": c.cpus = split(v, {';'}) - of "authors": c.authors = split(v, {';'}) - of "description": c.description = v - of "app": - case normalize(v) - of "console": c.app = appConsole - of "gui": c.app = appGUI - else: quit(errorStr(p, "expected: console or gui")) - of "license": c.license = UnixToNativePath(k.value) - else: quit(errorStr(p, "unknown variable: " & k.key)) - of "var": nil - of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin]) - of "config": filesOnly(p, k.key, v, c.cat[fcConfig]) - of "data": filesOnly(p, k.key, v, c.cat[fcData]) - of "documentation": filesOnly(p, k.key, v, c.cat[fcDoc]) - of "lib": filesOnly(p, k.key, v, c.cat[fcLib]) - of "other": filesOnly(p, k.key, v, c.cat[fcOther]) - of "windows": - case normalize(k.key) - of "files": addFiles(c.cat[fcWindows], split(v, {';'})) - of "binpath": c.binPaths = split(v, {';'}) - of "innosetup": c.innoSetupFlag = yesno(p, v) - else: quit(errorStr(p, "unknown variable: " & k.key)) - of "unix": - case normalize(k.key) - of "files": addFiles(c.cat[fcUnix], split(v, {';'})) - of "installscript": c.installScript = yesno(p, v) - of "uninstallscript": c.uninstallScript = yesno(p, v) - else: quit(errorStr(p, "unknown variable: " & k.key)) - of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin]) - of "innosetup": pathFlags(p, k.key, v, c.innoSetup) - of "ccompiler": pathFlags(p, k.key, v, c.ccompiler) - else: quit(errorStr(p, "invalid section: " & section)) - - of cfgOption: quit(errorStr(p, "syntax error")) - of cfgError: quit(errorStr(p, k.msg)) - close(p) - if c.name.len == 0: c.name = changeFileExt(extractFilename(c.infile), "") - else: - quit("cannot open: " & c.infile) - -# ------------------------- generate source based installation --------------- - -proc readCFiles(c: var TConfigData, osA, cpuA: int) = - var cfg: TCfgParser - var cfilesSection = false - var f = splitFile(c.infile).dir / "mapping.txt" - c.cfiles[osA][cpuA] = @[] - var input = newFileStream(f, fmRead) - if input != nil: - open(cfg, input, f) - while true: - var k = next(cfg) - case k.kind - of cfgEof: break - of cfgSectionStart: - if cfilesSection: break - cfilesSection = cmpIgnoreStyle(k.section, "cfiles") == 0 - of cfgKeyValuePair: nil - of cfgOption: - if cfilesSection and cmpIgnoreStyle(k.key, "file") == 0: - add(c.cfiles[osA][cpuA], k.value) - of cfgError: quit(errorStr(cfg, k.msg)) - close(cfg) - else: - quit("Cannot open: " & f) - -proc buildDir(os, cpu: int): string = - return "build" / ($os & "_" & $cpu) - -proc writeFile(filename, content, newline: string) = - var f: TFile - if open(f, filename, fmWrite): - for x in splitLines(content): - write(f, x) - write(f, newline) - close(f) - else: - quit("Cannot open for writing: " & filename) - -proc srcdist(c: var TConfigData) = - for x in walkFiles("lib/*.h"): CopyFile("build" / extractFilename(x), x) - for osA in 1..c.oses.len: - for cpuA in 1..c.cpus.len: - var dir = buildDir(osA, cpuA) - if existsDir(dir): removeDir(dir) - createDir(dir) - var cmd = ("nimrod compile -f --symbolfiles:off --compileonly " & - "--gen_mapping " & - " --os:$# --cpu:$# $# $#") % - [c.oses[osA-1], c.cpus[cpuA-1], c.nimrodArgs, - changeFileExt(c.infile, "nim")] - echo(cmd) - if execShellCmd(cmd) != 0: - quit("Error: call to nimrod compiler failed") - readCFiles(c, osA, cpuA) - for i in 0 .. c.cfiles[osA][cpuA].len-1: - var dest = dir / extractFilename(c.cfiles[osA][cpuA][i]) - CopyFile(dest, c.cfiles[osA][cpuA][i]) - c.cfiles[osA][cpuA][i] = dest - # second pass: remove duplicate files - for osA in countdown(c.oses.len, 1): - for cpuA in countdown(c.cpus.len, 1): - for i in 0..c.cfiles[osA][cpuA].len-1: - var dup = c.cfiles[osA][cpuA][i] - var f = extractFilename(dup) - for osB in 1..c.oses.len: - for cpuB in 1..c.cpus.len: - if osB != osA or cpuB != cpuA: - var orig = buildDir(osB, cpuB) / f - if ExistsFile(orig) and ExistsFile(dup) and - sameFileContent(orig, dup): - # file is identical, so delete duplicate: - RemoveFile(dup) - c.cfiles[osA][cpuA][i] = orig - writeFile(buildShFile, GenerateBuildScript(c), "\10") - if c.installScript: - writeFile(installShFile, GenerateInstallScript(c), "\10") - if c.uninstallScript: - writeFile(deinstallShFile, GenerateDeinstallScript(c), "\10") - -# --------------------- generate inno setup ----------------------------------- -proc setupDist(c: var TConfigData) = - var scrpt = GenerateInnoSetup(c) - var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version] - writeFile(n, scrpt, "\13\10") - when defined(windows): - if c.innoSetup.path.len == 0: - c.innoSetup.path = "iscc.exe" - var outcmd = if c.outdir.len == 0: "build" else: c.outdir - var cmd = "$# $# /O$# $#" % [c.innoSetup.path, c.innoSetup.flags, outcmd, n] - Echo(cmd) - if executeShellCommand(cmd) == 0: - removeFile(n) - else: - quit("External program failed") - -# ------------------ generate ZIP file --------------------------------------- -when haveZipLib: - proc zipDist(c: var TConfigData) = - var proj = toLower(c.name) - var n = "$#_$#.zip" % [proj, c.version] - if c.outdir.len == 0: n = "build" / n - else: n = c.outdir / n - var z: TZipArchive - if open(z, n, fmWrite): - addFile(z, proj / buildShFile, buildShFile) - addFile(z, proj / installShFile, installShFile) - addFile(z, proj / deinstallShFile, deinstallShFile) - for f in walkFiles("lib/*.h"): - addFile(z, proj / "build" / extractFilename(f), 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: addFile(z, proj / dir / extractFilename(f), f) - - for cat in items({fcConfig..fcOther, fcUnix}): - for f in items(c.cat[cat]): addFile(z, proj / f, f) - close(z) - else: - quit("Cannot open for writing: " & n) - -# ------------------- main ---------------------------------------------------- - -var c: TConfigData -initConfigData(c) -parseCmdLine(c) -parseIniFile(c) -if actionInno in c.actions: - setupDist(c) -if actionCSource in c.actions: - srcdist(c) -if actionZip in c.actions: - when haveZipLib: - zipdist(c) - else: - quit("libzip is not installed") |