Allow forcing the compilation backend that get enforced on the usual library compilations and also the code block evaluations done by nim doc invocations.
Certain Nim libraries cannot be compiled in _any_ backend the user wants.
A very good example is a wrapper Nim library for a backend-specific library.. e.g. a Nim wrapper for C++ std::vector. For such Nim libraries one can force the user to always compile using the cpp backend using something like:
when not defined(cpp):
{.error: "This library needs to be compiled with the cpp backend.".}
But there is not way to force the cpp backend when running the nim doc command on that library.
For example, this will always fail right now if I run nim doc on it.. because nim doc is always using the c backend to evaluate the code blocks in doc strings:
when not defined(cpp):
{.error: "This library needs to be compiled with the cpp backend.".}
{.push header: "<vector>".}
type
Vector*[T] {.importcpp: "std::vector".} = object
proc newVector*[T](): Vector[T] {.importcpp: "std::vector<'*0>()", constructor.}
# https://en.cppreference.com/w/cpp/container/vector/size
proc size*(v: Vector): int {.importcpp: "#.size()".}
## Return the number of elements in the Vector.
##
## .. code-block::
## :test:
## var
## v = newVector[int]()
## doAssert v.size() == 0
##
## v.add(100)
## v.add(200)
## doAssert v.len() == 2
{.pop.}
I tried putting this in the project's config.nims, but the nim doc still uses the c backend:
if getCommand() == "c":
setCommand("cpp")
Make the above NimScript code affect the nim doc command too.
std::vector Nim wrapper library std_vector, but stumbled upon this limitation where nim doc always uses the c backend.This issue can be fixed by removed the hardcoding of c backend here:
couldn't runnableExamples be used instead (IMO runnableExamples is always better); it already has the logic in place to pick the correct backend:
proc runAllExamples(d: PDoc) =
if d.examples.len == 0: return
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
"_examples.nim"))
writeFile(outp, d.examples)
let backend = if isDefined(d.conf, "js"): "js"
elif isDefined(d.conf, "cpp"): "cpp"
elif isDefined(d.conf, "objc"): "objc"
else: "c"
if os.execShellCmd(os.getAppFilename() & " " & backend &
" --warning[UnusedImport]:off" &
" --path:" & quoteShell(d.conf.projectPath) &
" --nimcache:" & quoteShell(outputDir) &
" -r " & quoteShell(outp)) != 0:
quit "[Examples] failed: see " & outp.string
else:
# keep generated source file `outp` to allow inspection.
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
removeFile(outp.changeFileExt(ExeExt))
doesn't seem to work since we can't jus pass -d:cpp without breaking a lot of assumptions eg:
proc fun*() =
runnableExamples:
echo "ok1"
discard
nim doc -d:cpp main.nim
/Users/timothee/git_clone/nim/Nim_devel/lib/system/excpt.nim(570, 12) Error: only a 'ref object' can be raised
/Users/timothee/git_clone/nim/Nim_devel/lib/system/excpt.nim(571, 52) Error: type mismatch: got <ref StdException>
We need a --backend:<x> switch.
instead of --backend:<x> we could have a more general: --doccmd:cmd eg:
--doccmd:"objc --threads:on -d:foo"
eg:
nim doc --doccmd:-d:foo main.nim
when defined(foo):
proc bar*()=discard
runnableExamples:
bar()
...
currently, it seems the -d:foo aren't passed on to the doc command that runs runnableExamples
another use case for --doccmd is for passing --lib:lib
just ran into some issues where I could make use of --doccmd or the like, or even if nim.cfg was read.
Most helpful comment
instead of
--backend:<x>we could have a more general:--doccmd:cmdeg:eg:
nim doc --doccmd:-d:foo main.nim
currently, it seems the
-d:fooaren't passed on to the doc command that runs runnableExamplesanother use case for
--doccmdis for passing--lib:lib