microsoft / vscode-makefile-tools

MAKE integration in Visual Studio Code
Other
184 stars 55 forks source link

makefile tools don't detect compiler #499

Closed srobertjames closed 6 months ago

srobertjames commented 10 months ago

My Makefile is set to use ARM gcc:

firmware.elf: $(SOURCES) link.ld
    arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@

Yet makefile tools can't detect this, and so the project tries to use Clang for intellisense. It builds fine, and invokes the make (not clang) - but some of the red squiggles in the C code are false positives, due to using clang and not arm-none-eabi-hcc.

Interestingly, it must be reading the Makefile, because it finds the includes properly:

CFLAGS  ?=  ...
            -I. -I$(CMSIS_DIR)/cmsis_core/CMSIS/Core/Include -I$(CMSIS_DIR)/cmsis_f4/Include \

Related points:

  1. For launch, I have a make flash - but it won't let me select that in the configurator (perhaps because it wants a file path, which isn't appropriate for embedded - in this case, launch needs to flash a physical device)
  2. If I have other tasks defined in the Makefile, which are standalone and useful - how can I tell Makefile tools to recognize them and let me invoke them?

Thank you for the great extension.

gcampbell-msft commented 10 months ago

@srobertjames Thanks for posting this issue! Could you provide us with some debug information?

To do this, recreate your scenario after ensuring that the makefile.loggingLevel is set to Debug and you've set a path for makefile.extensionLog. This should output information to this log that may help us investigate this.

For your related points, could you give some additional information regarding how they are defined in your Makefile and how you're attempting to use them with the extension? Are they defined as targets in your Makefile, etc.?

If you could provide your project for us to attempt to repro this would greatly help us investigate. Thanks!

srobertjames commented 9 months ago

I'm actually not able to reproduce this! Is it possible it had something to do with vscode caching? Intellisense seemed to be cached, because initially it seemed to use the LLVM header files, but, after getting back and coming an hour later, it switched to gcc's.

As said, I'm cross compiling for an embedded platform. So, I commonly do the following:

  1. Build via make. This is now working.
  2. Load the firmware on to the device via make flash. This is the only way to "run" it - it doesn't run on a PC. The Makefile is below.
  3. Attach my debugger to it, via make gdb.
  4. Browse the assembly, via make disasm (which produces an assembly file), make bdisasm (which cats the file to my console), or make r2 (which loads the binary in radare2 disassembler, for when things are really weird).

Of course, these tasks could be done manually via commands fairly easy - but it's likely then to be not using the latest binary, or not be in sync with the source - and debugging the old code is a surefire way to fail.

When using vscode, we could improve #4 like this: make disasm opens the resulting firmware.S in vscode. make r2 launches radare2 in a notebook within vscode!!! (See https://github.com/guedou/jupyter-radare2) These would be very nice benefits to using vscode.

Here are the relevant parts of the Makefile:

CC = arm-none-eabi-gcc
CFLAGS  ?=  -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion -Wformat-truncation -Wconversion \
            -Wno-attributes \
            -DSTM32F446RE -DSTM32F446XX -DSTM32F4 -DCPU_HZ='(16 * 1000 * 1000)' \
            -g3 -Os -fno-common -ffunction-sections -fdata-sections -fanalyzer\
            -I. -I./libopencm3/include \
            -MD \
            -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 $(EXTRA_CFLAGS)
            # On more recent compilers, I'd add -Wenum-int-mismatch
LDFLAGS ?= -Tlink.ld -Wl,--gc-sections -Wl,-Map=firmware.map -Wl,--cref \
            --static -nostartfiles -L./libopencm3/lib -lopencm3_stm32f4 \
            -Wl,--fatal-warnings
SOURCES = main.c ...

build: firmware.bin

firmware.elf: $(SOURCES) link.ld
    $(CC) $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@

firmware.bin: firmware.elf
    arm-none-eabi-objcopy -O binary $< $@

flash: firmware.bin
    st-flash --reset write $< 0x8000000

gdb: firmware.elf flash
    (st-util &) && sleep 1 && gdb-multiarch -q -ex "target remote :4242" firmware.elf

disasm: firmware.elf
    arm-none-eabi-objdump -dSrC firmware.elf > firmware.S

bdisasm: disasm
    less firmware.S

r2: firmware.bin
    r2 -a arm -b 16 -e asm.cpu=cortex -m 0x08000000 firmware.bin

Note that originally the Makefile didn't have a CC = ... section, but just specified the compiler by name on each line. I added that line in an attempt to help vscode Makefile tools figure out the compiler.

srobertjames commented 9 months ago

I was able to replicate this on a new project. vscode complained about not finding my includes. Deleting the "configurationProvider": "ms-vscode.makefile-tools" from the c_cpp_properties.json solved it.

I did this repeatedly: Every time I added the "configurationProvider": "ms-vscode.makefile-tools", I get the red squiggle and include error; every time I delete it, the squiggle goes away and the project goes green.

I set up makefile extension logging to debug but can't find any file at the path I gave it: /tmp/makefile_extension.log. When I tried to build via Makefile Extension, I get error Command 'Makefile: Build clean the current target' resulted in an error. A system error occurred (EISDIR: illegal operations on a directory, open '/tmp/').

(The error message isn't copyable, so I had to manually type it in here.)

The /tmp/ dir exists and is read/writeable, of course.

I tried changing the log to a different path, but still got the same exact error - it seems it didn't recognize the path has changed. I did this both via the GUI and via the JSON file, saving the JSON file and trying to rebuild, but still get the identical error.

I deleted the lines from the JSON file but still get the error.

At this point, I gave up.

srobertjames commented 9 months ago

@gcampbell-msft Do you need any more information?

gcampbell-msft commented 9 months ago

@srobertjames You mentioned that you were able to replicate this on a new project, is there any way that you can share this project so that we can have an easier time reproducing the issue?

Thanks!

srobertjames commented 9 months ago

Can it be shared privately? (If so, send instructions). Or does it need to be public?

gcampbell-msft commented 9 months ago

@srobertjames Yes! We created an external email that you can correspond with.

Please email using this address: makefile-external@microsoft.com

Thanks!

andreeis commented 9 months ago

@srobertjames, we are sorry that you encountered these issues. Let me address all bullets.

First, were you able to send an email? I didn't see it.

/tmp/ folder: I don't reproduce error when building nor when configuring related to /tmp/ folder not being accessible. Also, when I change the path, for me it takes effect immediately. You are using the 0.7 release, right?

Clang IntelliSense: we have some logic and IFs/ELSEs where there could be some bugs but in general if the "make --dry-run" command outputs any gcc compiler (any prefix) we detect it and we don't confuse it with clang. If building from terminal (outside of our extension) was using gcc even before defining the CC macro, then our extension doesn't need the CC macro either. We parse what "make --dry-run" (plus other few other switches) produce.

I understand that you gave up and couldn't produce a log. But, if you can go one more time to that project in the VSCode Makefile Tools context, you can also just look in the "output channel" (no tmp log... we recommend the file for easier sharing and in case it gets big), copy paste the txt in the output channel for Makefile Tools. Bottom area of VSCode, "Output" tab, Combo-box UI control to select which extension to see output channel for. The setting "makefile.loggingLevel": "Debug" is still needed.

Also, can help if we see the dryrun.log. In the output channel I mentioned above, you can see where the dryrun.log is saved, search for "dryrun.log". It will take you to a path you set (if you defined "makefile.extensionOutputFolder") or to a default somewhere in the user path. Share with us that dryrun.log. It is the output we parse. Sometimes, for some projects, it is too cryptic and the developers using our extension need to make their builds more verbose.

andreeis commented 9 months ago

The other user scenarios you mention are super interesting and I'm going to create work items for the future to better support embedded projects.

  1. Useful tasks. Currently, anything that is defined as a target in the makefile, can be selected as build target in the Makefile Tools left UI panel, then executed via "build". But indeed then you'd have to select back your "all" or what you use for building so not a convenient back and forth. We currently have work item https://github.com/microsoft/vscode-makefile-tools/issues/128 for being able to define more than one target in a list and build all that are selected. I'm thinking we can add to that a scenario (or open a new work item) about making available buttons for a selection of useful tasks that are all visible at once but can be executed one at a time with a click.
  2. Very cool to add a disasm action on a launch target and open the result assembly text in the editor.
  3. Another way to "artificially" launch "make flash" (other than via setting a build target and clicking build) is to edit manually the setting "makefile.launchConfigurations", add an entry with binary "make" and "flash" as binaryArgs (and any of its real arguments following still as binaryArgs). For now, the mainstream scenario is that the binary is an executable that is build by the makefile and args are its own arguments but to be able to launch in your case with the support available now, that setting can be used in various non standard ways to incorporate the flash functionality. Of course you will not be able to debug since it will try to debug "make". Hacky, but you can also try "binaryPath": "make flash" and continue with the real arguments via "binaryArgs". But all this manually in settings.json, not via the UI which handles only the mainstream scenario.
  4. I am not very familiar with debugging in the embedded area but I see this interesting demo. Are you using launch.json like there? If you do, then the Makefile Tools extension is providing a few commands that are useful and help with keeping targets in sync, debugging only freshly built code, not confusing between various different targets... This doc explains these commands that you can use.
bignand commented 8 months ago

Dear Fiends, I've found a similar issues and where the parser fail. This issues is releated also to this case. When using gcc for arm. The parser need to look to the core architecture. it looks for -march compile switch. So @srobertjames have to add -march=armv7-m (the correct one for his μC should -march=armv7e-m+fp) . But I found that is not correcly working due to small error, in my opinion.

the code in parser.ts is for function getTargetArchitecture(compilerArgs: string): util.TargetArchitecture {

when check for arm version7 or earlier it looks at the sixth char // Check if ARM version is 7 or earlier. const verStr: string | undefined = arch?.substr(5, 1);

but it has to look at the fifth char: // Check if ARM version is 7 or earlier. const verStr: string | undefined = arch?.substr(4, 1);

Please let me know If I'm not wrong. Best Regards Ferdinando

andreeis commented 8 months ago

@bignand , thank you for the pointer and analysis. We'll have a closer look and fix. Hopefully it's the same scenario that @srobertjames is seeing so that it fixes that problem as well.

srobertjames commented 8 months ago

Thank you for the great attention to this! It's great to see how attentive the vscode team.

I've actually been tasked with something else now, and so haven't been able to participate further currently. But I am tracking this and looking forward.

gcampbell-msft commented 7 months ago

@bignand I believe you are right! I did some quick testing, and you're right, we're scanning the wrong character. We will fix this, and I believe with this fix and the suggestion for specifying the march, this should also fix @srobertjames's issue.

Thanks!

github-actions[bot] commented 6 months ago

:tada: This issue has now been fixed and is now available in the latest release! :tada: