I came across several SO questions regarding specific aspects of improving the turn-around time of CMake enabled C++ projects lately (like "At what level should I distribute my build process?" or "cmake rebuild_cache for just a subdirectory?"), I was wondering if there is a more general guidance utilizing the specific possibilities CMake offers. If there is probably no cross-platform compile time optimization, I'm mainly interested in Visual Studio or GNU toochain based approaches.
And I'm already aware of and investing into the generally recommended areas to speed up C++ builds:
Change/Optimize/fine-tune the toolchain
Optimize your code base/software architecture (e.g by reducing the dependencies and use well-defined sub-projects - unit tests)
Invest in a better hardware (SSD, CPU, memory)
like recommended here, here or here. So my focus in this question is on the first point.
Plus I know of the recommendations to be found in CMake's Wiki:
CMake: building with all your cores
CMake Performance Tips
The former just handles the basics (parallel make), the later handles mostly how to speed-up parsing CMake files.
Just to make this a little more concrete, if I take my CMake example from here with 100 libraries using MSYS/GNU I got the following time measurement results:
$ cmake --version
cmake version 3.5.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
$ time -p cmake -G "MSYS Makefiles" ..
-- The CXX compiler identification is GNU 4.8.1
...
-- Configuring done
-- Generating done
-- Build files have been written to: [...]
real 27.03
user 0.01
sys 0.03
$ time -p make -j8
...
[100%] Built target CMakeTest
real 113.11
user 8.82
sys 33.08
So I have a total of ~140 seconds and my goal - for this admittedly very simple example - would be to get this down to about 10-20% of what I get with the standard settings/tools.
Here's what I had good results with using CMake and Visual Studio or GNU toolchains:
Exchange GNU make with Ninja. It's faster, makes use of all available CPU cores automatically and has a good dependency management. Just be aware of
a.) You need to setup the target dependencies in CMake correctly. If you get to a point where the build has a dependency to another artifact, it has to wait until those are compiled (synchronization points).
$ time -p cmake -G "Ninja" ..
-- The CXX compiler identification is GNU 4.8.1
...
real 11.06
user 0.00
sys 0.00
$ time -p ninja
...
[202/202] Linking CXX executable CMakeTest.exe
real 40.31
user 0.01
sys 0.01
b.) Linking is always such a synchronization point. So you can make more use of CMake's Object Libraries to reduce those, but it makes your CMake code a little bit uglier.
$ time -p ninja
...
[102/102] Linking CXX executable CMakeTest.exe
real 27.62
user 0.00
sys 0.04
Split less frequently changed or stable code parts into separate CMake projects and use CMake's ExternalProject_Add() or - if you e.g. switch to binary delivery of some libraries - find_library().
Think of a different set of compiler/linker options for your daily work (but only if you also have some test time/experience with the final release build options).
a.) Skip the optimization parts
b.) Try incremental linking
If you often do changes to the CMake code itself, think about rebuilding CMake from sources optimized for your machine's architecture. CMake's officially distributed binaries are just a compromise to work on every possible CPU architecture.
When I use MinGW64/MSYS to rebuild CMake 3.5.2 with e.g.
cmake -DCMAKE_BUILD_TYPE:STRING="Release"
-DCMAKE_CXX_FLAGS:STRING="-march=native -m64 -Ofast -flto"
-DCMAKE_EXE_LINKER_FLAGS:STRING="-Wl,--allow-multiple-definition"
-G "MSYS Makefiles" ..
I can accelerate the first part:
$ time -p [...]/MSYS64/bin/cmake.exe -G "Ninja" ..
real 6.46
user 0.03
sys 0.01
If your file I/O is very slow and since CMake works with dedicated binary output directories, make use of a RAM disk. If you still use a hard drive, consider switching to a solid state disk.
Depending of your final output file, exchange the GNU standard linker with the Gold Linker. Even faster than Gold Linker is lld from the LLVM project. You have to check whether it supports already the needed features on your platform.
Use Clang/c2 instead of Visual C++ compiler. For the Visual C++ compiler performance recommendations are provided from the Visual C++ team, see https://blogs.msdn.microsoft.com/vcblog/2016/10/26/recommendations-to-speed-c-builds-in-visual-studio/
Increadibuild can boost the compilation time.
References
CMake: How to setup Source, Library and CMakeLists.txt dependencies?
Replacing ld with gold - any experience?
Is the lld linker a drop-in replacement for ld and gold?
For speeding up the CMake configure time see: https://github.com/cristianadam/cmake-checks-cache
LLVM + Clang got a ~3x speedup.
Related
I'm a llvm new learner
after cmake -S llvm -B build -G Xcode -DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi"
I got a llvm project, compiling the project is so slow
How to make it compile faster?
Ninja is an option.
from the build folder, I see libLLVMWindowsManifest.a
i don't need windows platform version.
I just need X86 version
How to make the complier do less job, by avoid compiling unrelated CPU architecture?
-DLLVM_TARGETS_TO_BUILD="X86" is the flag you're looking for. But this alone won't speed up the build time significantly.
Play with CMAKE_BUILD_TYPE (-DCMAKE_BUILD_TYPE=Release/Debug/RelWithDebInfo/MinSizeRel) and see which suits you better. The default for CMAKE_BUILD_TYPE is Debug, and it's very slow.
If you want to debug builds, -DLLVM_OPTIMIZED_TABLEGEN=ON will improve your build time.
And finally, in my experience Ninja builds are slightly faster.
1. cmake is a command from CMake software: preparation for build automation system; make and make install are commands from Make software: build automation system.
2. From reading this post, what I understand is that:
a. This "cmake and make" stuffs actually use g++ / gcc in its implementation. cmake and make stuffs are basically just tools in using g++ / gcc. Is that correct?
b. gcc / g++ are the compiler that do the actual work.
c. So I can just use gcc / g++ directly without using the make and CMake things?
3. According to this stackoverflow answer: CMake takes a CMakeList.txt file, and outputs it to a platform-specific build format, e.g., a Makefile, Visual Studio, etc.
However when I came across this openCV installation :
mkdir release
cd release
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
It executes cmake command in a directory where there is no CMakeLists.txt file. Can you explain and elaborate on this?
4. The usual steps that I've seen are: cmake, make, sudo make install.
I read this stackoverflow post, what I understand:
(i) make is for building the project.
(ii) make install is to copy the binary / executables to the installed directories.
a. So when we make, where are the result / binary files / executables stored at?
b. If we only run make without make install, does it mean that the files are not generated?
c. I came across this openCV tutorial on using openCV with GCC and CMake. It uses:
cd <DisplayImage_directory>
cmake .
make
Why doesn't it do make install as well?
5. In summary:
CMake takes CMakeList.txt file (which is cross platform) to generate a Makefile (which is specific to a platform).
I can just write Makefile manually and skip the CMake step. but it is better to do with the CMake step because it is cross platform, otherwise I have to rewrite the Makefile again if I change platform.
Make takes Makefile (which is generated by CMake or written manually) as a guide to compile and build. Make basically uses gcc / g++ or other compiler in its work. Make itself is just a tool for the compiler.
Make install put the result / executables into the install path
CMake generates files for other build systems. These can be Makefiles, Ninja files or projects files for IDEs like Visual Studio or Eclipse. The build files contain calls to compilers like GCC, Clang, or cl.exe. If you have several compilers installed, you can choose one.
All three parts are independent. The compiler, the build system and CMake.
It is easier to understand when you have the history. People used their compiler. Over time they added so many flags, that it was cumbersome to type them every time. So they put the calls in a script. From that the build systems (Make, Ninja) evolved.
The people wanted to support multiple platforms, compilers, scenarios and so on and the build system files became hard to maintain and their use was error-prone. That's the reason people invented meta build system that creates the files for the actual build system. Examples are Autotools or CMake.
Yes
CMake does not use your compiler, make does not implement it, but it calls (uses) the compiler.
The CMakeLists.txt file should be in the parent directory of release. The last argument of the CMake call indicates the path where the CMakeLists.txt file is located.
Right, make generates the file in the build directory. In your example from 3. release is the build directory. You can find all the generated files and use them. Installing is optional, especially if you want to develop the software, you are not installing it.
Try writing Makefiles for a large project and you will see how much work it is. But yes, everything in 5 is right.
I've done everything, and it's payed off.
Trying to compile a mex file from MATLAB using the Windows 7.1 SDK.
~ I've created an compiled my C source code on GCC
~ I've created a MEX file that links and compiles fine via GCC on both Linux and OS X. Does not crash MATLAB, gateway function works fine
~ After much confusion, I switched my dev platform form 64-bit to x86 Win7
~ I've found .dll built files, but they do not link. Linking libs in MATLAB using MATLAB's linker flags will default to .lib, so...
~ I've found--after much googling--simple, pre-compiled x86 GSL .lib's and source files and linked them with MATLAB, eliminating any gsl_blas.h-and-it's-dependencies unrecognized external symbol errors
~ I've re-written every single variable declaration in my source code such that it is C89 standard compatible
~ I've set linker flags appropriately to avoid LIBCMT and any other LIB conflicts
~ I've installed the 2010 and 2012 VC C Runtime libraries
~ I've checked to make sure I have msvcrt.dll and msvcp60.dll in my System files
~ I've followed multiple tutorials online on how supposedly link everything together, most of which had nothing broken links or un-replicable results. I didn't find much to go off of for Cygwin or MinGW.
~ I've tried using the Lcc-win32 2.4.1 compiler
If I was doing basic matrix and vector operations, I'd be set, but unfortunately the various decomposition routines I'm utilizing require parts from the cblas library, which I linked as well, but I get ~30 errors all reporting the same thing...
cblas.lib(ctrsv.obj) : error LNK2001: unresolved external symbol __libm_sse2_sqrt_precise
Here's my MATLAB command.
mex -largeArrayDims -IC:\gsl\include -LC:\gsl\lib -lgsl -lcblas LINKFLAGS="$LINKFLAGS /NODEFAULTLIB:libcmt.lib" file1.c file2.c
So, out of options and frustrated out of my mind, I (naturally) come to stack overflow. Anyone have any idea how to solve this one? The only thing I've foudn on google points to wineHQ errors, not very helpful.
And, if possible, I'd rather not try to compile first on VS201X. I have access to whatever version I need, if necessary, but to me that just seems like a redundant step. Maybe I'm spoiled with Unix-based file system management and linking, though.
It's easy to compile the GSL library under MinGW, in fact the process of compiling from sources is exactly identical to that in Linux. Here are the steps I took:
Setup MinGW for Windows. I am using MinGW-w64 but there is also the popular TDM-GCC distribution which comes with a friendly web-installer.
Obtain GSL sources, and extract the tarball (gsl-1.16.tar.gz is the latest as of now)
Compile as usual, I've used the following commands:
$ ./configure --host=x86_64-w64-mingw32 --prefix=/mingw/local --enable-shared --enable-static
$ make
$ make install
It should take several minutes to finish. Maybe you can enable parallel builds to speed up compilation (make -j)
You'll end up with the necessary files installed in /mingw/local with the usual structure underneath (bin, lib, include).
Finally you can compile an example program with:
$ export PATH=/mingw/local:$PATH
$ gcc `gsl-config --cflags` -o main main.c `gsl-config --libs`
Of course if you prefer using Visual C++ as compiler, people out there have prepared solutions to build GSL using Visual Studio (either manually created project files, or using a build system like CMake and the like). See this question for such projects.
A third option is using Cygwin.
I was just trying to understand something about cross compilers which made me ask this question.
gcc is a cross-compiler.
By default what it the target architecture for gcc compilation if none is specified is the native target on which I am compiling the source. Correct ?
If the above is correct then how does it manage to generate the code for several different architectures even when it is explicitly specified ?
Shouldn't it have to know all the ISA's ? How is this managed ? Do they have all the information for all the existing ISA's ?
A given (particular) gcc is built for a particular given target. Use gcc -v to find out which.
Often, cross-compilers are installed as different commands, e.g. avr-gcc on Debian for the Atmel AVR processor (with specific options ...)
On some architectures and systems (typically x86 & Linux) you may compile for a different variant. See this. In particular you may want to use -mtune=native or -march=haswell or -m32 ...
If you build gcc yourself from its source tarball, you'll give it at configure time specific configure options (e.g. --program-suffix=-avr and --target=avr for the avr-gcc etc....)
How does one overwrite the default compile flags for Cython when building with distutils?
My question is similar to this , but the response involved manually running the cython steps - given the progress from 0.12 to 01.9 - is it possible for me to simplyy switch from -O to -O3?
Also have users seen a significant difference in speed depending on this switch?
I am on a windows machine.
If you use a setup.py script you can set the "extra_compile_args" option (see https://stackoverflow.com/a/16402557/2355197). Depending on your code, you can see significant differences. For example, on GCC, -O3 enables the option "-finline-functions" which
considers all functions for inlining.
Davide