[CMake] Reusing an already built object

Linghua Tseng uranus at tinlans.org
Fri Jun 11 22:10:44 EDT 2010


Continue the lastest post of this article:
http://www.cmake.org/pipermail/cmake/2009-October/032615.html

> On Tuesday 13 October 2009, Alexander Neundorf wrote:
> > On Tuesday 13 October 2009, Naram Qashat wrote:
> > Say I have a main executable and a number of shared libraries that rely on
> > that executable.  Say I have a certain C++ source that is required to be
> > built by not only the main executable, but also every single shared library
> > (the source in question is a Windows-specific file to handle memory
> > allocations).  I have found that when using a Visual Studio generator,
> > CMake causes the source file to be rebuilt for every single shared library,
> > causing an increase in build time.  Is there an easy way to have the object
> > file not be rebuilt every single time, but be reused for all the shared
> > libraries?  
> 
> No, it's a feature.
> You may use different compile flags etc. for your different targets, so you 
> may get different object files.
> 
> You may hack around that by creating a static library, figuring out the path 
> to the object files and then link these object files directly to your targets 
> (or something like that, but I've never done that and I don't recommend it).

Consider the following scenario:

gcc -c src1.c
gcc gen_src2.c -o gen_src2 src1.o
./gen_src2 > src2.c

gcc -c src2.c
gcc gen_src3.c -o gen_src3 src1.o src2.o
./gen_src3 > src3.c

gcc -c src3.c
gcc gen_src4.c -o gen_src4 src1.o src2.o src3.o
./gen_src4 > src4.c

...

gcc -c src99.c
gcc gen_src100.c -o gen_src100 src1.o src2.o src3.o ... src99.o
./gen_src100 > src100.c

gcc -c src100.c
ar rcu libmylib.a src1.o src2.o src3.o ... src100.o


To create a project by using CMake,
we'll have several targets by using add_executable():
  gen_src2, gen_src3, gen_src4, ... gen_src100
And we'll have a target by using add_library():
  mylib

Assume we already have gen_src1.c, gen_src2.c, ..., gen_src100.c, and src1.c
Without lost of generality, I reduce the example to src1 ~ src4.
Then we have to write the following CMakeLists.txt:

project(main)
cmake_minimum_required(VERSION 2.8)

set(gen_src2_SRCS src1.c gen_src2.c)
add_executable(gen_src2 ${gen_src2_SRCS})
get_target_property(gen_src2_EXE gen_src2 LOCATION)
add_custom_command(
        OUTPUT src2.c
        COMMAND ${gen_src2_EXE}
        ARGS > src2.c
        DEPENDS gen_src2
)

set(gen_src3_SRCS src1.c ${PROJECT_BINARY_DIR}/src2.c gen_src3.c)
add_executable(gen_src3 ${gen_src3_SRCS})
get_target_property(gen_src3_EXE gen_src3 LOCATION)
add_custom_command(
        OUTPUT src3.c
        COMMAND ${gen_src3_EXE}
        ARGS > src3.c
        DEPENDS gen_src3
)

set(gen_src4_SRCS src1.c ${PROJECT_BINARY_DIR}/src2.c ${PROJECT_BINARY_DIR}/src3.c gen_src4.c)
add_executable(gen_src4 ${gen_src4_SRCS})
get_target_property(gen_src4_EXE gen_src4 LOCATION)
add_custom_command(
        OUTPUT src4.c
        COMMAND ${gen_src4_EXE}
        ARGS > src4.c
        DEPENDS gen_src4
)

set(mylib_SRCS src1.c
               ${PROJECT_BINARY_DIR}/src2.c
               ${PROJECT_BINARY_DIR}/src3.c
               ${PROJECT_BINARY_DIR}/src4.c
)
add_library(mylib ${PROJECT_BINARY_DIR}/src4.c)

Now the compile-flow shows:
[  5%] Building C object CMakeFiles/gen_src2.dir/src1.c.o
[ 10%] Building C object CMakeFiles/gen_src2.dir/gen_src2.c.o
Linking C executable gen_src2
[ 10%] Built target gen_src2
[ 15%] Generating src2.c
[ 21%] Building C object CMakeFiles/gen_src3.dir/src1.c.o
[ 26%] Building C object CMakeFiles/gen_src3.dir/src2.c.o
[ 31%] Building C object CMakeFiles/gen_src3.dir/gen_src3.c.o
Linking C executable gen_src3
[ 31%] Built target gen_src3
[ 36%] Generating src3.c
[ 42%] Building C object CMakeFiles/gen_src4.dir/src1.c.o
[ 47%] Building C object CMakeFiles/gen_src4.dir/src2.c.o
[ 52%] Building C object CMakeFiles/gen_src4.dir/src3.c.o
[ 57%] Building C object CMakeFiles/gen_src4.dir/gen_src4.c.o
Linking C executable gen_src4
[ 63%] Built target gen_src4
[ 68%] Generating src4.c
[ 73%] Building C object CMakeFiles/mylib.dir/src1.c.o
[ 78%] Building C object CMakeFiles/mylib.dir/src2.c.o
[ 84%] Building C object CMakeFiles/mylib.dir/src3.c.o
[ 89%] Building C object CMakeFiles/mylib.dir/src4.c.o
Linking C static library libmylib.a
[100%] Built target mylib

In this case, `src1.c.o' was built 4 times.
If the example is src1~src100, it will need to be compiled 100 times.
It's really unnecessary because I don't want to use different CFLAGS for building them.
I know someone said I can build static libraries for avoiding this,
but it will fall into another issue:
[Cmake] How do I link a static library into a library
http://www.cmake.org/pipermail/cmake/2004-April/004990.html
Therefore, it still cannot solve my problem.

The scenario is simplified from a real application (a compiler's source code).
In order to port that compiler to a new target,
developers need to write some description files and execute generators to produce target-dependent codes.
The software architecture is not designed by me,
so I cannot change it although I know it's really a bad design.

I think this feature is really not suitable for this case.
Wouldn't anyone like to add an option or a command to disable it?


More information about the CMake mailing list