qtserialport with CMake in qtcreator-ros-plugin? - qt

I'm trying to compile qtserialport to my project in QtCreator4.9.2 with ROS plugin in.
Of course, I had follow the doc to install qtserialport to my Ubuntu16.04. And then, I had do some tests like this:
#include "QtSerialPort/qserialport.h"
#include "QtSerialPort/qserialportinfo.h"
...
Q_FOREACH(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
ROS_INFO("Name: %s", info.portName().toStdString().c_str());
ROS_INFO("Description: %s", info.description().toStdString().c_str());
ROS_INFO("Manufacturer: %s", info.manufacturer().toStdString().c_str());
...
}
But, get erros:
undefined reference to 'QSerialPortInfo::availablePorts()'
undefined reference to 'QSerialPortInfo::portName() const'
undefined reference to 'QSerialPortInfo::description() const'
...
undefined reference to 'QSerialPortInfo::~QSerialPortInfo()'
You know, I'm working with CMake, so the official docs about qmake or .pro introductions is useless to me. And I had find some suggestions like this, however, I'm confused with this: how to make the qtserialport as a module?
Anyway, all I want to say is that: how can I compile qtserialport with my ros CMake project? And certainly, it should also work with my QtCreator.
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.0)
project(xxx)
add_compile_options(-std=c++11)
find_package(catkin REQUIRED COMPONENTS qt_build roscpp)
include_directories(${catkin_INCLUDE_DIRS})
catkin_package()
rosbuild_prepare_qt4(QtCore QtGui QtOpenGL)
file(GLOB QT_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} rsources/*.qrc)
file(GLOB_RECURSE QT_MOC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS include/xxx/*.hpp)
QT4_ADD_RESOURCES(QT_RSOURCES_CPP ${QT_RESOURCES})
QT4_WRAP_CPP(QT_MOC_HPP ${QT_MOC})
set(QT_SOURCES ...)
if(MSVC)
set(...)
endif(MSVC)
add_definitions(...)
include_directories(...)
set(EXTERNAL_LIBRARIES OpenThreads osg osgDB osgViewer osgUtil osgText osgGA pthread lz4 bz2)
add_executable(... ${QT_SOURCES} ${QT_RESOURCES_CPP} ${QT_MOC_HPP})
target_link_libraries(xxx ${QT_LIBRARIES} ${EXTERNAL_LIBRARIES} ${catkin_LIBRARIES})
install(TARGETS xxx RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
Help!

QtCreator4.9.2 is your IDE's version, not the framework's version you probably are using Qt 5.1x.x version.
If you want to compile out of your IDE this line is essential
set(CMAKE_PREFIX_PATH your/qt/path/which/can/be/obtained)
check this path from QT Creator > Open a Qt Project > Projects option on Left bar > Project Build Option, on CMake settings check cmake_prefix_path
# Before add_executable
find_package(Qt5 COMPONENTS Core SerialPort REQUIRED)
# After add_executable
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt5::Core Qt5::SerialPort)
You also can learn package names under CMake folder of your Qt path.
/your/sys/path/Qt5/lib/cmake

Related

Creating a test project for QML QtQuick

I have a QLM project MyProject compiled with CMake, for which I wanted to add tests.
I figured I would create another project MyProject_tests, and a top level CMakeLists containing both :
MetaMyProject
|-CMakeLists.txt (1)
|-MyProject
| |-CMakeLists.txt (2)
|-MyProject_test
| |-CMakeLists.txt (3)
First CMakeLists contains
cmake_minimum_required(VERSION 3.3)
project(MetaMyProject CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
add_subdirectory(MyProject)
add_subdirectory(MyProject_Test)
Second CMakeLists is not changed, except I added set_property(TARGET ${PROJECT_NAME} PROPERTY ENABLE_EXPORTS 1) at the end.
Third CMakeLists contains
cmake_minimum_required(VERSION 3.1)
project(MyProject_ContraintsTest)
find_package(Qt6 COMPONENTS QuickTest REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(SOURCE_FILES
main.cpp
)
set(HEADER_FILES
)
set(QML_TESTCASE_FILES
testcases/tst_test.qml
)
add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/testcases")
add_executable(${PROJECT_NAME} ${SOURCE_FILES} ${HEADER_FILES} ${QML_TESTCASE_FILES})
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::QuickTest)
Now for the component defined in MyProject to be available in MyProject_test, I wanted to add on the last line a PIVATE MyProject. It does not raise warning, but import MyProject does not work then.
What is the correct way to link my test project to the base project in order for all the components to be available in the test project?
ENABLE_EXPORTS enables symbol exports from an executable, these symbols can be used in another library or executable. To be able to use a symbol in your qml, you would need to re-register the exported Qt Class in your MyProject_test/main.cpp using:
qmlRegisterType<MyExportedClass>("MyExportedClass", 1, 0, "MyExportedClass");
Then you would be able to use it with import MyExportedClass 1.0

How to get AUTOMOC to find header file in QT5

I'm using Qt 5 and I put all my headers in separate include folders, and AUTOMOC is unable to find my headers.
src
|- sim
|- include
|- sim
|- client.h (contains Q_OBJECT)
|- client.cpp
My CMake Code:
set(CMAKE_AUTOMOC ON)
find_package(Qt5 COMPONENTS Core Widgets REQUIRED)
add_library(client client.cpp)
target_include_directories(client PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_link_libraries(client sim Qt5::Widgets)
This results in undefined references to my signals because the QObject MOC class in client is not being generated. I tried adding this to force it to search for client.h...
#include "moc_client.cpp"
However then I get the error
AutoMoc error
-------------
"/home/peter/projects/smartmouse/smartmouse-simulator/src/sim/client.cpp"
The file includes the moc file "moc_client.cpp", but the header "client.{h,hh,h++,hm,hpp,hxx,in,txx}" could not be found.
I get why this is, because the docs only say it searches the current folder so it's not going to look int the include/sim folder. My question is how do I get AUTOMOC to find include/sim/client.h?
I also tried using qt5_wrap_cpp but it doesn't seem to actually call the moc compiler, it only sets up some information. I tried:
qt5_wrap_cpp(client include/sim/client.h)
But it did not generate any cmake targets as far as I can tell
EDIT:
I've also noticed in the AutogenInfo.cmake file that no header is found: set(AM_HEADERS "")
I just ran into this similar issue and while I'm not satisfied with this answer, it might be helpful.
CMAKE_AUTOMOC is not picking up client.cpp's #include "sim/client.h" but you can manually add it to the target sources:
add_library(client client.cpp include/sim/client.h)

Linux: Generate installer with dependencies

I would like to create an installer for my program, which uses OpenCV and some Qt libraries. I also want to make sure that all dependencies are included in the installer so that anyone could easily install my program without installing OpenCV and/or Qt.
I did some research and it seems that the easiest way to do so would be using Qt Installer Framework. I have the following CMakeLists.txt file:
cmake_minimum_required(VERSION 3.0)
# Add folder where are supportive functions
set(CMAKE_AUTOMOC ON)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_STANDARD 11)
# Include qt basic functions
include(QtCommon)
# Include qt current directories in order to use promoted objects
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/modules/app)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/modules/cores)
# Basic info about project
project(SSAT VERSION 1.0)
# Set PROJECT_VERSION_PATCH and PROJECT_VERSION_TWEAK to 0 if not present, needed by add_project_meta
fix_project_version()
file(GLOB APP_GUI_FILES "modules/app/*.ui")
file(GLOB APP_SOURCE_FILES "modules/app/*.cpp")
file(GLOB CORE_SOURCE_FILES "modules/core/*.cpp")
file(GLOB CORE_INCLUDE_FILES "modules/core/*.h")
file(GLOB CMT_SOURCE_FILES "modules/tracker/*.cpp")
file(GLOB CMT_INCLUDE_FILES "modules/tracker/*.h")
add_project_meta(META_FILES_TO_INCLUDE)
set(RESOURCE_FILES ssat.qrc)
find_package( OpenCV REQUIRED )
find_package(Qt5Widgets REQUIRED)
find_package(OpenCV COMPONENTS opencv_core opencv_imgproc opencv_imgcodecs opencv_highgui REQUIRED)
find_path(OpenCV_INCLUDE_DIR "opencv/cv.h" PATHS "${OpenCV_DIR}" PATH_SUFFIXES "include" DOC "")
# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
# source_group("UI Files" FILES ${UI_FILES})
add_library(${PROJECT_NAME}_CORE ${CORE_SOURCE_FILES} ${CORE_INCLUDE_FILES})
target_link_libraries(${PROJECT_NAME}_CORE ${OpenCV_LIBS})
target_include_directories(${PROJECT_NAME}_CORE PUBLIC modules/core/)
add_library(${PROJECT_NAME}_CMT ${CMT_SOURCE_FILES} ${CMT_INCLUDE_FILES})
target_link_libraries(${PROJECT_NAME}_CMT ${OpenCV_LIBS})
target_include_directories(${PROJECT_NAME}_CMT PUBLIC modules/tracker/)
add_executable(${PROJECT_NAME} ${OS_BUNDLE} # Expands to WIN32 or MACOS_BUNDLE depending on OS
${APP_GUI_FILES} ${APP_SOURCE_FILES} ${META_FILES_TO_INCLUDE} ${RESOURCE_FILES}
)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_CORE)
target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_CMT)
target_link_libraries(${PROJECT_NAME} pthread)
target_include_directories(${PROJECT_NAME} PUBLIC ${OpenCV_INCLUDE_DIR})
qt5_use_modules(${PROJECT_NAME} Widgets)
Since Qt Installer Framework demonstrates how to create an an installer from a Qt Project (.pro) instead of a CMake file, I would like to know if it is possible to create an installer from a CMake project in such a way that all its dependencies are included.

Qt binary linked to both Qt 5 and (wrongly) to Qt 4 causing segmentation fault when linked to Qwt

I have a Qt / ROS / Qwt application. Everything was going fine until I tried to link to Qwt. Note that I'm using Qwt 6.1.2 which should run on Qt 5.5. Indeed, the examples run fine.
When I run my binary, it crashes even if I'm not using Qwt. I just need to link the my code to Qwt for that to happen. And -here is the issue I think-, gdb gives the following error:
ram received signal SIGSEGV, Segmentation fault.
0x00007ffff25eadfc in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
Which is wrong since the binary should be using Qt 5.5. To make things more weird, ldd gives:
>> ldd dls_gui | grep 'Qt'
libQt5Widgets.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5Widgets.so.5 (0x00007f684cadc000)
libQt5Gui.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5Gui.so.5 (0x00007f684afad000)
libQt5Core.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5Core.so.5 (0x00007f684a867000)
libQtSvg.so.4 => /usr/lib/x86_64-linux-gnu/libQtSvg.so.4 (0x00007f684862c000)
libQtGui.so.4 => /usr/lib/x86_64-linux-gnu/libQtGui.so.4 (0x00007f6847979000)
libQtCore.so.4 => /usr/lib/x86_64-linux-gnu/libQtCore.so.4 (0x00007f6847493000)
libicui18n.so.54 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libicui18n.so.54 (0x00007f6844e33000)
libicuuc.so.54 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libicuuc.so.54 (0x00007f6844a85000)
libicudata.so.54 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libicudata.so.54 (0x00007f684305b000)
How can I be linked to both Qt5 and Qt4? Qwt seems to be linked to only Qt 5.5:
>> ldd /usr/local/qwt-6.1.2/lib/libqwt.so | grep 'Qt'
libQt5PrintSupport.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5PrintSupport.so.5 (0x00007fbcee13a000)
libQt5Svg.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5Svg.so.5 (0x00007fbcedee5000)
libQt5OpenGL.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5OpenGL.so.5 (0x00007fbcedc8e000)
libQt5Widgets.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5Widgets.so.5 (0x00007fbced410000)
libQt5Gui.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5Gui.so.5 (0x00007fbcecbfc000)
libQt5Core.so.5 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libQt5Core.so.5 (0x00007fbcec4b7000)
libicui18n.so.54 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libicui18n.so.54 (0x00007fbcea032000)
libicuuc.so.54 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libicuuc.so.54 (0x00007fbce9c84000)
libicudata.so.54 => /home/jcolmenares/Qt/5.5/gcc_64/lib/libicudata.so.54 (0x00007fbce825a000)
My CMakeList.txt file is:
cmake_minimum_required(VERSION 2.8.11)
project(dls_gui)
# Find the QtWidgets library
find_package(Qt5Widgets)
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Qwt related
# list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake_packages")
# find_package(Qwt REQUIRED)
find_path(QWT_INCLUDE_DIR qwt.h HINTS /usr/local/qwt-6.1.2/include)
find_library(QWT_LIBRARY qwt /usr/local/qwt-6.1.2/lib/)
include_directories(${QWT_INCLUDE_DIR})
# catkin related
catkin_package()
find_package(catkin REQUIRED COMPONENTS roscpp sensor_msgs urdf)
include_directories( ${catkin_INCLUDE_DIRS} include)
# source, header and resources files list
set(CPP_SOURCES src/main.cpp src/mainwindow.cpp src/basewidget.cpp src/rosQtNode.cpp
src/joints_sliders.cpp src/superslider.cpp src/support_polygon.cpp)
set(CPP_HDRS include/mainwindow.h include/basewidget.h include/rosQtNode.hpp
include/joints_sliders.hpp include/superslider.hpp include/support_polygon.hpp)
set(QRC_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/dls_gui.qrc)
# Add the include directories for the Qt 5 Widgets module to# the compile lines.
include_directories(${Qt5Widgets_INCLUDE_DIRS} )
# Use the compile definitions defined in the Qt 5 Widgets module
add_definitions(${Qt5Widgets_DEFINITIONS})
# Generate headers from ui files
qt5_wrap_ui(UIS_HDRS src/mainwindow.ui)
# Generate moc files from cpp
qt5_wrap_cpp(MOC_SOURCES ${CPP_SOURCES} ${CPP_HDRS})
# Generate resources
qt5_add_resources(RESOURCES_RCC ${RESOURCE})
# Add compiler flags for building executables (-fPIE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS} -std=c++11")
## Ros include dirs
include_directories(include ${catkin_INCLUDE_DIRS})
# Tell CMake to create the helloworld executable
add_executable(dls_gui ${CPP_SOURCES} ${UIS_HDRS} ${MOC_SOURCES} ${QRC_RESOURCES})
add_executable(testRos src/testRos.cpp)
qt5_use_modules(dls_gui Widgets)
#Link the helloworld executable to the Qt 5 widgets library.
target_link_libraries(dls_gui ${QWT_LIBRARY} Qt5::Widgets ${catkin_LIBRARIES} )
target_link_libraries(testRos ${catkin_LIBRARIES})
I don't think this is ROS related, nevertheless, is important to say that the source code is compiled via catkin_make etc.
Last but not least, qmake refers to version 5.5:
>> qmake --version
QMake version 3.0
Using Qt version 5.5.0 in /home/jcolmenares/Qt/5.5/gcc_64/lib
EDIT: Just to be clear: I want (need) everything compiled and linked to the same Qt versiĆ³n. But somehow, is not happening.
You need to link with qwt-qt5.
qwt is the Qt4 version of QWT, which uses libQtGui.so.4 etc., which you can see in your ldd output above. Linking with qwt-qt5 only requires Qt5 so files.
I switched everything back to Qt4. Got tired of wasting time on an issue that should not happen. Still have no idea how the binary ended linked to two different versions of Qt, only when linked to Qwt, where Qwt was linked only to Qt5 and the binary without the linkage to Qwt was also only linked to Qt5.

How do you do develop an SBT project, itself?

Background: I've got a Play 2.0 project, and I am trying to add something to do aspectj weaving using aspects in a jar on some of my classes (Java). (sbt-aspectj doesn't seem to do it, or I can't see how). So I need to add a custom task, and have it depend on compile. I've sort of figured out the dependency part. However, because I don't know exactly what I'm doing, yet, I want to develop this using the IDE (I'm using Scala-IDE). Since sbt projects (and therefore Play projects) are recursively defined, I assumed I could:
Add the eclipse plugin to the myplay/project/project/plugins.sbt
Add the sbt main jar (and aspectj jar) to myplay/project/project/build.sbt:
libraryDependencies ++= Seq(
"org.scala-sbt" % "main" % "0.12.2",
"aspectj" % "aspectj-tools" % "1.0.6"
)
Drop into the myplay/project
Run sbt, run the eclipse task, then import the project into eclipse as a separate project.
I can do this, though the build.scala (and other scala files) aren't initially considered source, and I have to fiddle with the build path a bit. However, even though I've got the sbt main defined for the project, both eclipse IDE and the compile task give errors:
> compile
[error] .../myplay/project/Build.scala:2: not found: object keys
[error] import keys.Keys._
[error] ^
[error] .../myplay/project/SbtAspectJ.scala:2: object Configurations is not a member of package sbt
[error] import sbt.Configurations.Compile
[error] ^
[error] .../myplay/project/SbtAspectJ.scala:3: object Keys is not a member of package sbt
[error] import sbt.Keys._
[error] ^
[error] three errors found
The eclipse project shows neither main nor aspectj-tools in its referenced-libraries. However, if I give it a bogus version (e.g. 0.12.4), reload fails, so it appears to be using
the dependency.
So,...
First: Is this the proper way to do this?
Second: If so, why aren't the libs getting added.
(Third: please don't let this be something dumb that I missed.)
If you are getting the object Keys is not a member of package sbt error, then you should check that you are running sbt from the base directory, and not the /project directory.
sbt-aspectj
sbt-aspectj doesn't seem to do it, or I can't see how.
I think this is the real issue. There's a plugin already that does the work, so try making it work instead of fiddling with the build. Using plugins from build.scala is a bit tricky.
Luckily there are sample projects on github:
import sbt._
import sbt.Keys._
import com.typesafe.sbt.SbtAspectj.{ Aspectj, aspectjSettings, compiledClasses }
import com.typesafe.sbt.SbtAspectj.AspectjKeys.{ binaries, compileOnly, inputs, lintProperties }
object SampleBuild extends Build {
....
// precompiled aspects
lazy val tracer = Project(
"tracer",
file("tracer"),
settings = buildSettings ++ aspectjSettings ++ Seq(
// stop after compiling the aspects (no weaving)
compileOnly in Aspectj := true,
// ignore warnings (we don't have the sample classes)
lintProperties in Aspectj += "invalidAbsoluteTypeName = ignore",
// replace regular products with compiled aspects
products in Compile <<= products in Aspectj
)
)
}
How do you do develop an SBT project, itself?
If you're interested in hacking on the build still the first place to go is the Getting Started guide. Specifically, your question should be answered in .scala Build Definition page.
I think you want your build to utilize "aspectj" % "aspectj-tools" % "1.0.6". If so it should be included in myplay/project/plugins.sbt, and your code should go into myplay/project/common.scala or something. If you want to use IDE, you have have better luck with building it as a sbt plugin. That way your code would go into src/main/scala. Check out sbt/sbt-aspectj or sbt/sbt-assembly on example of sbt plugin structure.

Resources