Still counts as JIT in my book, but you're right that it's a bit subtle.
Unix-style configure/build/install isn't considered JIT.
Installing a .Net application is pretty similar, but we don't consider it JIT.
In the usual .Net model, what's distributed is IR rather than source-code. Compilation to native code happens at install time. The build-and-install process is less explicit than the Unix way, and it's less error-prone (fewer dependency issues and issues with the compiler not liking your source code).
Really it's a very similar model to the Unix one, but we call one JIT and not the other.
Oracle Java, of course, only ever compiles to native code at runtime, and never caches native code. 'Proper' JIT. (This may be set to change in the near future though.)
Interestingly, .Net seems to be moving in the direction of full static compilation, or they wouldn't be asking devs to rebuild UWP apps to incorporate framework fixes - https://aka.ms/sqfj4h/
I think it would need to be integrated into the package management system pretty tightly (or have one of its own) to get all of the shared library dependencies.
Various research OSs are JIT-based, of course. It looks like JX (a Java operating system) caches its native code, so it's not 'pure JIT' https://github.com/mczero80/jx/blob/5fbeae79/libs/compiler_e...
It looks like Cosmos (a C# operating system) does the same https://en.wikipedia.org/wiki/IL2CPU
In that case the only real JIT I know of is basic-block-versioning. I think almost all JITs will compile branches or methods to some extent before they are actually needed.
Yours is probably not a reasonable definition therefore. I think a JIT is just a compiler that can compile as the program is running.
I mean, that's more or less what the name "just-in-time compiler" implies. I'm aware that the name is not necessarily a precise definition, but I'm not sure how far the definition stretches. Does JIT have a precise agreed-upon definition, or is it somewhat more vaguely defined?
Whether that lazy-compilation strategy is fine-grained or not isn't clearcut, I believe. I think if you distribute a C program with a bash bootstrapper calling plain old gcc to compile and run the C code only when needed, even gcc might be considered a (coarse-grained, rather rudimentary) JIT in that context.
If it means compile on start, it still requires the compiler to be used at load time.
Non JIT would mean you can distribute the code without the compiler. If you can't do that, its JITTED or interpreted, if instead of requiring a compiler to be present you require an interpreter.