<legend id='2jlb8'><style id='2jlb8'><dir id='2jlb8'><q id='2jlb8'></q></dir></style></legend>
  • <small id='2jlb8'></small><noframes id='2jlb8'>

      <tfoot id='2jlb8'></tfoot>
      <i id='2jlb8'><tr id='2jlb8'><dt id='2jlb8'><q id='2jlb8'><span id='2jlb8'><b id='2jlb8'><form id='2jlb8'><ins id='2jlb8'></ins><ul id='2jlb8'></ul><sub id='2jlb8'></sub></form><legend id='2jlb8'></legend><bdo id='2jlb8'><pre id='2jlb8'><center id='2jlb8'></center></pre></bdo></b><th id='2jlb8'></th></span></q></dt></tr></i><div id='2jlb8'><tfoot id='2jlb8'></tfoot><dl id='2jlb8'><fieldset id='2jlb8'></fieldset></dl></div>
        • <bdo id='2jlb8'></bdo><ul id='2jlb8'></ul>
      1. 库标题和#define

        时间:2023-08-27
        <i id='KpAFo'><tr id='KpAFo'><dt id='KpAFo'><q id='KpAFo'><span id='KpAFo'><b id='KpAFo'><form id='KpAFo'><ins id='KpAFo'></ins><ul id='KpAFo'></ul><sub id='KpAFo'></sub></form><legend id='KpAFo'></legend><bdo id='KpAFo'><pre id='KpAFo'><center id='KpAFo'></center></pre></bdo></b><th id='KpAFo'></th></span></q></dt></tr></i><div id='KpAFo'><tfoot id='KpAFo'></tfoot><dl id='KpAFo'><fieldset id='KpAFo'></fieldset></dl></div>
              <tbody id='KpAFo'></tbody>
            <tfoot id='KpAFo'></tfoot>

            <small id='KpAFo'></small><noframes id='KpAFo'>

              <bdo id='KpAFo'></bdo><ul id='KpAFo'></ul>

                  <legend id='KpAFo'><style id='KpAFo'><dir id='KpAFo'><q id='KpAFo'></q></dir></style></legend>
                1. 本文介绍了库标题和#define的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我不确定要搜索什么.如果这很简单,请原谅.但让我概述一下场景,看看有什么答案.

                  I wasn't sure what to search for for this one. So excuse me if this is simple. But let me outline the scenario and see what answers are out there.

                  假设我有一个定义如下结构的库:

                  Let's say I have a library which defines a structure like this:

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

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

                  This header gets installed as a part of the library's installation as a whole. My question here is that if my library defines B_ENABLED it will have a structure with these two variables included. However if my application does not define this as well. Then it will interpret the header as defining a struct with only one member.

                  处理这个问题的最好方法是生成某种选项"标头,其中包括库构建中指定的所有#defines?

                  Is the best way to handle this just to generate some kind of "options" header which would include all of the #defines that were specified in the library build?

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

                  My library builds with CMAKE. So a CMAKE solution for this is extra credit =D.

                  推荐答案

                  Solution #1 (configure + install)

                  在头文件中包含 config.hpp 文件(即 foo.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.hpp 是 configure_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 指令:

                  input file config.hpp.in use special cmakedefine directive:

                  #ifndef CONFIG_HPP_
                  #define CONFIG_HPP_
                  
                  #cmakedefine FOO_DEBUG
                  
                  #endif // CONFIG_HPP_
                  

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

                  Note that when you use installed library in other project:

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

                  安装(导出...)命令可以保存有关使用库的所有信息(又名使用要求:包括定义、链接库、配置等):

                  install(EXPORT ...) command can hold all information about using library (aka usage requirements: including definitions, linked library, configuration etc):

                  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):

                  Installing such project will produce files (CMAKE_DEBUG_POSTFIX is d):

                  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):

                  Include FooTargets.cmake file to import installed library to project. For example using find_package command (need config, see configure_package_config_file):

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

                  注意:

                  • include/Foo.hpp 的路径自动添加到编译器选项
                  • 依赖库 pthread 自动添加到 prog 链接器选项
                  • 定义 FOO_DEBUG=0 添加到发布构建类型
                  • 定义 FOO_DEBUG=1 添加到调试构建类型
                  • path to include/Foo.hpp automatically added to compiler options
                  • dependend library pthread is automatically added to prog linker option
                  • definition FOO_DEBUG=0 added to Release build type
                  • definition FOO_DEBUG=1 added to Debug build type
                  So excuse me if this is simple
                  

                  它不是 (:

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

                  The root of the problem is ODR (C++ Standard 2011, 3.2 [basic.def.ord], p.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 编译器将其链接到项目,该编译器链接到 libcxx).使用 工具链 文件可以解决其中一些问题(并非全部,仍然).请参阅示例.

                  IMHO good general solution still not exists. Using CMake with imported configuration can partially helps a little bit, but in some cases you still will get linker errors (for example if you use library compiled with gcc, which linked to libstdcxx by default, and try to link it to project with clang compiler, which linked to libcxx). Some of this problems (not all, still) can be solved using toolchain files. See examples.

                  • CMake 教程
                  • 导出/导入目标
                  • 使用 Qt 和 Boost 的现代 CMake

                  这篇关于库标题和#define的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:如何在 CMake 中更改 Win32 版本的可执行输出目录? 下一篇:添加“Qt5Widgets"的安装前缀;到 CMAKE_PREFIX_PATH

                  相关文章

                    <bdo id='hBwvA'></bdo><ul id='hBwvA'></ul>

                    <legend id='hBwvA'><style id='hBwvA'><dir id='hBwvA'><q id='hBwvA'></q></dir></style></legend>

                    1. <i id='hBwvA'><tr id='hBwvA'><dt id='hBwvA'><q id='hBwvA'><span id='hBwvA'><b id='hBwvA'><form id='hBwvA'><ins id='hBwvA'></ins><ul id='hBwvA'></ul><sub id='hBwvA'></sub></form><legend id='hBwvA'></legend><bdo id='hBwvA'><pre id='hBwvA'><center id='hBwvA'></center></pre></bdo></b><th id='hBwvA'></th></span></q></dt></tr></i><div id='hBwvA'><tfoot id='hBwvA'></tfoot><dl id='hBwvA'><fieldset id='hBwvA'></fieldset></dl></div>

                      <small id='hBwvA'></small><noframes id='hBwvA'>

                    2. <tfoot id='hBwvA'></tfoot>