Kevin Vermeer
Kevin Vermeer

Reputation: 2852

Simplifying compilation with each of a list of options

I've got a list of definitions: MASTER, SLAVE0, SLAVE1, ... SLAVE9 to control which array of audio data is programmed into a microcontroller. The micro can hold no more than one sound file, so I have included the following definitions at the top of my main.c file:

#define MASTER
#define SLAVE0
#define SLAVE1
....
#define SLAVE9 

Then, I write the following in my audio array:

#if defined(MASTER)
    uint8_t sound[4096] PROGMEM = {127,126, ... }
#elif defined(SLAVE0)
    uint8_t sound[4096] PROGMEM = {126,128, ... }
....
#else 
    #ERROR "One of MASTER-SLAVE9 must be defined!"
#endif

The person wishing to compile must then go through and comment out one and only one of the #define lines. This is not only tedious, but also error-prone. So, I'm looking to simplify the process. Any pointers for any of the following tasks would be helpful:

  1. How can I test a list of macros for the presence of one and only one of these options? A simple if defined(MASTER) && !(defined(SLAVE0) || defined(SLAVE1) ...) would require 11 such tests, each with 11 subtly different conditions. It's a one time expense, but it's kinda ugly. It feels like this might be a common need, and that there ought to be a better way.
  2. How can I simplify the compilation process? I've been using AVRStudio with WinAVR t0 compile. It has an 'export makefile' option, but I have no experience with it. I'm stuck doing this on Windows. An ideal process would build all 11 configurations in a single command, and then I could go through and program each one to the microcontroller individually. The current, very much less-than-ideal build process involves editing the source each time I want to build, and renaming/moving the output file.

Upvotes: 0

Views: 120

Answers (4)

Vovanium
Vovanium

Reputation: 3898

You are need an error message when you deined mre than one macro? Well, just write:

#ifdef MASTER
uint8_t sound = { ... };
#endif
#ifdef SLAVE0
uint8_t sound = { ... };
#endif
#ifdef SLAVE1
uint8_t sound = { ... };
#endif

And compiler will complain that one identifier defined multiple times.

Also why not use this?

#define SLAVE <n>

uint8_t sound_master = { ... };
uint8_t sound_slave_0 = { ... };
uint8_t sound_slave_1 = { ... };
uint8_t sound_slave_2 = { ... };

#define XCAT(a,b) a##b
#define CAT(a,b) XCAT(a,b)
#ifdef SLAVE
#define sound CAT(sound_slave_,SLAVE)
#endif
#ifdef MASTER
#ifdef sound
/* warnin or so. but if you need an error just remove this ifdef **/
#endif
#define sound sound_master
#endif

Upvotes: 0

Bitgamma
Bitgamma

Reputation: 652

I would just make a block comment with the name of all possible constants, and follow it with a single define. Who wants to compile just writes what he wants. First time he will check the comment to see the list, then he will just write.

Or even better, keep this list in a comment (for reference) and use the -D option that most compilers have (-DMASTER to define master for example) and if your tool supports it, make a build configuration for each where you change the -D value. Using a different build configuration i guess you could also change the output file name, so that would kill two birds with a stone.

Upvotes: 1

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272607

Why not something like:

#define ARRAY_NAME        (SLAVE0)

...


#if (ARRAY_NAME == MASTER)
    // blah
#elif (ARRAY_NAME == SLAVE0)
    // blah
// etc.

or even better, just:

#define ARRAY_MASTER { 1, 2, 3, 4 }
#define ARRAY_SLAVE0 { 5, 6, 7, 8 }
// etc.

...

const uint8_t sound[] = ARRAY_MASTER;

Upvotes: 0

James McNellis
James McNellis

Reputation: 355107

You can use a single test to ensure that only one of the macros is defined.

#if (defined(MASTER) + defined(SLAVE1) + defined(SLAVE2)) != 1
    #error "Too many macros defined"
#endif

As for the definition itself, most compilers allow you to define a macro using a command line option; this might be cleaner than a file with a "configurable options list." You would then be able to create multiple build configurations, each of which defines a different macro, and build them each in sequence (I'm not familiar with your build system to be able to explain how exactly you need to do that).

Upvotes: 2

Related Questions