Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nimdigger: build nim at any revision since v0.12.0~157, 1 liner git bisect to help find regressions #18119

Closed
wants to merge 23 commits into from

Conversation

timotheecour
Copy link
Member

@timotheecour timotheecour commented May 28, 2021

nimdigger is a tool to:

  • build nim at any revision (including custom branches), taking
    care of details such as figuring out automatically the correct csources/csources_v1 revision to use.
  • allow 1-liner git bisect to find nim regressions, take care of building nim (if not cached) at intermediate revisions

design goals

  • ease of use: 1 liner for running git bisect workflows, or to build nim at past revisions
  • performance: via caching both csources built binaries, and intermediate nim binaries
  • lazyness: build artifacts on demand
  • go as far back as possible, currently oldest buildable nim version is v0.12.0~157
  • isolated: all artifacts are kept under a (configurable) $HOME/.nimdigger/cache/Nim

examples

build at any revision >= v0.12.0~157

$ nim r tools/nimdigger.nim --compileNim --rev:v0.15.2~10
$ $HOME/.nimdigger/cache/Nim/bin/nim -v
Nim Compiler Version 0.15.2 (2021-05-28) [MacOSX: amd64] [...]

find a which commit introduced a regression

$ nim r tools/nimdigger.nim --oldnew:v0.19.0..v0.20.0 --bisectCmd:'bin/nim -v | grep 0.19.0'
66c0f7c3fb214485ca6cfd799af6e50798fcdf6d is the first REGRESSION commit

find a which commit introduced a bugfix

$ nim r tools/nimdigger.nim --oldnew:v0.19.0..v0.20.0 --bisectBugfix --bisectCmd:'bin/nim -v | grep 0.20.0'
be9c38d2659496f918fb39e129b9b5b055eafd88 is the first BUGFIX commit

actual examples

for regression #16376:
copy this snippet to /tmp/t16376.nim:

type Matrix[T] = object
  data: T
proc randMatrix*[T](m, n: int, max: T): Matrix[T] = discard
proc randMatrix*[T](m, n: int, x: Slice[T]): Matrix[T] = discard
template randMatrix*[T](m, n: int): Matrix[T] = randMatrix[T](m, n, T(1.0))
let B = randMatrix[float32](20, 10)
$ nim r tools/nimdigger.nim --oldnew:v0.19.0..v0.20.0 -- bin/nim c --hints:off --skipparentcfg --skipusercfg /tmp/t16376.nim
fd16875561634e3ef24072631cf85eeead6213f2 is the first REGRESSION commit

for regression #16496:

$ nim r tools/nimdigger.nim --oldnew:v1.2.0..v1.4.0 -- bin/nim c -r -d:case2 --hints:off --skipparentcfg --skipusercfg /tmp/t16376.nim
8b66412a8bfebcd53f09d0e608b418a05d13516a is the first REGRESSION commit

for regression #18113:

$ nim r tools/nimdigger.nim --oldnew:v1.2.0..origin/devel -- bin/nim c -r -d:case3 --hints:off --skipparentcfg --skipusercfg /tmp/t16376.nim
e5873b3a9300897443f0f2e2db128e3463089003 is the first REGRESSION commit

speed

the more you use the tool, the faster it gets because binaries get cached, eg re-running this takes 10 seconds:

nim r tools/nimdigger.nim --oldnew:v1.2.0..origin/devel -- bin/nim c -r -d:case3 --hints:off --skipparentcfg --skipusercfg /tmp/t16376.nim

links

future work

@timotheecour timotheecour marked this pull request as ready for review May 28, 2021 23:02
@timotheecour timotheecour changed the title nimdigger: build nim at any revision since v0.12.0~157, 1 liner git bisect to help find regressions nimdigger: build nim at any revision since v0.12.0~157, 1 liner git bisect to help find regressions May 28, 2021
Copy link
Contributor

@Varriount Varriount left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a really useful tool! The source code could use some polishing though.

In particular, I think some identifiers could be changed to make the code more readable, and certain functions could be split up to increase code organization.

tools/kochdocs.nim Outdated Show resolved Hide resolved
tools/nimdigger.nim Outdated Show resolved Hide resolved
tools/nimdigger.nim Outdated Show resolved Hide resolved
tools/nimdigger.nim Outdated Show resolved Hide resolved
tools/nimdigger.nim Show resolved Hide resolved
result = outp
stripLineEnd(result)

macro ctor(obj: untyped, a: varargs[untyped]): untyped =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that this is unnecessary - the amount of typing it saves is minimal compared to the decreased readability and increased mental parsing required. Also, it's only used once in the entire file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also using this in nim-lang/fusion#32 and intend to add it to std/sugar in subsequent PR which will refactor its different uses.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name should be sugar.construct IMO.

Copy link
Contributor

@Varriount Varriount Jun 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still feel that the tradeoff between writeability and readability limits its usefulness though. In the cases where it would be useful (types with only a few fields) the fact that it's a macro significantly limits its usefulness - the reader must mentally adjust their expectations when they see the macro being used. In cases where there are types with many fields, it's almost always a better idea to explicitly show which values are being used for each field, as the reader is less likely to know the order of the fields.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this remark but we can discuss this in an RFC about how we should have sugar.construct.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed to construct, RFC left TODO

Comment on lines +218 to +217
let make = "gmake"
else:
let make = "make"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this handle Windows systems?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't have windows; can you please try?

Copy link
Member Author

@timotheecour timotheecour May 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that azure-pipelines.yml runs on windows and calls nimBuildCsourcesIfNeeded which calls this, so with the right setup, this should work on windows; a windows user will have to confirm though (and future work by a windows user can improve windows support)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will work if the user is using WSL (which they may not be, if they are using Nim to build Windows executables).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so please try on windows and report back with how to improve windows support :)

tools/nimdigger.nim Outdated Show resolved Hide resolved
tools/nimdigger.nim Outdated Show resolved Hide resolved
tools/nimdigger.nim Outdated Show resolved Hide resolved
if opt.bisectBugfix:
msg2 = fmt"! ({msg2})" # negate exit code
let bisectCmd2 = fmt"{exe} --compileNim && ( {msg2} )"
runCmd(fmt"git -C {state.nimDir.quoteShell} bisect run bash -c {bisectCmd2.quoteShell}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not cross-platform. Git should be able to run the command without using a shell.

Copy link
Member Author

@timotheecour timotheecour May 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't windows subsystem for linux work here? (as done with azure-pipelines.yml on windows) Otherwise, I think this can be addressed in followup PR by people more familiar with windows (unless you have a concrete suggestion that makes it work for windows)

@Varriount
Copy link
Contributor

Some other thoughts on this:

  • I think the logic handling cloning the csources and Nim repositories is unnecessary. Users will likely have these repositories already cloned.
  • Cache data should be stored in a temporary directory (in order to check):
    • the directory in the XDG_CACHE_HOME environment variable,
    • /tmp on *nix, or MacOS.
    • %TEMP% on Windows (I think there's getTemporaryDirectory function somewhere?).
  • Is recompiling the executable necessary?

@timotheecour
Copy link
Member Author

timotheecour commented May 29, 2021

I think the logic handling cloning the csources and Nim repositories is unnecessary. Users will likely have these repositories already cloned.

It's necessary; an important design goal for nimdigger is isolation; it allows checking out revisions/bisecting without impacting your own git repo; it's much cleaner and safer to have nimdigger manage its own Nim/csources/csources_v1 repo (that can be wiped if needed) rather than reuse a users Nim checkout (which typically won't care about csources anymore since newer nim versions rely on csources_v1, not csources). Less risk of user data corruption etc.

Cache data should be stored in a temporary directory (in order to check):

as I mentioned in #18119 (comment), this should be handled instead as an API added to std/os which will offer a platform-independent way to access XDG_CACHE_HOME (as we already do with XDG_DATA_HOME via getConfigDir and TMP via getTempDir), instead of having tools like nimdigger redefine it. Once std/os adds this API, nimdigger will reuse it (separation of concerns). => timotheecour#744

Is recompiling the executable necessary?

since #17829, nim r caches binaries so it doesn't actually recompile; of course, nim c --outdir:bin tools/nimdigger is always possible

Copy link
Contributor

@dom96 dom96 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this needs to be in the Nim repo? I would push back against including it here and instead having it as its own standalone Nimble package.

@Araq
Copy link
Member

Araq commented May 31, 2021

I will test it on Windows. Not sure whether it should be a Nimble package or not, but it probably should. Nim core developers can be expected to type nimble install nimdigger or koch nimdigger, it should be mentioned in Nim's internal documentation.

@juancarlospaco
Copy link
Collaborator

Fusion ?. 🤔

@Varriount
Copy link
Contributor

After some thought, I do agree with Araq that this should be a separate, installable utility.

@dom96
Copy link
Contributor

dom96 commented Jun 1, 2021

@juancarlospaco why? It's trivial to install via Nimble and if for some reason it's not then we should fix Nimble.

I think we should close this, this utility doesn't need to be in the same repo as the compiler.

@timotheecour
Copy link
Member Author

I'm ok with a separate nimble package and linking to it in internal docs, I'll first address remaining comments and then update this PR accordingly

@narimiran
Copy link
Member

+1 for this being a standalone nimble package.

@timotheecour
Copy link
Member Author

timotheecour commented Jun 3, 2021

@Araq done with all comments, now working on moving this to a separate repo;

how about fusion/tools/nimdigger? the goal being to avoid multiplying repos (fewer repos has benefits eg code reuse, less boilerplate wrt testing, doc publishing, more potential contributors etc); note that fusion/tools/nimdigger is intended to also be usable as a library

this would then be runnable via:

nim r /pathto/fusion/tools/nimdigger.nim --compileNim --rev:v0.15.2~10
# in future work, `nim r pkg/fusion/tools/nimdigger` could be supported,
# allowing passing canonical module paths instead of having to pass actual paths)

or if nimble build accepts building multiple binaries (does it?) then it could also be usable via nimdigger --compileNim --rev:v0.15.2~10

this assumes ppl are ok with allowing fusion to have some modules with these dependencies:

  • nim devel (instead of 1.0)
  • cligen

if not, then i'll just make a separate nimble package for simplicity

note

I expect other similar tools to be added in future, eg nimdustmite (#8276)

@Araq
Copy link
Member

Araq commented Jun 4, 2021

if not, then i'll just make a separate nimble package for simplicity

Separate Nimble package please but feel free to name the nimble package in preparation for much more code/utilities of yours. We both agree on the value mono-repos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants