条件编译策略 - 如何避免C中的未定义符号

时间:2015-04-02 10:35:35

标签: c conditional-compilation keil

我正在尝试用C语言制作模块化项目。 我正在为嵌入式ARM CPU编写固件。它由不同的部分组成,由于内存限制,不能同时编译所有部分。

简化,假设我有一个模块A,它管理固件的所有可选部分,每个模块都在其模块中编码(B,C,D等......)

模块A中的

我使用#ifdef子句:

#ifdef USE_B
  #include "B.h"
#endif

#ifdef USE_C
  #include "C.h"
#endif

...

然后,我只需#define我想要包含的模块的关键字。

我在文件Z.c中有一些全局变量应该保留在那里。由于我的目标是最大限度地减少内存使用,我也将其声明包含在#ifdef中

#ifdef USE_B
  uint8_t usedonlybyb;
#endif

#ifdef USE_C
  uint8_t usedonlybyc;
#endif

...

即使文件B和文件C在编译时与项目的其他部分完全断开连接,在编译结束时我得到"未定义的符号"外部变量的错误" usedonlybyx",禁用的模块无法访问这些错误。

我想保留在模块Z中声明的usedonlybyx变量,因为那是一般设置模块。

是否有一种优雅的方法来抑制这些错误,并且仍能在我的范围内取得成功?

我应该简单地将整个模块B,C,...包含在#ifdef / #endif中吗?

2 个答案:

答案 0 :(得分:2)

更简单的解决方案是在b.hb.c内的#ifdef USE_B#endif文件中包含整个实施和声明。其他模块也一样。这样,一个模块的所有条件编译都是隔离的,而不必在使用#include "b.h"的其他代码中。

// b.h
#ifdef USE_B
// declarations and include guards
#endif

// b.c
#ifdef USE_B
// definitions
#endif

// a.c
#include "b.h" // <- no USE_B needed here

答案 1 :(得分:0)

您可以尝试将B和C模块拆分为离散库组件,确保这些库中包含的任何全局变量都包含在其中。这可能需要将变量的extern声明移动到库接口文件,或者根据需要提供访问器方法。

或者,如果你正在使用GCC,那么编译器的语言扩展名为__attribute__((weak)),它将声明一个'just-in-case-it-not-defined-anywhere-else'版本保持链接器满意的变量。