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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [Решено]CMake. Как правильно подключать макросы/дефайны в CMakeLists.txt?  (Прочитано 10270 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« : Сентябрь 17, 2010, 08:11 »

Доброго всем времени.

Когдато давно столкнулся с проблемой: http://www.prog.org.ru/topic_12491_0.html

т.е. в кратце,

для того чтобы собрать проект в qmake необходимо подключить инклуд типа:
Код:
#include "moc_filename.cpp" 

для того чтобы собрать проект в cmake необходимо подключить инклуд типа:
Код:
#include "filename.moc" 

Для этого я в файле "filename.cpp" в конце пишу так:
Код:
...
#if defined (BUILD_WITH_CMAKE)
  #include "filename.moc"
#else
  #include "moc_filename.cpp"
#endif

В CMakeLists.txt определяю и устанавливаю макрос BUILD_WITH_CMAKE:
Цитировать
...
set( QT_DEFINITIONS
    ...
    -DBUILD_WITH_CMAKE
    ...
)

add_definitions(
    ${QT_DEFINITIONS}
)
...

Т.е. по задумке при использовании CMake оно автоматом должно выставить BUILD_WITH_CMAKE и следовательно должны подключиться определенные секции. Но что-то оно не помогает.

Подскажите, что не правильно делаю и как надо правильно?

« Последнее редактирование: Сентябрь 17, 2010, 13:11 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
asvil
Гость
« Ответ #1 : Сентябрь 17, 2010, 09:13 »

Давайте начнем с qmake. В qt лабораториях любят делать
Код:
#include "moc_*.cpp"
#include "*.moc"
и определять Q_OBJECT и в заголовочных и файлах реализации.
moc_*.cpp - генерируется на основе *.h
*.moc - на основе *.cpp

Теперь cmake:
qt4_wrap_cpp генерирует moc_*.cpp на основе заголовочников
qt4_automoc генерирует *.moc на основе заголовочных файлов, при условии, что в реализации есть #include "*.moc"

qt4_generate_moc генерирует, что угодно на основе чего угодно.

В вашем случае необходимо оставить в qmake проекте все как есть. А в cmake проекте сделать qt4_generate_moc(filename.h moc_filename.cpp).
И сделать только такое включение:
Код:
#include "moc_filename.cpp"
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #2 : Сентябрь 17, 2010, 09:45 »

Цитировать
В вашем случае необходимо оставить в qmake проекте все как есть. А в cmake проекте сделать qt4_generate_moc(filename.h moc_filename.cpp).

Не проходит такой вариант. После вызова #make пишет:
Цитировать
D:\SVN\build>make
Scanning dependencies of target qserialdevice
[  4%] Building CXX object lib/CMakeFiles/qserialdevice.dir/qserialdevice/abstractserial.cpp.obj
D:\SVN\qserialdevice-qserialdevice\src\qserialdevice\abstractserial.cpp:1898:34: moc_abstractserial.cpp: No such file or directory
mingw32-make[2]: *** [lib/CMakeFiles/qserialdevice.dir/qserialdevice/abstractserial.cpp.obj] Error 1
mingw32-make[1]: *** [lib/CMakeFiles/qserialdevice.dir/all] Error 2
mingw32-make: *** [all] Error 2

где abstractserial.cpp == filename.cpp в упрощенной интерпретации.
Я даже не вижу сообщения в консоли (синим цветом как обычно) о том, что CMake генерирует moc.
Записан

ArchLinux x86_64 / Win10 64 bit
asvil
Гость
« Ответ #3 : Сентябрь 17, 2010, 09:49 »

Установите зависимость
Код:
set_source_files_properties( filename.cpp OBJECT_DEPENDS moc_filename.cpp )
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #4 : Сентябрь 17, 2010, 10:11 »

Цитировать
Установите зависимость
Установил, пишет теперь это:

Цитировать
D:\SVN\build>make
[  4%] Generating moc_abstractserial.cpp
moc: Cannot open options file specified with @
Usage: moc [options] <header-file>
  -o<file>           write output to file rather than stdout
  -I<dir>            add dir to the include path for header files
  -E                 preprocess only; do not generate meta object code
  -D<macro>[=<def>]  define macro, with optional definition
  -U<macro>          undefine macro
  -i                 do not generate an #include statement
  -p<path>           path prefix for included file
  -f[<file>]         force #include, optional file name
  -nw                do not display warnings
  @<file>            read additional options from file
  -v                 display version of moc
mingw32-make[2]: *** [lib/moc_abstractserial.cpp] Error 1
mingw32-make[1]: *** [lib/CMakeFiles/qserialdevice.dir/all] Error 2
mingw32-make: *** [all] Error 2

D:\SVN\build>
Записан

ArchLinux x86_64 / Win10 64 bit
asvil
Гость
« Ответ #5 : Сентябрь 17, 2010, 10:53 »

Возможно баг CMake 2.8.2:
http://www.vtk.org/Bug/bug_relationship_graph.php?bug_id=11120&graph=dependency

Решение:
Цитировать
Occasionally the MOC file creation when building a Qt4 project fails with the line "moc: Cannot open options file specified with @".

This is due to the fact, that the option files, which are the original source files appended an "_parameters" suffix, are placed in the SOURCE folder and not in the current building folder. Moc can't find them then and bails out.
Workaround: manually move those parameters into the corresponding build folder. Them moc is happy again.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #6 : Сентябрь 17, 2010, 10:56 »

В принципе генерация MOC идет если сделать так:

Цитировать
...
qt4_generate_moc( qserialdevice/abstractserial.h ${CMAKE_CURRENT_BINARY_DIR}/moc_abstractserial.cpp )
...
...

set ( QSERIALDEVICE_MOCS
    ${CMAKE_CURRENT_BINARY_DIR}/moc_abstractserial.cpp
...
...
)

...
add_library( ${LIB_TARGET} STATIC ${QSERIALDEVICE_SRCS} ${QSERIALDEVICE_MOCS} )


Но в этом случае начинают сыпаться другие ошибки:
Цитировать
D:\SVN\build>make
[  3%] Generating moc_serialnotifier.cpp
[  6%] Generating moc_abstractserial.cpp
[  9%] Generating moc_abstractserialengine.cpp
[ 12%] Generating moc_nativeserialengine.cpp
Scanning dependencies of target qserialdevice
[ 16%] Building CXX object lib/CMakeFiles/qserialdevice.dir/qserialdevice/abstractserial.cpp.obj
[ 19%] Building CXX object lib/CMakeFiles/qserialdevice.dir/qserialdevice/abstractserialengine.cpp.obj
[ 22%] Building CXX object lib/CMakeFiles/qserialdevice.dir/qserialdevice/nativeserialengine.cpp.obj
[ 25%] Building CXX object lib/CMakeFiles/qserialdevice.dir/qserialdevice/serialnotifier.cpp.obj
[ 29%] Building CXX object lib/CMakeFiles/qserialdevice.dir/qserialdevice/nativeserialengine_win.cpp.obj
[ 32%] Building CXX object lib/CMakeFiles/qserialdevice.dir/qserialdevice/serialnotifier_p_win.cpp.obj
[ 35%] Building CXX object lib/CMakeFiles/qserialdevice.dir/moc_abstractserial.cpp.obj
D:\SVN\build\lib\moc_abstractserial.cpp: In member function `virtual int AbstractSerial::qt_metacall(QMetaObject::Call, int, void**)':
D:\SVN\build\lib\moc_abstractserial.cpp:99: error: invalid use of undefined type `struct AbstractSerialPrivate'
D:\SVN\build\lib\../../qserialdevice-qserialdevice/src/qserialdevice/abstractserial.h:38: error: forward declaration of `struct AbstractSerialPrivate'

...
...
...

я их жирным выделил.  

т.е. упрощенно у меня методы "главного" класса определены в filename.h,
а приватного в filename_p.h.

И получается, что используя
Цитировать
qt4_generate_moc( filename.h ${CMAKE_CURRENT_BINARY_DIR}/moc_filename.cpp )
не парсится файл filename_p.h и сыпятся ошибки.. Имхо... А вот как сделать чтобы оно работало - я хз.  В замешательстве


Цитировать
Возможно баг CMake 2.8.2:
не, эт не баг, просто нужно ${CMAKE_CURRENT_BINARY_DIR} добавлять. Имхо.



« Последнее редактирование: Сентябрь 17, 2010, 11:02 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
asvil
Гость
« Ответ #7 : Сентябрь 17, 2010, 11:22 »

Ага, надо генерировать сразу в бинарную директорию.
Но раз moc исходник включается в другой, то его не надо повторно компилить. То есть не добавляйте в QSERIALDEVICE_MOCS
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #8 : Сентябрь 17, 2010, 11:30 »

Цитировать
То есть не добавляйте в QSERIALDEVICE_MOCS

А если я не добавляю в QSERIALDEVICE_MOCS - то ругается так:
Цитировать
D:\SVN\build>make
Scanning dependencies of target qserialdevice
[  4%] Building CXX object lib/CMakeFiles/qserialdevice.dir/qserialdevice/abstractserial.cpp.obj
D:\SVN\qserialdevice-qserialdevice\src\qserialdevice\abstractserial.cpp:1898:34: moc_abstractserial.cpp: No such file or directory
mingw32-make[2]: *** [lib/CMakeFiles/qserialdevice.dir/qserialdevice/abstractserial.cpp.obj] Error 1
mingw32-make[1]: *** [lib/CMakeFiles/qserialdevice.dir/all] Error 2
mingw32-make: *** [all] Error 2
и никакие moc не генерятся вообще
 В замешательстве
« Последнее редактирование: Сентябрь 17, 2010, 11:32 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
asvil
Гость
« Ответ #9 : Сентябрь 17, 2010, 11:35 »

))
В целом дела должны обстоять так:
Код:
qt4_generate_moc(filename.h ${CMAKE_CURRENT_BINARY_DIR}/moc_filename.cpp)
set_source_files_properties(filename.cpp OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_filename.cpp )
# или так set_source_files_properties(filename.h OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_filename.cpp )

add_library(filename STATIC filename.cpp filename.h)
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #10 : Сентябрь 17, 2010, 12:08 »

Михаил , СПАСИБО, все получилось!

Я забыл про set_source_files_properties  Смеющийся

Подведем итог.

Итак, если у нас имеется проект (библиотека, или приложение) например с такой структурой:
Цитировать
file1.h
file1_p.h //здесь определен приватный класс
file1.cpp
file2.h
file2_p.h //здесь определен приватный класс
file2.cpp
в котором используется pimpl (хотя не важно) и мы хотим
чтобы он (проект) собирался как и с помощью qmake так и с помощью CMake, то необходимо следующее:

1. Во всех файлах *.cpp проекта в которых имеются классы наследуемые от QObject в конце нужно подключить  moc_*.cpp файлы:
file1.cpp
Код:
...
//в самом конце файла
#include "moc_file1.cpp"

file2.cpp
Код:
...
//в самом конце файла
#include "moc_file2.cpp"

2. Создать CMakeLists.txt , в котором помимо "основного" содержимого необходимо чтобы было это:
CMakeLists.txt
Код:
...
...

#Перечисляем все файлы с реализацией.
set( PRJ_SRCS
    file1.cpp
    file2.cpp
)

...
...
#Перечисляем все файлы с определениями.
#Вот этот набор PRJ_HDRS не нужен в данном случае!
#т.е. в таком виде заголовки не нужны нам вообще в данном проекте,
#т.к. они не используются нигде!
#поэтому можно не писать вообще!
set( PRJ_HDRS
    file1.h
    file1_p.h
    file2.h
    file2_p.h
)

...
...

#Теперь заставляем генерить нужные нам moc_*.cpp файлы.
#Обязательна такая вещь как CMAKE_CURRENT_BINARY_DIR!
qt4_generate_moc( file1.h ${CMAKE_CURRENT_BINARY_DIR}/moc_file1.cpp )
qt4_generate_moc( file2.h ${CMAKE_CURRENT_BINARY_DIR}/moc_file2.cpp )

...
...

#Далее делаем обязательно так:
set_source_files_properties( file1.cpp OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_file1.cpp )
set_source_files_properties( file2.cpp OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_file2.cpp )


#Далее делаем так:
#и как видим, набора PRJ_HDRS здесь нету, он и не нужен!
#По крайней мере у меня все собралось.
add_library( ${LIB_TARGET} STATIC ${PRJ_SRCS} )

(ЗЫ: если у нас приложение - то вместо add_library пишем add_executable)
...
...


3. Компилим.

Всё, должно теперь работать.

ЗЫ: Спасибо Филоненко Михаилу за терпение!  Улыбающийся
« Последнее редактирование: Сентябрь 17, 2010, 12:12 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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