Nindiちゃん/GindiちゃんのIndi driverがとりあえず動くようになったところで、次はラズパイで動いているNindiちゃんアプリの方を移植します。
Indi対応のアプリを作るときは Indi::BaseClientクラスを継承して作りますが、このアプリはQtを使っているので、indiの方もIndi::BaseClientQtを継承して作ります。今回このQt周りでちょっと手間取ったのでメモしておきます。
IndiはデフォルトでビルドするとIndi Qt Clientがビルドされないので、CMakeLists.txtを編集して、INDI Qt ClientをOnにします。もちろん事前にQtをインストールしておくのを忘れずに。
でビルド。Qtパッケージが見つかっていることと、INID Qt Clientがビルド対象になっていることを確認。

でIndiのビルドが完了したら、Nindiちゃんからソースコードを持ってきます。必要なライブラリを設定してQt CreaterでNindiちゃんをビルドしてみると、何やらエラーが・・

INDI::BasicClientQt::qt_metacast(char const*)という関数がないよ、というエラーです。Geminiにこのqt_metacast()って何かきいてみると、
試しにビルドしたフォルダを検索してみると、確かに生成されていません。

Geminiにこの状況を報告すると、
「CMakeLists.txt で、Qtの自動処理が有効になっているか確認してください。最近の CMake では以下の設定が推奨されます。
で、indiをビルドすると、こんなエラーが・・・
qt_metacast()が2回定義されている、とのこと・・・なんで???
Geminiに聞くと、
「multiple definition エラーの中に indiclientqt_OBJECT と indiclientqt という2つのターゲット名が登場しています。
無事ビルドが通りました! (^O^)
nmコマンドで見ても、ちゃんとqt_metacallがあります。

ということで、ようやくNindiちゃんアプリを改めてビルドしてみると・・・
無事ビルドが通って実行できました!ヾ(〃^∇^)ノわぁい♪.

今回はGeminiのお陰でどうにか解決。 ありがとう!> Gemini
にしても、普通にビルドしてもmocが生成されないって、indiの不具合じゃないの?
IndiClientQtなんて使う人がいなくて、そもそもデフォルトではoffになっているし、ちゃんとテストされていないのかな?
ということで、Nindiちゃんとgphoto2は移植しました。UVCカメラは何もいじっていないのでそのまま動く(ハズ)。
あとはindiに自作プラネアプリ TeleSkymapBT2を繋ぐIndi driverが残っていますが、一旦それは後にして、次はNindiちゃんアプリの動作確認に進みましょう。
Indi対応のアプリを作るときは Indi::BaseClientクラスを継承して作りますが、このアプリはQtを使っているので、indiの方もIndi::BaseClientQtを継承して作ります。今回このQt周りでちょっと手間取ったのでメモしておきます。
IndiはデフォルトでビルドするとIndi Qt Clientがビルドされないので、CMakeLists.txtを編集して、INDI Qt ClientをOnにします。もちろん事前にQtをインストールしておくのを忘れずに。
でビルド。Qtパッケージが見つかっていることと、INID Qt Clientがビルド対象になっていることを確認。

でIndiのビルドが完了したら、Nindiちゃんからソースコードを持ってきます。必要なライブラリを設定してQt CreaterでNindiちゃんをビルドしてみると、何やらエラーが・・

INDI::BasicClientQt::qt_metacast(char const*)という関数がないよ、というエラーです。Geminiにこのqt_metacast()って何かきいてみると、
「Qtには、安全に型を変換するための qobject_cast という仕組みがあります。
例えば、「このオブジェクトは INDI::BasicClientQt 型として扱えるか?」を調べるとき、Qtは内部的にこの qt_metacast を呼び出します。
引数 (char const*): 変換したいクラス名(文字列)が渡されます。
戻り値: もし指定されたクラス(またはその親クラス)であれば、そのオブジェクトへのポインタを返し、そうでなければ nullptr を返します。」
とのこと。ビルド時に自動的にこの関数を生成するようです。
では、Indi::BaseClientQtのライブラリ、libindiclientqt.soにこの関数が含まれているかnmコマンドで確認してみたところ、qt_metacastが出てきません。どうもうまくqt_metacast()が生成されていないようです。

とのこと。ビルド時に自動的にこの関数を生成するようです。
では、Indi::BaseClientQtのライブラリ、libindiclientqt.soにこの関数が含まれているかnmコマンドで確認してみたところ、qt_metacastが出てきません。どうもうまくqt_metacast()が生成されていないようです。

試しにビルドしたフォルダを検索してみると、確かに生成されていません。

Geminiにこの状況を報告すると、
「CMakeLists.txt で、Qtの自動処理が有効になっているか確認してください。最近の CMake では以下の設定が推奨されます。
CMake
# CMakeLists.txt に追加
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)」
とのこと。CMAKE_AUTOMOC は Qtのメタ・オブジェクト・コンパイラ(MOC)を自動的に走らせて、qt_metacast()を自動生成してくれるらしいです。なるほどー。
そこでfind_package()でQtを探す前に入れてみました。
とのこと。CMAKE_AUTOMOC は Qtのメタ・オブジェクト・コンパイラ(MOC)を自動的に走らせて、qt_metacast()を自動生成してくれるらしいです。なるほどー。
そこでfind_package()でQtを探す前に入れてみました。
<略>
# Try Qt6 first, fall back to Qt5 if not found
set(CMAKE_AUTOMOC ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Network)
find_package(ZLIB REQUIRED)
find_package(CFITSIO REQUIRED)
message(STATUS "Using Qt${QT_VERSION_MAJOR} for indiclientqt")
<略>
で、indiをビルドすると、こんなエラーが・・・
/usr/bin/ld: CMakeFiles/indiclientqt_OBJECT.dir/indiclientqt_OBJECT_autogen/mocs_compilation.cpp.o: in function `std::__atomic_base::store(int, std::memory_order)': /home/XXXXXX/indi/libs/indidevice/property/indiproperty.h:249: multiple definition of `INDI::BaseClientQt::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)'; CMakeFiles/indiclientqt.dir/indiclientqt_autogen/mocs_compilation.cpp.o:/home/XXXXXX/indi/build/libs/indiclientqt/indiclientqt_autogen/mocs_compilation.cpp:64: first defined here
qt_metacast()が2回定義されている、とのこと・・・なんで???
Geminiに聞くと、
「multiple definition エラーの中に indiclientqt_OBJECT と indiclientqt という2つのターゲット名が登場しています。
これは INDI の CMake が、ソースを一度「オブジェクトライブラリ」としてコンパイルし、それを後で「共有ライブラリ(.so)」にまとめ上げるという二段構えの構成になっているためです。
そこに set(CMAKE_AUTOMOC ON) を追加したことで、両方の工程で moc が走ってしまい、同じ関数が2回作られている のが原因です。」
ふむふむ。
CMakeLists.txtを見てみるとstatic libraryと shared libraryを分けてビルドするところがあったので、それぞれにset(CMAKE_AUTOMOC ON)を入れてみると、
ふむふむ。
CMakeLists.txtを見てみるとstatic libraryと shared libraryを分けてビルドするところがあったので、それぞれにset(CMAKE_AUTOMOC ON)を入れてみると、
# Build Static Library if(INDI_BUILD_STATIC) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) add_library(${PROJECT_NAME}static STATIC) target_link_libraries(${PROJECT_NAME}static ${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) target_include_directories(${PROJECT_NAME}static PUBLIC . ) set_target_properties(${PROJECT_NAME}static PROPERTIES VERSION ${CMAKE_INDI_VERSION_STRING} SOVERSION ${INDI_SOVERSION} OUTPUT_NAME ${PROJECT_NAME} # this same name like shared library - backwards compatibility ) install(TARGETS ${PROJECT_NAME}static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() # Build Shared Library if(INDI_BUILD_SHARED) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) add_library(${PROJECT_NAME} SHARED) target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) target_include_directories(${PROJECT_NAME} PUBLIC . ) set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${CMAKE_INDI_VERSION_STRING} SOVERSION ${INDI_SOVERSION} OUTPUT_NAME ${PROJECT_NAME} ) install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif()
無事ビルドが通りました! (^O^)
nmコマンドで見ても、ちゃんとqt_metacallがあります。

ということで、ようやくNindiちゃんアプリを改めてビルドしてみると・・・
無事ビルドが通って実行できました!ヾ(〃^∇^)ノわぁい♪.

今回はGeminiのお陰でどうにか解決。 ありがとう!> Gemini
にしても、普通にビルドしてもmocが生成されないって、indiの不具合じゃないの?
IndiClientQtなんて使う人がいなくて、そもそもデフォルトではoffになっているし、ちゃんとテストされていないのかな?
ということで、Nindiちゃんとgphoto2は移植しました。UVCカメラは何もいじっていないのでそのまま動く(ハズ)。
あとはindiに自作プラネアプリ TeleSkymapBT2を繋ぐIndi driverが残っていますが、一旦それは後にして、次はNindiちゃんアプリの動作確認に進みましょう。
コメント