Compiling variations on a common code base: best practices?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Compiling variations on a common code base: best practices?

Jump to solution
2,296 Views
robertpoor
Senior Contributor I

I have a large-ish body of code that supports seven different analog sensor boards (and more in the future...).  About 90% of the code is shared among all the variants.  I've already conditionalized the code to support the different sensor boards with constructs along these lines:

void sensor_init() {
#ifdef IS_SENSOR_A
    sensor_a_init()
#elif IS_SENSOR_B
    sensor_b_init()
#else
    #error Unknown sensor!
#endif
}

When I build the project, MCUXpresso generates my_project.axf file compiled for one of the seven variants.  What I usually do then is rename my_project.axf to sensor_a.axf or sensor_b.axf depending on the conditionals in effect when I built it.

Of course, this approach is fraught with potential for errors -- it's easy to forget to rename the .axf file, and it's not obvious which variant  my_project.axf was compiled for after the fact.

Is there a way to do this automatically, or achieve the same effect?  (E.g. should I create seven different projects that share a common code base?  If so, how?)

Tags (1)
1 Solution
1,913 Views
lpcxpresso_supp
NXP Employee
NXP Employee

The simplest thing would probably be to create a number different build configurations (i.e. beyond the default Debug and Release build configs). To do this, right click on the project in the Project Explorer view, and select the menu:

  • Build Configurations -> Manage

Another approach might be to have a project for each build variant that you want, which then use "linked resources" to link to another "master project" that contains your sensor sources. Linked resources allow you to link a folder in one project into a folder in another. This is similar to a linux symbolic link. You can have a many linked folders as you need - there is no limit.

By using a master project plus "secondary" projects with linked folder, you get a single copy of your sources (editable from both projects) but with different project (and MCU) settings. It is fully compatible with source code control systems, such as Git or SVN. Details on linked resources can be found in the Help (Help->Help Contents and search for Linked Resources).

With regards to the master project, as this is really just a container of files rather than something you actually want to build, you might want to create it just using the

  • File -> New ->  Project -> General -> Project

A simple way to create your secondary projects with a linked folder is as follows:

  • Use the New Project Wizard to create a project with the appropriate settings
  • delete the src folder
  • Right-click on the project and File->New->Folder
  • Enter src into the Folder name
  • Press the Advanced>> button
  • Click on "Link to alternate location (Linked folder)"
  • Press "Variables"
  • In the new Dialog, select the WORKSPACE entry
  • press the Extend button
  • a Browser is shown - browse to the src folder in your 'master' project
  • Press OK
  • Press Finish

You new project will now have a src folder that is linked to the src folder in your master project. You can make changes to your secondary project(s) to provide different build options (e.g. defines).

Another possibility might be to consider using a library project, with build configs for each of your sensor options. Then have a project for each sensor type - which contains any project specific code, but also links to the appropriate build config of the central library project. I suspect that this is probably the most complex option though.

Regards,

MCUXpresso IDE Support

View solution in original post

4 Replies
1,913 Views
robertpoor
Senior Contributor I

For anyone who has arrived here seeking wisdom: 

As recommended by MCUXpresso IDE Support and by BlackNight, I started out using build configurations to create the different versions of the code, one version per sensor.

It worked well, but as scope of the project grew -- and the client wanted not only different sensors but multiple variations on individual sensors -- my code became increasingly cluttered with #ifdef and #ifndef statements and unexpected inter-dependencies.

So I made the jump: I converted the common code base into a library (see Erich's Creating a Library with Kinetis Design Studio).  A suite of projects -- one project per sensor configuration -- link to the common library base.  I found another of Erich's blogs, Creating and using Libraries with ARM gcc and Eclipse, to be helpful in setting that up.

The code base is now quite clean: the preprocessor conditionals are gone and the individual projects are very compact.  Adding a new sensor (or a variation on a sensor) is easy.  And if I find myself repeating code across multiple projects, I just add a new function in my sensor_utils.c library file so it can be shared.

One unexpected bonus of this approach: the new structure makes it easy to create a virtual "debugging sensor" that doesn't read a physical sensor, but rather allows me to test and validate the functions in the library.

As Erich might say, happy code sharing!

1,913 Views
BlackNight
NXP Employee
NXP Employee

HI Robert,

I recommend build targets as well (see Build Configurations in Eclipse | MCU on Eclipse ), especially if the set of sources files remains the same for all the different variants. You can control each build target compiler settings and output file name(s), and you would add your define to the compiler settings (-D option).

I hope this helps,

Erich

1,913 Views
robertpoor
Senior Contributor I

Using build configurations with -D options solves 95% of my needs nicely!

For the remaining 5%: is there a way to select one of two memory layouts / linker scripts?  In my case, it would be useful to choose between a "standalone" image (starting at 0x0) and a "bootloaded" image (starting at 0x4000 with a Boot Control Area). 

Since MCU / Memory Configuration / Linker Scripts don't appear to be under control of Build Configurations, perhaps this would be a case for linked projects -- a master project without relocation and a secondary project with relocation.

Does that sound sensible?

0 Kudos
1,914 Views
lpcxpresso_supp
NXP Employee
NXP Employee

The simplest thing would probably be to create a number different build configurations (i.e. beyond the default Debug and Release build configs). To do this, right click on the project in the Project Explorer view, and select the menu:

  • Build Configurations -> Manage

Another approach might be to have a project for each build variant that you want, which then use "linked resources" to link to another "master project" that contains your sensor sources. Linked resources allow you to link a folder in one project into a folder in another. This is similar to a linux symbolic link. You can have a many linked folders as you need - there is no limit.

By using a master project plus "secondary" projects with linked folder, you get a single copy of your sources (editable from both projects) but with different project (and MCU) settings. It is fully compatible with source code control systems, such as Git or SVN. Details on linked resources can be found in the Help (Help->Help Contents and search for Linked Resources).

With regards to the master project, as this is really just a container of files rather than something you actually want to build, you might want to create it just using the

  • File -> New ->  Project -> General -> Project

A simple way to create your secondary projects with a linked folder is as follows:

  • Use the New Project Wizard to create a project with the appropriate settings
  • delete the src folder
  • Right-click on the project and File->New->Folder
  • Enter src into the Folder name
  • Press the Advanced>> button
  • Click on "Link to alternate location (Linked folder)"
  • Press "Variables"
  • In the new Dialog, select the WORKSPACE entry
  • press the Extend button
  • a Browser is shown - browse to the src folder in your 'master' project
  • Press OK
  • Press Finish

You new project will now have a src folder that is linked to the src folder in your master project. You can make changes to your secondary project(s) to provide different build options (e.g. defines).

Another possibility might be to consider using a library project, with build configs for each of your sensor options. Then have a project for each sensor type - which contains any project specific code, but also links to the appropriate build config of the central library project. I suspect that this is probably the most complex option though.

Regards,

MCUXpresso IDE Support