Compile-time definition for serial port?

So, I've been all over the Googleverse trying to find a solution to this one. I have created a library of comms for my client's products, but I need to compile the library with a different definition for the serial port depending on what product is being built. Some of this junk runs on Due, some on Mega, some on Pro Mini. On the Due or Mega the control comms may run on Serial1, but on the Pro Mini there is only Serial.

How can I define the serial port used by the product at compile time? I want to stay within the IDE and not have to drop down into a regular CLI build environment with Make and everything else. The idea here is to leave the development in a state that any Arduino-capable clown can pick it up and run with it.

The Arduino build system defines a macro to indicate which board you are compiling for, so you can do this:

#if defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAM_DUE)
#define SERIAL_INTERFACE Serial1
#else
#define SERIAL_INTERFACE Serial
#endif

Then use the SERIAL_INTERFACE macro in your code like this:

SERIAL_INTERFACE.begin(9600);

Yeah, I did that already. However, I would still like the option of choosing a port at compile time, like a CLI option: -DUseSerial2 or -DUseSerial or maybe -DComms=Serial1. Something like that. Otherwise, I have fixed assignments based on the underlying hardware, hardly a flexible solution.

// Uncomment this line to use Serial for communication
#define SERIAL_INTERFACE Serial
// Uncomment this line to use Serial1 for communication
//#define SERIAL_INTERFACE Serial1

Yeah, see, that's editing the source code for selecting a particular value. I would like to select a value without changing the source itself, the way a symbol is used in a Makefile. I am hoping there is a canon way to do this within the environment of the Arduino IDE.

I use Pointer Power:

sketch:

HardwareSerial *myserial = &Serial;
extern void tryaprint();

void setup() {
  myserial->begin(9600);
}

void loop() {
  tryaprint();
}

Library:

#include <Arduino.h>

extern HardwareSerial  *myserial;

void tryaprint() {
  myserial->print("testing 1 2 3 \n");
}

It may require some additional finesse, since some boards have “HardwareSerial”, some have “UartClass”, some have “Uart”, etc :frowning: And then there are the USBSerial ports to deal with.
I think you can use Stream* instead, if you separate out the hardware-specific initialization, and only need things at the stream level.

MartySchrader:
I am hoping there is a canon way to do this within the environment of the Arduino IDE.

The way to do it would be by adding custom Tools menus to every board definition that your code would be used with:
https://arduino.github.io/arduino-cli/platform-specification/#custom-board-options
The menu would configure the build.extra_flags properties to define a macro via the -D flag. Without knowing exactly the use case, I would say this is very likely not going to be a good idea.

westfw:
I think you can use Stream* instead, if you separate out the hardware-specific initialization, and only need things at the stream level.

Yeah, that's the rub, ain't it? Using the Serial type I can initialize without knowing which specific port is being used for debug. I even wanted to potentially swap ports between debug and application comms. Nonetheless, I think pert's idea of using the board.local.txt definitions may have some merit. I'll be looking into that.

Thanks everybody.

If nothing else, it's fun to learn how the Arduino IDE offers boards platform authors the ability to make some nice customizations to the UI and play around with it a bit.

If you are going to go this route, I think using boards.local.txt is a good approach, since it allows you to modify a boards platform without editing any of its files. That means you can save your boards.local.txt files somewhere safe, then just drop the file in the platform's installation folder to replace your modifications after they are lost each time you update the platform to a new version.