I'm trying to precompile my headers using gcc and cmake.
I know some scripts like cotire or customPCH do it, but I would like to write my own script.
The project is pretty simple : there is a shared library with some files, and a main calling functions defined in those files. I have manages to build the library (with precompiled header), but I have a strange compilation error when building the main ("precompiled.hpp", no such file or directory), even if the preompiled header is in the include search path (the library uses the same include paths and does not complain)
[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"
I have set up a working toy example available here : git clone -b toy https://bitbucket.org/mrdut/precompiled_header.git
Does anyone have any advice ?
Thanks in advance,
Here is the content of my project:
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()
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