Best way to flash same code with different configs?

I need to flash code revisions to 7 devices, only differing in the config of IP, hostname and MQTT channel.
I want to keep the configuration as atomic as possible to avoid inconsistencies.
Is it somehow possible to access the upload IP as a precompiler definition?

On the other hand, I considered setting the configuration choose define in a header file and determine the upload IP via the /etc/hosts, because that would avoid recompiling the whole project due to change of platformio.ini.

Anything I have missed?

What about using preprocessor defines?

If you do something like this (snipped from a project I’m working on):

[env]
platform = atmelavr
framework = arduino
board = uno
lib_deps = 
    433@1.3.3  ; RF24

[env:Sensor 1]
build_flags = -D TX_PIPE=1 -D RX_PIPE=0

[env:Sensor 2]
build_flags = -D TX_PIPE=2 -D RX_PIPE=0

[env:Sensor 3]
build_flags = -D TX_PIPE=3 -D RX_PIPE=0

then when you build Sensor 1 TX_PIPE is defined as 1, Sensor 2 as 2, Sensor 3 as 3, etc. RX_PIPE is always zero, but it can also be changed, etc, etc.

i.e. the actual code using TX_PIPE is

radio.openWritingPipe(pipes[TX_PIPE]);

Well, that is kind of what I wanted to do, however I am flashing OTA, so I need to flash to different IPs. It would have been great if I could have decided on the config on the basis of that IP, so I cannot accidentally flash the wrong config to the wrong IP.

Actually, I have taken anoter way now: I put a hostname into my /etc/hosts now, which I change for every flash.
I select the config with a prec define in the code. This has the danger for wrong flashes in theory (but I have to put my devices into flash mode individually anyway), but since the platformio.ini remains untouched, only very few cpps are recompiled.

Hm… I take it the devices have been allocated static IPs or by MAC?

In that case, you could specify the IP for each env with something like upload_port = 192.168.0.1, naturally with the right IP for that env, in addition to the build_flags…