VisualGDB Makefiles

When you create a Makefile-based project using VisualGDB, it generates a Makefile (and a separate .mak file for each configuration). That will be used to build the project.

Note that we do not recommend using Makefiles for new projects. For greater reliability, build speed, and a much better integration with Visual Studio GUI, please use MSBuild projects instead. If you would like to build the projects outside Visual Studio, please use the Advanced CMake Project Subsystem together with Ninja.

Typical Structure

A VisualGDB-generated Makefile normally has the following structure:

#VisualGDB: AutoSourceFiles
 
TARGETNAME := ProjectName.elf
TARGETTYPE := APP
CONFIG ?= DEBUG
 
<...>
 
include $(CONFIGURATION_FLAGS_FILE)
include $(ADDITIONAL_MAKE_FILES)
 
SOURCEFILES := <...>
 
#VisualGDB: FileSpecificTemplates
$(BINARYDIR)/%.o : %.cpp $(all_make_files) |$(BINARYDIR)
	$(CXX) $(CXXFLAGS) -c $< -o $@ $(CC_DEPENDENCY_FILE_SPECIFIER) $(@:.o=.dep)
 
<...>
 
#VisualGDB: GeneratedRules
 
$(BINARYDIR)/startup_stm32f407xx.o : $(BSP_ROOT)/STM32F4xxxx/StartupFiles/startup_stm32f407xx.c $(all_make_files) |$(BINARYDIR)
	$(CC) $(CFLAGS) -c $< -o $@ $(CC_DEPENDENCY_FILE_SPECIFIER) $(@:.o=.dep)
<...>

The SOURCEFILES line lists all source files used in the project. VisualGDB will automatically update this line when you add new files to the project. The “%.cpp” and “%.c” lines define generic rules to build .o files from the C/C++ source files.

The configuration-specific .mak file (e.g. debug.mak) contains various configuration-specific parameters:

PREPROCESSOR_MACROS := DEBUG=1
INCLUDE_DIRS := 
 
<...>
 
CFLAGS := -ggdb -ffunction-sections -O0
CXXFLAGS := -ggdb -ffunction-sections -fno-exceptions -fno-rtti -O0
 
<...>
 
ADDITIONAL_MAKE_FILES := stm32.mak
GENERATE_BIN_FILE := 1
GENERATE_IHEX_FILE := 0

The following table summarizes all variables defined in flags.mak:

Variable Meaning Example
CC Location of the GCC compiler c:/gcc/gcc.exe
CXX Location of the C++ compiler c:/gcc/g++.exe
LD Location of the linker (typically GCC/G++ is used for linking) c:/gcc/g++.exe
COMMON_MACROS Preprocessor definitions to be defined in all configurations. _WIN32 _CONSOLE
DEBUG_MACROS Preprocessor definitions to be defined in DEBUG configuration only _DEBUG DEBUG
RELEASE_MACROS Preprocessor definitions to be defined in RELEASE configuration only _NDEBUG _RELEASE
MCUFLAGS Additional flags specifying microcontroller type -mmcu=msp430f2013
INCLUDE_DIRS Additional include directories relative to the project location ../lib1 ../lib2
LIBRARY_DIRS Additional library directories ../lib1/bin ../lib2/bin
LIBRARY_NAMES Additional libraries to link with (no “lib” prefix) 1 2
CFLAGS Additional GCC flags for all configurations -ggdb -ffunction-sections
DEBUG_CFLAGS Additional GCC flags for DEBUG configuration -O0
RELEASE_CFLAGS Additional GCC flags for RELEASE configuration -O3
CXXFLAGS Additional C++ flags for all configurations -fno-exceptions
DEBUG_CXXFLAGS Additional C++ flags for DEBUG configuration
RELEASE_CXXFLAGS Additional C++ flags for RELEASE configuration
MACOS_FRAMEWORKS Additional framework names (MacOS only) iokit
LDFLAGS Additional flags to the linker (with -Wl, prefix when GCC is used for linking)
DEBUG_LDFLAGS Additional linker flags for DEBUG configuration
RELEASE_LDFLAGS Additional linker flags for RELEASE configuration
START_GROUP Either an empty string, or “-Wl,–start-group”
END_GROUP Either an empty string, or “-Wl,–end-group”

The START_GROUP/END_GROUP flags surround the library/object file list and allow specifying them in an arbitrary order (otherwise the object file list has to be sorted manually). You can set those variables to empty strings if your linker (e.g. MacOS linker) does not require those flags.

Makefile Lifecycle

Once the Makefile is created, VisualGDB will not regenerate the Makefile anymore. Instead, when you build the project, it will edit the following statements each time you build the project:

  • SOURCEFILES will be set to the list of all source files in the .vcxproj file.
  • EXTERNAL_LIBS will be set to libraries produced by referenced projects.
  • All rules below the #VisualGDB: GeneratedRules line will be regenerated based on the #VisualGDB: GeneratedRules templates.

The synchronization process is very straight-forward, e.g. the following contents in the .vcxproj file:

<ItemGroup>
  <ClCompile Include="EmbeddedProject5.cpp" />
  <ClCompile Include="system_stm32f4xx.c" />
  <ClCompile Include="$(BSP_ROOT)\STM32F4xxxx\StartupFiles\startup_stm32f407xx.c" />
</ItemGroup>

will get translated into this:

SOURCEFILES := EmbeddedProject5.cpp system_stm32f4xx.c $(BSP_ROOT)/STM32F4xxxx/StartupFiles/startup_stm32f407xx.c

This allows preserving any custom Make targets or rules added to the Makefile and generally allows using VisualGDB with any Makefile structure, as long as it has has the #VisualGDB: AutoSourceFiles tag and uses SOURCEFILES and EXTERNAL_LIBS variables. Note that this is extremely limited compared to Advanced CMake Project Subsystem that supports multiple targets per project and can render the exact CMake project layout in Solution Explorer.

You can also disable the automatic updating of Makefiles by completely removing the #VisualGDB: AutoSourceFiles line from the Makefile. This will keep your manual edits to SOURCEFILES and EXTERNAL_LIBS regardless of the files referenced in the .vxcproj file.

You can edit various common properties (e.g. preprocessor macros) via VisualGDB Project Properties -> Makefile Settings:Any changes made via the VisualGDB GUI will be automatically saved to both Makefile and the VC++-level IntelliSense settings.

Embedded Makefile Projects

For Embedded Makefile projects, VisualGDB generates an extra .mak file (e.g. stm32.mak) containing device-specific flags:

CC := $(TOOLCHAIN_ROOT)/bin/arm-none-eabi-gcc.exe
CXX := $(TOOLCHAIN_ROOT)/bin/arm-none-eabi-g++.exe
 
<...>
 
PREPROCESSOR_MACROS += ARM_MATH_CM4 flash_layout STM32F407VG STM32F407xx USE_HAL_DRIVER 
INCLUDE_DIRS += . $(BSP_ROOT)/STM32F4xxxx/STM32F4xx_HAL_Driver/Inc <...>

This file will get included for all configurations of the project and will get regenerated each time you change the MCU-specific settings, or click the “Regenerate MCU files” button in VisualGDB Project Properties:

Building Outside Visual Studio

The Makefile projects can be built independently from Visual Studio (e.g. on a continuous integration server). You can dump the build command used by VisualGDB into a batch file via the VisualGDB Build window and then run it manually:

IntelliSense

Internally, Makefile-based projects are implemented as VC++ NMake-based projects. Their IntelliSense settings (e.g. include directories and preprocessor macros) are stored in the NMake settings:Note that the preprocessor macros are stored in the gcc_<Configuration>.h files that are referenced as forced includes.
When you use the VisualGDB GUI to edit the Makefile settings, it updates the NMake settings based on them, however modifying the Makefiles manually will not have the same effect. For better IntelliSense integration, please consider using Advanced CMake projects, or MSBuild projects.

Troubleshooting

GNU Make projects will always display the full GCC/linker command lines during build:You can use them to see the exact parameters passed to the compiler, and troubleshoot the build problems.

Limitations

Makefile-based projects are relatively limited compared to other project types. The list below shows their main limitations:

  • Makefile projects do not automatically create response files (.rsp). Hence some embedded BSPs (e.g. Nordic nRF5x) could exceed the Windows command line length limit and fail the build.
  • Makefile projects store the list of source files redundantly. The list shown in Solution Explorer is stored in the .vcxproj file, and the list used for the actual build is shown stored in the Makefile itself (SOURCEFILES). Although VisualGDB synchronizes them during build, it may not work in some advanced cases (e.g. MSBuild property sheets or dynamic MSBuild rules).
  • Makefile projects store IntelliSense settings (include directories and preprocessor macros) separately from the actual build settings. VisualGDB automatically updates IntelliSense settings when using VisualGDB Project Properties, however editing the Makefile manually will keep the old IntelliSense settings.
  • Editing the main Makefile, or any of the .mak files will invalidate all object files, and not only affected ones (i.e. next build will be equivalent to a full rebuild).
  • Makefile-based projects do not support precompiled headers and cannot have different build settings (e.g. preprocessor macros) for different source files.

If you are planning to use Makefiles for a new project, please consider using MSBuild or Advanced CMake instead.