Hi Jussi,

before we continue let me add some words to avoid misunderstandings. In
no way I'm trying to cast a bad light on CMake or want to defend our
trial approach "just because". But before I consider to support a
different approach I want to get the essential problems discussed in the
same depth as we did it ourselves when evaluating the GNU Make approach.

If CMake solved our essential problems it could be a nice alternative as
it gives us the additional benefit of possible "native" builds on
Windows (I assume we could still choose to use GNU Make also on
Windows/Cygwin for now).

Of course, TANSTAAFL: I'm sure we will be the first to explore this
(native Windows builds with CMake) for a project of such a big size and
diversity. Surely we will find many "interesting" problems. But that
shouldn't stop us from discussing it now. :-)

Jussi Pakkanen wrote:

> On Thu, Jan 21, 2010 at 10:50 AM, Mathias Bauer <mathias.ba...@sun.com> wrote:
> 
>> So, how can we implement "include, not execute" with CMake?
> 
> You can do this, if it is absolutely necessary. I'll describe that at
> the end of the message.
> 
>> Consider that you have the modules A, B, C and D. D depends on B and C,
>> that both depend on A. This is reflected by corresponding entries in the
>> build.lst files of these modules. Let's assume what happens if I forget
>> to add the dependency on A in the build.lst from C.
>>
>> When I do a complete build from scratch for module D, it will work if B
>> is built before C as building B will also build A, so C got its
>> precondition met and will build fine also. If C is built before B, the
>> build will break as it will miss A.
> 
> CMake has no concept of "modules" as used in OOo. My understanding is
> that a "module" is roughly one subdirectory (or as defined in
> build.lst) that produces one or more libraries, executables and so on.

As I wrote, it doesn't matter if we are looking at "modules" or single
targets (libraries, jar files, executables etc.), the problem is the
same. I just started with "modules" as this is what we have now.

> In CMake all dependencies are between deliverables (i.e. libraries,
> binaries, etc). Subdirectories are just a convenience. So in your
> example we would have in subdirectory A something like this:
> 
> add_library(A SHARED sourceA.cxx)
> 
> Then in B you would have
> 
> add_library(B SHARED sourceB.cxx)
> target_link_libraries(B A)
> 
> Similarly in C you would have
> 
> add_library(C SHARED sourceC.cxx)
> target_link_library(C A)
> 
> And finally in D:
> 
> add_executable(foo source.cxx)
> target_link_library(D C B)
> 
> What happens if we change C to accidentally remove the dependency to A?
> 
> When make is run, it will produce a link error for C. It will not use
> a stale library file one you may have in your build tree. Thus the
> error will be immediately apparent to the person doing the change so
> he will not check in code that will break on other people.

Sure? What if you do a parallel build and "by accident" the library A is
built before C is linked? That's exactly what happens in our current
build system. For this trivial example it is close to impossible that a
bug like this one stays unnoticed. But the multitude of targets and
dependencies we have in OOo makes it much more probable to happen. And
experience proves that: it happens at times and is a major PITA.

The step forward in the "all in one process" solution is that the
possible link error is detected in the process of checking the
dependency tree, regardless how much stuff is built afterwards and how
many parallel processes you will use then. I still can't see how this is
done with CMake. It's totally possible that this is my fault. ;-)

The CMake documentation isn't very helpful here. I can mainly see very
trivial examples, nothing that comes even close to the complexity we
have in OOo.

Beside that I wouldn't be astonished if CMake couldn't do that - in my
current (admittedly limited) understanding CMake never is meant to
explore the whole dependency tree from top level binaries down to the
included header files (or even further in case they are generated from
other sources). That's what happens in the created "native" makefiles.
Or does CMake double that effort and evaluates all dependencies by
itself before the "native" makefile does the same again?

> I tested the behavior just now with a sample to make sure it actually
> does this. I can send a sample project if someone wants to try it
> themselves.

I would appreciate to be able to get my hands on it. :-) Trying is so
much better than talking. Until now I only found rather trivial examples
in the web (even more trivial like my examples with 4 libraries).

I also will have a look on what Martin Hollmichel has created until now,
maybe we already have something to try and see.

>> Wouldn't it be better if the error detection is "built in"?
> 
> Yes, and with CMake, it already is. :)

So CMake *does* check all source and header files, libraries etc.? How
does it do that? In GNU Make e.g. you either have to specify header
files as prerequisites (what nobody with a sane mind would do) or
generate .d files "on the fly" and include them into the makefile.

> What CMake does is roughly the same. Whenever you run make, it checks
> whether the build setup has changed (in practice, whether
> CMakeLists.txt's have been touched) in any way. If yes, then it will
> automatically recheck the build system's validity and regenerate the
> necessary makefiles. Then it runs make.

So will CMake detect the missing dependency while it creates the
"native" makefiles?

BTW: those CMakeList.txt files are a PITA. We are currently moving away
from cluttering our source tree with files that are not under control of
the SCM. Is there a way to avoid the placement of these files into the
source tree? Can it be put somewhere else?

> If you do something like this in CMake:
> 
> target_link_libraries(some_exe misspelled_or_missing_library_name)
> 
> it will not detect it before build starts (because the latter may be a
> system library such as xlib) but it will give an error when linking
> some_exe. It will not allow it to pass.

Again this is the problem I want to avoid: errors caused by missing
dependencies/prerequisites don't appear before you actually execute the
build. This leaves too much room for random behavior caused by parallel
builds.

BTW: how does CMake organize the parallel build? The "all in one
process" approach has another major advantage: as it is one process, it
can find the optimum distribution for the available processes. This is
not possible if the build runs in several processes, even if they are
called recursively.

If we e.g. have 16 processes avalailable (a good number for 8 cores), a
single process would always use 16 processes to build 16 targets and
never run dry.

In case the "central" make has to start e.g. 50 processes, it has to
decide if it should start e.g. 4 of them and give each of them 4
processes or 8 of them with 2. The latter is what we do now and we
already have proven that this give mediocre scalability already for 8
processes (4 cores).

> CMake allows CMake script files to include other files. You could
> write a subdir.cmake file for each module/subdir and then just include
> them in your master CMakeLists.txt. The end result is one makefile
> (or, I guess, O(1) makefiles due to implementation issues).
> 
> Since CMake solves the stability issue differently, I do not think you
> should do this. But if you really, really need to, you can.

And the actual build (execution of GNU Make or VC++) would happen in one
process?

Regards,
Mathias

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tools.openoffice.org
For additional commands, e-mail: dev-h...@tools.openoffice.org

Reply via email to