Linking files in STM32CubeIDE means telling the compiler where your source code, headers, and libraries live so it can find them during the build process

When you create a new STM32 project in STM32CubeIDE, the IDE automatically links the core files it generates for you. But when you add your own code files, move files between folders, or use external libraries, you need to tell the IDE where those files are and how to include them. This happens through two main mechanisms: the project structure itself and the build configuration settings.

The most common reason linking fails is that a file exists on your computer but the IDE doesn't know to look for it. You might see errors like "undefined reference to" or "cannot find -l[libraryname]". These errors mean the compiler found the code that calls a function, but couldn't find where that function is actually defined. Fixing this usually takes just a few clicks in the IDE's settings.

Key Takeaways

  • Files in your project folder are automatically linked if they're added through the IDE's file creation or import dialogs, but manually copied files need to be added to the project structure.
  • Include paths tell the compiler where to find header files (.h), and you set them in Project Properties under C/C++ General > Paths and Symbols.
  • Library paths and library names are separate settings: the path tells the compiler where the .a or .lib file lives, and the name tells it which library to link.
  • External libraries from vendors like STMicroelectronics come with documentation showing which library files and headers you need, and STM32CubeIDE's device configuration tool often adds these automatically.

Adding your own source files to the project

The simplest way to add a file is to create it inside STM32CubeIDE itself. Right-click your project name in the Project Explorer panel on the left, select New, then choose File. Name it with the correct extension (.c for C source, .h for headers). The IDE automatically places it in the right folder and registers it with the build system.

If you already have files on disk that you want to add, don't just copy them into the project folder manually. Instead, right-click the project, select Import, then choose File System. Navigate to the folder where your files are, select them, and click Finish. The IDE will copy them into your project and link them correctly. If you've already copied files manually, right-click the project and select Refresh (or press F5) to force the IDE to scan the folder again.

Once a file is added, it appears in the Project Explorer tree. If you see a file with a red X or question mark icon, it means the IDE recognizes the file but can't parse it — usually because it can't find the headers that file includes. This is a linking problem, not a file-location problem, and the next section covers how to fix it.

Setting include paths for header files

An include path is a folder where the compiler looks for .h files when it encounters a line like #include "myheader.h" or #include <stdio.h>. By default, STM32CubeIDE includes paths for the standard C library and the STM32 HAL (Hardware Abstraction Layer) files. If you create your own headers or use a third-party library, you need to add its folder to the include path.

To add an include path, right-click your project name and select Properties. In the window that opens, navigate to C/C++ General > Paths and Symbols. Click the Includes tab. You'll see a list of folders already included. Click Add, then either type the path directly or click Workspace to browse your project folders. Use a relative path like ../Libraries/MyLib so the project stays portable if you move it to another computer.

After you add the path, click explore and Close. The IDE will re-index your project, and the red X icons should disappear. If they don't, check that the path is spelled correctly and that the header files actually exist in that folder. A common mistake is adding the path to the folder that contains the headers, rather than the folder that contains the subfolder with the headers.

Linking external libraries and object files

A library is a compiled collection of functions packaged as a single file, usually with a .a extension (on Linux and embedded systems) or .lib (on Windows). When you link a library, you're telling the linker to include all the compiled code from that library in your final program. This is different from including a header file, which just tells the compiler what functions exist.

To link a library, go to Project Properties again and navigate to C/C++ Build > Settings. Click the Libraries tab. In the Libraries section, click Add and type the library name without the .a or .lib extension and without the "lib" prefix. For example, if your library file is named libmath.a, type math. In the Library search path section below, click Add and specify the folder where the library file actually lives, again using a relative path like ../Libraries.

If you're using an STM32 peripheral library or a vendor-supplied library, check the documentation to find the exact library name and where it's located. Many STM32 projects use the STM32 Standard Peripheral Library or the newer STM32CubeMX-generated HAL, and these are often already linked by default. If you're adding a third-party library, the vendor usually provides a guide showing which library files to link and which include paths to add.

Using STM32CubeMX to configure linked files automatically

STM32CubeMX is a separate tool from STM32CubeIDE that generates the initial project structure and configuration. When you create a new STM32 project in CubeIDE, you can use CubeMX to select which peripherals (like UART, SPI, or timers) you want to use, and it automatically generates the correct code and links the necessary libraries.

If you've already created a project and want to add a peripheral, you can open CubeMX from within CubeIDE. Right-click your project and select Open STM32CubeMX. Make your changes in CubeMX, save, and it will regenerate the configuration files and update the project links. This is much safer than manually editing configuration files, because CubeMX knows exactly which files and libraries each peripheral needs.

After CubeMX regenerates your project, you may see a dialog asking whether to merge changes. Choose Merge to keep your custom code while updating the generated files. The IDE will then re-link everything automatically.

Fixing common linking errors

The error "undefined reference to [function name]" means the compiler found a call to a function but couldn't find where that function is defined. This usually means either the source file containing that function isn't added to the project, or a library containing it isn't linked. Check that the file or library is in your project, that include paths are set if it's a header, and that library paths and names are correct if it's a library.

The error "cannot find -l[libraryname]" means the linker looked in all the library search paths you specified but didn't find a file matching that library name. Double-check the spelling, make sure the library file actually exists in the path you specified, and verify that you're using the correct name format (without .a or .lib, without the lib prefix on Linux).

If you see "file not found" for a header file, the include path is wrong or missing. Open Project Properties, go to C/C++ General > Paths and Symbols, and verify that the path to the folder containing that header is listed in the Includes tab. If the header is in a subfolder, you may need to add the subfolder path as well.

Organizing files in larger projects

As your project grows, keeping files organized makes linking easier. Create subfolders in your project for different components: one for drivers, one for process code, one for utilities. In STM32CubeIDE, right-click your project and select New > Folder to create these folders inside the IDE.

When you add files to subfolders, the IDE automatically updates the build configuration. If you have headers in a subfolder, add that subfolder to your include paths. For example, if you create a folder called Drivers and put header files in Drivers/UART, add Drivers/UART to your include paths. This keeps your project structure clear and makes it easier to find and link files later.

Frequently Asked Questions

Do I need to add every .c file to the project, or does the IDE find them automatically?

The IDE only builds files that are part of the project. If you manually copy a .c file into your project folder without using the Import dialog, you need to refresh the project (F5) for the IDE to see it. Once it appears in Project Explorer, it will be built automatically.

What's the difference between #include "file.h" and #include <file.h>?

Quotes tell the compiler to look in the current folder first, then in include paths. Angle brackets tell it to look only in include paths. For your own headers, use quotes. For system and library headers, use angle brackets. Both require the header to be in an include path or the current folder.

Can I link a library that's outside my project folder?

Yes. In the Library search path setting, use an absolute path or a relative path that points outside your project, like ../../external_libs. Relative paths are better for portability, but absolute paths work if you're the only person using the project.

Why does my project build successfully but the program doesn't run?

A successful build means the compiler and linker found all the files and libraries. If the program doesn't run, the issue is usually in your code logic, not linking. Check that your main() function is defined, that you're flashing the correct binary to the microcontroller, and that your hardware connections are correct.

Do I need to link the STM32 HAL library manually?

No. When you create a new STM32 project in CubeIDE, the HAL library is linked automatically. If you're importing an old project or one created with different tools, you may need to add it manually through the library settings, but CubeIDE projects handle this by default.