Каждый *.c файл содержит обвязку типа #include "common.h"
#ifdef BUILD_SNTPC
< Реализация клиента SNTP >
#endif // BUILD_SNTPC
Если подразумевается вариативность, например нужно выбрать конкретный ethernet phy из нескольких, то обвязка другая
#include "common.h"
#ifdef PHY_TYPE_KSZ8895
< Реализация для свича >
#endif // PHY_TYPE_KSZ8895
Заголовок "common.h" содержит прототипы всего-всего и включает еще и заголовок project.h, который относится к конкретному проекту и содержит кучу дефайнов
#define PHY_TYPE_KSZ8895
//#define PHY_TYPE_IP175D
//#define PHY_TYPE_KSZ8031R
//#define BUILD_SYSLOG
#define BUILD_NBNS
#define BUILD_SNTPC
//define BUILD_I2C
#define BUILD_I2C_SW
Таким макаром во все проекты включены все .c файлы, но если некий функционал не нужен - то он и не скомпилируется.