How to select subroutine to include during compile?

The question is how do I write, or what do I do to compile a program with one of two subroutines that are named the same?

Let me try to break it down. I have a project which will have two versions, but don't want to maintain two programs, when less than 25% of the programming different between them. One of the items that is different is the menu subroutine (called display_menu()). I tried to create display_menu1() and display_menu2() and use a #define and if statement to select the correct function call. Problem is I ran out of space. There is enough space for one menu or the other, but not for both. The fact is that I don't need both. It is either version A or version B. It will never be switched between them.

I would like is to remove the current #define and if statement combo, call only display_menu() and use another command or directive to switch between compiling the two menus. The program will have display_menu() twice, but only one gets compiled in. Is this possible?

Another option would be to move the menus to two separate files (which would make three in total, 1-main program, 2-menu A, 3-menu B) and use a directive to only compile main program & menu A or main program & menu B. Can it be done this way?

Is there another option? (besides a larger board, ie., upgrading from UNO to MEGA)

If you have a preprocessor conditional that's false, the code inside will definitely not be compiled.

The compiler will also try to optimize out any code that can be determined at compile time to never be used.

So it's not clear to me how you're ending up with the unused code causing you to run out of space. It would probably be helpful if you posted the code.

adwsystems:
The program will have display_menu() twice, but only one gets compiled in. Is this possible?

Sure, you can do something like this:

#ifdef MODE_A
display_menu() {
  // Mode A code
}
#else
display_menu() {
  // Mode B code
}
#endif

You can be sure that only one of those will be compiled. There are other ways to do this as well. My advice is to avoid the use of the preprocessor unless you have no other option. Usually I would only do something like this if one of the two required a library that the other didn't and I only wanted to include the library in the mode that required it. In that case, there is no option other than to use the preprocessor since any compile time options will fail due to references to the undeclared library code.

adwsystems:
Another option would be to move the menus to two separate files (which would make three in total, 1-main program, 2-menu A, 3-menu B) and use a directive to only compile main program & menu A or main program & menu B. Can it be done this way?

Yes, if the code is in a .h file. You can do this:

#ifdef MODE_A
#include "ModeA.h"
#else
#include "ModeB.h"
#endif

Are you saying this doesn't work?

//#define MENU_A

#if defined MENU_A
void display_menu() {
  // version A of the function
#  pragma message "Version A of display_menu()"

  //...
}

#else
void display_menu() {
  // version B of the function
  //...
#  pragma message "Version B of display_menu()"
}

#endif
void setup() {
  
}


void loop() {
  display_menu();
}

I didn't say I was using #ifdef, just if statement.

I said I tried:

#define OPTION 1

...

void loop()
{
 if (OPTION == 1)
  { display_menu1(); }
  else
   { display_menu2(); }
 }

but it didn't fit.

pert:
Sure, you can do something like this:

#ifdef MODE_A

display_menu() {
  // Mode A code
}
#else
display_menu() {
  // Mode B code
}
#endif




You can be sure that only one of those will be compiled. There are other ways to do this as well. My advice is to avoid the use of the preprocessor unless you have no other option. Usually I would only do something like this if one of the two required a library that the other didn't and I only wanted to include the library in the mode that required it. In that case, there is no option other than to use the preprocessor since any compile time options will fail due to references to the undeclared library code.

What other ways? Easy to explain or example of?

As I said, the compiler is pretty good about optimizing out unused code. For example:

const bool modeA = true;

display_menu() {
  if(modeA) {
    // Mode A code
  }
  else {
    // Mode B code
  }
}

The compiler is going to see that there is absolutely no way the mode B code will be needed, so it will just optimize it out. This version of the code is much easier to read and debug than the nasty code that tends to result from using the preprocessor. There are times when the compiler won't be able to optimize things out so it really depends on the specific situation but it does generally do a very good job. Now if the value of modeA was dependent on runtime conditions (a pin state, for example), the compiler would have no way of knowing whether it can optimize that code out, so it won't.

Shouldn't my code in post #3 and your code in post #4 react the same (compiler doesn't include the always false portion of the if statement)?

You can help the compiler to optimize out unused functions in your sketch by making them static. This limits their scope to that translation unit. I also like that it enables helpful "defined but not used" warnings.

For example, the BareMinimum sketch:

void setup() {}
void loop() {}

compiles to:

Sketch uses 444 bytes (1%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.

Add this function without ever calling it:

void setup() {}
void loop() {}

void foo() {
  Serial.print("hello");
}

and you get:

Sketch uses 1332 bytes (4%) of program storage space. Maximum is 32256 bytes.
Global variables use 184 bytes (8%) of dynamic memory, leaving 1864 bytes for local variables. Maximum is 2048 bytes.

Make the unused function static and the problem is solved:

void setup() {}
void loop() {}

static void foo() {
  Serial.print("hello");
}
Sketch uses 444 bytes (1%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.