Replacing with build_flags that contain spaces

I am using build_flags and build_unflags to replace settings in my platformio.ini configurations like this:

[env:due]
platform = atmelsam
board = due
framework = arduino
build_flags = -std=gnu++1z --param max-inline-insns-single=1000
build_unflags = -std=gnu++11 --param max-inline-insns-single=500

It works very well for regular arguments (e.g. -std=gnu++11-std=gnu++1z).
However, I don’t get it to work for flag pairs with spaces (e.g. --param max-inline-insns-single=500--param max-inline-insns-single=1000)

Here is my example ouput:

$ pio run -v -e due
Processing due (platform: atmelsam; board: due; framework: arduino; build_type: debug; build_flags: -std=gnu++1z --param max-inline-insns-single=1000; build_unflags: -std=gnu++11 –param max-inline-insns-single=500)
[…]
arm-none-eabi-g++ -o .pio/build/due/src/main.cpp.o -c -std=gnu++1z -fno-rtti -fno-exceptions -fno-threadsafe-statics -ffunction-sections -fdata-sections -Wall -mcpu=cortex-m3 -mthumb -nostdlib –param max-inline-insns-single=500 -Og -g2 […]

I tried some typical wrapping schemes for pair parameters like '--param name=value' and \'--param name=value\' and escaping the space character like "--param\ name=value", but so far nothing helped.

Using quotes in build_unflags and no quotes in build_flags causes no error, but the old one isn’t filtered out:

build_flags = -std=gnu++1z --param max-inline-insns-single=1000
build_unflags = -std=gnu++11 "--param max-inline-insns-single=500"

Not sure this is a really good solution, but for the moment I can use a custom Python script:

extra_build_unflags = ["--param max-inline-insns-single=500"]

def filterTuple(flags, tuple):
    matched = 0
    for index, value in enumerate(flags):
        if value == tuple[matched]:
            matched += 1
        else:
            matched = 0
        if matched == len(tuple):
            before = max(index - matched, 0)
            after = min(index + 1, len(flags) - 1)
            return flags[:before] + filterTuple(flags[after:], tuple)
    return flags # No (further) matches

Import("env")
Import("projenv")

for e in [env, projenv]:
    for group in ["CCFLAGS", "ASFLAGS", "LINKFLAGS"]:
        filtered = e[group]
        for unflags in extra_build_unflags:
            filtered = filterTuple(filtered, unflags.split(" "))
        print(f"e[${group}] =", filtered) # for debugging
        e.Replace(group = filtered)

Is there a way to access the the build_unflags from the platformio.ini configuration(s) from Python? Then it could be much more generic.

What if you quote the flag? build_unflags = "-std=gnu++11 --param max-inline-insns-single=500". If this does not work, it would be a good feature to have it, so please file an issue in GitHub - platformio/platformio-core: A professional collaborative platform for embedded development.

The only other option would be directly changing / filtering the build flags (env["CCFLAGS"]) via an advanced script as e.g. in here. As there might be multiple --param flags, you will want to write a logic that first stores all flags, then finds the index of the max-inline-.. flag, and then deletes this element and the element before that (--param).

@maxgerhardt Thanks for your feedback.

What if you quote the flag? build_unflags = "-std=gnu++11 --param max-inline-insns-single=500"

Yes, quoting the whole block doesn’t do the trick either. I will file a feature request then. Not sure if it has high priority as my above filterTuple() is doing fine so far (will mention that and this thread as well).

As there might be multiple --param flags, you will want to […]

IIUC every max-inline-.. flag would have its own --param prefix. So the proposed filterTuple() should do right? Didn’t test this case yet, but will do.

The only missing piece would be how to access the build_unflags settings of my platformio.ini from Python?