0

The background about this question is: my project(C++ language) contains too many files, which including boost, thrift, zookeeper, etc. Now the compilation duration takes too long.

As you know, Visual Studio supports precompiled headers, so as GCC. Because I use automake to manager the Make procedure, so What I want to ask for is whether automake supports precompiled headers? How can I write automake files if so?

Waiting and thranks for your answers.

Roland Yim
  • 36
  • 6
  • Just use `ccache`. `.gch` approach is unreliable – basin Dec 26 '15 at 10:46
  • Thanks @basin Does ccache support automake? I have read ccache help documents in its site, what I understand is that ccache only takes effect on previous built resulst, not the first time when you build the project, is it right? – Roland Yim Dec 26 '15 at 11:37
  • `ccache` does not conflict with it, yes, it only good for when you recompile often. – basin Dec 26 '15 at 14:02

1 Answers1

2

The whole thing is not about automake, but rather about writing makefiles.

Actually, you can try the .gch, but there're restrictons:

  • write one common header to include everything (like stdafx.h)
  • It should be the 1st include in all your sources
  • use same CFLAGS to compile all your sources

It's a new functionality. You'd want to detect it in your configure.ac

Write a rule in your Makefile.am, name it like stdafx.gch:. Make it empty, if gch is not supported:

stdafx.gch: stdafx.h
    $(OPTIONAL_COMPILE_GCH)
.PHONY: $(OPTIONAL_STDAFX_GCH)

Make your _OBJECTS depend on stdafx.gch:

$(foo_SOURCES:.cpp=.$(OBJEXT)): stdafx.gch
# or (is it documented var?)
$(foo_OBJECTS)): stdafx.gch

Youc can use the documented CXXCOMPILE command to be sure that all CXXFLAGS are the same.

Detect in your configure.ac:

if ...; then
    [OPTIONAL_COMPILE_GCH='$(CXXCOMPILE) -c -o $@ $<']
    [OPTIONAL_STDAFX_GCH=]
else
    [OPTIONAL_COMPILE_GCH=]
    [OPTIONAL_STDAFX_GCH='stdafx.gch']
fi
AC_SUBST(OPTIONAL_COMPILE_GCH)
AC_SUBST(OPTIONAL_STDAFX_GCH)

Update

You want your .gch to be recompiled, when any header file indirectly used by stdafx.h is modified.

Then you could add stdafx.cpp that does nothing, but includes stdagx.h and make .gch depend on stdafx.o. This way the dependency tracking would be managed by automake, but there's a problem:

stdafx.o itself could make use of .gch to compile faster, but if we add such dependency, it would be circular. It's not easy for me to find a solution.

Here's an example that uses status files to solve this: https://gist.github.com/basinilya/e00ea0055f74092b4790

Ideally, we would override the compilation command for stdafx.o, so it first creates .gch and then runs the standard automake compilation, but automake does not use $(CXXCOMPILE) as is. It creates a complex recipe from it (and it depends on automake version):

Update 2

Another solution is to use gcc dependency tracking directly:

stdafx.h.gch: stdafx.h
    g++ -MT stdafx.h.gch -MD -MP -MF .deps/stdafx.Tpo -c -o stdafx.h.gch stdafx.h
    mv .deps/stdafx.Tpo .deps/stdafx.Po

-include .deps/stdafx.Po

By default, if precompiled header is used, gcc -MD will not put the list of header files into the generated dependencies file, just .gch. There's an option to fix this : -fpch-deps (see bug), but perhaps the default behavior is not that bad: if only the .gch depends on the headers, make will have less work to do.

basin
  • 3,949
  • 2
  • 27
  • 63
  • Thanks @basin. My project's struct is just same as your description, and it can be built using VS2010(used precompiled-headers). I don't know how to implement precompiled-headers in automake or GCC. Your solution is perfect, followings are my understanding: 1) generate precompiled-headers as gch-suffix obj files. 2) add the gch-suffix obj files into *_SOURCES. 3) then gcc will use precompiled-headers automaticly. Would the *.gch be compiled automatically when some precompiled-headers changes? – Roland Yim Dec 26 '15 at 15:16
  • It will make sense, if you have just one precompiled header. Include `boost` etc. in `stdafx.h` – basin Dec 26 '15 at 16:50
  • > `Would the *.gch be compiled automatically when some precompiled-headers changes?` You can rely on `automake` dependencies tracking. Just add `stdafx.cpp` that does nothing, but includes `stdafx.h` (just like in VisualStudio). Then make the `gch` depend on `stdafx.$(OBJEXT)`. Don't add that `.cpp` to `_SOURCES` to avoid circular dependency – basin Dec 26 '15 at 16:53
  • There's a problem with above: if `.gch` depends on `stdafx.o`, then `.gch` cannot be used to compile `stdafx.o` – basin Dec 26 '15 at 17:03
  • As you said, The Makefile should be: stdafx.gch: stdafx.o stdafx.o: stdafx.cpp $(CXXCOMPILE) -c -o $@ $<' *_SOURCES = stdafx.gch This can solve the change-and-recompile problem, Thanks very much, You are very knowledgeable and professional. How should I translate this into automake? Do you have some advice on this? – Roland Yim Dec 26 '15 at 17:34
  • Everything you put in `Makefile.am` will appear in `Makefile` (with some exceptions) – basin Dec 26 '15 at 17:37
  • Thanks a lot, I got it! – Roland Yim Dec 26 '15 at 17:40
  • I test the precompiled-headers solution, the result seems strange. using precompilded-header takes: real 5m52.302s user 20m55.365s sys 1m22.463s but not using precompiled-header takes real 4m48.445s user 17m27.339s sys 1m9.939s – Roland Yim Dec 28 '15 at 03:51
  • @rolandrxw Check your dependencies files in `.deps/`. If they're big, gcc ignores your precompiled header – basin Dec 28 '15 at 11:13
  • Thanks @basin. On your help I have implemented the precompiled-headers in automake. Following are the results: not using precompiled-headers:real 10m59.815s user 35m59.854s sys 2m43.815s using precompiled-headers:real 7m59.478s user 21m23.465s sys 2m4.518s – Roland Yim Dec 29 '15 at 10:01