[CMake] 'AUTOMOC' feature skips sources of executable targets?

Haroogan haroogan at gmail.com
Mon Apr 29 18:36:20 EDT 2013


On 29-Apr-13 23:27, Alexander Neundorf wrote:
> On Monday 29 April 2013, Haroogan wrote:
>> Have a look at my post on StackOverflow
>> <http://stackoverflow.com/questions/16286872/cmake-automoc-feature-skips-so
>> urces-of-executable-targets> for details.
>> <http://stackoverflow.com/questions/16286872/cmake-automoc-feature-skips-so
>> urces-of-executable-targets>
> can you please create a small testcase and post it here, or create an entry on
> http://public.kitware.com/Bug and attach it there ?
>
> It should work.
>
> Alex
>
I've found the cause, and I think that's very confusing behavior. I'll 
try to do my best explaining it.

Let's begin with top 'CMakeLists.txt':

...

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

...

# NOTE: Order matters (the most independent ones go first)
# because some libraries expose variables through cache (see below).
add_subdirectory(components/B)
add_subdirectory(components/A)

add_subdirectory(components/Executable)

So imagine that we have the 'FindMyPrecious.cmake' custom CMake module 
to locate 3rd party framework "MyPrecious":

find_package(Qt4
              4.7.4
              COMPONENTS QtCore
                         QtGui
                         QtXml
              REQUIRED)

find_path(MyPrecious_INCLUDE_DIR...)

find_library(MyPrecious_LIBRARY_DEBUG...)

find_library(MyPrecious_LIBRARY_RELEASE...)

set(QT_DEFINITIONS ${QT_DEFINITIONS}
                    -DQT_CORE_LIB
                    -DQT_GUI_LIB
                    -DQT_XML_LIB)

if (CMAKE_BUILD_TYPE MATCHES [Dd][Ee][Bb][Uu][Gg])
   set(QT_DEFINITIONS ${QT_DEFINITIONS}
                      -DQT_DEBUG)
else ()
   set(QT_DEFINITIONS ${QT_DEFINITIONS}
                      -DQT_NO_DEBUG)
endif ()

set(MyPrecious_DEFINITIONS ${QT_DEFINITIONS})

set(MyPrecious_INCLUDE_DIRS ${MyPrecious_INCLUDE_DIR}
                             ${QT_INCLUDE_DIR}
${QT_QTCORE_INCLUDE_DIR}
${QT_QTGUI_INCLUDE_DIR}
${QT_QTXML_INCLUDE_DIR})

set(MyPrecious_LIBRARY debug     ${MyPrecious_LIBRARY_DEBUG}
                        optimized ${MyPrecious_LIBRARY_RELEASE})

set(MyPrecious_LIBRARIES ${MyPrecious_LIBRARY}
                          ${QT_QTCORE_LIBRARY}
                          ${QT_QTGUI_LIBRARY}
                          ${QT_QTXML_LIBRARY})

include(FindPackageHandleStandardArgs)

find_package_handle_standard_args(MyPrecious
                                   DEFAULT_MSG
MyPrecious_INCLUDE_DIR
MyPrecious_LIBRARY
MyPrecious_LIBRARY_DEBUG
MyPrecious_LIBRARY_RELEASE)

mark_as_advanced(MyPrecious_INCLUDE_DIR
MyPrecious_LIBRARY
MyPrecious_LIBRARY_DEBUG
MyPrecious_LIBRARY_RELEASE)

Everything is cool so far. One thing to note is that since "MyPrecious" 
depends on Qt we are employing transitive dependency strategy as 
recommended on CMake Wiki.

Now let's move to the shared library "A" (from our project) which 
depends on "MyPrecious":

cmake_minimum_required(VERSION 2.8.10)

project(A C CXX)

find_package(MyPrecious REQUIRED)

file(GLOB CPP_FILES sources/*.cpp)

add_definitions(${MyPrecious_DEFINITIONS})

include_directories(${B_INCLUDE_DIRS}# some other library B (in this 
case header-only); B exposed includes with the same strategy
                     ${MyPrecious_INCLUDE_DIRS})

add_library(${PROJECT_NAME} SHARED ${CPP_FILES})

target_link_libraries(${PROJECT_NAME} ${MyPrecious_LIBRARIES})

# Pay attention here, we want to make definitions and includes visible 
(through cache) to the executable since it is going to link against this 
library A
set(${PROJECT_NAME}_DEFINITIONS ${MyPrecious_DEFINITIONS}
     CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)

set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/includes
                                  ${B_INCLUDE_DIRS}# some other library 
B (in this case header-only);B exposed includes with the same strategy
                                  ${MyPrecious_INCLUDE_DIRS}
     CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)

Finally, let's move to the executable project:

cmake_minimum_required(VERSION 2.8.10)

project(Executable C CXX)

# -------------------------------
# ATTENTION: Theoretically, I don't have to add the line below.
# -------------------------------
# find_package(MyPrecious REQUIRED)
# -------------------------------
# Furthermore, as I said if I use plain old 'qt4_wrap_cpp', I don't add 
it and everything builds fine indeed.
# However, now when using 'AUTOMOC' approach it turns out that without 
this line CMake does not create 'AUTOMOC' target for sources of this 
project.
# The above line simply finds "MyPrecious", which you can see is not 
even used any further. I.e. all the definitions and includes of Qt, 
"MyPrecious", B, and A are
# obtained transitively through the cache variables (see below/above). 
However, we know that the above line finds Qt too.
# So the only logical thing that comes to my mind is that CMakes 
'AUTOMOC' feature works only when one explicitly or implicitly (like in 
this case) finds Qt (with `find_package`)
# for the project which is desired to be 'AUTOMOC'ed. I have to admit 
that it's annoying, confusing, and counter-intuitive. Is this the 
intended behavior? Is this going to be fixed?
# -------------------------------

file(GLOB CPP_FILES sources/*.cpp)

# Pay attention here, we are utilizing the definitions and includes of 
library A (exposed earlier through cache).
# Furthermore, we now transitively and implicitly depend on Qt, 
"MyPrecious", and even B (since A depends on them).
add_definitions(${A_DEFINITIONS})

include_directories(${A_INCLUDE_DIRS})

add_executable(${PROJECT_NAME} ${CPP_FILES})

target_link_libraries(${PROJECT_NAME} A)

The cause and the corresponding question are above (under the ATTENTION).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.cmake.org/pipermail/cmake/attachments/20130430/f59ff91f/attachment-0001.htm>


More information about the CMake mailing list