2

I am trying to time how long each file in my codebase takes to compile.

According to this SO answer, you can write a script which does times the actual compilation and then stores the results in a file

/tmp/time-build:

#!/bin/bash
{ time g++ "$@"; } 2> >(cat <(echo "g++ $@") - >> /tmp/results.txt)

You can then override CMAKE_CXX_COMPILER when calling cmake so that make uses the script to perform the compilation

cmake .. -DCMAKE_CXX_COMPILER=/tmp/time-build
make

This works as advertised, and yields results similar to the following:

real    0m1.190s
user    0m1.044s
sys     0m0.140s
g++ -Werror -Wall -Wextra ... /src/test/foo.cpp

However, to ease processing, I would like to store only the real time, and have it on the same line as the g++ command.

Question:

My command line fu is not up to the task of turning this:

{ time g++ "$@"; } 2> >(cat <(echo "g++ $@") - >> /tmp/results.txt)

Into a command which captures only the real output of time, and includes it along with the echo "g++ $@" on a single line.

I don't know what the >(cat <( and ) - parts of the above command mean, and my attempts to incorporate a grep real and echo have failed

How can I do that?

Alternately, if there is a more idiomatic way to get cmake to output timings for each file processed, that too would be ideal.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
Steve Lorimer
  • 27,059
  • 17
  • 118
  • 213
  • 1
    Add a bit of `sed` trickery inlined? – πάντα ῥεῖ Jun 29 '17 at 14:16
  • @πάνταῥεῖ can you suggest some? – Steve Lorimer Jun 29 '17 at 14:17
  • Well, my sed fu is just a bit rusty now ;-). Did you spot the [related](https://stackoverflow.com/questions/5962285/cmake-compilation-statistics) question? – πάντα ῥεῖ Jun 29 '17 at 14:19
  • If you already use CMake, I recommend you use ninja instead of make (with `-G Ninja`), which outputs compilation times into `.ninja_log` file. – Ilya Popov Jun 29 '17 at 14:20
  • @πάνταῥεῖ yes, that is the question I linked to in this one, and the comment on the answer I referred to is from me! No answer there yet, so hence this question – Steve Lorimer Jun 29 '17 at 14:20
  • @Steve Ah, sorry I didn't spot the link (was my 1st google result). Nevertheless piping the result of `time` to `sed` should do what you want according to [this post](https://stackoverflow.com/questions/2112469/delete-specific-line-numbers-from-a-text-file-using-sed) easily. – πάντα ῥεῖ Jun 29 '17 at 14:23

2 Answers2

3

Probably the best way to get compile times for a CMake-based project is to use ninja instead of make.

To do this you have to specify ninja generator while configuring:

cmake -G Ninja <...>

Then build using ninja:

ninja

After that, look at the file called .ninja_log. First column is start time in milliseconds, second is end time, forth is target name and the last one is a hash of the command line used.

There are even some solutions for viewing and analyzing this log: ninjatracing converts .ninja_log to a format readable by Chrome's tracing tool.

Ilya Popov
  • 3,765
  • 1
  • 17
  • 30
1
cmd=(clang "$@")
{ time "${cmd[@]}"; } 2> >( tee >( real=$(grep -Po 'real\K.*'); echo "${cmd[*]} $real" >>result.txt ) )
Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36