Use Custom Toolchain (ARMCC instead of GCC)

-lc comes from "c" being inside env["LIBS"], aka the target libraries to link against (aka the libc standard C library of GCC). Remove / replace as needed.

1 Like

Okay, I have seen LIBS before, in Makefile. Thanks for letting me know about it!

These two error logs remain:

Fatal error: C3900U: Unrecognized option '-l,--start-group.
Fatal error: C3900U: Unrecognized option '-l,--end-group.

It seems these options are GNU linker relevant. But I’m pretty sure I have overwritten all possible linker-relevant flags with empty array. Just in case, I used e.Replace() with LINKFLAGS and LDFLAGS, where I tried filtering out these two options but without success.

Any other idea that might come handy in this case?

That’s tricky.

Somehow env.GetCompilerType() has to be overwritten there…

Huh…

1 Like

@maxgerhardt Is there any documentation where I could check which flags can be accessed inside env? I’m pretty sure there might be more flags I’m not overwriting yet…

EDIT: Oh, you beat me hehe. I will try inspecting previous answer

Can you add someting like

env["GetCompilerType"] = lambda e: return "ARMCC"
# or
env.GetCompilerType = lambda e: return "ARMCC"

to the script?

1 Like

In any case, you will want to open an issue at

to get ARMCC support tracked.

I just used e.Replace(_LIBFLAGS = []) and these two options aren’t included into build process anymore.

What exactly do you mean I should do there? What should I ask about ARMCC?

Well if we want to see PlatformIO officially integrate the ARMCC as possible compiler option is should get tracked in an issue there.

1 Like

@maxgerhardt One more thing. How skillful are you with compiler/linker flags? I’m getting an error, where linker cannot find .o files. It’s true that there are no .o files under .pio/build/armcc_compiler/src/Drivers/STM32F1xx_HAL_Driver/Src/. How can I generate .o files in this folder during compilation? How can I make linker know there are .o files in this folder?

I tried the following but ˙.o` files aren’t generated anywhere in the workspace folder.

Maybe there I can overwrite default build path. Because I’m clearly adding armcc_compiler string into the build path and therefore the default build path won’t be useful anymore, I think.

@maxgerhardt In case any idea comes to mind, what else I could do to fully integrate a specific toolchain into PIO… From data I have currently collected, the only thing that keeps me from using MDK-ARM toolchain is because linker isn’t able to to create .elf file because there are no .o output files generated under the default .pio folder.

I have tried using the pio run -t envdump command inside PIO CLI. I checked multiple build paths and found that all path are set to correct folders. Except that no output files are generated during build (all except the startup file will have its output file generated, which is a bit strange).

What’s the full current state of the script? Did you remove an -o flags?

I have rebuild script a little in such way that I append additional options to specific build flags. Then I filter out GCC options that cause errors in ARMCC from all available flag variables. Just a tiny change but doesn’t really change much. Here is the script:

import os
from SCons.Script import Import

Import("env")
Import("projenv")
platform = env.PioPlatform()

# Filter out excluded build options from flag variable
def FilterFlags(flagVar, filteredOptions):
    filteredFlags = [flag for flag in flagVar if flag not in filteredOptions]
    return filteredFlags

# Define list of flag variables for option exclude
filteredBuildFlags = ["CPPFLAGS", "CFLAGS", "CCFLAGS", "CXXFLAGS", "ASFLAGS", "LINKFLAGS", "_LIBFLAGS"]

# Define default flags to exclude from all flag variables
filteredOptions = [
    "-Wall",
    "-ffunction-sections",
    "-fdata-sections",
    "-mcpu=cortex-m3",
    "-Os",
    "nostdlib",
    "-T",
    "-l",
    "-mthumb",
    "-Wl,--gc-sections,--relax",
    "-specs=nano.specs",
    "-l,--gc-sections,--relax",
    # Add more flags to exclude as needed
]

# Use ARMCC for framework
for e in [env, projenv, DefaultEnvironment()]:

    e.Replace(
        AR = "armar",
        AS = "armasm",
        CC = "armcc",
        CXX = "armcc",
        LD = "armlink",
        GDB = "arm-none-eabi-gdb",  # to retain compatibility
        OBJCOPY = "fromelf",
        SIZE = "armsize"
    )

    # Remove GCC "-Wl" options completely
    e.Replace(_LIBFLAGS = [])

    e.Append(CPPFLAGS = [
        "-DUSE_HAL_DRIVER",
        "-DSTM32F103xE",
        "-DUSER_VECT_TAB_ADDRESS",
        # Add more flags to exclude as needed
    ])

    e.Append(CCFLAGS = [
        "--c99",
        "-c",
        "--cpu=Cortex-M3",
        "-g",
        "-O0",
        "-M",
        "--thumb",
        "--apcs=interwork",
        #"-o C:\\Users\\gacnik\\Desktop\\PVC2-SES-PlatformIO\\PVC2 test\\.pio\\build\\genericSTM32F103VC\\src\\Drivers\\STM32F1xx_HAL_Driver\\Src"
        # Add more flags to exclude as needed
    ])

    e.Append(ASFLAGS = [
        "--cpu=Cortex-M3",
        "-g",
        "--apcs=interwork",
        "-M",
        # Add more flags to exclude as needed
    ])

    e.Append(LINKFLAGS = [
        "--cpu=Cortex-M3",
        # "-o C:\\Users\\gacnik\\Desktop\\PVC2-SES-PlatformIO\\PVC2 test\\.pio\\build\\genericSTM32F103VC\\src\\Drivers\\STM32F1xx_HAL_Driver\\Src"
        # Add more flags to exclude as needed
    ])

    # Filter out excluded flags from all flag variables
    for flag in filteredBuildFlags:
        existingFlags = e.get(flag, [])
        filteredFlags = FilterFlags(existingFlags, filteredOptions)
        e.Replace(**{flag: filteredFlags})

    # Add to path.. somehow PlatformIO does not do this although it's the toolchain package.
    pkg = platform.get_package("toolchain-armcc")
    e.PrependENVPath(
        "PATH",
        os.path.join(pkg.path, "bin")
        if os.path.isdir(os.path.join(pkg.path, "bin"))
        else pkg.path,
    )

One thing I noticed about _LIBFLAGS is that PIO provides these options for linker:

"-Wl,--start-group", "${_stripixes(LINKPREFIX, LIBS, LINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}", "-Wl,--end-group"

The _stripixes appears at the end of env object (check the file below). So my guess is that this part adds some additional simbols to the linker? The -Wl option isn’t supported by ARM linker and therefore, since I couldn’t find appropriate replacement I delete all _LIBFLAGS options. (Actually what I found is --scatter=file for ARM and tried it out, e.g. --scatted=LINKPREFIX, but it doesn’t work - gives an error)

After this point only the issue of “output files not being generated” remains. I think there is some trick with PIO’s makefile. Something might get overwritten or deleted so that either output files aren’t generated or are subsequently deleted. If I try to build one file manually from project workspace inside PIO CLI, file is compiled and output file is generated. I used the following minimalistic build setup:

C:\Keil_v5\ARM\ARMCC\bin\armcc.exe --c99 -O0 --thumb --apcs=interwork -c --cpu=Cortex-M3 -g -DUSE_HAL_DRIVER -DSTM32F103xE -DUSER_VECT_TAB_ADDRESS -Isrc/Core/Inc -Isrc/Drivers/STM32F1xx_HAL_Driver/Inc -Isrc/Drivers/CMSIS/Device/ST/STM32F1xx/Include -Isrc/Drivers/CMSIS/Include -Isrc/Drivers/STM32F1xx_HAL_Driver/ src/Core/Src/main.c

Just in case you want to check the state of flags in env object after building this project using the upper script, you can check it here.

Okay now that one doesn’t have any -o at all, that’s bad. Can you add back a "-o", "$TARGET" to the CCFLAGS and LINKFLAGS?

I can. However these build options are the ones I used in manual build of main.c only. And it built the main.o for a change. Can I use something like -o $TARGET$ when building from command line?

After adding "-o", "$TARGET" to CCFLAGS and LINKFLAGS, I still get the same error (no output files exist).

Okay let me just cut this discussion short by downloading Keil MDK ARM myself and seeing if I can get it to work…

1 Like

Okay, good to hear. One more thing. I compared state of env object text files side by side of the case where I build with MDK ARM (doesn’t generate output files under .pio) and where I build with ARM GCC (generates output files under .pio). The only meaningfull difference I could find is the content of _LIBFLAGS (now that I delete all options for MDK ARM since -Wl option is not available for it).

Hm actually I’m starting to get allread different things here. There is no “armcc.exe” but there’s armclang.exe.

I’ve downloaded the newest

MDK-ARM
MDK-ARM Version 5.38a

And the IDE says

grafik

Are you on the old version 5 or something? The thing that says “LEGACY”?

Yeah and I can’t download the Arm Compiler 5 version (which may even cost money??) because account confirmation is manual! How great.

grafik

Yeah sorry, I don’t know exactly. I recently started working with MDK ARM and yes, as you have seen, this toolchain is mostly of any use if you buy licence for it (like how they do it where I work). Maybe I can send you somewhere the files I have (and use for building my project in PIO) from MDK ARM. Not sure if this alone would be enough for you to build a project just like me. However we can try. I think I’m not using licenced version therefore someone like you should be able to build a project using ARMCC if you would have the same toolchain files as I do?

This is the version I’m using:

2023-05-23 13_07_26-About µVision

Please note that this discussion could be avoided alltogether if I could use already supported arm-gcc-none-eabi toolchain. However, due to certain specifics I’m not allowed to use it for what I’m currently working on.

I checked with my senior coworker and found out that I have a licenced version as well that cannot be re-distributed.

Strange that you have only ARMCLANG. I have both but then again I don’t have the standard free version of it.

Maybe you can check, if you have the inspiration to do so, building an application with ARMCLANG? Most likely you could could use the same .ini and python script setup as I am using, and would also have different flag options available. However if only flag options would be different between ARMCLANG and ARMCC then you would (most probably) get the same behavior as I get (no output files generated).