Nim: Allow specifying/forcing the compilation backend in Nim for `nim doc`

Created on 13 Jan 2020  路  5Comments  路  Source: nim-lang/Nim

Summary

Allow forcing the compilation backend that get enforced on the usual library compilations and also the code block evaluations done by nim doc invocations.

Description

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.}

Failed attempts

I tried putting this in the project's config.nims, but the nim doc still uses the c backend:

if getCommand() == "c":
  setCommand("cpp")

Suggestion

Make the above NimScript code affect the nim doc command too.

Additional Information

Doc Generation

Most helpful comment

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

All 5 comments

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))

EDIT

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.

Was this page helpful?
0 / 5 - 0 ratings