【问题标题】:cmake precompiled header in shared library共享库中的 cmake 预编译头文件
【发布时间】:2015-11-09 13:25:45
【问题描述】:

我正在尝试使用 gcc 和 cmake 预编译我的头文件。

我知道像 cotire 或 customPCH 这样的脚本可以做到这一点,但我想编写自己的脚本。

该项目非常简单:有一个包含一些文件的共享库,以及在这些文件中定义的主要调用函数。 我已经设法构建了库(带有预编译的头文件),但是在构建主文件时出现了一个奇怪的编译错误(“precompiled.hpp”,没有这样的文件或目录),即使预编译的头文件位于包含搜索路径中(该库使用相同的包含路径并且不会抱怨)

[100%] Building CXX object CMakeFiles/prog.dir/src/bin/main.cpp.o
/usr/bin/c++ -DUSE_PRECOMPILED -Isrc -Ibuild -Winvalid-pch -fPIC -o CMakeFiles/prog.dir/src/bin/main.cpp.o -c src/bin/main.cpp
src/lib/dir2/file2.hpp:7:42: fatal error: build/precompiled_header.hpp: No such file or directory
     #include "precompiled_header.hpp"

我在这里设置了一个可用的玩具示例:git clone -b toy https://bitbucket.org/mrdut/precompiled_header.git

有人有什么建议吗?

提前致谢,

这是我项目的内容:

run.sh
CMakeLists.txt
src/
   lib/
      dir1/file1.cpp, file1.hpp
      dir2/file2.cpp, file2.hpp
   bin/main.cpp

运行.sh:

mkdir build
cd build/
cmake .. && make VERBOSE=1 && ./bin/prog
cd ..

CMakeslist.txt:

cmake_minimum_required(VERSION 2.8.11)

project('PRECOMPILED' CXX)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY lib)

add_compile_options(-Winvalid-pch)

set(use_precompiled_header 1) # <= everything is fine if not using precompiled header
set(executable_name prog)
set(library_name erty)
set(precompiled_header_name precompiled_header )

###########
# library #
###########
add_library(${library_name} SHARED src/lib/dir1/file1.cpp src/lib/dir2/file2.cpp)
target_include_directories(${library_name} PUBLIC src )

##############
# executable #
##############
add_executable(${executable_name} src/bin/main.cpp)
target_include_directories(${executable_name} PUBLIC src )
target_link_libraries(${executable_name} ${library_name})
target_compile_options(${executable_name} PRIVATE "-fPIC") # because we are building SHARED library

######################
# precompiled header #
######################
if( ${use_precompiled_header} )

    set(precompiled_header_dir ${CMAKE_CURRENT_BINARY_DIR} )
    set(precompiled_header_src ${CMAKE_CURRENT_SOURCE_DIR}/src/header.hpp )
    set(precompiled_header_dst precompiled_header.hpp.gch )

    add_custom_target( ${precompiled_header_name} ALL DEPENDS ${precompiled_header_dst} )
    add_custom_command( OUTPUT ${precompiled_header_dst}
                            COMMAND ${CMAKE_CXX_COMPILER} -fPIC -DUSE_PRECOMPILED ${precompiled_header_src} -o ${precompiled_header_dst}
                            MAIN_DEPENDENCY ${precompiled_header_src}
                            WORKING_DIRECTORY ${precompiled_header_dir}
                            VERBATIM )

    add_dependencies( ${library_name} ${precompiled_header_name} )

    target_compile_definitions(${library_name} PUBLIC -DUSE_PRECOMPILED )
    target_compile_definitions(${executable_name} PUBLIC -DUSE_PRECOMPILED )

    target_include_directories(${library_name} PUBLIC ${precompiled_header_dir})
    target_include_directories(${executable_name} PUBLIC ${precompiled_header_dir})

endif()

src/header.hpp:

#ifndef HEADER_HPP
#define HEADER_HPP
    #include <iostream>
#endif

src/bin/main.cpp:

#include "lib/dir1/file1.hpp"
#include "lib/dir2/file2.hpp"
int main(int argc, char** argv)
{
    std::cout << "\n -= " << argv[0] << " =-\n";
    libfunc1();
    libfunc2();
    return 0;
}

src/lib.dir1/file1.cpp:

#include "lib/dir1/file1.hpp"
void libfunc1() { std::cout << "function 1" << std::endl; }

src/lib.dir1/file1.hpp:

#ifndef LIBRARY_FILE_1_HPP
#define LIBRARY_FILE_1_HPP
    #ifndef USE_PRECOMPILED
        #include "header.hpp"
    #else
        #include "precompiled_header.hpp"
    #endif
    void libfunc1();
#endif

src/lib.dir2/file2.cpp:

#include "lib/dir2/file2.hpp"
void libfunc2() { std::cout << "function 2" << std::endl; }

src/lib.dir1/file2.hpp:

#ifndef LIBRARY_FILE_2_HPP
#define LIBRARY_FILE_2_HPP
    #ifndef USE_PRECOMPILED
        #include "header.hpp"
    #else
        #include "precompiled_header.hpp"
    #endif
    void libfunc2();
#endif

【问题讨论】:

  • I have manages to build the library (with precompiled header), but I have a strange compilation error when building the main - 请以MCVE 的形式提供您的代码以及由代码引起的错误消息。
  • 感谢您的建议,我已经更新了我的帖子

标签: gcc cmake precompiled


【解决方案1】:

因为file1.hppfile2.hpp 包含您的precompiled_header.hpp,所以您还需要对它们进行预编译才能正常工作。

来自 gcc 预编译头文件documentation:

一旦看到第一个 C 标记,就不能使用预编译的标头。您可以在预编译头文件之前使用预处理器指令; 您不能在另一个头文件中包含预编译头文件

【讨论】:

    【解决方案2】:

    如果我在 main.cpp 中的另一个头文件之前首先包含预编译头文件,这似乎可以工作

    #ifdef USE_PRECOMPILED
        #include "precompiled_header.hpp"
        #undef USE_PRECOMPILED
    #endif
    

    【讨论】:

    • 这样,您既可以使用来自main.cpp 的普通标头header.hpp,也可以使用来自file.hpp 的预编译标头precompiled_header.hpp(也包括来自main.cpp)。这种用法只是消除了对预编译头的需求,这可能不是你想要的。
    猜你喜欢
    • 2020-07-19
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    • 2010-09-13
    • 2014-02-23
    • 1970-01-01
    相关资源
    最近更新 更多