nimble
nimble copied to clipboard
`nimble test`, `nimble build` etc should build all artifacts under `./build`
Out of source builds (and tests) is standard practice with many benefits over in-source builds (eg https://cgold.readthedocs.io/en/latest/tutorials/out-of-source.html or many other resources), such as easy gitignore (just gitignore a single dir, avoid having to do this https://github.com/nim-lang/nimble/pull/786), preventing accidental checking in of binaries or generated files (eg in nimble repo itself, see https://github.com/nim-lang/nimble/commit/4a2aaa07dc6b52247bc0b7d40fac30a1f7eabac0#diff-b39306cdc7f9dc8317cd6f5356f31a61), makes it trivial to cleanup (remove a single well-known, gitignore'd dir) while avoiding accidental removal of important files (thus, avoiding doing things like this https://github.com/nim-lang/nimble/pull/745); furthermore, it enables keeping separate builds, say when comparing 2 options, and makes it easy to ignore generated files in tools like grep/ripgrep etc
proposal
- by default, all nimble commands (eg
nimble test
,nimble build
,nimble doc
etc) should build all artifacts (binaries, shared libs, and other files generated by running tests) rooted under a standardized dir (let's say,@build=@pkg/build
where@pkg
expands to full path of root of current nimble package - that dir can be overriden with
nimble --buildDir:otherdir
, expanding to@pgk/otherdir
if not absolute - nim's
pathSubs
logic can be reused so that special tokens like--buildDir:@nimcache/@pkgname
work -
nimble init
gets updated to add a .gitignore file (if doesn't exist) with a single entry:/build
so thatgit status
stays clean afternimble build
,nimble test
etc - I'm using
@
instead of$
so that it works cross platform and without quoting needed, which always cause issues cross platform. nim'spathSubs
supports@
. -
nimble doc
, if task isn't provided, can use the newly introducednim doc --project --outDir:@build/docs --docroot --index:on pathto/foo.nim
(see https://github.com/nim-lang/Nim/pull/13223)
implementation
- when running tasks (eg
nimble test
),nimble
adds an implicit cmdline flag--outdir:@build/@pkgprojdir
. This causesnim c -r tests/foo/tbar.nim
to generate the binary@build/tests/foo/tbar
. The usual overriding rules apply, in case cmd line invocation or the task add-o
or--outDir
flags
note
-
--outDir
needs to be smarter to make this seamless; right now,--outDir:relativePath
doesn't work as you'd expect, and--outDir:/hardCodedAbsolutePath
is obviously bad, and--outDir:"$nimcache"/foo
does a buggy path substitution (via nim'spathSubs
logic), but I intend to fix this innim
so nimble or individual packages can use this feature
path substitution variables that can be used:
(via nim's pathSubs
)
- @pkg indicates path to a nimble package, eg for cligen:
@pkg=/Users/timothee/git_clone/cligen
- @build (new) indicates root under which all files are built; loose analog to
DESTDIR=... make
for makefile projects. This is overridden via nimble--buildDir:otherdir
as explained above - @pkgprojdir (new) indicates relative path to main project file being compiled, eg, in
cd /Users/timothee/git_clone/cligen
cd tests
nim c -r --outdir:@build/@pkgprojdir foo/main.nim`
@pkgprojdir
resolves tests/foo/
(regardless which dir we are in), ie indicates parentDir of relative path of file being compiled relative to @pkg
optional ones:
-
@pkgname (new) indicates current package's name, eg
cligen
-
note that this is independent of git repo layout since 1 git repo can contain multiple nimble packages
-
for
nimble build
, we can also symlink (or just copy) the generated build files artifacts eg, autogenerate symlink@bin/toast
that points to@build/@pkgprojdir/toast
, so that binaries are in a predictable (flat) location; if not specified in nimble file,@bin
shall default to@build/bin
benefits
- the logic for nimble is extremely simple: just forward one implicit flag
--outdir:@build/@pkgprojdir
(in the same way as--path:@src
is being passed already) -
git status
status clean even after runningnimble test
andnimble build
- gitignore files in nimble projects can be kept extremely simple (just 1 line)
- enables running concurrent tests/builds, say with different options, each going in their own isolated dir, eg:
nimble --buildDir:buildDanger -d:danger test # or `build` or `doc` etc
nimble --buildDir:buildCustom -u:release test
- I'm honoring the relative hierarchy in the package (via
@pkgprojdir
) so that generated output files (eg binaries) don't clobber each other in case they have same filename eg:
tests/trunner.nim => @build/trunner
tests/foo/trunner.nim => @build/foo/trunner
tests/bar/trunner.nim => @build/bar/trunner
- no need for a default
nimble clean
(ie, this could close https://github.com/nim-lang/nimble/issues/555), since all artifacts go under a single gitignore dir by default. Users can of course overridenimble clean
if they have test artifacts produced in nonstandard location (and not gitignored). In fact, I consider https://github.com/nim-lang/nimble/pull/745 rather dangerous and fragile, it's pretty much guaranteed to either err on side of safety (lots of false negatives) or cause harm (deleting important files). I'll comment on that PR later.
note
There's a lot of other things we could borrow from homebrew
's design, which is an excellent package manager that managed to present a uniform API that abstracts over significant OS/build/language differences.
brew test
can be run from anywhere, doesn't require a local git checkout (it'll install it (after its dependencies), and run the tests); I really wish we could do that with nimble
btw.
-
brew test
runs in a sandbox, eg
brew test gdb --verbose
Testing gdb
/usr/bin/sandbox-exec -f /private/tmp/homebrew20200326-60443-132dh8p.sb ruby -W0 -I $LOAD_PATH -- /usr/local/Homebrew/Library/Homebrew/test.rb /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/gdb.rb --verbose
==> /usr/local/Cellar/gdb/9.1_1/bin/gdb /usr/local/Cellar/gdb/9.1_1/bin/gdb -configuration
This GDB was configured as follows:
configure --host=x86_64-apple-darwin19.3.0 --target=x86_64-apple-darwin19.3.0
- it builds out of source so that
brew cleanup
is safe to run (and doesn't need to be clever), simply by making sure everything gets generated in well known brew-managed directories instead of in-source - and in fact, cache files are automatically garbage collected when needed, so users don't even need to worry about it.
I like this idea, but there is too much going on in your proposal. Please focus on a simple implementation that does not include all these fancy path substitution variables.
This should be as simple as possible, and I'm not sure we should even make it customisable.
-
nimble test
->build/tests/mytest
,build/tests/mytest2
Furthermore, I'm not sure this should apply to anything other than nimble test
. But it's late so I don't have the energy to make a decision on this :)
I second this because it's littering my file explorer with random .exe files since VSCode does not always recognize that the temporary binaries nimble test creates were deleted (and then I have to do a refresh).