Hello! I’m Mohamed Ashraf, and today I’ll show you how to manage your embedded systems projects.


Introduction

In the world of embedded systems development, managing your project’s build process can often be a complex and time-consuming task. This is where build system utilities like CMake and Make come into play. But why should you use a compiled language utility, and how can it benefit your embedded projects?

Why Use a Compiled Language Utility?

Using a compiled language utility like CMake or Make brings several benefits:

  1. Efficiency and Performance: Compiled code runs faster and more efficiently than interpreted code, which is crucial for embedded systems where resources are often limited.
  2. Manageability: These tools help manage dependencies, build configurations, and streamline the build process, making it easier to maintain and scale your projects.
  3. Cross-Platform Compatibility: Tools like CMake can generate build scripts for different platforms, ensuring that your code can be compiled and run on various target systems with minimal modifications.
  4. Automation: Automate repetitive tasks such as compilation, linking, and testing, freeing up more time to focus on actual development.

CMake

CMake is a powerful tool that helps you manage your embedded projects. It’s a build system generator that provides a clean and efficient way to define and organize the build process. By using CMake, you can easily configure your project to build across different environments and platforms.

Key benefits of CMake:

  • Platform Independence: CMake can generate build scripts for various platforms, including Windows, Linux, Mac, etc.
  • Portability: Generate native build files for different platforms (e.g., Makefiles, Visual Studio projects).
  • Ease of Use: Simplify complex build processes with clear and concise configuration files.
  • Flexibility: Customize the build process to suit your project’s specific needs.

In the next part, I’ll continue with a detailed look at my personal project structure, including the specifics of how I set up and use CMake for my embedded projects.

My Personal Project Structure

In this section, I’ll share my personal project structure and explain how I use CMake to streamline my development process.

First, we talk about the root folder structure which contains:

Root Folder Structure

When organizing your embedded project, it’s essential to maintain a clear and well-structured root directory. Here’s an overview of the key directories and files you’ll find in the root folder:

Directories

  1. .devcontainer
    This directory contains configuration files for setting up a development container. It typically includes:
    • devcontainer.json: Defines the settings and extensions for the development environment.
  2. .github
    This directory is used to store GitHub-specific files, such as:
    • GitHub Actions workflows for Continuous Integration/Continuous Deployment (CI/CD).
    • Issue and pull request templates to standardize contributions.
  3. backup
    A directory to store backup copies of important files and configurations, ensuring that you can restore your project in case of data loss or corruption.

  4. doc
    This directory contains documentation related to your project. It might include user manuals, developer guides, and other relevant documentation.

  5. software
    This directory houses the main source code of your embedded project. It includes all the modules, libraries, and components necessary for your project.

  6. tools
    This directory is for CMake/IDE build folders and utility scripts and tools that assist in the development process, such as build scripts, code analysis tools, and custom utilities.

  7. wiki
    A directory for storing wiki pages and documentation that can be rendered as a wiki on platforms like GitHub.

Files

  1. .gitignore, .gitattributes, .gitmodules
    • .gitignore: Specifies files and directories that should be ignored by Git, preventing them from being tracked in the repository.
    • .gitattributes: Defines attributes that affect how Git handles certain files (e.g., line endings, merge strategies).
    • .gitmodules: Lists the submodules used in the project, allowing you to include external repositories within your project.
  2. build.sh
    A shell script to automate the build process. It typically compiles the source code, runs tests, and generates binaries. Also if there are any build-specific things to be done.

  3. CMakeLists.txt
    The main configuration file for CMake. It defines the build process, including which files to compile, project dependencies, and build options.

  4. Dockerfile
    A file used to build a Docker image for the development environment. It contains instructions for setting up the required tools, libraries, and dependencies.

  5. Makefile
    Defines a set of tasks to be executed, such as building the project, cleaning up build artifacts, and running tests. It uses the make utility to automate these tasks.

  6. Makefile.variables
    A file to store environment-specific variables used in the Makefile. This separation allows for easy modification of variables without altering the main Makefile.

  7. project.code-workspace
    A workspace configuration file for Visual Studio Code. It sets up the environment, including folder structure, settings, and extensions, to provide a consistent development experience and make it easy to port it in the docker container.

By maintaining this structured root folder and understanding the purpose of each file and directory, you can ensure a more organized and manageable project setup.

References

Software Directory

The software directory is the heart of your embedded project, containing the main source code and necessary librares and tools. It consists of any software required by the project on its folder structure which is:

software/
├── application
    └── xyz_swc
        ├── core/
            ├── Xyz.c
            └── Xyz.h
            └── modules/ (Optional)
        ├── tests/
            ├── stubs/
                ├── stubs_xyz.h
            ├── test_runners/
                ├── xyz_runner.c
                └── test_main.c
            └── test_xyz_swc.c
        ├── tools/
            └── CMake/
                └── xyz_swc_compile.cmake
                └── xyz_swc_test.cmake
        └── CMakeLists.txt
├── drivers
    ├── xyz_driver/
        ├── core/
            ├── xyz_driver.c
            └── xyz_driver.h
            ... Same goes for it like the xyz_swc.
        └── CMakeLists.txt
        ... etc
    └── CMakeLists.txt
├── doc
    └── README.md
├── tools
    └── README.md
└── CMakeLists.txt

The core/ directory is used to store the swc C/C++ files and it even could be extended by adding ad subdirectories modules/ with the required CMakeLists.txt file options.

The tests/ directory is used to perform unit testing for the swc with the help of CMock/Unity/Gtest.

The tools/ directory is used to store any additional tools required by the project, such as CMake build tools.

The CMakeLists.txt used to add/organize the each subdirectory included in the directory. But for the CMakeLists.txt located at the xyz_swc it used to build for compile/test the swc. with the help of the xyz_swc_compile/xyz_swc_test to congifure sources/includes/libs etc.

Note: The generator is generating the dependeicies required by CMock/Unity.

Note: You need to add the CMock repo as git subnmodule by typing

> git submodule add CMock_Repo_Link
> git submodule update --init --recursive

Cmake build flow

post-ecmake

Asset Generator

The Asset Generator is a tool I created to generate the base templates required for the embedded project structure. It is designed to make it easier to start developing without the overhead of copying, documenting, and skeletoning.

It generally generates all of the previous section files. you can learn more about it in my github repo AssetGenerator.

(c) 2024, MoWx-04-06