Skip to content

Feature/build lib - #1801

Open
moigagoo wants to merge 8 commits into
nim-lang:masterfrom
moigagoo:feature/build_lib
Open

Feature/build lib#1801
moigagoo wants to merge 8 commits into
nim-lang:masterfrom
moigagoo:feature/build_lib

Conversation

@moigagoo

Copy link
Copy Markdown
Contributor

No description provided.

@arnetheduck

Copy link
Copy Markdown
Contributor

so the way I have the library set up is a mylib.nim.cfg file adjacent to the library entry point - it contains the --app:lib - this way, if I compile with nim c .. it "just works".

I can't say I'm a fan of nimble recreating the output logic that already exists in nim - it would be better if it didn't do that and just relied on what nim does (which also handles things like conflicting directory names etc)

@moigagoo

Copy link
Copy Markdown
Contributor Author

Hmmm, I thought you wanted nimble build to produce the library in the first place 🤔 This is useful in the sense that all packages have the same universal commands, so you don't have to learn anything.

If you're OK with nim c than config.nims, nim.cfg, mylib.nim.cfg, or --app:lib would all work.

@arnetheduck

Copy link
Copy Markdown
Contributor

Hmmm, I thought you wanted nimble build to produce the library in the first place

the problem here is that nimble overrides the name that nim chooses by default - if nimble build did not mess up the name with its -o, using a .cfg file would work for both nimble build and nim c.

The broader issue here is that nim c ... and nimble build should ideally be as close as possible / do the same thing so you can use them interchangeably - sometimes I would do nimble build (to build all the binaries) and sometimes I might nim c (because that's what vscode does when you press f6).

The open question is whether there's a lib needed to accompany bin, ie whether nimble needs to know that it's a shared library being built - this might be interesting for installing the build outputs (which is why nimble needs to know about them).

@moigagoo

Copy link
Copy Markdown
Contributor Author

the problem here is that nimble overrides the name that nim chooses by default - if nimble build did not mess up the name with its -o, using a .cfg file would work for both nimble build and nim c.

100% agree, this is why I removed -o from nimble build and let Nim choose the name.

The broader issue here is that nim c ... and nimble build should ideally be as close as possible / do the same thing so you can use them interchangeably - sometimes I would do nimble build (to build all the binaries) and sometimes I might nim c (because that's what vscode does when you press f6).

I'm totally with you on that. To me, build should be:
a) something trivial like nim c -d:release --outdir:BINDIR (and I'm not even sure -d:release is necessary, but it has to stay for historic reasons)
b) overridable just like test

The open question is whether there's a lib needed to accompany bin, ie whether nimble needs to know that it's a shared library being built - this might be interesting for installing the build outputs (which is why nimble needs to know about them).

I think if you can override build, you don't need lib and it's a cleaner solution. Basically, all tasks should be overridable with sane defaults provided.

@arnetheduck

Copy link
Copy Markdown
Contributor

I think if you can override build

there's a contract to follow here though - ie build, bin etc exist for install to be able to do its job, part of which is to transport binaries to their final locations - this means that if you override build and do something else, downstream commands will break meaning that any presumptive build overriding must have a protocol to follow that gives nimble the above information.

@moigagoo

Copy link
Copy Markdown
Contributor Author

there's a contract to follow here though

Yeah, I missed that... Well, at least now I understand why the builtin commands are not oevrridable yet, makes sense.

@jmgomez

jmgomez commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

@moigagoo You forgot to import your new test file in tester.nim
Also did you study how stop forcing -o interacts with the other commands? If so, it would be good for you to elaborate here :)

@moigagoo

Copy link
Copy Markdown
Contributor Author

You forgot to import your new test file in tester.nim

Sorry, added it.

Also did you study how stop forcing -o interacts with the other commands? If so, it would be good for you to elaborate here :)

Well, I did try running various commands, apart from the tests of course.

I couldn't spot the difference in behavior apart from when I actually do change something that affects the output file name, i.e. switch("app", "lib"). With that added, <BINDIR>/lib<NAME>.so is produced instead of <BINDIR>/<NAME>, as you'd expect.

nimble c does the same as nim c: compiles to the same directory as the source file, respects config.nims.

nimble install behaves a bit weirdly if you have switch("app", "lib"): it will build the library and put a binary named <NAME> (not lib) to ~/.nimble/bin. Which, if you run it, returns an error. Which is expected because it's a library, not an execuatable. However, nimble install does the right thing and puts the expected binary under the expected name in the expected location; that this binary is broken is the programmer's fault. What did you expect, installing a library?

@jmgomez

jmgomez commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

The more I think about this, the more I come to the conclusion that if we want to support libs, I think we should introduce a first-class lib target variable like I mentioned before in the issue. nimble build could build it, while nimble run would reject it with a clear message.

Without explicit metadata, Nimble cannot reliably know ahead of compilation whether a target is an executable or a library. We could try to infer that by evaluating the compiler configuration or inspecting its output, but that adds complexity and potentially another compiler invocation. It also leaves questions around installation and executable symlinks (i.e how do we know if we should produce a symlink?)

This is what I meant by considering how the change interacts with the other actions, although I haven’t mapped out every implication yet.

Nimble has accumulated quite a few edge cases where a feature initially addressed one command and later required several follow-up patches to fit with everything else—develop is a good example. I’d like us to avoid repeating that pattern and make sure this fits coherently with the existing model from the beginning.

@moigagoo

moigagoo commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@jmgomez thanks for the explanation. I'm happily passing the task to you as we discussed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants