库头和#define

时间:2013-12-30 04:11:13

标签: c++ cmake shared-libraries

我不知道该搜索什么。如果这很简单,请原谅。但是,让我概述一下情景,看看那里有什么答案。

假设我有一个库,它定义了这样的结构:

struct Example {
    int a;
#if B_ENABLED
    int b;
#endif
};

此标头作为整个库安装的一部分安装。我的问题是,如果我的库定义了B_ENABLED,它将包含一个包含这两个变量的结构。 然而如果我的应用程序也没有定义它。然后它会将标题解释为定义只有一个成员的结构。

处理此问题的最佳方法是生成某种“选项”标题,其中包含库构建中指定的所有#defines吗?

我的库使用CMAKE构建。因此,针对此的CMAKE解决方案是额外信用 = D.

1 个答案:

答案 0 :(得分:15)

解决方案#1(配置+安装)

在您的标头文件中包含config.hpp文件:

#ifndef FOO_HPP_
#define FOO_HPP_

#include "config.hpp" // FOO_DEBUG

class Foo {
 public:
  int result() const;

 private:
  int a_;
#ifdef FOO_DEBUG
  int b_;
#endif // FOO_DEBUG
};

#endif // FOO_HPP_

config.hppconfigure_file命令的输出:

configure_file(config.hpp.in "${PROJECT_BINARY_DIR}/config/config.hpp")
include_directories("${PROJECT_BINARY_DIR}/config")
install(FILES Foo.hpp "${PROJECT_BINARY_DIR}/config/config.hpp" DESTINATION include)

输入文件config.hpp.in使用特殊cmakedefine指令:

#ifndef CONFIG_HPP_
#define CONFIG_HPP_

#cmakedefine FOO_DEBUG

#endif // CONFIG_HPP_

请注意,在其他项目中使用已安装的库时:

  • 您仍需要为库
  • 指定包含目录
  • 如果您的库有依赖关系,则需要手动链接它们
  • 您不能拥有2个配置文件(调试/发布)

解决方案#2(导出/导入目标,推荐)

install(EXPORT ...)命令可以包含有关使用库的所有信息 (又名使用要求:包括定义,链接库,配置等):

add_library(Foo Foo.cpp Foo.hpp)

# Target which used Foo will be compiled with this definitions
target_compile_definitions(Foo PUBLIC $<$<CONFIG:Release>:FOO_DEBUG=0>)
target_compile_definitions(Foo PUBLIC $<$<CONFIG:Debug>:FOO_DEBUG=1>)

# This directory will be used as include
target_include_directories(Foo INTERFACE "${CMAKE_INSTALL_PREFIX}/include")

# This library will be linked
target_link_libraries(Foo PUBLIC pthread)

# Regular install
install(FILES Foo.hpp DESTINATION include)

# Install with export set
install(TARGETS Foo DESTINATION lib EXPORT FooTargets)
install(EXPORT FooTargets DESTINATION lib/cmake/Foo)

安装此类项目将生成文件(CMAKE_DEBUG_POSTFIXd):

include/Foo.hpp
lib/libFoo.a
lib/libFood.a
lib/cmake/Foo/FooTargets-debug.cmake
lib/cmake/Foo/FooTargets-release.cmake
lib/cmake/Foo/FooTargets.cmake

包含FooTargets.cmake文件以将已安装的库导入项目。例如,使用find_package命令(需要配置,请参阅configure_package_config_file):

add_executable(prog main.cpp)
find_package(Foo REQUIRED) # import Foo
target_link_libraries(prog Foo)

请注意:

  • 自动添加到编译器选项的include/Foo.hpp路径
  • dependend library pthread会自动添加到prog链接器选项
  • 定义FOO_DEBUG=0已添加到发布版本类型
  • 定义FOO_DEBUG=1已添加到Debug构建类型

原理

So excuse me if this is simple

不是(:

问题的根源是ODR(C ++ Standard 2011,3.2 [basic.def.ord],第3页):

Every program shall contain exactly one definition of every non-inline function
or variable that is odr-used in that program; no diagnostic required. The
definition can appear explicitly in the program, it can be found in the
standard or a user-defined library

恕我直言好的一般解决方案仍然不存在。在导入配置中使用CMake 可以部分帮助一点,但在某些情况下,你仍然会得到链接器错误 (例如,如果您使用与gcc编译的库,默认情况下链接到libstdcxx, 并尝试使用链接到clang的{​​{1}}编译器将其链接到项目。 使用toolchain文件可以解决其中一些问题(并非所有问题)。 请参阅examples

相关

相关问题
最新问题