【问题标题】:Using #ifdef in static libraries (C++, Eclipse CDT)在静态库(C++、Eclipse CDT)中使用#ifdef
【发布时间】:2018-10-31 13:29:18
【问题描述】:

我有一个关于我在 Eclipse CDT 中的项目管理、在 C++ 中编程和使用 GCC 编译的问题。 假设我有一个适用于 A 型微控制器 (driverA.hpp) 的驱动程序库和一个适用于 B 型微控制器 (driverB.hpp) 的驱动程序库(外围设备等)。在这两个库中,函数接口是相同的。此外,我有某些设备的库,例如设备 X,它们应该可用于两种控制器类型(例如:deviceX.hpp)。在使用这些东西的项目(projectY)中,我将添加相应的驱动程序库(driverA.hpp 或 driverB.hpp),并且我想添加一个编译器标志以命名我要使用的控制器类型。

在deviceX.hpp中,我想区分这两种类型,所以我想添加这样的东西:

#ifdef CONTROLLER_A
  #include driverA.hpp
#elseif CONTROLLER_B
  #include driverB.hpp
#endif

这个库也将链接到 projectY,我想在其中添加一个编译器标志,如 CONTROLLER_A,并且将链接具有正确控制器类型的库 deviceX。

但是,我知道,这是行不通的。这就是为什么我要问你:做这种库依赖的最好(或:常见)方法是什么?将 deviceX 库添加为源位置?还是有别的办法?

最好的问候

【问题讨论】:

  • 我可能会在构建系统中执行此操作。
  • 是的,可能就是这样,但我对 Eclipse 中的 C++ 构建系统不够精通,无法知道如何做到这一点,并且在网上找不到好的答案,这就是为什么我我在这里问。
  • 如果可能的话,我会简单地避免使用静态库——这也会产生更好的二进制文件。
  • 如果我理解正确,您会建议将所需的驱动程序直接添加到源文件夹中吗?
  • 调查 Eclipse 帮助系统中的构建配置。我已经十多年没有使用它了,但我记得他们确实为您提供了 UI 来设置单独的构建配置,这样 /DCONTROLLER_A 宏定义将在命令行上提供给编译器。

标签: c++ c eclipse linker microcontroller


【解决方案1】:

有很多方法可以实现您想要的,但需要注意的一点是,如果两个 MCU 的驱动程序具有相同的接口(根据您的问题),那么基于不同的 MCU 包含不同的标头绝对没有意义#定义。如果您希望解决方案基于#define,您可以执行以下操作:

头文件(some_driver.h):

// init.
void some_driver_init(struct init_params ip);

// start driver
void some_driver_start();

“假”实现(some_driver.c):

#if defined(ARM_CORTEX_M3)  
#include "some_driver_arm_m3.c"
#elif defined(TI_MSP430) 
#include "some_driver_msp430.c"
#elif defined(...)  
//... and so on...
#else  
#pragma warning "MCU NOT SUPPORTED!"
#endif 

然后是每个 MCU 的“真正”实现:

some_driver_arm_m3.c

// init. M3 Cortex driver
void some_driver_init(struct init_params ip)
{
// actual M3 implementation goes here
}

// start M3 Cortex driver
void some_driver_start()
{
// actual M3 implementation goes here
}

some_driver_msp430.c

// init. MSP430 driver
void some_driver_init(struct init_params ip)
{
// actual MSP430 implementation goes here
}

// start MSP430 driver
void some_driver_start()
{
// actual MSP430 implementation goes here
}

...等等。

【讨论】:

  • 感谢您的回答!是的,我理解你的提议,它看起来很有希望,我会使用它。我还不明白的是,如果可以在静态库(.a 文件)中使用这种方法,它将由链接器通过 -l 命令添加。这将在我的项目之前自动编译,并且据我尝试,它不会响应(我猜就是这样)我的全局符号和定义。编译前是否有机会传递全局符号?
  • 执行此操作的能力取决于您计划使用的特定编译器。大多数现代编译器都支持这一点,我过去实际上使用过这种方法来构建一个“不可知的”静态库,可以将其传递给客户而无需泄露源代码。
  • 举个例子,在 IAR 的 Embedded Workbench(我碰巧安装了一个流行的嵌入式编译器)中,您可以通过使用“定义的符号”(在项目选项->编译器->预处理器下)来完成此操作在编译 lib 之前预定义 ARM_CORTEX_M3 符号(或您可能需要的任何符号)。
  • 另一种方法是在名为 cortex_m3_defines.h 的文件中#define ARM_CORTEX_M3,然后根据需要使用“预包含文件”将该文件强制包含在编译中,这将自动包含该头文件您项目的所有编译单元(在 IAR 上,这又在编译器->预处理器->预包含文件下)。
  • 显然,这些选项可以从命令行以及编译标志的形式获得,如果你碰巧使用了一个,用于将编译过程与你的构建系统(例如 make)集成。
猜你喜欢
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 2016-12-05
  • 2012-07-23
  • 2011-10-09
相关资源
最近更新 更多