0

I am going to build a simple library (.a file) in IAR Workbench for STM8. In this library, I want to implement both hardware SPI and software SPI for users to choose.

In my library.c, I wrote:

#include "library.h"

void LibraryInit()
{
#ifdef HARDWARE_SPI
   funcToInitHardwareSPI();
#else
   funcToInitSoftwareSPI();
#endif
}

And in my library.h, I wrote:

#ifndef __LIB_H
#define __LIB_H

#define HARDWARE_SPI

void LibraryInit();

#endif

Then I think if user define #define HARDWARE_SPI in the target project, the library will run hardware SPI part. If not, software SPI should be in use.

But after I build the project and added library.a and library.h into testing project, with library.h has no #define HARDWARE_SPI, the routine is still going into hardware SPI part. How can I build the library.a that can let user choose the function by writing #define in the header file?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Unrelated to your question, but don't use symbols with two leading underscores, or one leading underscore followed by an upper-case letter. Those symbols are reserved in all scopes for the compiler and standard library. – Some programmer dude Jun 02 '17 at 13:26
  • @Someprogrammerdude Got you! Thanks for teaching me some fundamental! – SoWaiSam Jun 02 '17 at 16:15
  • See [How can I compile two version of my code in IAR Embbedded Workbench](https://stackoverflow.com/questions/46426871/how-can-i-compile-two-version-of-my-code-in-iar-embbedded-workbench) – ecle Sep 01 '18 at 14:47

1 Answers1

0

The .a file is build before a user decides hard or soft spi, so you can't. You must build both codepaths. Is there an issue with providing the library as source?

Considering you're using an 8 bit mcu, I assume you don't want to mess with big abstractions with function pointers, therefore all selection of your code-path must happen in your provided header. If your compiler supports C99, you can place the functions that switch between the implementations inline in your header:

/* library.h */

#pragma once
void funcToInitHardwareSPI();
void funcToInitSoftwareSPI();

inline void LibraryInit()
{
#ifdef HARDWARE_SPI
   funcToInitHardwareSPI();
#else
   void funcToInitSoftwareSPI();
#endif
}

Considering both codepaths are now added to your library, you might want to compile it with each function in a separate section, and then remove all unused sections during linking.

Lanting
  • 3,060
  • 12
  • 28
  • Thanks for the answer. The compiler supports c99 so I will try it. Just want to make sure one thing: those code are written in .h? or I still can only put `inline void LibraryInit();` in .h as decoration and definition in .c? I am not familiar with those preprocessor commands so not sure how to code it. I want to hide it because the setting is too complicated and I don't want people change it too much lead to huge debug time. – SoWaiSam Jun 02 '17 at 16:23
  • @SoWaiSam yep, that's in the header. The function that forwards the call to the correct implementation during compile time must be in the header. Also I don't think that having your code visible is necessarily a bad thing. Even the big operating systems for embedded devices are provided as plain source (though they may not be free software), so everything can be compiled and optimized in a single step. – Lanting Jun 02 '17 at 19:57
  • Alternatively, provide two `.a` files containing the same signatures and let the user link to the one they need. – Lanting Jun 02 '17 at 19:58