Make targets can be whatever you want, and don't have to produce files.
Make -n TARGET will list everything that Make thinks it needs to do to achieve TARGET, including anything that has to happen for any expressed dependencies (which can be tasks, and don't have to produce files).
Make recipes are arbitrary shell scripts that can do whatever you want, including changing directory. Make can also include other Makefiles, or call other Makefiles.
At its core, Make is a way to express "snippets of shell scripts, with a dependency graph between them". It can track files as dependency input and output -if you want-, but Make does not care if you don't. Call your targets whatever, and don't have them produce files. Boom, command runner. Make also has a powerful design, with a lot that you can do at parse-time.
And as it turns out, most tasks -do- have some amount of file dependencies. Maybe they need to consume a key file. Maybe they download a tarball. Maybe they produce a logfile that another task uploads. Being able to express as much (or as little) of that dependency graph as I want is a feature, not a bug.