Decrease clang parse/reparse time with chained precompiled headers? - xcode

I'm working on text editor (almost IDE) and i'm using llvm/clang behind the scenes (tokenizing, diagnostics). Almost every file that is edited includes main header file which includes some headers too which include some other headers (tree of included files):
UserFile.h
L----MainHeader.h
L----string.h
L----device.h
| L----(in some conditions)---concreteDevice.h
L----math.h
|
...
The main idea is skip reparsing headers that remain the same during editing 'UserFile.cpp' in clang_parseTranslationUnit and clang_reparseTranslationUnit invocations.
I've read about Clang's chained precompiled headers or even modules which seems to be what i need.
I've generated PCH for MainHeader.h like clang++ -x c++-header MainHeader.h -emit-pch -o MainHeader.h.pch and used it like clang++ -include-pch MainHeader.h.pch .... I'm not sure if it's PCH for the whole headers tree (chained) or for that file only (most likely).
Do i need chained precompiled headers since there is CXTranslationUnit_PrecompiledPreamble clang option?
How can i generate chained precompiled headers?
Headers tree is pretty complicated because of multiple #ifdef SOME_CONDITION .. #include <SomeHeader.h> #endif and it's pretty difficult to understand the whole tree and precompile PCH for each header file manually (but i do know arguments -DSOME_CONDITION to pass which affect inclusions tree).

Related

CMake: Use variables from existing Makefile of 3rdparty library

I'm facing the following scenario:
Existing project which uses cmake
External 3rdparty library which only comes with Makefiles
The difference of my situation compared to existing questions is that I don't need to have cmake to build the 3rdparty library via the Makefile. Instead, the 3rdparty library provides a library.mk Makefile which has variables like LIB_SRCS and LIB_INCS containing all source and header files required to compile the library.
My idea is to include the library.mk into the project's CMakeLists.txt and then adding those $(LIB_SRCS) and $(LIB_INCS) to target_sources().
My question: How can I include library.mk into the existing CMakeLists.txt to get access to the $(LIB_SRCS) and $(LIB_INCS) for adding them to target_sources()? I'm looking for something like this:
include("/path/to/library.mk") # Somehow include the library's `library.mk` to expose variables to cmake.
add_executable(my_app)
target_sources(
my_app
PRIVATE
main.c
$(LIB_SRCS) # Add 3rd-party library source files
$(LIB_INCS) # Add 3rd-party library header files
)
Using include() does not work as the library.mk is not a CMake list/file.
Since you can't be sure that your target system will even have Make on it, the only option is to parse the strings out of the .mk file, which might be easy if the variables are set directly as a list of filenames, or really hard if they are set with expansions of other variables, conditionals, etc. Do this with FILE(STRINGS) cmake doc.
Your plan will only work if the Makefiles are trivial, and do not set important compiler flags, define preprocessor variables, modify the include directory, etc. And if they really are trivial, skip the parsing, and just do something like aux_source_directory(<dir> <variable>) to collect all the sources from the library directory.
You might also consider building and maintaining a CMakeLists.txt for this third-party library. Do the conversion once, and store it as a branch off of the "vendor" main branch in your version control system. Whenever you update, update the vendor branch from upstream, and merge or rebase your modifications. Or just store it in your existing project, referring to the source directory of the 3rd-party stuff.

cmake - preprocess entire project and store output in file

i have a huge arm-none-eabi (gcc) cmake project.
i would like to run the entire project and abort after the preprocessor.
so example:
if i have 500 headers and 600 source files, i would like to get 1100 additional files after the preprocessor, all in a preprocessed state.
eg
// my procject
main.cpp
src/dummy.cpp
src/etc.cpp
...
// my project after preprocessor
main.cpp
main_preprocessed.cpp
src/dummy.cpp
src/dummy_preprocessed.cpp
...
if i just add the compiler flag -E, the prepocessing happens and thells me 'linker input file unused because linking not done'. which is ok, but i dont get the preprocessed files.
just preprocessing one file is no good to me because i would need to add a lot of header files with -I, which takes a long time.
ADDITIONAL INFO:
also, what is important is that i need my project files preprocessed. additionally to my project files i do have some libraries from different manufacturers, those i build first into a static lib, then link against the lib.

Scons: how to specify file dependency for 3rd party compile result?

It seem to me that scons targets are being generated not in declaration sequence. My problem is, I need to generate some code first, I'm using protoc to process a my.proto file into .h and .cc file, I need some pseudo code like this(what should the working code look like?)
import os
env=Environment(ENV=os.environ,LIBPATH='/usr/local/lib')
env.ShellExecute('protoc', '--outdir=. --out-lang=cpp', 'my.proto')//produces my.cc
myObj=Object('my.cc')//should wait until 'my.cc' is generated by protoc
Dependency(myObj, 'my.cc')
mainObj=Object('main.cpp')
My question is:
How to specify this ShellExecution of protoc in SConstruct/SConscript?
How to make sure that the compilation of 'main.cpp' depends on the existence of 'my.cc', in another word, wait until 'my.cc' is generated and then execute?
Your observations and assumptions are correct, SCons will not execute the single build commands in the order that you list them in the SConstruct files. It will run them based on the dependencies of the targets and source files in your build, either defined implicitly (header includes in C++, for example) or explicitly (via the Depends() method).
So you have to define and setup your dependencies correctly, such that SCons delivers the output that you want. For the special protoc case in your example, a special Builder exists that will help you to get the dependency graph right. It is available in our ToolsIndex, where also support for a variety of other languages and dialects can be found.
These special builders will emit the correct target nodes, e.g. when given a *.proto input file, and SCons is then able to automatically detect the dependency between the protoc input file and your main program if you say something like:
env=Environment(tools=['default','protoc'])
env.Protoc([], "test.proto")
env.Program('main', ['main.cpp'] + Glob('*.cc'))
The Glob('*.cc') will detect your *.cc files, coming out of the protoc Tool, and include them as dependencies for your final target main.
You can always write your own Builders and Emitters in SCons, which is the canonical way of making new tools/toolchains known to SCons dependency analysis. In the UserGuide, sect. "18 Writing Your Own Builders", and especially our ToolsForFools Guide you can find more infos about this.

Best way to define makefile dependencies when the compiler doesn't generate them?

I'm creating a makefile to build an existing project. We're using GNU Make 4, but the compiler doesn't automatically generate dependency information so I'm trying to determine the best way to specify dependencies for code that includes header files which in turn may include header files. Due to the complexity of the codebase, I think it will be unrealistic to traverse the entire #include tree, gather up all the header files, and then specify them for each source file.
One solution is to create makefile definitions of each header file and its direct dependencies, then create a recipe for a header file that touches that header file to trigger the recompile of the source that includes it:
a123.o: a123.c header1.h
header1.h: header2.h
header2.h: header3.h
# Recipes
%.o:
# compile command for building a .o
%.h:
#touch $#
This seems to work; if header3.h changes, then the %.h recipe updates header2.h's timestamp, which causes header1.h's timestamp to be updated, which causes a123.o to be rebuilt.
However, it seems messy, with all the touching, plus it seems odd to create a recipe for a source file that isn't directly compiled. Is this the correct way to do this sort of thing, or is there a cleaner approach? Please note that I simplified my question; in reality several languages are in use with different file extensions, the compiler isn't GCC, and the output isn't a .o file. But the logic is exactly the same.

force object files in current directory even when subdir-objects is on

I have 2 libraries that share same source files:
# src/lib_mt/Makefile.am:
libppb_la_SOURCES = rphs_mt.c timer_mt.c
# src/sipplib/Makefile.am:
libsipp_a_SOURCES = ../lib_mt/rphs_mt.c ../lib_mt/timer_mt.c
Each source file compiled twice. First for lib_mt with -fPIC, second for sipplib without -fPIC.
Object files for each library created in corresponding directory.
Eventually subdir-objects becomes default. How to keep current behavior for these 2 source files? Some explicit rule maybe?
There is no way to disable that the moment it becomes the default. What you can do instead is migrate this to a non-recursive Automake buildsystem. At that point, it will know that there are different targets compiling the same source files with different flags (it requires AC_PROG_CC_C_O to be called in configure.ac.)
Alternatively, the hacky version is to create a src/sipplib/rphs_mt.c file that only contains
#include "../libmt/rphs_mt.c"
so that it is actually a separate build target.

Resources