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.