2

I have 3 files in my c++/qt project and I'm using CMake. I'm trying to compile it Here are some code:

CMakeLists contains:

cmake_minimum_required(VERSION 3.8)
project(untitled)

set(CMAKE_CXX_STANDARD 14)

set(CMAKE_PREFIX_PATH /Users/username/Qt/5.9.2/clang_64/)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

find_package(Qt5Core)
find_package(Qt5Network)

set(SOURCE_FILES main.cpp server.cpp)

add_executable(untitled ${SOURCE_FILES})

target_link_libraries(${PROJECT_NAME} Qt5::Core)
target_link_libraries(${PROJECT_NAME} Qt5::Network)

Main.cpp contains:

#include <iostream>
#include <QCoreApplication>
#include <QtDebug>
#include "server.cpp"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    MyTcpServer server;
    return app.exec();
}

and finally server.cpp contains:

#include <QObject>
#include <QTcpSocket>
#include <QTcpServer>
#include "server.moc"

class MyTcpServer : public QObject
{
Q_OBJECT
public:
    explicit MyTcpServer(QObject *parent = 0);

public slots:
    void slotNewConnection();
    void slotServerRead();
    void slotClientDisconnected();

private:
    QTcpServer * mTcpServer;
    QTcpSocket * mTcpSocket;
};

MyTcpServer::MyTcpServer(QObject *parent) : QObject(parent)
{
  ...
}

void MyTcpServer::slotNewConnection()
{
  ...
}

void MyTcpServer::slotServerRead()
{
  ...
}

void MyTcpServer::slotClientDisconnected()
{
    mTcpSocket->close();
}

I'm trying to compile my project with CMake, and when I run the CMake, I have this problems :

duplicate symbol __ZN11MyTcpServer18qt_static_metacallEP7QObjectN11QMetaObject4CallEiPPv in:
    CMakeFiles/untitled.dir/main.cpp.o
    CMakeFiles/untitled.dir/server.cpp.o
                      ...
duplicate symbol __ZN11MyTcpServer16staticMetaObjectE in:
    CMakeFiles/untitled.dir/main.cpp.o
    CMakeFiles/untitled.dir/server.cpp.o
ld: 13 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Telling me that there is a duplicate symbol. How to resolve this?

Teivaz
  • 5,462
  • 4
  • 37
  • 75
  • 3
    It's considered a really bad practice to include `.cpp` files. Just move the declaration of your `MyTcpServer` class to a separate header file `server.h`, include that into `main.cpp` and remove the inclusion of `server.moc` from `server.cpp`. – Dmitry Oct 29 '17 at 09:56
  • 2
    In addition to Dmitry: Due to the `#include "server.cpp"` in `main.cpp`, everything in `server.cpp` is compiled twice, 1st as part of `main.cpp`, 2nd as `server.cpp` as you listed both files as `SOURCE_FILES`. Removing the latter from `SOURCE_FILES` would fix your problem also, but I warmly recommend what Dmitry did. – Scheff's Cat Oct 29 '17 at 10:02
  • Not related to your issue but I recommend to use `${PROJECT_NAME}` in your `add_executable` too. This makes the CMakeLists.txt easier re-usable. – Th. Thielemann Oct 29 '17 at 18:21
  • After your answer I have make like your advice but I have seem problem, but problem just on the MacOS M1 – Pouney Design Mar 03 '23 at 11:35

2 Answers2

0

It is better not to use #include for .cpp files. It is good practice to split definition and declaration into different files.

(One exception from this is the private declaration in case of PIMPL pattern.)

In case you want to avoid the split because you have only small pieces of code use a header file and implement your methods within the definition of the class.

In case a library is implemented: Do not install the header file in case your class must not accessible from outside.

Th. Thielemann
  • 2,592
  • 1
  • 23
  • 38
0

The simple fix for your case would be fo#include "server.cpp" from your cpp as mentioned in comments (it is rarely needs to be done and virtually never is a good thing).

And the second thing would be to move the #include "server.moc" line to the end of the cpp file. This is important because this file contains implementation of some member functions injected with Q_OBJECT and the class needs to be defined before implementing member functions outside of its body.

Teivaz
  • 5,462
  • 4
  • 37
  • 75