I have (and probably will) never voluntarily use a DI framework in any language. There's zero downside to manually doing it. It's explicit, incredibly easy, and you can easily trace backward to see how the program is constructed.
If it's 5000 lines and messy it is indeed a problem, but only because it's messy.
I've never worked in a large codebase that did this manually so I'm not sure what it looks like. The large codebases I've seen that don't use DI have used something like a service locator, singletons, or constructed everything where it was needed (and used extensive mocking framework functionality for testing).
Manual DI reveals problems like this way earlier.
DI frameworks, IMO, are some of the most useless around. Solution seeking a problem.