«

»

Oct 15

CMake build for QExtSerialPort for all those lonely cross-platform Qt4 projects

rect6492So QSerialPort only became part of Qt core on Qt5.1, but what should all those Qt4 projects do for an easy serial port access?
There is the excellent QExtSerialPort project, but it only has a QMake build system, and I like CMake!
Not to worry, a CMake build is easy to set up...

First, I'll mention I'm working with QExtSerialPort version 1.2 (and not the beta 2.0), and also that there is a tiny patch needed in the qextserialenumerator_p.h file so it works on WIN32 (found the solution somewhere online).
I also need to mention that I'm taking QExtSerialPort to be part of my project's source and not as a precompiled framework or a library of sorts. But the CMake script can be made to create a library just the same, and doesn't have to be part of an executable. QExtSerialPort itself comes with a QMake script to make a framework/library, so opt for that if you're into QMake.

Download QExtSerialPort source: http://qextserialport.googlecode.com/files/qextserialport-1.2rc.zip

The diff on qextserialenumerator_p.h:

53,54c53,55
< #    define _WIN32_WINNT 0x0501
< #    define WINVER 0x0501
---
> #    define _WIN32_WINNT 0x0500
> #    define _WIN32_WINDOWS 0x0500
> #    define WINVER 0x0500

I assume QExtSerialPort you've just downloaded is in a directory called "QExtSerialPort-1.2rc" in your root source directory.

Now setup CMake to deal with the files in "QExtSerialPort-1.2rc":

######## Qt stuff ########
ADD_DEFINITIONS(${QT_DEFINITIONS})
include_directories(${QT_INCLUDES})
include(${QT_USE_FILE}) 

INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} ) #qt wrapping creates some sources
##########################

SET(QEXTSERIALPORT_SOURCES "QExtSerialPort-1.2rc/qextserialport.cpp;QExtSerialPort-1.2rc/qextserialenumerator.cpp")

IF(WIN32)
    SET(QEXTSERIALPORT_LIBS "setupapi;advapi32;user32")
    SET(QEXTSERIALPORT_SOURCES "${QEXTSERIALPORT_SOURCES};QExtSerialPort-1.2rc/qextserialenumerator_win.cpp;QExtSerialPort-1.2rc/qextserialport_win.cpp")
ELSEIF(APPLE)
    SET(QEXTSERIALPORT_LIBS "-framework IOKit -framework CoreFoundation")
    SET(QEXTSERIALPORT_SOURCES "${QEXTSERIALPORT_SOURCES};QExtSerialPort-1.2rc/qextserialenumerator_osx.cpp;QExtSerialPort-1.2rc/qextserialport_unix.cpp")
ELSE()
    SET(QEXTSERIALPORT_SOURCES "${QEXTSERIALPORT_SOURCES};QExtSerialPort-1.2rc/qextserialenumerator_linux.cpp;QExtSerialPort-1.2rc/qextserialport_unix.cpp")

ENDIF()
file(GLOB QEXTSERIALPORT_HEADERS QExtSerialPort-1.2rc/*.h)

SOURCE_GROUP(QEXTSERIALPORT FILES ${QEXTSERIALPORT_SOURCES} ${QEXTSERIALPORT_HEADERS})
QT4_WRAP_CPP( QEXTSERIALPORT_HEADERS_MOC ${QEXTSERIALPORT_HEADERS} )

When setting up your executable, don't forget to add the MOCs to the build

add_executable(MyProgram
     ${MY_SOURCES} ${MY_HEADERS}
     ${QEXTSERIALPORT_SOURCES} ${QEXTSERIALPORT_HEADERS} ${QEXTSERIALPORT_HEADERS_MOC}
     )

target_link_libraries(MyProgram
     ${QT_LIBRARIES}
     ${QEXTSERIALPORT_LIBS}
     )

You should be good to go with easy serial port connections within Qt 4.8 projects, for example:

#include <QDebug>

#include "QExtSerialPort-1.2rc/qextserialport.h"

//I like this STRINGIFY macro, it's very useful!
#ifndef SSTR
#include <sstream>
#define SSTR( x ) dynamic_cast< std::ostringstream & >( \
( std::ostringstream() << x ) ).str()
#endif

int main(int argc, char** argv) {

    std::string portname = "COM3";

    port.setPortName(QString(portname.c_str()));
    port.setBaudRate(BAUD9600);
    if(!port.open(QIODevice::ReadWrite)) {
        qDebug() << "cannot connect to " << portname.c_str();
        exit(0);
    }

    int val = 5;
    qDebug() << "Sending " << (int)val;
    port.write(&val, 1);
    port.waitForBytesWritten(5);

    qDebug() << "Port received " << port.readAll();

    port.close();
}
Share