Getting the Most out of Ceedling’s Module Generator

Ceedling is an open-source tool that provides features which help C developers build and test their code. It pulls together Unity (unit test framework) and CMock (mocking framework), as well a handful of other pieces like plugin support and dependency generation.

Ceedling includes a plugin called module-generator that I use quite often. It’s a handy script that, given a module name, will create a source, header, and test file for you.

Basic Usage

The basic usage is like this:

rake module:create[foo]

By default, this will create the following three files:

  • ./test/test_foo.c
  • ./src/foo.c
  • ./src/foo.h

Let’s take a look at the contents of these files. First the test file, ./test/test_foo.c.

#include "unity.h"
#include "foo.h"

void setUp(void) { }

void tearDown(void){ }

void test_module_generator_needs_to_be_implemented(void)
{
	TEST_IGNORE_MESSAGE("Implement me!");
}

As you can see, the module generator created a stub test file. It automatically added the basic include statements that we will need, setup and teardown functions, and a placeholder for our first test.

The source file that was created ./src/foo.c contains just one line of code:

#include foo.h`

And it gives us a header file containing include guards:

#ifndef foo_H
#define foo_H

#endif // foo_H

Custom Directory Structure

That’s great, but what if you like to use a different directory structure for your projects? What if you don’t want your test files in ./test/ and your source code in ./src?

I’m so glad you asked! The module generator is easy to configure. Just add the following to your project.yml file:

:module_generator:
  :project_root: ./
  :source_root: src/
  :test_root: test/

You can change the project_root, source_root, and test_root to whatever your heart desires. Say, for example, that you want to structure your project like this:

    AwesomeProject
      - ModuleA
        - ModuleA.c
        - ModuleA.h
        - test_ModuleA.c
      - ModuleB
        ...

You can do so with the following settings:

:module_generator:
  :project_root: ./
  :source_root: AwesomeProject/
  :test_root: AwesomeProject/

Modifying the Templates

Finally, lets’s dig a little deeper into the module-generator itself. Many software companies require that developers put legal jargon (or other comments) in the header and/or footer of every file. That can get really annoying to copy and paste into every new file you create. Why not make the module generator do it for you?

Take a look in the vendor/ceedling/plugins directory in your project. That’s where the default source code for the module-generator lives. Make a copy of the entire module_generator directory, and put it some place convenient. I usually do something like /CustomCeedlingPlugins/module_generator.

Inside the module_generator/lib directory is a ruby file named module_generator.rb. This file defines the functionality of the plugin and includes three instance variables, @source_template, @header_template and @test_template. These variables are used to specify the templates for the source, header, and test files that the plugin generates. To customize the output of rake module:create, all you need to do is update these templates.

For example, say we wanted to add the project name and company name to the top of each source file. You could modify the @source_template variable to look like this:

    @source_template = (<<-EOS).left_margin
      // Company: Atomic Object
      // This file is part of: <%=PROJECT_NAME%>
      <%if defined?(MODULE_GENERATOR_SOURCE_INCLUDES) &&                     (MODULE_GENERATOR_SOURCE_INCLUDES.class == Array) &&                    !MODULE_GENERATOR_SOURCE_INCLUDES.empty?%>
      <%MODULE_GENERATOR_SOURCE_INCLUDES.each do |header_file|%>
      #include "<%=header_file%>"
      <%end%>
      <%end%>
      #include "<%=@context[:headername]%>"
      EOS

If you’re not familiar with this syntax, it’s ERB, a feature of Ruby that provides a means of generating code from templates.

In order to make this work, there are two small adjustments that need to be made to the project.yml file. First, you need to add your project name:

:project:
  :name: Awesome Project II

Then you have to tell Ceedling to use the new module generator rather than the default one. Down at the bottom, add the path to the directory that you placed your custom module generator in. Make sure to add it before the default path that is already there so that Ceedling loads your plugin first.

:plugins:
  :load_paths:
    - CustomCeedlingPlugins
    - vendor/ceedling/plugins

I encourage you to look though the other plugins that exist in the vendor/ceedling/plugins directory in order to better familiarize yourself with how Ceedling plugins work. What other custom plugins could you make or have you made already?
 

Conversation
  • Chris says:

    Hi, This explanation is great ! Is there a way I can include multiple source directories in the module generator source path ? My project directory is large and distributed in different folders. When I use module:create[] I would like the generator scan through all directories before creating a .c, .h file. I am trying to run this on legacy code hence I only need to create new test files and not source files.

  • Comments are closed.