Russian Qt Forum
Апрель 20, 2024, 07:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: pimpl + CMake + qmake + #include "moc_...." . Кто решил проблему?  (Прочитано 14296 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« : Февраль 18, 2010, 14:56 »

Доброго времени!

Бьюсь над переводом своего проекта с qmake на CMAke

Но возникает проблема с тем, что в реализации моего проекта при использовании pimpl приходится для qmake в некоторых *.cpp файлах проекта в самом их конце инклюдить moc_*.cpp файлы.

Так вот: если использовать для сборки qmake - то все собирается прекрасно, НО как только использую CMake - так оно ругается на отсутствие этих самых файлов moc_*.cpp   (точнее одного единственного).

Я на этом форуме наткнулся на: http://www.prog.org.ru/index.php?topic=9165.msg65906
где была аналогичгая проблема. Там советовали убрать вообще инклюд  #include "moc_*.cpp"  из файла   *.cpp проекта - тогда CMake будет собирать, но qmake - нет!
-----------

Вопрос: как решить эту проблему, чтобы и qmake и CMake могли собрать проект?

и в догонку: как реализовать в CMake аналогию этого:
Код:
...
CONFIG          -= debug_and_release debug
...
...
OBJECTS_DIR     = build/obj
MOC_DIR         = build/moc
...

win32 {
    SOURCES     += xyz.cpp
}

unix {
    SOURCES     += zyx.cpp
}
??
« Последнее редактирование: Февраль 18, 2010, 15:03 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #1 : Февраль 19, 2010, 10:05 »

Еще в догонку:

если собирать статик библиотеку используя CMake - то она собирается, никаких ворнингов и ошибок при сборке нет. НО если её потом подключить к проекту и попытаться собрать при помощи qmake - то при компиляции вылезают ошибки типа:
Цитировать
...
...... undefined reference to `vtable for ...
....

уже не знаю и как быть...

На всякий случай привожу CMakeLists.txt библиотечки:
Код:
project( SerialDeviceWatcher )
cmake_minimum_required( VERSION 2.6.0 )

set(TARGET "qserialdevicewatcher"   CACHE string "Name of the library")

set( OPTIMIZATION_FLAGS "-O2" )

set( SERIALDEVICEWATCHER_SRCS
    serialdevicewatcher.cpp
    serialdevicewatcher_p_win.cpp
)

set( SERIALDEVICEWATCHER_MOC_HDRS
    serialdevicewatcher.h
    serialdevicewatcher_p.h    
)

find_package( Qt4 REQUIRED )
include( ${QT_USE_FILE} )

set( QT_DONT_USE_QTGUI )

#qt4_wrap_cpp( SERIALDEVICEWATCHER_MOC_SOURCES ${SERIALDEVICEWATCHER_SRCS} )
qt4_automoc ( ${SERIALDEVICEWATCHER_SRCS} ${SERIALDEVICEWATCHER_MOC_HDRS} )  

add_definitions(
    -Wall
    -DQT_NO_DEBUG
    ${OPTIMIZATION_FLAGS}
    ${QT_DEFINITIONS}
)

#include_directories(
#    ${QT_INCLUDES}
#    ${QT_INCLUDE_DIR}
#    ${CMAKE_BINARY_DIR}
#    .
#)

add_library(
    ${TARGET}
    STATIC
    ${SERIALDEVICEWATCHER_SRCS}
)

TARGET_LINK_LIBRARIES(
    ${TARGET}
    ${QT_LIBRARIES}
)
« Последнее редактирование: Февраль 19, 2010, 10:10 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #2 : Февраль 19, 2010, 10:16 »

Попробуй так:

Код:
project( SerialDeviceWatcher )
cmake_minimum_required( VERSION 2.6.0 )

set(TARGET "qserialdevicewatcher"   CACHE string "Name of the library")

set( OPTIMIZATION_FLAGS "-O2" )

set( SERIALDEVICEWATCHER_SRCS
    serialdevicewatcher.cpp
    serialdevicewatcher_p_win.cpp
)

set( SERIALDEVICEWATCHER_MOC_HDRS
    serialdevicewatcher.h
    serialdevicewatcher_p.h   
)

find_package( Qt4 REQUIRED )
include( ${QT_USE_FILE} )

set( QT_DONT_USE_QTGUI )

qt4_wrap_cpp( SERIALDEVICEWATCHER_MOC_SOURCES ${SERIALDEVICEWATCHER_MOC_HDRS} ) # <<<<<<
#qt4_automoc ( ${SERIALDEVICEWATCHER_SRCS} ${SERIALDEVICEWATCHER_MOC_HDRS} )   

add_definitions(
    -Wall
    -DQT_NO_DEBUG
    ${OPTIMIZATION_FLAGS}
    ${QT_DEFINITIONS}
)

#include_directories(
#    ${QT_INCLUDES}
#    ${QT_INCLUDE_DIR}
#    ${CMAKE_BINARY_DIR}
#    .
#)

add_library(
    ${TARGET}
    STATIC
    ${SERIALDEVICEWATCHER_SRCS}
    ${SERIALDEVICEWATCHER_MOC_SOURCES} # <<<<<<<<<<
)

TARGET_LINK_LIBRARIES(
    ${TARGET}
    ${QT_LIBRARIES}
)
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #3 : Февраль 19, 2010, 10:41 »

А при таком раскладе:
Код:
#


project( SerialDeviceWatcher )
cmake_minimum_required( VERSION 2.6.0 )

set(TARGET "qserialdevicewatcher" CACHE string "Name of the library")

set( OPTIMIZATION_FLAGS "-O2" )

set( SERIALDEVICEWATCHER_SRCS
    serialdevicewatcher.cpp
    serialdevicewatcher_p_win.cpp
)

set( SERIALDEVICEWATCHER_HDRS
    serialdevicewatcher.h
    serialdevicewatcher_p.h
)

find_package( Qt4 REQUIRED )
include( ${QT_USE_FILE} )

set( QT_DONT_USE_QTGUI )

qt4_wrap_cpp( SERIALDEVICEWATCHER_MOC_SOURCES ${SERIALDEVICEWATCHER_HDRS})
#qt4_automoc( ${SERIALDEVICEWATCHER_SRCS} ${SERIALDEVICEWATCHER_MOC_SOURCES} )   

add_definitions(
    -Wall
    -DQT_NO_DEBUG
    ${OPTIMIZATION_FLAGS}
    ${QT_DEFINITIONS}
)

#include_directories(
#    .
#)

add_library(
    ${TARGET}
    STATIC
    ${SERIALDEVICEWATCHER_SRCS}
    ${SERIALDEVICEWATCHER_MOC_SOURCES}
)

TARGET_LINK_LIBRARIES(
    ${TARGET}
    ${QT_LIBRARIES}
)

Пишет:
Цитировать
D:\SVN\qserialdevice-scm-2010-02-17\qserialdevicewatcher-build>make
[ 16%] Generating moc_serialdevicewatcher_p.cxx
D:/SVN/qserialdevice-scm-2010-02-17/qserialdevicewatcher/serialdevicewatcher_p.h:0: Warning: No relevant classes found. No output generated.
[ 33%] Generating moc_serialdevicewatcher.cxx
Scanning dependencies of target qserialdevicewatcher
[ 50%] Building CXX object CMakeFiles/qserialdevicewatcher.dir/serialdevicewatcher.cpp.obj
[ 66%] Building CXX object CMakeFiles/qserialdevicewatcher.dir/serialdevicewatcher_p_win.cpp.obj
[ 83%] Building CXX object CMakeFiles/qserialdevicewatcher.dir/moc_serialdevicewatcher.cxx.obj
D:\SVN\qserialdevice-scm-2010-02-17\qserialdevicewatcher-build\moc_serialdevicewatcher.cxx: In member function `virtual int SerialDeviceWatcher::qt_me
tacall(QMetaObject::Call, int, void**)':
D:\SVN\qserialdevice-scm-2010-02-17\qserialdevicewatcher-build\moc_serialdevicewatcher.cxx:72: error: invalid use of undefined type `struct SerialDevi
ceWatcherPrivate'
D:\SVN\qserialdevice-scm-2010-02-17\qserialdevicewatcher-build\../qserialdevicewatcher/serialdevicewatcher.h:31: error: forward declaration of `struct
 SerialDeviceWatcherPrivate'
mingw32-make[2]: *** [CMakeFiles/qserialdevicewatcher.dir/moc_serialdevicewatcher.cxx.obj] Error 1
mingw32-make[1]: *** [CMakeFiles/qserialdevicewatcher.dir/all] Error 2
mingw32-make: *** [all] Error 2

D:\SVN\qserialdevice-scm-2010-02-17\qserialdevicewatcher-build>
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #4 : Февраль 19, 2010, 11:32 »

kuzulis, прикрепи архив с проектом, что бы его не искать.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #5 : Февраль 19, 2010, 12:28 »

Ссылка тут: http://fireforge.net/scm/?group_id=199

В аттаче - архив со ВСЕМ проектом + CMakeLists.txt с которым я в данный момент ковыряюсь.
Мне необходимо пока что портировать /qserialdevicewatcher на CMake.


 
Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #6 : Февраль 19, 2010, 12:51 »

Так, нашел в чем была проблема при сборке CMake:
- в файле serialdevicewatcher_p_win.cpp в самом его конце нужно написать:
Код:
#include "serialdevicewatcher.moc"

т.е. чтобы собрать с CMake нужно:
Код:
 //#include "moc_serialdevicewatcher.cpp"
#include "serialdevicewatcher.moc"

т.е. чтобы собрать с qmake нужно:
Код:
#include "moc_serialdevicewatcher.cpp"
//#include "serialdevicewatcher.moc"

Вот CMakeLists.txt:
Код:
#


project( SerialDeviceWatcher )
cmake_minimum_required( VERSION 2.6.0 )

set(TARGET "qserialdevicewatcher" CACHE string "Name of the library")

set( OPTIMIZATION_FLAGS "-O2" )

set( SERIALDEVICEWATCHER_SRCS
    serialdevicewatcher.cpp
    serialdevicewatcher_p_win.cpp
)

set( SERIALDEVICEWATCHER_HDRS
    serialdevicewatcher.h
    serialdevicewatcher_p.h
)

find_package( Qt4 REQUIRED )
include( ${QT_USE_FILE} )

set( QT_DONT_USE_QTGUI )

qt4_automoc( ${SERIALDEVICEWATCHER_SRCS} )  

add_definitions(
    -Wall
    -DQT_NO_DEBUG
    ${OPTIMIZATION_FLAGS}
    ${QT_DEFINITIONS}
)

include_directories(
    ${CMAKE_CURRENT_BINARY_DIR}
    ${QT_INCLUDES}
    .
)

add_library(
    ${TARGET}
    STATIC
    ${SERIALDEVICEWATCHER_SRCS}
)

TARGET_LINK_LIBRARIES(
    ${TARGET}
    ${QT_LIBRARIES}
)

Вот такая штука получается Грустный  . т.е. как сделать не меняя(правя) исходники , можно было бы собирать проекты в CMake и qmake я не знаю Грустный

-------------
------
и я тут посмотрел, что файлы "moc_serialdevicewatcher.cpp" и  "serialdevicewatcher.moc" - имеют одинаковое содержимое.
У меня возникла мысль сделать так, чтобы CMake генерил вместо файла "serialdevicewatcher.moc" -> "moc_serialdevicewatcher.cpp" - и тогда не пришлось бы править исходники!!! Но что-то пока не удается заставить CMake генерить файл с именем отличным от *.moc Грустный
« Последнее редактирование: Февраль 19, 2010, 13:40 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Февраль 19, 2010, 13:56 »

Нашел интересную закономерность, которая заключается в том, что даже если и удается заставить генерировать CMake *.moc файл с нужным именем, и, если это имя заканчивается на *.cpp - то проект не собирается!!!

Пример:
в файле "serialdevicewatcher_p_win.cpp" в самом конце пишу : #include "moc_serialdevicewatcher.cpp1"

Далее создаю CMakeLists.txt c таким содержанием:
Код:
#


project( SerialDeviceWatcher )
cmake_minimum_required( VERSION 2.6.0 )

set(TARGET "qserialdevicewatcher" CACHE string "Name of the library")

set( OPTIMIZATION_FLAGS "-O2" )

set( SERIALDEVICEWATCHER_SRCS
    serialdevicewatcher.cpp
    serialdevicewatcher_p_win.cpp
)

set( SERIALDEVICEWATCHER_HDRS
    serialdevicewatcher.h
    serialdevicewatcher_p.h
)

find_package( Qt4 REQUIRED )
include( ${QT_USE_FILE} )

set( QT_DONT_USE_QTGUI )

qt4_generate_moc(serialdevicewatcher.h ${CMAKE_CURRENT_BINARY_DIR}/moc_serialdevicewatcher.cpp1) 

add_definitions(
    -Wall
    -DQT_NO_DEBUG
    ${OPTIMIZATION_FLAGS}
    ${QT_DEFINITIONS}
)

include_directories(
    ${CMAKE_CURRENT_BINARY_DIR}
    ${QT_INCLUDES}
    .
)

add_library(
    ${TARGET}
    STATIC
    ${SERIALDEVICEWATCHER_SRCS}
    ${CMAKE_CURRENT_BINARY_DIR}/moc_serialdevicewatcher.cpp1
)

TARGET_LINK_LIBRARIES(
    ${TARGET}
    ${QT_LIBRARIES}
)


и собираю проект - то собирается нормально и все работает!

НО - стоит лишь изменить везде moc_*.cpp1 (или любое другое имя файла)  на moc_*.cpp и попробовать заново собрать - то сборка вылетает с ошибками!

ЗЫ: я это затеял с тем, чтобы сделать возможной сборку проекта как CMake, так и qmake не меняя ничего в исходниках!

И вся "фишка" в том, что qmake -то создает файл moc_*.cpp и все работает (собирается). Но стоит лишь только сделать чтобы CMake генерил такое же имя - то начинаются проблемы Грустный
Записан

ArchLinux x86_64 / Win10 64 bit
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #8 : Февраль 25, 2010, 07:22 »

Инклюды можно вот так сделать:
Код
C++ (Qt)
#ifdef -=CMAKE=-
#include "file.moc"
#else
#include "moc_file.cpp"
#endif
 
Не проверял. Дефайн -=CMAKE=- объявить в CMakeLists, если нет стандартного.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #9 : Февраль 25, 2010, 11:29 »

2 Пантер ,

спасибо, наверное так и придется сделать.

---

Но у меня есть еще один вопрос (в тему) : почему при сборке своего проекта с помощью CMake - результирующий размер бинарика получается больше , чем при сборке c помощью qmake (у меня по крайней мере) ?
Цитировать
qmake   -> 190270 Байт
CMake   -> 230502 Байт

Какие нужно опции дописать в CMake , чтобы отключить ненужные сущности и чтобы в результате размеры скомпилированных бинариков примерно совпали?

Сейчас у меня только это есть:
Код:
...
set( OPTIMIZATION_FLAGS "-O2" )
set( QT_DONT_USE_QTGUI )

add_definitions( -Wall -DQT_NO_DEBUG )
...
« Последнее редактирование: Февраль 25, 2010, 11:35 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #10 : Февраль 25, 2010, 12:34 »

Скорее всего в случае с CMake файл создается с отладочной информацией.
Попробуй при генерации добавить в опции cmake:
-DCMAKE_BUILD_TYPE=Release
а для сборки в режиме debug соответственно:
-DCMAKE_BUILD_TYPE=Debug
Записан
Rcus
Гость
« Ответ #11 : Февраль 25, 2010, 12:38 »

А сравнить Makefile от qmake и CMakeFiles/<target>.dir/flags.make? Может CMake добавляет -rdynamic или еще чего.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #12 : Февраль 25, 2010, 13:03 »

Итак, сделал другим путем:
посмотрел Makefile который генерит qmake и написал в CMakeLists.txt так: (под виндовс)
Цитировать
set( QT_DEFINITIONS
    -DUNICODE
    -DQT_NO_DEBUG
    -DQT_CORE_LIB
    -DQT_THREAD_SUPPORT
)

set( QT_DONT_USE_QTGUI )

add_definitions( -Wall
    ${OPTIMIZATION_FLAGS}
    ${QT_DEFINITIONS}
)

и размер бинарика собранного CMake уменьшился до: 191372 Байт Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #13 : Февраль 25, 2010, 13:14 »

Цитировать
А сравнить Makefile от qmake и CMakeFiles/<target>.dir/flags.make? Может CMake добавляет -rdynamic или еще чего.
Сравнил после того как добился уменьшения размера:

Makefile от qmake:
Цитировать
...
CC            = gcc
CXX           = g++
DEFINES       = -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_THREAD_SUPPORT
CFLAGS        = -O2 -Wall $(DEFINES)
CXXFLAGS      = -O2 -frtti -fexceptions -mthreads -Wall $(DEFINES)
INCPATH       = -I"..\..\..\..\Qt\2009.04\qt\include\QtCore" -I"..\..\..\..\Qt\2009.04\qt\include" -I"..\..\..\..\Qt\2009.04\qt\include\ActiveQt" -I"build\moc" -I"..\..\..\..\Qt\2009.04\qt\mkspecs\win32-g++"
...

flags.make от CMake:
Цитировать
...
CXX_FLAGS = -ID:\Qt\2009.04\qt\include -ID:\Qt\2009.04\qt\include\QtGui -ID:\Qt\2009.04\qt\include\QtCore   -Wall -O2

CXX_DEFINES = -DQT_DLL -DQT_GUI_LIB -DQT_CORE_LIB -DUNICODE -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_THREAD_SUPPORT
...

как видно, в flags.make есть лишнее: -DQT_DLL -DQT_GUI_LIB !!! Почему? Ведь я явно указал НЕ использовать GUI в CMakeLists.txt:
Цитировать
...
set( QT_DONT_USE_QTGUI )
...

и не указывал нигде -DQT_DLL!!
Записан

ArchLinux x86_64 / Win10 64 bit
Rcus
Гость
« Ответ #14 : Февраль 25, 2010, 13:45 »

А find_package с аргументом COMPONENTS использовали? Я попробовал на Arch'е с пакетами из репов - все нормально работает.
C QT_DLL непонятно почему вас это беспокоит.
Цитировать
  # build using shared Qt needs -DQT_DLL
  IF(NOT QT_CONFIG MATCHES "static")
    # warning currently only qconfig.pri on Windows potentially contains "static"
    # so QT_DLL might not get defined properly on other platforms.
    SET(QT_DEFINITIONS ${QT_DEFINITIONS} -DQT_DLL)
  ENDIF(NOT QT_CONFIG MATCHES "static")
See? No magic
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.15 секунд. Запросов: 22.