2015-11-09 3 views
0

Я пытаюсь перекомпилировать свои заголовки с помощью gcc и cmake.cmake precompiled header в общей библиотеке

Я знаю, что некоторые скрипты, такие как cotire или customPCH, делают это, но я хотел бы написать собственный скрипт.

Проект довольно прост: есть общая библиотека с некоторыми файлами и основные функции вызова, определенные в этих файлах. Мне удалось создать библиотеку (с предварительно скомпилированным заголовком), но у меня возникла странная ошибка компиляции при создании основного («precompiled.hpp», никакого такого файла или каталога), даже если предварительно скомпилированный заголовок находится в пути поиска include (библиотека использует те же включает в себя пути и не жалуется)

[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 клон -b игрушку 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 

run.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() 

ЦСИ /header.hpp:

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

SRC/бен/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 
+0

'У меня есть удается построить библиотеку (с скомпилированным заголовком), но у меня есть странная ошибка компиляции при построении в main' - Пожалуйста, укажите ваш код в виде [MCVE] (HTTP: // stackoverflow.com/help/mcve) и сообщение об ошибке, вызванное кодом. – Tsyvarev

+0

Спасибо за ваш совет, я обновил свой пост – flod

ответ

0

Поскольку file1.hpp и file2.hpp включают ваш precompiled_header.hpp вам нужно перекомпилировать их также делать работу.

Из НКУ прекомпилированы заголовков documentation:

прекомпилированный заголовка не может быть использован после того, как первый маркер С виден. Перед прекомпилированным заголовком вы можете иметь директивы препроцессора; вы не можете включить предварительно скомпилированный заголовок из другого заголовка.

0

Кажется, что это работает, если я сначала включу предварительно скомпилированный заголовок перед другим заголовком в главном.каст

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

Такой способ использования как обычного заголовка 'header.hpp' из' main.cpp', так и прекомпилированного одного из 'precompiled_header.hpp' из' file.hpp' (также включенного в ' main.cpp'). Такое использование просто устраняет потребности предварительно скомпилированного заголовка, который, вероятно, не тот, который вы хотите. – Tsyvarev