Decrease clang compile time with precompiled headers - c++

I am working on a database project that compiles queries (expressed in some higher level language) into c++ code. This code is compiled and executed by the database. That part works perfectly fine.
Right now, I am trying to reduce the compile time for the C++ query code. I was wondering whether I can use precompiled headers to gain performance here.
The query is translated into a file called Query.cpp which includes library/src/Database.hpp. The Database.hpp file includes further files like StandardTypes.hpp and so on. Can I precompile all those header files to speed up the compilation of Query.cpp? If yes, how can I do that? I could not find any good example for precompiled headers so far, only some really basic stuff.
I use the following command to compile Query.cpp:
clang++ -fPIC -std=c++11 Query.cpp -I./library/src/ -shared -o libquery.so;

to create pre-compiled header include all the headers you don't change into Query.h and use:
clang -cc1 Query.h -emit-pch -o Query.h.pch
to use the pre-compiled header type:
clang -cc1 -include-pch Query.h.pch Query.cpp -shared -o libquery.so;
Query.cpp needs to include Query.h

Related

How do I generate and use precompiled headers with Clang++?

The official docs state how precompiled headers are to be used through the -cc1 interface, like so to generate them:
$ clang -cc1 test.h -emit-pch -o test.h.pch
And to use them:
$ clang -cc1 -include-pch test.h.pch test.c -o test.s
The problem is that the -cc1 interface is way too low-level to be used by developers from the CLI. In fact, the regular high-level interface ultimately calls into the low-level -cc1 interface by supplying it with a very large set of arguments that are necessary for its correct operation, for example the include paths appropriate for the compile time system. Without these arguments, the -cc1 interface has no prayer of working:
$ clang++ -cc1 /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h -emit-pch -o std.pch
/usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h:33:10: fatal error: 'cassert' file not found
#include <cassert>
^~~~~~~~~
1 error generated.
Is there a way to use precompiled headers from the high-level interface, such that a developer may conveniently tap into this feature during their daily work?
I don't know why the clang docs do not explain this, but indeed as #selbie surmises, it is possible to use Clang precompiled headers (PCH) without using -cc1.
To generate a PCH file:
$ clang -c -o big-header.hh.pch big-header.hh <other options>
This is the normal compile command, except the input file has the .hh (C++ header) extension. clang will recognize that means to generate a PCH. Alternatively, pass -xc++-header before the header file name if you do not want to use that extension (or another, like .H or .hpp, that is unambiguously C++).
You can tell that big-header.hh.pch is not object code (despite the -c on the command line) because file will say it is "data" (at least my version does) rather than object code. To be extra sure, run strings big-header.hh.pch | head. The first line should be "CPCH" (meaning "Clang PCH").
To use the PCH file:
$ clang -c -include-pch big-header.hh.pch <other compile options>
The addition of -include-pch big-header.hh.pch is the key step that is different compared to gcc. Clang will not automatically pick up PCH files just due their name.
The above was tested with Clang+LLVM-14.0.0 on Linux.
I think the root of your problem is that your filename is test.h and clang thinks you are compiling C code, not C++ code. Hence, when you include <cassert>, clang doesn't know it should be looking at the C++ include path. Try naming your file test.hpp. You only have to name the file you want as the precomp header with .hpp. You can keep all your header files with .h extensions.
In any case, I might be getting this confused with gcc/g++, but Clang follows the same behavior whenever I compile my code on Mac. This is how I make use of precompiled headers. Read on...
If you've got a C++ header file you want to precompile, just compile it as any other .cpp file. Notice that I'm using .hpp as the file extension so the compiler picks it up as a C++ header file.
clang -c precomp.hpp
This will produce precomp.hpp.gch
Now to use the precomp by any other ordinary C++ file, just include the ordinary .hpp file:
// main.cpp
#include "precomp.hpp"
void func1() {...}
void main() {...}
The compiler will automatically use the corresponding .gch file if its present in place of the original .hpp file.

C++ compilation clang error multiple output files

I can't figure out why i can't compile my program with
g++ -std=c++0x main.cpp Sale.h iProduct.h -o w7
every time i try and compile with this command i get a clang error
clang: error: cannot specify -o when generating multiple output files
the program complies fine as a.out and i know i could just rename the a.out file and be on my way but i would like to know why I'm getting this error and how i should fix it.
Thanks
why I'm getting this error and how i should fix it
may I ask why do the .h files affect it?
Because of recent versions of gcc can compile heaader files,
Example:
g++ test.h -o out
file out
out: GCC precompiled header (version 014) for C++
It(gcc) produce precompiled files (https://en.wikipedia.org/wiki/Precompiled_header) in this case.
So when you compile .cpp file and header at the same time,
it can not decide what produce as output precompiled headers, or elf executable.

Automatically split (refactor) .h into header and implementation (h+cpp)

When writing C++ code, I often start by writing full 'implementation' code in my header files, then later need to refactor the implementation into a .cpp file.
This is great, but I find this process laborious, but otherwise pretty easy, so I wondered about whether is there any automated way to do this?
Specifically, I want to convert all class and function definitions in the .h to declarations, and have them declared in a new .cpp file.
I'm using xcode, but I am open to any solutions.
There is Lazy C++ where you only write one .lzz file and it generates .h and .cpp for you.
I am really looking forward for C++ modules where you only write .cpp and the import file is generated automatically. But we will have to wait for a few years even though Clang has started to implement modules. Here are some examples.
You can use some tools such as Makeheaders
http://www.hwaci.com/sw/mkhdr/
but in general, these tools are not complete, especially meeting new c++11 files.
You may be also interested in Eclipse's function "Refactor/Toggle function". It not always work properly however.
C++20 modules essentially do that for us
As mentioned at: https://quuxplusone.github.io/blog/2019/11/07/modular-hello-world/ clang 2019-11 implements it along:
clang++ -std=c++2a -c helloworld.cpp -Xclang -emit-module-interface -o helloworld.pcm
clang++ -std=c++2a -c -fprebuilt-module-path=. -o helloworld.o helloworld.cpp
clang++ -std=c++2a -fprebuilt-module-path=. -o main.out main.cpp helloworld.o
where:
helloworld.cpp contains the implementation
helloworld.pcm is a precompiled module, basically an auto-extracted header from the .cpp (but in a clang internal language format) which gets used by main.cpp without an .hpp
So basically clang is the tool, and thus parsing is perfect.

equivalent gcc flags for g++ call

I'm playing around with a toolchain that seems to wrap gcc (qcc), but also uses g++ for a few things. This caused a bit of confusion when I couldn't link libs I built with g++ using g(q)cc even though it was for the same architecture (due to missing lib errors). After a bit more research, I found that g++ is basically gcc with a few default flags and a slightly different interpretation mechanism for file extensions (there may be other differences I've glanced over). I'd like to know exactly which flags can be passed to gcc to amount to the equivalent g++ call. For instance:
g++ -g -c hello.cpp // I know at the very least that this links in stl
gcc -g -c -??? // I want the exact same result as I got with g++... what flags do I use?
The way the tool chain is set up makes it sort of difficult to simply replace the gcc calls with g++. It'd be much easier to know which flags I need to pass.
The differences between using gcc vs. g++ to compile C++ code is that (a) g++ compiles files with the .c, .h, and .i extensions as C++ instead of C, and that (b) it automatically links with the C++ standard library (-lstdc++). See the man page.
So assuming that you're not compiling .c, .h., or .i files as C++, all you need to do to make gcc act like g++ is add the -lstdc++ command line option to your linker flags. If you are compiling those other files as C++, you can add -x c++, but I'd advise you instead to rename them to use .cc or .ii files (.h can stay that way, if you're using precompiled headers).

gcc compilation without using system defined header locations

I am attempting to compile a c++ class using gcc. Due to the nature of the build, I need to invoke gcc from a non-standard location and include non-system defined headers, only to add a set from a different location. However, when I do this, I run into an issue where I cannot find some base symbols (suprise suprise). So i am basically running this command to compile my code:
-->(PARENT_DIR)/usr/bin/gcc # invoke compiler
-B$(PARENT_DIR)/usr/lib64/gcc/suselinux-x8664
-B$(PARENT_DIR)/usr/lib64
#C/C++ flags
-fPIC -fvisibility=default -g -c -Wall -m64 -nostdinc
# source files
-I$(SRC_DIR_ONE)/
-I$(SRC_DIR_TWO)
-I../include
# 'Mock' include the system header files
-I$(PARENT_DIR)/usr/include/c++/$(GCC_VERSION)
-I$(PARENT_DIR)/usr/include/c++/$(GCC_VERSION)/backward
-I$(PARENT_DIR)/usr/include/c++/$(GCC_VERSION)/x86_64-suse-linux
-I$(PARENT_DIR)/usr/lib64/x86_64-suse-linux/$(GCC_VERSION)/include
-I$(PARENT_DIR)/usr/lib64/gcc/x86_64-suse-linux/$(GCC_VERSION)/include
-I$(PARENT_DIR)/usr/lib64/gcc/x86_64-suse-linux/$(GCC_VERSION)/include-fixed
-I$(PARENT_DIR)/usr/src/linux/include
-I$(PARENT_DIR)/usr/x86_64-suse-linux/include
-I$(PARENT_DIR)/usr/include/suselinux-x8664
-I$(PARENT_DIR)/usr/suselinux-x8664/include
-I$(PARENT_DIR)/usr/include
-I$(PARENT_DIR)/usr/include/linux
file.cpp
I am getting several errors which indicate that the base headers are not being included: such as:
$(PARENT_DIR)/usr/include/c++/$(GCC_VERSION)/cstddef ::prtdiff_t has not been declared
$(PARENT_DIR)/usr/include/c++/$(GCC_VERSION)/cstddef ::size_t has not bee declared.
Is there something that I am doing wrong when I include the header file directories? Or am I looking in the wrong place?
Perhaps the --sysroot arg would help, see gcc docs.