Generate .a file
Build a (web-based) library generator (again one .c and .h file)
Neither of these is a good option. The former is, for the reason you covered, platform-specific. The latter leaves anyone wanting to alter the set of modules compiled into their binary dependent on you continuing to run a server that can generate a new version. You could provide the sources for that server, but having to set one up just for that would be inconvenient or impossible in some shops.
Generate a single .c and .h file
I think this is the best way to go since you can generate it as part of your distribution and it's the same every time.
(+) Very portable & simple to use
The portability issue is a big thing in the embedded space. There are lots of odd little development environments for various platforms that don't provide a lot of the kinds of features you find in a Unixy environment, so anything you can do to make it easier to incorporate will increase adoption.
An added bonus is that many compilers can do size and speed optimizations on a single file that aren't possible when the code is split. Being able to squeeze your code into a smaller footprint and wring more out of it is welcome in constrained environments.
(-) Nightmare to do debugging
Not as much as you'd think. Most debuggers don't care if you have one giant file or 50 little ones. Once you've worked the kinks out of determining what gets included and what doesn't, you probably won't notice it because most debugging is done intra-function. Odds are quite good that most of the bugs you encounter are going to be due to flaws in the code and will show up in both the un-merged and merged versions. Speaking of same, if you have a test battery, it would be good to run it against both.
You do want to keep the original files separate because it's lots easier to do reviews and poke around in your version control system looking at smaller chunks.
One reason to avoid custom builds for each combination of features is that it effectively puts 2^n versions of the source out there, where n is the number of features you can enable or disable. If somebody points out a bug in line 456 if your sources, you're going to have to determine the set of features is enabled so you know which line 456 it is.
(-) Will need external scripts to remove #includes and merge files together
This shouldn't be too big a deal. The important thing is to make sure the process is automated and repeatable so it becomes a set-and-forget part of your distribution process.
(-) All modules would be included, therefore we'll probably have to add some more compilation flags
That shouldn't be too disruptive, especially if you already have feature selection built into the code. If you're doing it as part of your build environment (i.e., the decision to include or exclude something is part of your Makefile, I would recommend getting away from that.
Before diving into a single-file distribution, I would highly recommend studying SQLite. That project has been around for 16 years, is pretty much the gold standard for that sort of thing and does many of the things you're looking at doing.