X-Ryl669 / eMQTT5

An embedded MQTTv5 client in C++ with minimal footprint, maximal performance
MIT License
65 stars 14 forks source link

Problems including the library #10

Closed jissoe closed 1 year ago

jissoe commented 1 year ago

Hello, I am having trouble including the library and I am not sure if I installed or used it correctly. Sorry, I am not an experienced programmer. I tried to google how cmake should be used, but I haven't found a solution.

I use Ubuntu 20.04 and tried this:

Thanks for your help!

X-Ryl669 commented 1 year ago

You're doing right, except for few points:

  1. Don't run cmake in the same folder as the project. You should mkdir build && cd build && cmake ../CMakeLists.txt. This is because CMake is creating a lot of trash files and removing them is a PITA. If it's run in its own folder, you can just delete the folder content and you're safe.
  2. I strongly advice to use ccmake instead of cmake because it shows you all the options like the installation base path. I guess the default installation prefix path is /usr/local/ but it changes depending on your system, don't rely on it.
  3. The default CMake configuration is not to install the headers (if you need this, you'll need to change eMQTT5/lib/CMakeLists.txt install section to read this:
    install(TARGETS eMQTT5 
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        PUBLIC_HEADER DESTINATION include)
  4. I advice you use #include <Network/Clients/MQTT.hpp> instead of the relative path with double quote. Then you'll need to set the include search path of the compiler by adding -I/path/to/eMQTT5/include to the compiler's options (and -L/path/to/eMQTT5/lib for the linker's options). In your case, it's -I../../eMQTT5/lib/include/ and -L/usr/local/lib/.

I wasn't sure if it's a good idea to install header files for a library, since most libraries on my system don't have them by default. Maybe I should add an option for this, let me know if you think it should be the default.

X-Ryl669 commented 1 year ago

I've committed a new version that's exporting the headers and a pkg-config file. You'll need to add -I/usr/local/include/eMQTT5 to your CXXFLAGS in your makefile, and -L/usr/local/lib -leMQTT5 to your LDFLAGS.

jissoe commented 1 year ago

Thanks for your quick response! I think it would be better to install the headers by default, but as I said before I am not an expert and still have trouble understanding how this works. The libraries I used before only needed compiler arguments like e.g. -leMQTT5 and had header files in /usr/local/include. I have followed your advice and changed eMQTT5/lib/CMakeLists.txt, executed cmake and the other commands again, but nothing was added to /usr/local/include/. I also tried to add the compiler options you mentioned, but #include <Network/Clients/MQTT.hpp> can't be found :(

When I copy the the headers from eMQTT5/lib/include to /usr/local/include/eMQTT5/ , #include <eMQTT5/Network/Clients/MQTT.hpp> and add eMQTT5/ to all includes in the headers, I get rid of the include errors.

Hope this works :)

edit: I just saw your new post. Thanks I will try this also.

jissoe commented 1 year ago

Unfortunately it still does not work. With the changes of my last post, Visual Studio code was accepting the includes, but the compiler could not find them. With your new commit, I noticed all the header files are located directly in /user/local/include, so the includes did not work. I tried #include <eMQTT5/MQTT.hpp> which is found, but the includes in this file are still not working.

I think there is one MQTT.hpp missing, because there was one in Network/Clients/ and one in Protocol/MQTT/ , so I removed the files in /user/local/include and copied the folders again, but still no succes.

Maybe the problem is my Visual Studio code configuration, in tasks.json, i got these args:

"args": [
                "-fdiagnostics-color=always",
                "-g",
                "${workspaceFolder}/src/*.cpp",
                "-pthread",
                "-I/usr/local/include/eMQTT5",
                "-L/usr/local/lib",                
                "-leMQTT5",
                "-o",
                "${workspaceFolder}/bin/Device"
            ],

( I also tried spacing behind -I and -L )

and my c_cpp_properties.json looks like this:

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu17",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}
X-Ryl669 commented 1 year ago

I noticed all the header files are located directly in /user/local/include, so the includes did not work.

They should land in /usr/local/include/eMQTT5 if you've set the installation prefix to /usr/local. Then, in your code, you'll need to write this include:

#include <Network/Clients/MQTT.hpp>

Notice: they are between <> not "" for system include, and the relative path to the MQTT file must be specified (from the /usr/local/include/eMQTT5 folder).

X-Ryl669 commented 1 year ago

In the c_cpp_properties.json file, you might also add like this:

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/local/include/eMQTT5"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu17",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

Everything else seems good to me.

I tried #include <eMQTT5/MQTT.hpp> which is found

It shouldn't. There isn't any MQTT.hpp in eMQTT5 folder. There's something fishy here, maybe from a previous install. If I were you, I'd remove the folders /usr/local/include/Network, /usr/local/include/Platform, /usr/local/include/Protocol and /usr/local/include/eMQTT5 and re-install from latest master.

jissoe commented 1 year ago

Hi again,

I have removed the files from the directories and reinstalled. The files are going to /usr/local/include/eMQTT5/ but there are no subfolders:

sudo make install
[sudo] Passwort für sysadmin: 
[  7%] Built target eMQTT5
[ 57%] Built target MQTTc
[100%] Built target MQTTParsePacket
Install the project...
-- Install configuration: ""
-- Up-to-date: /usr/local/lib/libeMQTT5.a
-- Installing: /usr/local/include/eMQTT5/Platform.hpp
-- Installing: /usr/local/include/eMQTT5/StackHeapBuffer.hpp
-- Installing: /usr/local/include/eMQTT5/MQTT.hpp
-- Installing: /usr/local/include/eMQTT5/MQTTConfig.hpp
-- Up-to-date: /usr/local/include/eMQTT5/MQTT.hpp
-- Installing: /usr/local/include/eMQTT5/Types.hpp
-- Up-to-date: /usr/local/lib/pkgconfig/eMQTT5.pc
-- Up-to-date: /usr/local/bin/MQTTc
-- Up-to-date: /usr/local/bin/MQTTParsePacket

When I copy them myself to to subdirecories in /usr/local/include/eMQTT5/ , I have to use #include <eMQTT5/Network/clients/MQTT.hpp> and change the include in the headers with the trailing eMQTT5/.

A simple testcode compiles after adding the include to /usr/local/include/eMQTT5/ :) But I can't use #include "Network/Address.hpp" and the other includes like in your MQTTc.cpp test. My simple test unfortunately fails to connect with errorcode -6 (Network error):

MessageReceiver receiver;
const char *server = "mqtt://127.0.0.1";
int port = 1883;
std::string publishMessage = "testmessage";
const char *publishTopic = "testtopic";

Network::Client::MQTTv5 client("device123", &receiver);
Network::Client::MQTTv5::ErrorType ret = client.connectTo(server, port);
if (ret)
{
     return fprintf(stderr, "Failed connection with error: %d\n", (int)ret);
}

ret = client.publish(publishTopic, (const uint8_t *)publishMessage.c_str(), publishMessage.size());
if (ret)
{
    return fprintf(stderr, "Failed subscribing with error: %d\n", (int)ret);
}

(I have setup and sucessfully tested my broker with your test binary MQTTc)

X-Ryl669 commented 1 year ago

Ok, I figured this out, and it's my fault. It's due to a bug in older cmake that flattens header hierarchy in the installation path and that breaks the code obviously.

I've just committed a fix that's doing what I'm expecting even on older CMake version, it should now work as expected (you don't need to change anything in the files, just have -I/usr/local/include/eMQTT5).

And for the network error you're seeing, you don't need the "mqtt://" part. This only something I'm using in MQTTc to figure out if I need to use TLS (with mqtts://) or not (with mqtt://). In your code, you just need client.connectTo("127.0.0.1", 1883). You'll also need to make sure your broker allows anonymous login. (see MQTTClient.cpp:458 for the connection code and the error -6).

X-Ryl669 commented 1 year ago

Your code shouldn't compile as MessageReceiver is abstract for messageReceived which must be overloaded. I guess you've done this, right ?

jissoe commented 1 year ago

Yes, it works now :) I had overloaded messageReceived and the mqtt:// was the reason for the connection problem.

Thanks alot for your effort!

X-Ryl669 commented 1 year ago

Ok, great!