Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Need assistance with error: Symbols not found for architecture x86_64
Qt 6.11 is out! See what's new in the release blog

Need assistance with error: Symbols not found for architecture x86_64

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 849 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    NoticeMeSenpai
    wrote on last edited by NoticeMeSenpai
    #1

    Hi all,

    Fair warning, the majority of code here is exactly from an exercise on Pluralsight (I completed the prior chapter a week or two ago on a different machine and decided to download the files to pick back up where I left off). That being said, I do understand the majority of what is written and what the application is actually doing and will be happy to answer any questions as to thoughts behind why something may be written a particular way.

    From what I've found on Google, I believe the issue is that the Q_OBJECT macro is not being recognized any more. The issue seems to have cropped up after I did a bit refactoring of the Settings.h declarations but, I'm not seeing what specifically is causing the issue is or why the issue appeared. As far as I can tell, building / compiling was fine before I "intelligently" -insert a sarcastic snicker here- refactored the code.

    Thank you again in advance to you all for any assistance you can give.

    Screenshot of Error
    oh geez rick... what did I do?
    Link to the full project: https://www.dropbox.com/s/coz48htffj1kbg3/pluralsight-vfp-app.zip?dl=0

    I'll only provide the Settings.h and Settings.cpp files beneath since I believe the others are not a part of the issue, if it would be better to dump the entire contents of the project here (or if there a better location to put the project such as GitHub) please let me know.

    Settings.h

    #pragma once
    #include <QObject>
    
    class QString;
    class QStringListModel;
    struct QJsonParseError;
    class QJsonObject;
    class QFile;
    class QDir;
    
    
    namespace Ps{
    
        typedef std::pair<QJsonObject, QJsonParseError> JsonObjErrPair;
    
        class Settings : public QObject
        {
            Q_OBJECT
        public:
            explicit Settings(QObject *parent, QString filename);
            ~Settings();
            void ParseJsonData();
    
        signals:
            void NotifyStatusMessage(QString message);
    
        private:
            QString m_filename;
            QString m_applicationName;
            QString m_appShortName;
            QString m_hostName;
            quint16 m_portNumber;
            int m_waitMs;
            int m_readWaitMs;
            QStringListModel& m_modelCommands;
    
            QString ReadJsonFileFromInternalResource();
            JsonObjErrPair GetJsonObject(const QString& raw);
    
            QString ReadJsonFile();
            void SetupCommands(QJsonObject jsonObj);
            void SendErrorMessage(const QString& msg);
            void ShowJsonParseError(QJsonParseError jsonErr);
    
            explicit Settings(const Settings& rhs) = delete;
            Settings& operator= (const Settings& rhs) = delete;
        };
    }
    

    Settings.cpp

    #include "settings.h"
    #include <QDir>
    #include <QString>
    #include <QJsonObject>
    #include <QJsonParseError>
    #include <QJsonDocument>
    #include <QMessageBox>
    #include <QJsonArray>
    #include <QStringList>
    #include <QStringListModel>
    #include <utility>
    
    namespace Ps
    {
        //the default prefix used when opening the default config
        static auto RES_PREFIX = QString(":/json");
    
        Settings::Settings(QObject *parent, QString filename) :
            QObject(parent),
            m_filename(filename),
            m_modelCommands(*new QStringListModel(this))
        {
            //DEBUG:
            ReadJsonFile();
        }
    
        //Read settings from a json file
        QString Settings::ReadJsonFile()
        {
            //load default config first
            auto default_settings = ReadJsonFileFromInternalResource();
    
            //return default settings while testing
            return default_settings;
        }
    
        //Load the default config
        QString Settings::ReadJsonFileFromInternalResource()
        {
            //create a container to a directory
            QDir res_dir(RES_PREFIX);
    
            //check the prefix was valid / container exists
            if(!res_dir.exists())
            {
                //[ERR]: path does not exist error
                SendErrorMessage("Internal resource path is missing: " +
                                 res_dir.canonicalPath());
                return "";
            }
    
            //set a reference to the file
            auto path = res_dir.filePath(m_filename);
    
            //create a file resource using that file reference
            QFile res_file(path);
    
            //check that the file can be opened read only \
            //  as a plain text file
            if(!res_file.open(QFile::ReadOnly | QFile::Text))
            {
                //[ERR]: file was not opened properly
                SendErrorMessage("Could not open internal resource: " +
                                 path);
                return "";
            }
    
            //save content to string
            QString my_settings = res_file.readAll();
    
            //return the string to caller
            return my_settings;
    
        }
    
        //Parse the Json Data
        void Settings::ParseJsonData()
        {
            //read the config
            QString raw_json = ReadJsonFile();
    
            //is the config is empty, nothing to parse, exit
            if(raw_json.size() == 0) return;
    
            //transform settings into json object
            auto json_result = GetJsonObject(raw_json);
    
            //pull any errors returned from result
            auto json_err = json_result.second;
    
            //if an error was returned
            if(json_err.error != QJsonParseError::NoError)
            {
                //[ERR]: Json could not be parsed
                ShowJsonParseError(json_err);
            }
    
            //pull the object out for assignment
            auto json_obj = json_result.first;
    
            //set application variables
            m_applicationName = json_obj["applicationName"].toString();
            m_appShortName = json_obj["appShortName"].toString();
            m_hostName = json_obj["hostName"].toString();
            m_portNumber = json_obj["port"].toInt();
            m_waitMs = json_obj["tcpLongWaitMs"].toInt();
            m_readWaitMs = json_obj["tcpShortWaitMs"].toInt();
    
            //assign the cmd list within the json data
            //to our combobox
            SetupCommands(json_obj);
        }
    
        //Parse command list from json
        void Settings::SetupCommands(QJsonObject raw)
        {
            //create a new array to hold the list of strings
            QJsonArray cmd_array = raw["commands"].toArray();
    
            //create a list to temp hold the strings
            QStringList cmd_list;
    
            //iterate through each string in cmd_array
            //each value referenced as item
            for(auto item: cmd_array)
            {
                //append each value to the list
                cmd_list.append(item.toString());
            }
    
            //save the list to the app variable
            m_modelCommands.setStringList(cmd_list);
        }
    
        //Extract the json object from the data
        JsonObjErrPair Settings::GetJsonObject(const QString& raw)
        {
            //QJsonDoc needs a reference to a QJsonParseError for errors
            QJsonParseError json_parse_err;
    
            //load the json from the raw data
            QJsonDocument json_doc = QJsonDocument::fromJson(raw.toUtf8(),
                                                             &json_parse_err);
    
            //create an object from the JsonDocument
            QJsonObject json_obj = json_doc.object();
    
            //return the pair with data and any errors
            return std::make_pair(json_obj, json_parse_err);
        }
    
        //Show errors from parsing the settings file
        void Settings::ShowJsonParseError(QJsonParseError jsonErr)
        {
            //create a flavor string
            QString msg = tr("Error parsing JSON settings file.\n");
    
            //append the error using the errorString method to extract the details
            msg.append(jsonErr.errorString());
    
            //open a msg box to alert the user of the issue
            QMessageBox::critical(nullptr, tr("VFP"), msg);
        }
    
        //Show general errors
        void Settings::SendErrorMessage(const QString& msg)
        {
            emit NotifyStatusMessage(msg);
        }
    }
    
    aha_1980A 1 Reply Last reply
    0
    • N NoticeMeSenpai

      Hi all,

      Fair warning, the majority of code here is exactly from an exercise on Pluralsight (I completed the prior chapter a week or two ago on a different machine and decided to download the files to pick back up where I left off). That being said, I do understand the majority of what is written and what the application is actually doing and will be happy to answer any questions as to thoughts behind why something may be written a particular way.

      From what I've found on Google, I believe the issue is that the Q_OBJECT macro is not being recognized any more. The issue seems to have cropped up after I did a bit refactoring of the Settings.h declarations but, I'm not seeing what specifically is causing the issue is or why the issue appeared. As far as I can tell, building / compiling was fine before I "intelligently" -insert a sarcastic snicker here- refactored the code.

      Thank you again in advance to you all for any assistance you can give.

      Screenshot of Error
      oh geez rick... what did I do?
      Link to the full project: https://www.dropbox.com/s/coz48htffj1kbg3/pluralsight-vfp-app.zip?dl=0

      I'll only provide the Settings.h and Settings.cpp files beneath since I believe the others are not a part of the issue, if it would be better to dump the entire contents of the project here (or if there a better location to put the project such as GitHub) please let me know.

      Settings.h

      #pragma once
      #include <QObject>
      
      class QString;
      class QStringListModel;
      struct QJsonParseError;
      class QJsonObject;
      class QFile;
      class QDir;
      
      
      namespace Ps{
      
          typedef std::pair<QJsonObject, QJsonParseError> JsonObjErrPair;
      
          class Settings : public QObject
          {
              Q_OBJECT
          public:
              explicit Settings(QObject *parent, QString filename);
              ~Settings();
              void ParseJsonData();
      
          signals:
              void NotifyStatusMessage(QString message);
      
          private:
              QString m_filename;
              QString m_applicationName;
              QString m_appShortName;
              QString m_hostName;
              quint16 m_portNumber;
              int m_waitMs;
              int m_readWaitMs;
              QStringListModel& m_modelCommands;
      
              QString ReadJsonFileFromInternalResource();
              JsonObjErrPair GetJsonObject(const QString& raw);
      
              QString ReadJsonFile();
              void SetupCommands(QJsonObject jsonObj);
              void SendErrorMessage(const QString& msg);
              void ShowJsonParseError(QJsonParseError jsonErr);
      
              explicit Settings(const Settings& rhs) = delete;
              Settings& operator= (const Settings& rhs) = delete;
          };
      }
      

      Settings.cpp

      #include "settings.h"
      #include <QDir>
      #include <QString>
      #include <QJsonObject>
      #include <QJsonParseError>
      #include <QJsonDocument>
      #include <QMessageBox>
      #include <QJsonArray>
      #include <QStringList>
      #include <QStringListModel>
      #include <utility>
      
      namespace Ps
      {
          //the default prefix used when opening the default config
          static auto RES_PREFIX = QString(":/json");
      
          Settings::Settings(QObject *parent, QString filename) :
              QObject(parent),
              m_filename(filename),
              m_modelCommands(*new QStringListModel(this))
          {
              //DEBUG:
              ReadJsonFile();
          }
      
          //Read settings from a json file
          QString Settings::ReadJsonFile()
          {
              //load default config first
              auto default_settings = ReadJsonFileFromInternalResource();
      
              //return default settings while testing
              return default_settings;
          }
      
          //Load the default config
          QString Settings::ReadJsonFileFromInternalResource()
          {
              //create a container to a directory
              QDir res_dir(RES_PREFIX);
      
              //check the prefix was valid / container exists
              if(!res_dir.exists())
              {
                  //[ERR]: path does not exist error
                  SendErrorMessage("Internal resource path is missing: " +
                                   res_dir.canonicalPath());
                  return "";
              }
      
              //set a reference to the file
              auto path = res_dir.filePath(m_filename);
      
              //create a file resource using that file reference
              QFile res_file(path);
      
              //check that the file can be opened read only \
              //  as a plain text file
              if(!res_file.open(QFile::ReadOnly | QFile::Text))
              {
                  //[ERR]: file was not opened properly
                  SendErrorMessage("Could not open internal resource: " +
                                   path);
                  return "";
              }
      
              //save content to string
              QString my_settings = res_file.readAll();
      
              //return the string to caller
              return my_settings;
      
          }
      
          //Parse the Json Data
          void Settings::ParseJsonData()
          {
              //read the config
              QString raw_json = ReadJsonFile();
      
              //is the config is empty, nothing to parse, exit
              if(raw_json.size() == 0) return;
      
              //transform settings into json object
              auto json_result = GetJsonObject(raw_json);
      
              //pull any errors returned from result
              auto json_err = json_result.second;
      
              //if an error was returned
              if(json_err.error != QJsonParseError::NoError)
              {
                  //[ERR]: Json could not be parsed
                  ShowJsonParseError(json_err);
              }
      
              //pull the object out for assignment
              auto json_obj = json_result.first;
      
              //set application variables
              m_applicationName = json_obj["applicationName"].toString();
              m_appShortName = json_obj["appShortName"].toString();
              m_hostName = json_obj["hostName"].toString();
              m_portNumber = json_obj["port"].toInt();
              m_waitMs = json_obj["tcpLongWaitMs"].toInt();
              m_readWaitMs = json_obj["tcpShortWaitMs"].toInt();
      
              //assign the cmd list within the json data
              //to our combobox
              SetupCommands(json_obj);
          }
      
          //Parse command list from json
          void Settings::SetupCommands(QJsonObject raw)
          {
              //create a new array to hold the list of strings
              QJsonArray cmd_array = raw["commands"].toArray();
      
              //create a list to temp hold the strings
              QStringList cmd_list;
      
              //iterate through each string in cmd_array
              //each value referenced as item
              for(auto item: cmd_array)
              {
                  //append each value to the list
                  cmd_list.append(item.toString());
              }
      
              //save the list to the app variable
              m_modelCommands.setStringList(cmd_list);
          }
      
          //Extract the json object from the data
          JsonObjErrPair Settings::GetJsonObject(const QString& raw)
          {
              //QJsonDoc needs a reference to a QJsonParseError for errors
              QJsonParseError json_parse_err;
      
              //load the json from the raw data
              QJsonDocument json_doc = QJsonDocument::fromJson(raw.toUtf8(),
                                                               &json_parse_err);
      
              //create an object from the JsonDocument
              QJsonObject json_obj = json_doc.object();
      
              //return the pair with data and any errors
              return std::make_pair(json_obj, json_parse_err);
          }
      
          //Show errors from parsing the settings file
          void Settings::ShowJsonParseError(QJsonParseError jsonErr)
          {
              //create a flavor string
              QString msg = tr("Error parsing JSON settings file.\n");
      
              //append the error using the errorString method to extract the details
              msg.append(jsonErr.errorString());
      
              //open a msg box to alert the user of the issue
              QMessageBox::critical(nullptr, tr("VFP"), msg);
          }
      
          //Show general errors
          void Settings::SendErrorMessage(const QString& msg)
          {
              emit NotifyStatusMessage(msg);
          }
      }
      
      aha_1980A Offline
      aha_1980A Offline
      aha_1980
      Lifetime Qt Champion
      wrote on last edited by aha_1980
      #2

      @NoticeMeSenpai

      We need the full compile log, including linker command to give any hints.

      Hint: Use a version control system to archive your code. Once you have a working version, you can always go back there in case something breaks later. By diffing, it's also easier to see what changed and what could cause the problem.

      Regards

      Edit: The platform, compiler and Qt version would also be nice.

      Qt has to stay free or it will die.

      N 1 Reply Last reply
      3
      • aha_1980A aha_1980

        @NoticeMeSenpai

        We need the full compile log, including linker command to give any hints.

        Hint: Use a version control system to archive your code. Once you have a working version, you can always go back there in case something breaks later. By diffing, it's also easier to see what changed and what could cause the problem.

        Regards

        Edit: The platform, compiler and Qt version would also be nice.

        N Offline
        N Offline
        NoticeMeSenpai
        wrote on last edited by NoticeMeSenpai
        #3

        @aha_1980

        ~~Thanks for the prompt response. I hate to show my lack of knowledge but, would you be able to assist me with getting the compilation log?

        You are absolutely right, I've been playing around with git but admittedly I've not actually used it proper. I'll definitely make that a part of my regular workflow so I can sidestep these types of issues quicker.

        As for my QT version and environment; I'm running QT Creator 4.7.0 on Mac OS Sierra 10.12.6, using Clang 8.0.~~

        Actually, I found the issue thanks to your assistance. I had not realised that my compilation output was "empty" because the project was "already built". So I ended up cleaning the project and rebuilding. After which I found the following error in the output that then led me to realise that I added a definition for the destructor in the header but never defined a method for it in the class.

        Adding in the proper method for the destructor has solved the issue! I'll mark the issue as solved and +1 you for pointing me to the right location to look.

        OpenGL -framework AGL 
        Undefined symbols for architecture x86_64:
          "Ps::Settings::~Settings()", referenced from:
              vtable for Ps::Settings in moc_settings.o
          "Ps::Settings::~Settings()", referenced from:
              Ps::Startup::Startup() in startup.o
              vtable for Ps::Settings in moc_settings.o
        ld: symbol(s) not found for architecture x86_64
        clang: error: linker command failed with exit code 1 (use -v to see invocation)
        make: *** [Vfp.app/Contents/MacOS/Vfp] Error 1
        03:30:05: The process "/usr/bin/make" exited with code 2.
        Error while building/deploying project Vfp (kit: Desktop Qt 5.11.1 clang 64bit)
        When executing step "Make"
        03:30:05: Elapsed time: 00:10.
        
        1 Reply Last reply
        1

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved