Print is not the only facility where strongly typed variadic arguments are useful. If you implement it as a builtin, all those other cases will have to be implemented as a library, and as a result, argument passing looks very different from print. And it is desirable that the same thing is consistently expressed in the same manner.
Because plenty of places where C is used won't need it, or indeed any part of libc.
Also, it's a fairly simple to decide upon dividing line between the language and the library - if it can be implemented in a handful of assembly instructions (or, ideally, 1 instruction) it's part of the language. If it can't and needs a "function" (either in C, or implemented in assembly) to work, or needs to talk to some other part of the computer (like a kernel, or a BIOS) it's part of the library.
Like malloc()/free() - again, not part of the core language spec, but part of the standard library, which can be omitted in some ("freestanding", as opposed to "hosted") implementations.
Remember, C was created in the '70s. Memory was measured in kilobytes. Tens of kilobytes if you were lucky. Even through the '80s, 1 megabyte was a lot.
what's the point of not having print provided as part of the language implementation, though?