nimbus.nim: use a custom build script
This commit is contained in:
parent
f43973d392
commit
10b0b6501b
|
@ -2,6 +2,8 @@
|
|||
|
||||
* ninjasyntax.nim (build): don't escape args automatically
|
||||
|
||||
* nimbus.nim: use a custom build script
|
||||
|
||||
2023-04-25 Anna <cyber@sysrq.in>
|
||||
|
||||
* nimbus.nim: drop support for patched Nim compilers
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
# SPDX-FileCopyrightText: 2023 Anna <cyber@sysrq.in>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
## This module is used to generate a NimScript file that, when executed, tells
|
||||
## Nim to generate a build script in a custom JSON format.
|
||||
|
||||
import std/strutils
|
||||
|
||||
import common, options
|
||||
|
||||
proc writeBuilderScript*(f: File, options: Options) =
|
||||
f.write("""#!/usr/bin/env nim e
|
||||
|
||||
import std/[os, parseopt, strformat, strutils]
|
||||
|
||||
mode = Verbose
|
||||
|
||||
const
|
||||
nimBin = $1.quoteShell
|
||||
nimFlags = $2
|
||||
nimCache = $3
|
||||
|
||||
type
|
||||
Options = object
|
||||
target: string
|
||||
inFile: string
|
||||
outFile: string
|
||||
paths: seq[string]
|
||||
|
||||
proc build(options: Options) =
|
||||
var paths = ""
|
||||
if options.paths.len != 0:
|
||||
paths = "-p:" & options.paths.join(" -p:")
|
||||
|
||||
exec fmt"{nimBin} {nimFlags} c --genScript:on --nimcache:{nimCache.quoteShell}" &
|
||||
fmt" -o:{options.outFile.quoteShell} {paths} {options.inFile.quoteShell}"
|
||||
|
||||
let txt2deps = findExe("txt2deps")
|
||||
if txt2deps.len != 0:
|
||||
let nimDepsFile = nimCache / options.target.addFileExt("deps")
|
||||
let gccDepsFile = options.target.addFileExt("d")
|
||||
exec fmt"{txt2deps} -T:{options.target.quoteShell}" &
|
||||
fmt" -i:{nimDepsFile.quoteShell} -o:{gccDepsFile.quoteShell}"
|
||||
|
||||
proc parseCmdLine(): Options =
|
||||
for kind, key, val in getOpt():
|
||||
case kind
|
||||
of cmdArgument:
|
||||
result.inFile = key
|
||||
of cmdShortOption:
|
||||
case key.normalize()
|
||||
of "t":
|
||||
result.target = val
|
||||
result.outFile = val.addFileExt(ExeExt)
|
||||
of "p":
|
||||
result.paths.add(val)
|
||||
else:
|
||||
discard
|
||||
of cmdEnd, cmdLongOption:
|
||||
discard
|
||||
|
||||
let opts = parseCmdLine()
|
||||
build(opts)
|
||||
""" % [options.getNimBin().tripleQuoted,
|
||||
options.getNimFlags().tripleQuoted,
|
||||
options.getNimCache().tripleQuoted])
|
|
@ -1,4 +1,5 @@
|
|||
# SPDX-FileCopyrightText: Copyright (C) Dominik Picheta. All rights reserved.
|
||||
# SPDX-FileCopyrightText: 2022-2023 Anna <cyber@sysrq.in>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import std/strutils
|
||||
|
@ -13,6 +14,7 @@ const
|
|||
packageMetadataFileName* = "nimblemeta.json"
|
||||
nimCacheDirName* = "nimcache"
|
||||
|
||||
builderFileName* = "builder.nims"
|
||||
installerFileName* = "installer.nims"
|
||||
testerFileName* = "tester.nims"
|
||||
queryToolFileName* = "querytool.nims"
|
||||
|
@ -32,4 +34,5 @@ const
|
|||
]
|
||||
|
||||
func tripleQuoted*(s: string): string =
|
||||
## Applies """triple quotes""" to a string.
|
||||
return '"'.repeat(3) & s & '"'.repeat(3)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# SPDX-FileCopyrightText: 2023 Anna <cyber@sysrq.in>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import std/[logging, os, parseopt, strutils]
|
||||
import std/[logging, os, parseopt, strformat, strutils]
|
||||
|
||||
import common
|
||||
|
||||
|
@ -21,7 +21,7 @@ type
|
|||
cmdLine*: seq[string] # only flags, not arguments
|
||||
|
||||
const
|
||||
help* = """
|
||||
help* = fmt"""
|
||||
Usage: nimbus [-h] [--debug] [--nimbleDir:path] [--binDir:path] [--nim:path]
|
||||
[--url:url] [nim opts...] sourceDir [buildDir]
|
||||
|
||||
|
@ -30,15 +30,15 @@ positional arguments:
|
|||
buildDir
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-h, --help Show this help message and exit.
|
||||
--debug Show debugging information.
|
||||
--nimbleDir:path Nimble directory (default: $1).
|
||||
--binDir:path Executable directory (default: $2).
|
||||
--nimbleDir:path Nimble directory (default: {defaultNimbleDir}).
|
||||
--binDir:path Executable directory (default: {defaultBinDir}).
|
||||
--nim:path Nim compiler (default: nim).
|
||||
--url:url Package URL.
|
||||
|
||||
Unrecognized flags are passed to the Nim compiler.
|
||||
""" % [defaultNimbleDir, defaultBinDir]
|
||||
""".strip()
|
||||
|
||||
proc writeHelp*() =
|
||||
echo(help)
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
# SPDX-FileCopyrightText: 2022 Anna <cyber@sysrq.in>
|
||||
# SPDX-FileCopyrightText: 2022-2023 Anna <cyber@sysrq.in>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import std/[os, strutils]
|
||||
import std/strutils
|
||||
|
||||
import common, options
|
||||
|
||||
proc writeTesterScript*(f: File, options: Options) =
|
||||
f.write("""#!/usr/bin/env nim e
|
||||
|
||||
import os, strformat, strutils
|
||||
import std/[os, strformat, strutils]
|
||||
|
||||
const
|
||||
nimBin = $1
|
||||
nimBin = $1.quoteShell
|
||||
nimFlags = $2
|
||||
nimCacheDir = $3
|
||||
nimCache = $3.quoteShell
|
||||
|
||||
withDir($4):
|
||||
for test in listFiles("tests"):
|
||||
if test.startsWith("tests/t") and test.endsWith(".nim"):
|
||||
echo "-- Running test ", test, "..."
|
||||
exec(fmt"{nimBin} --hints:off {nimFlags} r --nimcache:{nimCacheDir} {test.quoteShell}")
|
||||
""" % [options.getNimBin().quoteShell.tripleQuoted,
|
||||
""" % [options.getNimBin().tripleQuoted,
|
||||
options.getNimFlags().tripleQuoted,
|
||||
options.getNimCache().quoteShell.tripleQuoted,
|
||||
options.getNimCache().tripleQuoted,
|
||||
options.getSourceDir().tripleQuoted])
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
# SPDX-FileCopyrightText: 2022 Anna <cyber@sysrq.in>
|
||||
# SPDX-FileCopyrightText: 2022-2023 Anna <cyber@sysrq.in>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import std/[logging, os, sequtils, strtabs, strformat, strutils]
|
||||
import std/strutils except escape
|
||||
import std/[logging, os, sequtils, strtabs, strformat]
|
||||
|
||||
import nimbs/[common, dependencyresolver, installerscript, ninjasyntax,
|
||||
nimbleexecutor, options, packageinfo, packagemetadata,
|
||||
querytoolscript, testerscript, version]
|
||||
import nimbs/[common, options]
|
||||
import nimbs/[ninjasyntax]
|
||||
import nimbs/[
|
||||
dependencyresolver,
|
||||
nimbleexecutor,
|
||||
packageinfo,
|
||||
packagemetadata,
|
||||
version
|
||||
]
|
||||
import nimbs/[
|
||||
builderscript,
|
||||
installerscript,
|
||||
querytoolscript,
|
||||
testerscript
|
||||
]
|
||||
|
||||
proc processDependencies(requires: seq[string], options: Options): seq[string] =
|
||||
## Checks package dependencies and returns list of paths for the Nim compiler,
|
||||
|
@ -21,17 +34,26 @@ proc processDependencies(requires: seq[string], options: Options): seq[string] =
|
|||
else:
|
||||
result.add(dep.getPath(options).quoteShell)
|
||||
|
||||
proc application(ninja: File, input, output: string, paths: seq[string]) =
|
||||
debug(fmt"[build.ninja] Generating target for application '{output}'")
|
||||
proc application(ninja: File, input, target: string, paths: seq[string]) =
|
||||
debug(fmt"[build.ninja] Generating target for application '{target}'")
|
||||
|
||||
let depfile = quoteShell(output & ".d")
|
||||
var vars = newStringTable()
|
||||
vars["target"] = "$builddir" / target.escape(body = true)
|
||||
vars["sourcefile"] = input.escape(body = true)
|
||||
if paths.len != 0:
|
||||
vars["paths"] = "-p:" & paths.join(" -p:")
|
||||
vars["paths"] = escape("-p:" & paths.join(" -p:"), body = true)
|
||||
|
||||
ninja.build([output.escape],
|
||||
rule = "nimc",
|
||||
let jsonScript = "$nimcache" / target.addFileExt("json").escape
|
||||
ninja.build([jsonScript],
|
||||
rule = "genscript",
|
||||
inputs = [input.escape, "$builder"],
|
||||
variables = vars
|
||||
)
|
||||
|
||||
ninja.build([target.addFileExt(ExeExt).escape],
|
||||
rule = "jsonscript",
|
||||
inputs = [input.escape],
|
||||
implicit = [jsonScript],
|
||||
variables = vars
|
||||
)
|
||||
|
||||
|
@ -91,10 +113,11 @@ proc setup(options: Options) =
|
|||
nimblemeta.writeMetaData(options.url)
|
||||
nimblemeta.close()
|
||||
|
||||
echo "-- Generating installer script"
|
||||
let installer = open(options.getBuildDir() / installerFileName, fmWrite)
|
||||
installer.writeInstallerScript(pkgInfo, options)
|
||||
installer.close()
|
||||
if pkgInfo.bin.len != 0:
|
||||
echo "-- Generating builder script"
|
||||
let builder = open(options.getBuildDir() / builderFileName, fmWrite)
|
||||
builder.writeBuilderScript(options)
|
||||
builder.close()
|
||||
|
||||
if "test" notin tasks and dirExists(options.getSourceDir() / "tests"):
|
||||
echo "-- Generating tester script"
|
||||
|
@ -103,6 +126,11 @@ proc setup(options: Options) =
|
|||
tester.close()
|
||||
nimbleTests = true
|
||||
|
||||
echo "-- Generating installer script"
|
||||
let installer = open(options.getBuildDir() / installerFileName, fmWrite)
|
||||
installer.writeInstallerScript(pkgInfo, options)
|
||||
installer.close()
|
||||
|
||||
echo "-- Generating build.ninja"
|
||||
let ninja = open(options.getBuildDir() / "build.ninja", fmWrite)
|
||||
|
||||
|
@ -114,10 +142,9 @@ proc setup(options: Options) =
|
|||
debug("[build.ninja] Writing variables")
|
||||
ninja.variable("nim", options.getNimBin().escape(body = true))
|
||||
ninja.variable("nimbus", getAppFilename().escape(body = true))
|
||||
ninja.variable("nimflags", options.getNimFlags().escape(body = true))
|
||||
ninja.variable("sourcedir", options.getSourceDir().escape(body = true))
|
||||
ninja.variable("nimcache", options.getNimCache().escape(body = true))
|
||||
ninja.variable("cmdline", options.getCmdLine().escape(body = true))
|
||||
ninja.variable("builder", builderFileName.escape(body = true))
|
||||
ninja.newline()
|
||||
|
||||
debug("[build.ninja] Generating 'REGENERATE_BUILD' rule")
|
||||
|
@ -135,6 +162,25 @@ proc setup(options: Options) =
|
|||
pool = "console")
|
||||
ninja.newline()
|
||||
|
||||
if pkgInfo.bin.len != 0:
|
||||
debug("[build.ninja] Generating 'genscript' rule")
|
||||
ninja.rule("genscript",
|
||||
command = "$nim --hints:off e $builder -T:$target $paths $sourcefile",
|
||||
description = "Generating build script for Nim application $out",
|
||||
depfile = "$target".addFileExt("d"),
|
||||
deps = "gcc",
|
||||
pool = "console")
|
||||
ninja.newline()
|
||||
|
||||
debug("[build.ninja] Generating 'jsonscript' rule")
|
||||
ninja.rule("jsonscript",
|
||||
command = "$nim jsonscript --nimcache:$nimcache -o:$out $sourcefile",
|
||||
description = "Compiling Nim application $out",
|
||||
depfile = "$target".addFileExt("d"),
|
||||
deps = "gcc",
|
||||
pool = "console")
|
||||
ninja.newline()
|
||||
|
||||
if tasks.len != 0:
|
||||
# most tasks are supposed to be run from the project root
|
||||
debug("[build.ninja] Generating 'nimbletask' rule")
|
||||
|
@ -144,16 +190,6 @@ proc setup(options: Options) =
|
|||
pool = "console")
|
||||
ninja.newline()
|
||||
|
||||
if pkgInfo.bin.len != 0:
|
||||
debug("[build.ninja] Generating 'nimc' rule")
|
||||
ninja.rule("nimc",
|
||||
command = "$nim $nimflags c --nimcache:$nimcache -o:$out $paths $in",
|
||||
description = "Compiling Nim application $out",
|
||||
depfile = "$out.d",
|
||||
deps = "gcc",
|
||||
pool = "console")
|
||||
ninja.newline()
|
||||
|
||||
debug("[build.ninja] Generating 'PHONY' target")
|
||||
ninja.comment("Phony build target, always out of date")
|
||||
ninja.build(["PHONY"], rule = "phony")
|
||||
|
@ -176,9 +212,8 @@ proc setup(options: Options) =
|
|||
ninja.newline()
|
||||
|
||||
for bin in pkgInfo.bin:
|
||||
let output = bin.lastPathPart.addFileExt(ExeExt)
|
||||
let input = pkgInfo.getSourceDir(options) / bin.addFileExt("nim")
|
||||
ninja.application(input, output, depPaths)
|
||||
ninja.application(input, bin.lastPathPart, depPaths)
|
||||
ninja.newline()
|
||||
|
||||
debug("[build.ninja] Generating 'all' target")
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# SPDX-FileCopyrightText: 2023 Anna <cyber@sysrq.in>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
discard """
|
||||
disabled: "win"
|
||||
"""
|
||||
|
||||
import std/[os, strutils, tempfiles]
|
||||
import nimbs/[builderscript, options]
|
||||
|
||||
const outputExpected = """#!/usr/bin/env nim e
|
||||
|
||||
import std/[os, parseopt, strformat, strutils]
|
||||
|
||||
mode = Verbose
|
||||
|
||||
const
|
||||
nimBin = @/usr/bin/nim@.quoteShell
|
||||
nimFlags = @-d:release --threads:on@
|
||||
nimCache = @build dir/nimcache@
|
||||
""".replace("@", '"'.repeat(3))
|
||||
|
||||
let opts = Options(buildDir: "build dir",
|
||||
nim: "/usr/bin/nim",
|
||||
passNimFlags: @["-d:release", "--threads:on"])
|
||||
|
||||
let (cfile, path) = createTempFile("builderscript_", ".nims")
|
||||
cfile.writeBuilderScript(opts)
|
||||
|
||||
cfile.setFilePos(0)
|
||||
assert cfile.readAll().startsWith outputExpected
|
||||
|
||||
cfile.close()
|
||||
removeFile(path)
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2022 Anna <cyber@sysrq.in>
|
||||
# SPDX-FileCopyrightText: 2022-2023 Anna <cyber@sysrq.in>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
discard """
|
||||
|
@ -10,12 +10,12 @@ import nimbs/options, nimbs/testerscript
|
|||
|
||||
const outputExpected = """#!/usr/bin/env nim e
|
||||
|
||||
import os, strformat, strutils
|
||||
import std/[os, strformat, strutils]
|
||||
|
||||
const
|
||||
nimBin = @/usr/bin/nim@
|
||||
nimBin = @/usr/bin/nim@.quoteShell
|
||||
nimFlags = @-d:release --threads:on@
|
||||
nimCacheDir = @'build dir/nimcache'@
|
||||
nimCache = @build dir/nimcache@.quoteShell
|
||||
|
||||
withDir(@tests/testerscript@):
|
||||
for test in listFiles("tests"):
|
||||
|
|
Loading…
Reference in New Issue