nim doc --backend:js, nim doc --doccmd:-d:foo, nim r --backend:js, --doccmd:skip + other improvements (#14278)
* `nim doc --backend:js|cpp...` `nim doc --doccmd:'-d:foo --threads:on'` `nim r --backend:cpp...` (implies --run --usenimcache) * --usenimcache works with all targets * --docCmd:skip now skips compiling snippets; 50X speedup for doc/manual.rst
This commit is contained in:
parent
d11cb9d495
commit
9502e39b63
22 changed files with 213 additions and 99 deletions
|
|
@ -46,7 +46,7 @@ proc generateThreadLocalStorage(m: BModule) =
|
||||||
|
|
||||||
proc generateThreadVarsSize(m: BModule) =
|
proc generateThreadVarsSize(m: BModule) =
|
||||||
if m.g.nimtv != nil:
|
if m.g.nimtv != nil:
|
||||||
let externc = if m.config.cmd == cmdCompileToCpp or
|
let externc = if m.config.backend == backendCpp or
|
||||||
sfCompileToCpp in m.module.flags: "extern \"C\" "
|
sfCompileToCpp in m.module.flags: "extern \"C\" "
|
||||||
else: ""
|
else: ""
|
||||||
m.s[cfsProcs].addf(
|
m.s[cfsProcs].addf(
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,7 @@ proc genProc(m: BModule, prc: PSym)
|
||||||
proc raiseInstr(p: BProc): Rope
|
proc raiseInstr(p: BProc): Rope
|
||||||
|
|
||||||
template compileToCpp(m: BModule): untyped =
|
template compileToCpp(m: BModule): untyped =
|
||||||
m.config.cmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags
|
m.config.backend == backendCpp or sfCompileToCpp in m.module.flags
|
||||||
|
|
||||||
proc getTempName(m: BModule): Rope =
|
proc getTempName(m: BModule): Rope =
|
||||||
result = m.tmpBase & rope(m.labels)
|
result = m.tmpBase & rope(m.labels)
|
||||||
|
|
@ -1066,11 +1066,11 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
|
proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
|
||||||
result = (sfCompileToCpp in m.module.flags and
|
result = (sfCompileToCpp in m.module.flags and
|
||||||
sfCompileToCpp notin sym.getModule().flags and
|
sfCompileToCpp notin sym.getModule().flags and
|
||||||
m.config.cmd != cmdCompileToCpp) or (
|
m.config.backend != backendCpp) or (
|
||||||
sym.flags * {sfInfixCall, sfCompilerProc, sfMangleCpp} == {} and
|
sym.flags * {sfInfixCall, sfCompilerProc, sfMangleCpp} == {} and
|
||||||
sym.flags * {sfImportc, sfExportc} != {} and
|
sym.flags * {sfImportc, sfExportc} != {} and
|
||||||
sym.magic == mNone and
|
sym.magic == mNone and
|
||||||
m.config.cmd == cmdCompileToCpp)
|
m.config.backend == backendCpp)
|
||||||
|
|
||||||
proc genProcPrototype(m: BModule, sym: PSym) =
|
proc genProcPrototype(m: BModule, sym: PSym) =
|
||||||
useHeader(m, sym)
|
useHeader(m, sym)
|
||||||
|
|
@ -1867,7 +1867,7 @@ proc writeHeader(m: BModule) =
|
||||||
proc getCFile(m: BModule): AbsoluteFile =
|
proc getCFile(m: BModule): AbsoluteFile =
|
||||||
let ext =
|
let ext =
|
||||||
if m.compileToCpp: ".nim.cpp"
|
if m.compileToCpp: ".nim.cpp"
|
||||||
elif m.config.cmd == cmdCompileToOC or sfCompileToObjc in m.module.flags: ".nim.m"
|
elif m.config.backend == backendObjc or sfCompileToObjc in m.module.flags: ".nim.m"
|
||||||
else: ".nim.c"
|
else: ".nim.c"
|
||||||
result = changeFileExt(completeCfilePath(m.config, withPackageName(m.config, m.cfilename)), ext)
|
result = changeFileExt(completeCfilePath(m.config, withPackageName(m.config, m.cfilename)), ext)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,8 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
|
||||||
# XXX This is hacky. We need to find a better way.
|
# XXX This is hacky. We need to find a better way.
|
||||||
case conf.command
|
case conf.command
|
||||||
of "cpp", "compiletocpp":
|
of "cpp", "compiletocpp":
|
||||||
conf.cmd = cmdCompileToCpp
|
conf.backend = backendCpp
|
||||||
|
conf.cmd = cmdCompileToBackend
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -434,11 +434,18 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
of "outdir":
|
of "outdir":
|
||||||
expectArg(conf, switch, arg, pass, info)
|
expectArg(conf, switch, arg, pass, info)
|
||||||
conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
|
conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
|
||||||
|
of "usenimcache":
|
||||||
|
processOnOffSwitchG(conf, {optUseNimcache}, arg, pass, info)
|
||||||
of "docseesrcurl":
|
of "docseesrcurl":
|
||||||
expectArg(conf, switch, arg, pass, info)
|
expectArg(conf, switch, arg, pass, info)
|
||||||
conf.docSeeSrcUrl = arg
|
conf.docSeeSrcUrl = arg
|
||||||
of "docroot":
|
of "docroot":
|
||||||
conf.docRoot = if arg.len == 0: "@default" else: arg
|
conf.docRoot = if arg.len == 0: "@default" else: arg
|
||||||
|
of "backend", "b":
|
||||||
|
let backend = parseEnum(arg.normalize, TBackend.default)
|
||||||
|
if backend == TBackend.default: localError(conf, info, "invalid backend: '$1'" % arg)
|
||||||
|
conf.backend = backend
|
||||||
|
of "doccmd": conf.docCmd = arg
|
||||||
of "mainmodule", "m":
|
of "mainmodule", "m":
|
||||||
discard "allow for backwards compatibility, but don't do anything"
|
discard "allow for backwards compatibility, but don't do anything"
|
||||||
of "define", "d":
|
of "define", "d":
|
||||||
|
|
@ -495,7 +502,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
defineSymbol(conf.symbols, "gcmarkandsweep")
|
defineSymbol(conf.symbols, "gcmarkandsweep")
|
||||||
of "destructors", "arc":
|
of "destructors", "arc":
|
||||||
conf.selectedGC = gcArc
|
conf.selectedGC = gcArc
|
||||||
if conf.cmd != cmdCompileToCpp:
|
if conf.backend != backendCpp:
|
||||||
conf.exc = excGoto
|
conf.exc = excGoto
|
||||||
defineSymbol(conf.symbols, "gcdestructors")
|
defineSymbol(conf.symbols, "gcdestructors")
|
||||||
defineSymbol(conf.symbols, "gcarc")
|
defineSymbol(conf.symbols, "gcarc")
|
||||||
|
|
@ -506,7 +513,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
defineSymbol(conf.symbols, "nimV2")
|
defineSymbol(conf.symbols, "nimV2")
|
||||||
of "orc":
|
of "orc":
|
||||||
conf.selectedGC = gcOrc
|
conf.selectedGC = gcOrc
|
||||||
if conf.cmd != cmdCompileToCpp:
|
if conf.backend != backendCpp:
|
||||||
conf.exc = excGoto
|
conf.exc = excGoto
|
||||||
defineSymbol(conf.symbols, "gcdestructors")
|
defineSymbol(conf.symbols, "gcdestructors")
|
||||||
defineSymbol(conf.symbols, "gcorc")
|
defineSymbol(conf.symbols, "gcorc")
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import
|
||||||
const
|
const
|
||||||
exportSection = skField
|
exportSection = skField
|
||||||
htmldocsDir = RelativeDir"htmldocs"
|
htmldocsDir = RelativeDir"htmldocs"
|
||||||
|
docCmdSkip = "skip"
|
||||||
|
|
||||||
type
|
type
|
||||||
TSections = array[TSymKind, Rope]
|
TSections = array[TSymKind, Rope]
|
||||||
|
|
@ -196,6 +197,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||||
initStrTable result.types
|
initStrTable result.types
|
||||||
result.onTestSnippet =
|
result.onTestSnippet =
|
||||||
proc (gen: var RstGenerator; filename, cmd: string; status: int; content: string) =
|
proc (gen: var RstGenerator; filename, cmd: string; status: int; content: string) =
|
||||||
|
if conf.docCmd == docCmdSkip: return
|
||||||
inc(gen.id)
|
inc(gen.id)
|
||||||
var d = TDocumentor(gen)
|
var d = TDocumentor(gen)
|
||||||
var outp: AbsoluteFile
|
var outp: AbsoluteFile
|
||||||
|
|
@ -444,21 +446,26 @@ proc testExample(d: PDoc; ex: PNode) =
|
||||||
d.examples.add "import r\"" & outp.string & "\"\n"
|
d.examples.add "import r\"" & outp.string & "\"\n"
|
||||||
|
|
||||||
proc runAllExamples(d: PDoc) =
|
proc runAllExamples(d: PDoc) =
|
||||||
if d.examples.len == 0: return
|
let docCmd = d.conf.docCmd
|
||||||
|
let backend = d.conf.backend
|
||||||
|
# This used to be: `let backend = if isDefined(d.conf, "js"): "js"` (etc), however
|
||||||
|
# using `-d:js` (etc) cannot work properly, eg would fail with `importjs`
|
||||||
|
# since semantics are affected by `config.backend`, not by isDefined(d.conf, "js")
|
||||||
|
if d.examples.len == 0 or docCmd == docCmdSkip: return
|
||||||
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
|
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
|
||||||
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
|
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
|
||||||
"_examples.nim"))
|
"_examples.nim"))
|
||||||
writeFile(outp, d.examples)
|
writeFile(outp, d.examples)
|
||||||
let backend = if isDefined(d.conf, "js"): "js"
|
let cmd = "$nim $backend -r --warning:UnusedImport:off --path:$path --nimcache:$nimcache $docCmd $file" % [
|
||||||
elif isDefined(d.conf, "cpp"): "cpp"
|
"nim", os.getAppFilename(),
|
||||||
elif isDefined(d.conf, "objc"): "objc"
|
"backend", $d.conf.backend,
|
||||||
else: "c"
|
"path", quoteShell(d.conf.projectPath),
|
||||||
if os.execShellCmd(os.getAppFilename() & " " & backend &
|
"nimcache", quoteShell(outputDir),
|
||||||
" --warning[UnusedImport]:off" &
|
"file", quoteShell(outp),
|
||||||
" --path:" & quoteShell(d.conf.projectPath) &
|
"docCmd", docCmd,
|
||||||
" --nimcache:" & quoteShell(outputDir) &
|
]
|
||||||
" -r " & quoteShell(outp)) != 0:
|
if os.execShellCmd(cmd) != 0:
|
||||||
quit "[Examples] failed: see " & outp.string
|
quit "[runnableExamples] failed: generated file: '$1' cmd: $2" % [outp.string, cmd]
|
||||||
else:
|
else:
|
||||||
# keep generated source file `outp` to allow inspection.
|
# keep generated source file `outp` to allow inspection.
|
||||||
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
|
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
|
||||||
|
|
|
||||||
|
|
@ -307,14 +307,12 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
|
||||||
# use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given
|
# use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given
|
||||||
# for niminst support
|
# for niminst support
|
||||||
let fullSuffix =
|
let fullSuffix =
|
||||||
if conf.cmd == cmdCompileToCpp:
|
case conf.backend
|
||||||
".cpp" & suffix
|
of backendCpp, backendJs, backendObjc: "." & $conf.backend & suffix
|
||||||
elif conf.cmd == cmdCompileToOC:
|
of backendC: suffix
|
||||||
".objc" & suffix
|
|
||||||
elif conf.cmd == cmdCompileToJS:
|
|
||||||
".js" & suffix
|
|
||||||
else:
|
else:
|
||||||
suffix
|
doAssert false
|
||||||
|
""
|
||||||
|
|
||||||
if (conf.target.hostOS != conf.target.targetOS or conf.target.hostCPU != conf.target.targetCPU) and
|
if (conf.target.hostOS != conf.target.targetOS or conf.target.hostCPU != conf.target.targetCPU) and
|
||||||
optCompileOnly notin conf.globalOptions:
|
optCompileOnly notin conf.globalOptions:
|
||||||
|
|
@ -481,10 +479,10 @@ proc needsExeExt(conf: ConfigRef): bool {.inline.} =
|
||||||
(conf.target.hostOS == osWindows)
|
(conf.target.hostOS == osWindows)
|
||||||
|
|
||||||
proc useCpp(conf: ConfigRef; cfile: AbsoluteFile): bool =
|
proc useCpp(conf: ConfigRef; cfile: AbsoluteFile): bool =
|
||||||
conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c")
|
conf.backend == backendCpp and not cfile.string.endsWith(".c")
|
||||||
|
|
||||||
proc envFlags(conf: ConfigRef): string =
|
proc envFlags(conf: ConfigRef): string =
|
||||||
result = if conf.cmd == cmdCompileToCpp:
|
result = if conf.backend == backendCpp:
|
||||||
getEnv("CXXFLAGS")
|
getEnv("CXXFLAGS")
|
||||||
else:
|
else:
|
||||||
getEnv("CFLAGS")
|
getEnv("CFLAGS")
|
||||||
|
|
@ -535,7 +533,7 @@ proc ccHasSaneOverflow*(conf: ConfigRef): bool =
|
||||||
|
|
||||||
proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
|
proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
|
||||||
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
|
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
|
||||||
elif optMixedMode in conf.globalOptions and conf.cmd != cmdCompileToCpp: CC[compiler].cppCompiler
|
elif optMixedMode in conf.globalOptions and conf.backend != backendCpp: CC[compiler].cppCompiler
|
||||||
else: getCompilerExe(conf, compiler, AbsoluteFile"")
|
else: getCompilerExe(conf, compiler, AbsoluteFile"")
|
||||||
|
|
||||||
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
|
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
|
||||||
|
|
@ -626,8 +624,10 @@ proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
|
||||||
getCompileCFileCmd(conf, cfile))
|
getCompileCFileCmd(conf, cfile))
|
||||||
|
|
||||||
proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
|
proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
|
||||||
if conf.cmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM, cmdNone}:
|
case conf.backend
|
||||||
return false
|
of backendInvalid: doAssert false
|
||||||
|
of backendJs: return false # pre-existing behavior, but not sure it's good
|
||||||
|
else: discard
|
||||||
|
|
||||||
var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
|
var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
|
||||||
var currentHash = footprint(conf, cfile)
|
var currentHash = footprint(conf, cfile)
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ template isIterator*(owner: PSym): bool =
|
||||||
proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
|
proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
|
||||||
## lambda lifting can be harmful for JS-like code generators.
|
## lambda lifting can be harmful for JS-like code generators.
|
||||||
let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
|
let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
|
||||||
result = conf.cmd == cmdCompileToJS and not isCompileTime
|
result = conf.backend == backendJs and not isCompileTime
|
||||||
|
|
||||||
proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) =
|
proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) =
|
||||||
createTypeBoundOps(g, nil, refType.lastSon, info)
|
createTypeBoundOps(g, nil, refType.lastSon, info)
|
||||||
|
|
@ -846,14 +846,14 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
|
||||||
fn.typ.callConv = oldCC
|
fn.typ.callConv = oldCC
|
||||||
|
|
||||||
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
|
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
|
||||||
# XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
|
# XXX backend == backendJs does not suffice! The compiletime stuff needs
|
||||||
# the transformation even when compiling to JS ...
|
# the transformation even when compiling to JS ...
|
||||||
|
|
||||||
# However we can do lifting for the stuff which is *only* compiletime.
|
# However we can do lifting for the stuff which is *only* compiletime.
|
||||||
let isCompileTime = sfCompileTime in fn.flags or fn.kind == skMacro
|
let isCompileTime = sfCompileTime in fn.flags or fn.kind == skMacro
|
||||||
|
|
||||||
if body.kind == nkEmpty or (
|
if body.kind == nkEmpty or (
|
||||||
g.config.cmd == cmdCompileToJS and not isCompileTime) or
|
g.config.backend == backendJs and not isCompileTime) or
|
||||||
fn.skipGenericOwner.kind != skModule:
|
fn.skipGenericOwner.kind != skModule:
|
||||||
|
|
||||||
# ignore forward declaration:
|
# ignore forward declaration:
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,7 @@ when not defined(leanCompiler):
|
||||||
let conf = graph.config
|
let conf = graph.config
|
||||||
conf.exc = excCpp
|
conf.exc = excCpp
|
||||||
|
|
||||||
if conf.outDir.isEmpty:
|
setOutDir(conf)
|
||||||
conf.outDir = conf.projectPath
|
|
||||||
if conf.outFile.isEmpty:
|
if conf.outFile.isEmpty:
|
||||||
conf.outFile = RelativeFile(conf.projectName & ".js")
|
conf.outFile = RelativeFile(conf.projectName & ".js")
|
||||||
|
|
||||||
|
|
@ -128,7 +127,6 @@ when not defined(leanCompiler):
|
||||||
setTarget(graph.config.target, osJS, cpuJS)
|
setTarget(graph.config.target, osJS, cpuJS)
|
||||||
#initDefines()
|
#initDefines()
|
||||||
defineSymbol(graph.config.symbols, "ecmascript") # For backward compatibility
|
defineSymbol(graph.config.symbols, "ecmascript") # For backward compatibility
|
||||||
defineSymbol(graph.config.symbols, "js")
|
|
||||||
semanticPasses(graph)
|
semanticPasses(graph)
|
||||||
registerPass(graph, JSgenPass)
|
registerPass(graph, JSgenPass)
|
||||||
compileProject(graph)
|
compileProject(graph)
|
||||||
|
|
@ -190,25 +188,46 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||||
conf.lastCmdTime = epochTime()
|
conf.lastCmdTime = epochTime()
|
||||||
conf.searchPaths.add(conf.libpath)
|
conf.searchPaths.add(conf.libpath)
|
||||||
setId(100)
|
setId(100)
|
||||||
template handleC() =
|
|
||||||
conf.cmd = cmdCompileToC
|
## Calling `setOutDir(conf)` unconditionally would fix regression
|
||||||
if conf.exc == excNone: conf.exc = excSetjmp
|
## https://github.com/nim-lang/Nim/issues/6583#issuecomment-625711125
|
||||||
defineSymbol(graph.config.symbols, "c")
|
when false: setOutDir(conf)
|
||||||
commandCompileToC(graph)
|
if optUseNimcache in conf.globalOptions: setOutDir(conf)
|
||||||
|
|
||||||
|
template handleBackend(backend2: TBackend) =
|
||||||
|
conf.backend = backend2
|
||||||
|
conf.cmd = cmdCompileToBackend
|
||||||
|
defineSymbol(graph.config.symbols, $backend2)
|
||||||
|
case backend2
|
||||||
|
of backendC:
|
||||||
|
if conf.exc == excNone: conf.exc = excSetjmp
|
||||||
|
commandCompileToC(graph)
|
||||||
|
of backendCpp:
|
||||||
|
if conf.exc == excNone: conf.exc = excCpp
|
||||||
|
commandCompileToC(graph)
|
||||||
|
of backendObjc:
|
||||||
|
commandCompileToC(graph)
|
||||||
|
of backendJs:
|
||||||
|
when defined(leanCompiler):
|
||||||
|
globalError(conf, unknownLineInfo, "compiler wasn't built with JS code generator")
|
||||||
|
else:
|
||||||
|
if conf.hcrOn:
|
||||||
|
# XXX: At the moment, system.nim cannot be compiled in JS mode
|
||||||
|
# with "-d:useNimRtl". The HCR option has been processed earlier
|
||||||
|
# and it has added this define implictly, so we must undo that here.
|
||||||
|
# A better solution might be to fix system.nim
|
||||||
|
undefSymbol(conf.symbols, "useNimRtl")
|
||||||
|
commandCompileToJS(graph)
|
||||||
|
of backendInvalid: doAssert false
|
||||||
|
|
||||||
case conf.command.normalize
|
case conf.command.normalize
|
||||||
of "c", "cc", "compile", "compiletoc": handleC() # compile means compileToC currently
|
of "c", "cc", "compile", "compiletoc": handleBackend(backendC) # compile means compileToC currently
|
||||||
of "cpp", "compiletocpp":
|
of "cpp", "compiletocpp": handleBackend(backendCpp)
|
||||||
conf.cmd = cmdCompileToCpp
|
of "objc", "compiletooc": handleBackend(backendObjc)
|
||||||
if conf.exc == excNone: conf.exc = excCpp
|
of "js", "compiletojs": handleBackend(backendJs)
|
||||||
defineSymbol(graph.config.symbols, "cpp")
|
|
||||||
commandCompileToC(graph)
|
|
||||||
of "objc", "compiletooc":
|
|
||||||
conf.cmd = cmdCompileToOC
|
|
||||||
defineSymbol(graph.config.symbols, "objc")
|
|
||||||
commandCompileToC(graph)
|
|
||||||
of "r": # different from `"run"`!
|
of "r": # different from `"run"`!
|
||||||
conf.globalOptions.incl {optRun, optUseNimcache}
|
conf.globalOptions.incl {optRun, optUseNimcache}
|
||||||
handleC()
|
handleBackend(conf.backend)
|
||||||
of "run":
|
of "run":
|
||||||
conf.cmd = cmdRun
|
conf.cmd = cmdRun
|
||||||
when hasTinyCBackend:
|
when hasTinyCBackend:
|
||||||
|
|
@ -216,18 +235,6 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||||
commandCompileToC(graph)
|
commandCompileToC(graph)
|
||||||
else:
|
else:
|
||||||
rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc")
|
rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc")
|
||||||
of "js", "compiletojs":
|
|
||||||
when defined(leanCompiler):
|
|
||||||
quit "compiler wasn't built with JS code generator"
|
|
||||||
else:
|
|
||||||
conf.cmd = cmdCompileToJS
|
|
||||||
if conf.hcrOn:
|
|
||||||
# XXX: At the moment, system.nim cannot be compiled in JS mode
|
|
||||||
# with "-d:useNimRtl". The HCR option has been processed earlier
|
|
||||||
# and it has added this define implictly, so we must undo that here.
|
|
||||||
# A better solution might be to fix system.nim
|
|
||||||
undefSymbol(conf.symbols, "useNimRtl")
|
|
||||||
commandCompileToJS(graph)
|
|
||||||
of "doc0":
|
of "doc0":
|
||||||
when defined(leanCompiler):
|
when defined(leanCompiler):
|
||||||
quit "compiler wasn't built with documentation generator"
|
quit "compiler wasn't built with documentation generator"
|
||||||
|
|
|
||||||
|
|
@ -88,17 +88,19 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
|
||||||
tccgen.run(conf, conf.arguments)
|
tccgen.run(conf, conf.arguments)
|
||||||
if optRun in conf.globalOptions:
|
if optRun in conf.globalOptions:
|
||||||
let output = conf.absOutFile
|
let output = conf.absOutFile
|
||||||
let ex = quoteShell output
|
|
||||||
case conf.cmd
|
case conf.cmd
|
||||||
of cmdCompileToJS:
|
of cmdCompileToBackend:
|
||||||
execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
|
var cmdPrefix = ""
|
||||||
|
case conf.backend
|
||||||
|
of backendC, backendCpp, backendObjc: discard
|
||||||
|
of backendJs: cmdPrefix = findNodeJs() & " "
|
||||||
|
else: doAssert false, $conf.backend
|
||||||
|
execExternalProgram(conf, cmdPrefix & output.quoteShell & ' ' & conf.arguments)
|
||||||
of cmdDoc, cmdRst2html:
|
of cmdDoc, cmdRst2html:
|
||||||
if conf.arguments.len > 0:
|
if conf.arguments.len > 0:
|
||||||
# reserved for future use
|
# reserved for future use
|
||||||
rawMessage(conf, errGenerated, "'$1 cannot handle arguments" % [$conf.cmd])
|
rawMessage(conf, errGenerated, "'$1 cannot handle arguments" % [$conf.cmd])
|
||||||
openDefaultBrowser($output)
|
openDefaultBrowser($output)
|
||||||
of cmdCompileToC, cmdCompileToCpp, cmdCompileToOC:
|
|
||||||
execExternalProgram(conf, ex & ' ' & conf.arguments)
|
|
||||||
else:
|
else:
|
||||||
# support as needed
|
# support as needed
|
||||||
rawMessage(conf, errGenerated, "'$1 cannot handle --run" % [$conf.cmd])
|
rawMessage(conf, errGenerated, "'$1 cannot handle --run" % [$conf.cmd])
|
||||||
|
|
|
||||||
|
|
@ -104,12 +104,26 @@ const
|
||||||
harmlessOptions* = {optForceFullMake, optNoLinking, optRun,
|
harmlessOptions* = {optForceFullMake, optNoLinking, optRun,
|
||||||
optUseColors, optStdout}
|
optUseColors, optStdout}
|
||||||
|
|
||||||
|
type
|
||||||
|
TBackend* = enum
|
||||||
|
backendInvalid = "" # for parseEnum
|
||||||
|
backendC = "c"
|
||||||
|
backendCpp = "cpp" # was cmdCompileToCpp
|
||||||
|
backendJs = "js" # was cmdCompileToJS
|
||||||
|
backendObjc = "objc" # was cmdCompileToOC
|
||||||
|
# backendNimscript = "nimscript" # this could actually work
|
||||||
|
# backendLlvm = "llvm" # probably not well supported; was cmdCompileToLLVM
|
||||||
|
|
||||||
type
|
type
|
||||||
TCommands* = enum # Nim's commands
|
TCommands* = enum # Nim's commands
|
||||||
# **keep binary compatible**
|
# **keep binary compatible**
|
||||||
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
cmdNone,
|
||||||
cmdCompileToJS,
|
cmdCompileToC, # deadcode
|
||||||
cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
cmdCompileToCpp, # deadcode
|
||||||
|
cmdCompileToOC, # deadcode
|
||||||
|
cmdCompileToJS, # deadcode
|
||||||
|
cmdCompileToLLVM, # deadcode
|
||||||
|
cmdInterpret, cmdPretty, cmdDoc,
|
||||||
cmdGenDepend, cmdDump,
|
cmdGenDepend, cmdDump,
|
||||||
cmdCheck, # semantic checking for whole project
|
cmdCheck, # semantic checking for whole project
|
||||||
cmdParse, # parse a single file (for debugging)
|
cmdParse, # parse a single file (for debugging)
|
||||||
|
|
@ -121,6 +135,7 @@ type
|
||||||
cmdInteractive, # start interactive session
|
cmdInteractive, # start interactive session
|
||||||
cmdRun, # run the project via TCC backend
|
cmdRun, # run the project via TCC backend
|
||||||
cmdJsonScript # compile a .json build file
|
cmdJsonScript # compile a .json build file
|
||||||
|
cmdCompileToBackend, # compile to backend in TBackend
|
||||||
TStringSeq* = seq[string]
|
TStringSeq* = seq[string]
|
||||||
TGCMode* = enum # the selected GC
|
TGCMode* = enum # the selected GC
|
||||||
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcArc, gcOrc,
|
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcArc, gcOrc,
|
||||||
|
|
@ -208,6 +223,7 @@ type
|
||||||
## fields marked with '*' are subject to
|
## fields marked with '*' are subject to
|
||||||
## the incremental compilation mechanisms
|
## the incremental compilation mechanisms
|
||||||
## (+) means "part of the dependency"
|
## (+) means "part of the dependency"
|
||||||
|
backend*: TBackend
|
||||||
target*: Target # (+)
|
target*: Target # (+)
|
||||||
linesCompiled*: int # all lines that have been compiled
|
linesCompiled*: int # all lines that have been compiled
|
||||||
options*: TOptions # (+)
|
options*: TOptions # (+)
|
||||||
|
|
@ -274,6 +290,7 @@ type
|
||||||
docSeeSrcUrl*: string # if empty, no seeSrc will be generated. \
|
docSeeSrcUrl*: string # if empty, no seeSrc will be generated. \
|
||||||
# The string uses the formatting variables `path` and `line`.
|
# The string uses the formatting variables `path` and `line`.
|
||||||
docRoot*: string ## see nim --fullhelp for --docRoot
|
docRoot*: string ## see nim --fullhelp for --docRoot
|
||||||
|
docCmd*: string ## see nim --fullhelp for --docCmd
|
||||||
|
|
||||||
# the used compiler
|
# the used compiler
|
||||||
cIncludes*: seq[AbsoluteDir] # directories to search for included files
|
cIncludes*: seq[AbsoluteDir] # directories to search for included files
|
||||||
|
|
@ -402,7 +419,7 @@ proc newConfigRef*(): ConfigRef =
|
||||||
cIncludes: @[], # directories to search for included files
|
cIncludes: @[], # directories to search for included files
|
||||||
cLibs: @[], # directories to search for lib files
|
cLibs: @[], # directories to search for lib files
|
||||||
cLinkedLibs: @[], # libraries to link
|
cLinkedLibs: @[], # libraries to link
|
||||||
|
backend: backendC,
|
||||||
externalToLink: @[],
|
externalToLink: @[],
|
||||||
linkOptionsCmd: "",
|
linkOptionsCmd: "",
|
||||||
compileOptionsCmd: @[],
|
compileOptionsCmd: @[],
|
||||||
|
|
@ -522,7 +539,10 @@ proc setConfigVar*(conf: ConfigRef; key, val: string) =
|
||||||
conf.configVars[key] = val
|
conf.configVars[key] = val
|
||||||
|
|
||||||
proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): AbsoluteFile =
|
proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): AbsoluteFile =
|
||||||
conf.outDir / changeFileExt(filename, ext)
|
# explains regression https://github.com/nim-lang/Nim/issues/6583#issuecomment-625711125
|
||||||
|
# Yet another reason why "" should not mean "."; `""/something` should raise
|
||||||
|
# instead of implying "" == "." as it's bug prone.
|
||||||
|
result = conf.outDir / changeFileExt(filename, ext)
|
||||||
|
|
||||||
proc absOutFile*(conf: ConfigRef): AbsoluteFile =
|
proc absOutFile*(conf: ConfigRef): AbsoluteFile =
|
||||||
if false:
|
if false:
|
||||||
|
|
@ -615,7 +635,7 @@ proc getNimcacheDir*(conf: ConfigRef): AbsoluteDir =
|
||||||
# XXX projectName should always be without a file extension!
|
# XXX projectName should always be without a file extension!
|
||||||
result = if not conf.nimcacheDir.isEmpty:
|
result = if not conf.nimcacheDir.isEmpty:
|
||||||
conf.nimcacheDir
|
conf.nimcacheDir
|
||||||
elif conf.cmd == cmdCompileToJS:
|
elif conf.backend == backendJs:
|
||||||
conf.projectPath / genSubDir
|
conf.projectPath / genSubDir
|
||||||
else:
|
else:
|
||||||
AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name &
|
AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name &
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ proc processImportCpp(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||||
incl(s.flags, sfImportc)
|
incl(s.flags, sfImportc)
|
||||||
incl(s.flags, sfInfixCall)
|
incl(s.flags, sfInfixCall)
|
||||||
excl(s.flags, sfForward)
|
excl(s.flags, sfForward)
|
||||||
if c.config.cmd == cmdCompileToC:
|
if c.config.backend == backendC:
|
||||||
let m = s.getModule()
|
let m = s.getModule()
|
||||||
incl(m.flags, sfCompileToCpp)
|
incl(m.flags, sfCompileToCpp)
|
||||||
incl c.config.globalOptions, optMixedMode
|
incl c.config.globalOptions, optMixedMode
|
||||||
|
|
@ -797,8 +797,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
of wExportc, wExportCpp:
|
of wExportc, wExportCpp:
|
||||||
makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
if k == wExportCpp:
|
if k == wExportCpp:
|
||||||
if c.config.cmd != cmdCompileToCpp:
|
if c.config.backend != backendCpp:
|
||||||
localError(c.config, it.info, "exportcpp requires `nim cpp`, got " & $c.config.cmd)
|
localError(c.config, it.info, "exportcpp requires `cpp` backend, got " & $c.config.backend)
|
||||||
else:
|
else:
|
||||||
incl(sym.flags, sfMangleCpp)
|
incl(sym.flags, sfMangleCpp)
|
||||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||||
|
|
@ -819,7 +819,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
of wImportCpp:
|
of wImportCpp:
|
||||||
processImportCpp(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
processImportCpp(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
of wImportJs:
|
of wImportJs:
|
||||||
if c.config.cmd != cmdCompileToJS:
|
if c.config.backend != backendJs:
|
||||||
localError(c.config, it.info, "`importjs` pragma requires the JavaScript target")
|
localError(c.config, it.info, "`importjs` pragma requires the JavaScript target")
|
||||||
let name = getOptionalStr(c, it, "$1")
|
let name = getOptionalStr(c, it, "$1")
|
||||||
incl(sym.flags, sfImportc)
|
incl(sym.flags, sfImportc)
|
||||||
|
|
|
||||||
|
|
@ -660,7 +660,7 @@ proc hasUnresolvedArgs(c: PContext, n: PNode): bool =
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
||||||
if n.kind == nkHiddenDeref and not (c.config.cmd == cmdCompileToCpp or
|
if n.kind == nkHiddenDeref and not (c.config.backend == backendCpp or
|
||||||
sfCompileToCpp in c.module.flags):
|
sfCompileToCpp in c.module.flags):
|
||||||
checkSonsLen(n, 1, c.config)
|
checkSonsLen(n, 1, c.config)
|
||||||
result = n[0]
|
result = n[0]
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||||
while st.kind in skipPtrs:
|
while st.kind in skipPtrs:
|
||||||
st = st[^1]
|
st = st[^1]
|
||||||
computeSizeAlign(conf, st)
|
computeSizeAlign(conf, st)
|
||||||
if conf.cmd == cmdCompileToCpp:
|
if conf.backend == backendCpp:
|
||||||
OffsetAccum(
|
OffsetAccum(
|
||||||
offset: int(st.size) - int(st.paddingAtEnd),
|
offset: int(st.size) - int(st.paddingAtEnd),
|
||||||
maxAlign: st.align
|
maxAlign: st.align
|
||||||
|
|
|
||||||
|
|
@ -411,7 +411,7 @@ proc transformYield(c: PTransf, n: PNode): PNode =
|
||||||
|
|
||||||
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode =
|
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode =
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
if c.graph.config.cmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return
|
if c.graph.config.backend == backendCpp or sfCompileToCpp in c.module.flags: return
|
||||||
var n = result
|
var n = result
|
||||||
case n[0].kind
|
case n[0].kind
|
||||||
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
|
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
|
||||||
|
|
@ -447,7 +447,7 @@ proc generateThunk(c: PTransf; prc: PNode, dest: PType): PNode =
|
||||||
|
|
||||||
# we cannot generate a proper thunk here for GC-safety reasons
|
# we cannot generate a proper thunk here for GC-safety reasons
|
||||||
# (see internal documentation):
|
# (see internal documentation):
|
||||||
if c.graph.config.cmd == cmdCompileToJS: return prc
|
if c.graph.config.backend == backendJs: return prc
|
||||||
result = newNodeIT(nkClosure, prc.info, dest)
|
result = newNodeIT(nkClosure, prc.info, dest)
|
||||||
var conv = newNodeIT(nkHiddenSubConv, prc.info, dest)
|
var conv = newNodeIT(nkHiddenSubConv, prc.info, dest)
|
||||||
conv.add(newNodeI(nkEmpty, prc.info))
|
conv.add(newNodeI(nkEmpty, prc.info))
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,7 @@ when defined(nimHasInvariant):
|
||||||
of linkOptions: result = conf.linkOptions
|
of linkOptions: result = conf.linkOptions
|
||||||
of compileOptions: result = conf.compileOptions
|
of compileOptions: result = conf.compileOptions
|
||||||
of ccompilerPath: result = conf.cCompilerPath
|
of ccompilerPath: result = conf.cCompilerPath
|
||||||
|
of backend: result = $conf.backend
|
||||||
|
|
||||||
proc querySettingSeqImpl(conf: ConfigRef, switch: BiggestInt): seq[string] =
|
proc querySettingSeqImpl(conf: ConfigRef, switch: BiggestInt): seq[string] =
|
||||||
template copySeq(field: untyped): untyped =
|
template copySeq(field: untyped): untyped =
|
||||||
|
|
@ -215,7 +216,7 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||||
|
|
||||||
proc hashVmImpl(a: VmArgs) =
|
proc hashVmImpl(a: VmArgs) =
|
||||||
var res = hashes.hash(a.getString(0), a.getInt(1).int, a.getInt(2).int)
|
var res = hashes.hash(a.getString(0), a.getInt(1).int, a.getInt(2).int)
|
||||||
if c.config.cmd == cmdCompileToJS:
|
if c.config.backend == backendJs:
|
||||||
# emulate JS's terrible integers:
|
# emulate JS's terrible integers:
|
||||||
res = cast[int32](res)
|
res = cast[int32](res)
|
||||||
setResult(a, res)
|
setResult(a, res)
|
||||||
|
|
@ -232,7 +233,7 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||||
bytes[i] = byte(arr[i].intVal and 0xff)
|
bytes[i] = byte(arr[i].intVal and 0xff)
|
||||||
|
|
||||||
var res = hashes.hash(bytes, sPos, ePos)
|
var res = hashes.hash(bytes, sPos, ePos)
|
||||||
if c.config.cmd == cmdCompileToJS:
|
if c.config.backend == backendJs:
|
||||||
# emulate JS's terrible integers:
|
# emulate JS's terrible integers:
|
||||||
res = cast[int32](res)
|
res = cast[int32](res)
|
||||||
setResult(a, res)
|
setResult(a, res)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ Advanced commands:
|
||||||
//js compile project to Javascript
|
//js compile project to Javascript
|
||||||
//e run a Nimscript file
|
//e run a Nimscript file
|
||||||
//rst2html convert a reStructuredText file to HTML
|
//rst2html convert a reStructuredText file to HTML
|
||||||
|
use `--docCmd:skip` to skip compiling snippets
|
||||||
//rst2tex convert a reStructuredText file to TeX
|
//rst2tex convert a reStructuredText file to TeX
|
||||||
//jsondoc extract the documentation to a json file
|
//jsondoc extract the documentation to a json file
|
||||||
//ctags create a tags file
|
//ctags create a tags file
|
||||||
|
|
@ -29,6 +30,8 @@ Runtime checks (see -x):
|
||||||
Advanced options:
|
Advanced options:
|
||||||
-o:FILE, --out:FILE set the output filename
|
-o:FILE, --out:FILE set the output filename
|
||||||
--outdir:DIR set the path where the output file will be written
|
--outdir:DIR set the path where the output file will be written
|
||||||
|
--usenimcache will use `outdir=$$nimcache`, whichever it resolves
|
||||||
|
to after all options have been processed
|
||||||
--stdout:on|off output to stdout
|
--stdout:on|off output to stdout
|
||||||
--colors:on|off turn compiler messages coloring on|off
|
--colors:on|off turn compiler messages coloring on|off
|
||||||
--listFullPaths:on|off list full paths in messages
|
--listFullPaths:on|off list full paths in messages
|
||||||
|
|
@ -69,13 +72,17 @@ Advanced options:
|
||||||
--clib:LIBNAME link an additional C library
|
--clib:LIBNAME link an additional C library
|
||||||
(you should omit platform-specific extensions)
|
(you should omit platform-specific extensions)
|
||||||
--project document the whole project (doc2)
|
--project document the whole project (doc2)
|
||||||
--docRoot:path nim doc --docRoot:/foo --project --outdir:docs /foo/sub/main.nim
|
--docRoot:path `nim doc --docRoot:/foo --project --outdir:docs /foo/sub/main.nim`
|
||||||
generates: docs/sub/main.html
|
generates: docs/sub/main.html
|
||||||
if path == @pkg, will use nimble file enclosing dir
|
if path == @pkg, will use nimble file enclosing dir
|
||||||
if path == @path, will use first matching dir in --path
|
if path == @path, will use first matching dir in `--path`
|
||||||
if path == @default (the default and most useful), will use
|
if path == @default (the default and most useful), will use
|
||||||
best match among @pkg,@path.
|
best match among @pkg,@path.
|
||||||
if these are nonexistant, will use project path
|
if these are nonexistant, will use project path
|
||||||
|
-b, --backend:c|cpp|js|objc sets backend to use with commands like `nim doc` or `nim r`
|
||||||
|
--docCmd:cmd if `cmd == skip`, skips runnableExamples
|
||||||
|
else, runs runnableExamples with given options, eg:
|
||||||
|
`--docCmd:"-d:foo --threads:on"`
|
||||||
--docSeeSrcUrl:url activate 'see source' for doc and doc2 commands
|
--docSeeSrcUrl:url activate 'see source' for doc and doc2 commands
|
||||||
(see doc.item.seesrc in config/nimdoc.cfg)
|
(see doc.item.seesrc in config/nimdoc.cfg)
|
||||||
--docInternal also generate documentation for non-exported symbols
|
--docInternal also generate documentation for non-exported symbols
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@
|
||||||
|
|
||||||
Command:
|
Command:
|
||||||
//compile, c compile project with default code generator (C)
|
//compile, c compile project with default code generator (C)
|
||||||
//r compile & run $nimcach/projname [arguments]
|
//r compile to $nimcache/projname, run with [arguments]
|
||||||
//doc generate the documentation for inputfile
|
using backend specified by `--backend` (default: c)
|
||||||
|
//doc generate the documentation for inputfile for
|
||||||
|
backend specified by `--backend` (default: c)
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
arguments are passed to the program being run (if --run option is selected)
|
arguments are passed to the program being run (if --run option is selected)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ type
|
||||||
linkOptions, ## additional options passed to the linker
|
linkOptions, ## additional options passed to the linker
|
||||||
compileOptions, ## additional options passed to the C/C++ compiler
|
compileOptions, ## additional options passed to the C/C++ compiler
|
||||||
ccompilerPath ## the path to the C/C++ compiler
|
ccompilerPath ## the path to the C/C++ compiler
|
||||||
|
backend ## the backend (eg: c|cpp|objc|js); both `nim doc --backend:js`
|
||||||
|
## and `nim js` would imply backend=js
|
||||||
|
|
||||||
MultipleValueSetting* {.pure.} = enum ## \
|
MultipleValueSetting* {.pure.} = enum ## \
|
||||||
## settings resulting in a seq of string values
|
## settings resulting in a seq of string values
|
||||||
|
|
|
||||||
36
tests/nimdoc/m13129.nim
Normal file
36
tests/nimdoc/m13129.nim
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
when defined(cpp):
|
||||||
|
{.push header: "<vector>".}
|
||||||
|
type
|
||||||
|
Vector[T] {.importcpp: "std::vector".} = object
|
||||||
|
elif defined(js):
|
||||||
|
proc endsWith*(s, suffix: cstring): bool {.noSideEffect,importjs: "#.endsWith(#)".}
|
||||||
|
elif defined(c):
|
||||||
|
proc c_printf*(frmt: cstring): cint {.
|
||||||
|
importc: "printf", header: "<stdio.h>", varargs, discardable.}
|
||||||
|
|
||||||
|
proc main*() =
|
||||||
|
runnableExamples:
|
||||||
|
import std/compilesettings
|
||||||
|
doAssert not defined(m13129Foo1)
|
||||||
|
doAssert defined(m13129Foo2)
|
||||||
|
doAssert not defined(nimdoc)
|
||||||
|
echo "ok2: backend: " & querySetting(backend)
|
||||||
|
# echo defined(c), defined(js),
|
||||||
|
|
||||||
|
import std/compilesettings
|
||||||
|
when defined nimdoc:
|
||||||
|
# import std/compilesettings
|
||||||
|
static:
|
||||||
|
doAssert defined(m13129Foo1)
|
||||||
|
doAssert not defined(m13129Foo2)
|
||||||
|
echo "ok1:" & querySetting(backend)
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
when not defined(js):
|
||||||
|
import std/os
|
||||||
|
let cache = querySetting(nimcacheDir)
|
||||||
|
doAssert cache.len > 0
|
||||||
|
let app = getAppFilename()
|
||||||
|
doAssert app.isRelativeTo(cache)
|
||||||
|
doAssert querySetting(projectFull) == currentSourcePath
|
||||||
|
echo "ok3"
|
||||||
2
tests/nimdoc/readme.md
Normal file
2
tests/nimdoc/readme.md
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
the html validation is tested by nimdoc/tester.nim
|
||||||
|
the runnableExamples + nim doc logic (across backend) is tested here
|
||||||
|
|
@ -6,7 +6,7 @@ discard """
|
||||||
## tests that don't quite fit the mold and are easier to handle via `execCmdEx`
|
## tests that don't quite fit the mold and are easier to handle via `execCmdEx`
|
||||||
## A few others could be added to here to simplify code.
|
## A few others could be added to here to simplify code.
|
||||||
|
|
||||||
import std/[strformat,os,osproc]
|
import std/[strformat,os,osproc,unittest]
|
||||||
|
|
||||||
const nim = getCurrentCompilerExe()
|
const nim = getCurrentCompilerExe()
|
||||||
|
|
||||||
|
|
@ -15,8 +15,9 @@ const mode =
|
||||||
elif defined(cpp): "cpp"
|
elif defined(cpp): "cpp"
|
||||||
else: static: doAssert false
|
else: static: doAssert false
|
||||||
|
|
||||||
|
const testsDir = currentSourcePath().parentDir
|
||||||
|
|
||||||
proc runCmd(file, options = ""): auto =
|
proc runCmd(file, options = ""): auto =
|
||||||
const testsDir = currentSourcePath().parentDir
|
|
||||||
let fileabs = testsDir / file.unixToNativePath
|
let fileabs = testsDir / file.unixToNativePath
|
||||||
doAssert fileabs.existsFile, fileabs
|
doAssert fileabs.existsFile, fileabs
|
||||||
let cmd = fmt"{nim} {mode} {options} --hints:off {fileabs}"
|
let cmd = fmt"{nim} {mode} {options} --hints:off {fileabs}"
|
||||||
|
|
@ -55,11 +56,11 @@ ret=[s1:foobar s2:foobar age:25 pi:3.14]
|
||||||
|
|
||||||
else: # don't run twice the same test
|
else: # don't run twice the same test
|
||||||
import std/[strutils]
|
import std/[strutils]
|
||||||
template check(msg) = doAssert msg in output, output
|
template check2(msg) = doAssert msg in output, output
|
||||||
|
|
||||||
block: # mstatic_assert
|
block: # mstatic_assert
|
||||||
let (output, exitCode) = runCmd("ccgbugs/mstatic_assert.nim", "-d:caseBad")
|
let (output, exitCode) = runCmd("ccgbugs/mstatic_assert.nim", "-d:caseBad")
|
||||||
check "sizeof(bool) == 2"
|
check2 "sizeof(bool) == 2"
|
||||||
doAssert exitCode != 0
|
doAssert exitCode != 0
|
||||||
|
|
||||||
block: # ABI checks
|
block: # ABI checks
|
||||||
|
|
@ -72,11 +73,11 @@ else: # don't run twice the same test
|
||||||
# on platforms that support _StaticAssert natively, errors will show full context, eg:
|
# on platforms that support _StaticAssert natively, errors will show full context, eg:
|
||||||
# error: static_assert failed due to requirement 'sizeof(unsigned char) == 8'
|
# error: static_assert failed due to requirement 'sizeof(unsigned char) == 8'
|
||||||
# "backend & Nim disagree on size for: BadImportcType{int64} [declared in mabi_check.nim(1, 6)]"
|
# "backend & Nim disagree on size for: BadImportcType{int64} [declared in mabi_check.nim(1, 6)]"
|
||||||
check "sizeof(unsigned char) == 8"
|
check2 "sizeof(unsigned char) == 8"
|
||||||
check "sizeof(struct Foo2) == 1"
|
check2 "sizeof(struct Foo2) == 1"
|
||||||
check "sizeof(Foo5) == 16"
|
check2 "sizeof(Foo5) == 16"
|
||||||
check "sizeof(Foo5) == 3"
|
check2 "sizeof(Foo5) == 3"
|
||||||
check "sizeof(struct Foo6) == "
|
check2 "sizeof(struct Foo6) == "
|
||||||
doAssert exitCode != 0
|
doAssert exitCode != 0
|
||||||
|
|
||||||
import streams
|
import streams
|
||||||
|
|
@ -103,3 +104,21 @@ else: # don't run twice the same test
|
||||||
var (output, exitCode) = execCmdEx(cmd)
|
var (output, exitCode) = execCmdEx(cmd)
|
||||||
output.stripLineEnd
|
output.stripLineEnd
|
||||||
doAssert output == expected
|
doAssert output == expected
|
||||||
|
|
||||||
|
block: # nim doc --backend:$backend --doccmd:$cmd
|
||||||
|
# test for https://github.com/nim-lang/Nim/issues/13129
|
||||||
|
# test for https://github.com/nim-lang/Nim/issues/13891
|
||||||
|
const buildDir = testsDir.parentDir / "build"
|
||||||
|
const nimcache = buildDir / "nimcacheTrunner"
|
||||||
|
# `querySetting(nimcacheDir)` would also be possible, but we thus
|
||||||
|
# avoid stomping on other parallel tests
|
||||||
|
let file = testsDir / "nimdoc/m13129.nim"
|
||||||
|
for backend in fmt"{mode} js".split:
|
||||||
|
let cmd = fmt"{nim} doc -b:{backend} --nimcache:{nimcache} -d:m13129Foo1 --doccmd:'-d:m13129Foo2 --hints:off' --usenimcache --hints:off {file}"
|
||||||
|
check execCmdEx(cmd) == (&"ok1:{backend}\nok2: backend: {backend}\n", 0)
|
||||||
|
# checks that --usenimcache works with `nim doc`
|
||||||
|
check fileExists(nimcache / "m13129.html")
|
||||||
|
|
||||||
|
block: # mak sure --backend works with `nim r`
|
||||||
|
let cmd = fmt"{nim} r --backend:{mode} --hints:off --nimcache:{nimcache} {file}"
|
||||||
|
check execCmdEx(cmd) == ("ok3\n", 0)
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,4 @@ static:
|
||||||
|
|
||||||
doAssert "myNimCache" in nc
|
doAssert "myNimCache" in nc
|
||||||
doAssert "myNimblePath" in np[0]
|
doAssert "myNimblePath" in np[0]
|
||||||
|
doAssert querySetting(backend) == "c"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue