PlatformIO Community

Pass env variables at build time


I am working on an open source project which however connects to some private cloud service.
I want the DSN string for the service (mqtt) to be “added” at build time, so my code on github doesn’t expose any credentials. Any idea how to achieve this?

Also, I see that even when working on arduino, I am not handling a .ino file anymore but a .cpp one. Can I use regular cpp syntax in platformio or am I still constrained to the C-like arduino language?

Thank you!



Thanks! Actually I found those pages before but how do I actually put those in my code? Those examples only have the .ini file…



platform = ...
build_flags = -D SOME_ENV_VAR=${sysenv.ENV_VAR}


Thanks! Not sure tho, I have added those build flags but then in my code

    client.begin(MQTT_HOSTNAME, net);

I get an error at the comma in MQTT_HOSTNAME, with message “expression expected”.
You can see more here:


Actually now I get this from the compiler:

:0:15: error: ‘m23’ was not declared in this scope
src/main.cpp:60:18: note: in expansion of macro ‘MQTT_HOSTNAME’
client.begin(MQTT_HOSTNAME, net);

Where m23 is part of my MQTT connection string (


@valeros could you help here?


Hi @lucavallin! How did you set MQTT_HOSTNAME? I couldn’t reproduce the issue on Windows.


Hi @valeros, with some debugging I see that the env variables are set correctly.
However, the same firmware will connect to mqtt when compiled and uploaded via the Arduino IDE, and not connect via Platformio.

You can see the code here:

EDIT: if I define the vars as string in the code itself, everything will work. However via serial monitor I see that they’re defined also via env. Maybe a different type?


Solved! MQTT port was being passed as string instead of int. Sorry, I’m new to debugging embedded systems.

Thanks your for help!


This works but I wonder if it is possible to have a default value, when the environment variable is not set. Something like this:

build_flags = -D SOME_ENV_VAR=${sysenv.ENV_VAR:-someDefaultValue}


You can do that with


Thanks for quick response. Thats a solution alright, but it can easily create a lot of boilerplate code. I think it would be good to add this kind of functionality in PIO since it can be found in other modern frameworks as well.


In this case you can use Dynamic build flags.

build_flags = !python -c "import os; print('-DSOME_ENV_VAR=%s' % os.getenv('ENV_VAR', 'someDefaultValue'))"