This forum has been archived. All content is frozen. Please use KDE Discuss instead.

[SOLVED] CMake: How determinate order of compilation of subdirs (to satisfy dependency?)

Tags: None
(comma "," separated)
User avatar
urwald
Registered Member
Posts
30
Karma
0
OS
Hello.

Again, I don't get started with CMake dependency handling.


The situation:

The source code of my project is distributed in several directories:

[font=Courier]src/kcfg/*
src/radiostation/*
src/service_classes/*
src/settings_general_dialog/*
src/*[/font]

Each subdirectory contains it's own CMakeLists.txt which produces a small static library. And in [font=Courier]src[/font], the CMakeLists.txt compiles the files who are directly in this directory, and than produces an executable from this and links it with all the static libraries:

[font=Courier]# preparations
include(${QT_USE_FILE})
include(KDE4Defaults) # some special KDE4 options for cmake
add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
include_directories(${QT_INCLUDE} ${KDE4_INCLUDES} ./ service_classes radiostation settings_general_dialog kcfg ${CMAKE_CURRENT_BINARY_DIR}/radiostation ${CMAKE_CURRENT_BINARY_DIR}/kcfg)

# modules without dependencies
add_subdirectory(kcfg)
add_subdirectory(service_classes)

# modules with dependencies
add_subdirectory(radiostation) # depends on module kcfg
add_subdirectory(settings_general_dialog) # depends on module kcfg

# define source files which are part of the project and have to be compiled
set(kradioripper_SRCS main.cpp mainwindow.cpp stationlistmodel.cpp stationlistwidget.cpp)

# compile and link
qt4_automoc(${kradioripper_SRCS})
kde4_add_executable(kradioripper ${kradioripper_SRCS})
target_link_libraries(kradioripper ${KDE4_KDEUI_LIBS} ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBS} ${KDE4_PHONON_LIBS} ${QT_LIBRARIES} kcfg service_classes radiostation settings_general_dialog)

# install
install(TARGETS kradioripper DESTINATION ${BIN_INSTALL_DIR})[/font]


The problem:

The subdirectory [font=Courier]src/kcfg[/font] contains a .kcfg file and .kcfgc file (KConfigXT), integrated in the CMakeLists.txt of the subdirectory with [font=Courier]kde4_add_kcfg_files(kcfg_LIB_SRCS settings_general.kcfgc)[/font]. This generated settings_general.cpp and settings_general.h at compile time.

Several .cpp files include settings_general.h - also in the other directories.

When I start to compile, [font=Courier]src/settings_general_dialog[/font] is the subdirectory which is compiled first (also [font=Courier]src/kcfg[/font] was the subdirectory that's listed first of all). And compiling fails because the necessary settings_general.h is still not generated.


The question:

How can be made sure that settings_general.h is generated before compiling all the other stuff in the other directories?

Tim


urwald, proud to be a member of KDE forums since 2008-Oct.
User avatar
bcooksley
Administrator
Posts
19765
Karma
87
OS
Could you please provide a location to download the sources from? Others will be able to more easily diagnose the issue if they are provided.

You could try adding ${CMAKE_CURRENT_BUILD_DIR}/kcfg to include_directories()

Last edited by bcooksley on Thu Jan 22, 2009 9:57 pm, edited 1 time in total.


KDE Sysadmin
[img]content/bcooksley_sig.png[/img]
User avatar
urwald
Registered Member
Posts
30
Karma
0
OS
bcooksley wrote:Could you please provide a location to download the sources from? Others will be able to more easily diagnose the issue if they are provided.


Sources are now uploaded and available from https://sourceforge.net/project/showfiles.php?group_id=217306&package_id=291914&release_id=655673 showing the described problem.

bcooksley wrote:You could try adding ${CMAKE_CURRENT_BUILD_DIR}/kcfg to include_directories()


Hm, I've yet done this, like you see in my first post. (This was the problem talked about in the thread CMake: don't get working KConfigXT with out-of-source builds. And that's also working fine for [font=Courier]src/radiostation/settings_stream.kcfgc[/font].)

But here I have a different problem: It's not a problem of out-of-source builds where the generated headers are not found, but it's a problem of build order.

The [font=Courier]src/kcfg/settings_general.kcfg[/font] file must produce a [font=Courier].h[/font] file. And this [font=Courier].h[/font] file is used ([font=Courier]#include[/font]) by various [font=Courier].cpp[/font] files in other directories as [font=Courier]src/kcfg[/font].

For example, [font=Courier]src/settings_general_dialog/settings_general_dialog.cpp[/font] includes [font=Courier]src/kcfg/settings_general.h[/font]. But unfortunately CMake tries to compile the files in [font=Courier]src/settings_general_dialog[/font] before compiling the files in [font=Courier]src/kcfg[/font], so the necessary [font=Courier]src/kcfg/settings_general.h[/font] is still not available. And this leads to an error.

With a usual [font=Courier]cmake ./[/font] and than [font=Courier]make[/font], I get:

[font=Courier][ 2%] Generating ui_settings_general_widget_relayserver.h
Generating moc_settings_general_widget_relayserver.cpp
Generating moc_settings_general_widget_general.cpp
Generating moc_settings_general_widget_saving.cpp
Generating moc_settings_general_dialog.cpp
[ 5%] Generating ui_settings_general_widget_general.h
[ 8%] Generating ui_settings_general_widget_saving.h
Scanning dependencies of target settings_general_dialog
Generating moc_settings_general_widget_relayserver.cpp
Generating moc_settings_general_widget_general.cpp
Generating moc_settings_general_widget_saving.cpp
Generating moc_settings_general_dialog.cpp
[ 11%] Building CXX object src/settings_general_dialog/CMakeFiles/settings_general_dialog.dir/settings_general_dialog_automoc.o
[ 14%] Building CXX object src/settings_general_dialog/CMakeFiles/settings_general_dialog.dir/settings_general_widget_general.o
[ 17%] Building CXX object src/settings_general_dialog/CMakeFiles/settings_general_dialog.dir/settings_general_widget_saving.o
[ 20%] Building CXX object src/settings_general_dialog/CMakeFiles/settings_general_dialog.dir/settings_general_widget_relayserver.o
[ 22%] Building CXX object src/settings_general_dialog/CMakeFiles/settings_general_dialog.dir/settings_general_dialog.o
/home/tim/Documents/KRadioRipper/test/kradioripper/src/settings_general_dialog/settings_general_dialog.cpp:23:30: error: settings_general.h: Datei oder Verzeichnis nicht gefunden
/home/tim/Documents/KRadioRipper/test/kradioripper/src/settings_general_dialog/settings_general_dialog.cpp: In constructor ‘settings_general_dialog::settings_general_dialog(QWidget*, QString)’:
/home/tim/Documents/KRadioRipper/test/kradioripper/src/settings_general_dialog/settings_general_dialog.cpp:29: error: ‘settings_general’ has not been declared
make[2]: *** [src/settings_general_dialog/CMakeFiles/settings_general_dialog.dir/settings_general_dialog.o] Fehler 1
make[1]: *** [src/settings_general_dialog/CMakeFiles/settings_general_dialog.dir/all] Fehler 2
make: *** [all] Fehler 2[/font]


urwald, proud to be a member of KDE forums since 2008-Oct.
User avatar
bcooksley
Administrator
Posts
19765
Karma
87
OS
It built fine on my KDE 4 Trunk ( to be 4.3 ) system, after I added the following line to the top of CMakeLists.txt:
Code: Select all
find_package(KDE4 REQUIRED)


I see "make[1]" and "make[2]" in your output, try running just plain "make" without any "-j" options.
You might also wish to check that you have CMake version 2.6.2 installed, which is what KDE trunk ( and 4.2 ) requires.

Last edited by bcooksley on Fri Jan 23, 2009 10:01 am, edited 1 time in total.


KDE Sysadmin
[img]content/bcooksley_sig.png[/img]
User avatar
urwald
Registered Member
Posts
30
Karma
0
OS
bcooksley wrote:It built fine on my KDE 4 Trunk ( to be 4.3 ) system, after I added the following line to the top of CMakeLists.txt:
Code: Select all
find_package(KDE4 REQUIRED)


Hm, that's interesting. I've tried this out on my local machine and it didn't help. You mean [font=Courier]src/CMakeLists.txt[/font]? In the CMakeLists.txt in the base directory (=directory above [font=Courier]src[/font]), this line exists yet...

bcooksley wrote:I see "make[1]" and "make[2]" in your output, try running just plain "make" without any "-j" options.


After trying this, I get the very same message like before - this message seems to have nothing to do with the number of threads used by make.

On the other hand, it would not be a reliable solution when the make process only works when make is limited to one thread.

bcooksley wrote:You might also wish to check that you have CMake version 2.6.2 installed, which is what KDE trunk ( and 4.2 ) requires.


The cmake version is cmake version 2.6-patch 2, but that's on my local machine. With the openSUSE build service, I produce binaries for various distributions, and the older ones of them will have an old cmake, and maybe KDE 4.0 or 4.1 - and the package should work there also.

So the only question is IMHO if there is a (reliable) solution to force CMake to execute [font=Courier]add_subdirectory(kcfg)[/font] before even starting one of all the other commands.

If not, I could put all the source files directly in [font=Courier]src[/font], without any subdirectories. In this case, it will probably work very reliable. But I would not really like to do so, because with the big number of files, the [font=Courier]src[/font] directory will be confusing.

Or alternatively I could guard the subdirectories of [font=Courier]src[/font], but delete only the CMakeLists.txt in these subdirectory and instead put all these things in [font=Courier]src/CMakeLists.txt[/font]...

Last edited by urwald on Fri Jan 23, 2009 11:25 pm, edited 1 time in total.


urwald, proud to be a member of KDE forums since 2008-Oct.
pinotree
KDE Developer
Posts
222
Karma
7
OS
One of the solutions you can do is sorting using subdirectories your sources, but actually compiling them from the top level CMakeLists.txt (in src/, in your case).

Another thing more: you don't need to manually call
Code: Select all
qt4_automoc(...)

when you are using kde4_* macros for libraries and executables, as automoc'ing is done automatically.

Last: if you really want to use static libraries, then you can manually set dependencies between them using
Code: Select all
add_dependencies(target dependency1 dependency2 ...)

But (at least IMHO) better go with single compilation.


Pino Toscano
User avatar
bcooksley
Administrator
Posts
19765
Karma
87
OS
From the provided build directory I executed:
Code: Select all
cmake ../src

I just performed a clean build like this
Code: Select all
cmake ..
from a new build directory and it also worked.
Note that I did that with my changes reverted.

I noticed that you are running cmake like this, is it a typo or otherwise?
Code: Select all
cmake ./


KDE Sysadmin
[img]content/bcooksley_sig.png[/img]
User avatar
urwald
Registered Member
Posts
30
Karma
0
OS
bcooksley wrote:From the provided build directory I executed:
Code: Select all
cmake ../src

I just performed a clean build like this
Code: Select all
cmake ..
from a new build directory and it also worked.
Note that I did that with my changes reverted.

I noticed that you are running cmake like this, is it a typo or otherwise?
Code: Select all
cmake ./



Hm, I suspect that it was working because the build order produced by CMake on your machine compiles casually [font=Courier]src/kcfg[/font] at first.

"[font=Courier]cmake ./[/font]" should be the same as "[font=Courier]cmake .[/font]".

pinotree wrote:One of the solutions you can do is sorting using subdirectories your sources, but actually compiling them from the top level CMakeLists.txt (in src/, in your case).


Yet tried this out. Works great :-D Thanks.

pinotree wrote:Another thing more: you don't need to manually call
Code: Select all
qt4_automoc(...)

when you are using kde4_* macros for libraries and executables, as automoc'ing is done automatically.


The corresponding calls are now removed.

pinotree wrote:Last: if you really want to use static libraries, then you can manually set dependencies between them using
Code: Select all
add_dependencies(target dependency1 dependency2 ...)

But (at least IMHO) better go with single compilation.


Oh, the static libs where just an intent to have a clearly arranged build process. However, that's not really important, and the solution with the single CMakeLists.txt is great. (But nice to know how to add dependencies...)

Thank you very much.

Tim


urwald, proud to be a member of KDE forums since 2008-Oct.


Bookmarks



Who is online

Registered users: bartoloni, Bing [Bot], Google [Bot], Sogou [Bot], Yahoo [Bot]