-2

I want to play around with network programming using ZeroMQ

I'm trying to install it on my Linux Mint 18.2 machine. Maybe I'm just dumb (which is why I come here for help) but I can't seem to get these instructions work.

Mainly following this, from the hyper-linked instructions:

To build on UNIX-like systems

If you have free choice, the most comfortable OS for developing with ZeroMQ is probably Ubuntu.

  1. Make sure that libtool, pkg-config, build-essential, autoconf, and automake are installed.
  2. Check whether uuid-dev package, uuid/e2fsprogs RPM or equivalent on your system is installed.
  3. Unpack the .tar.gz source archive.
  4. Run ./configure, followed by make.
  5. To install ZeroMQ system-wide run sudo make install.
  6. On Linux, run sudo ldconfig after installing ZeroMQ.

Using the tarball from release 4.2.2.

To test, I used the hello world example from 0mq (in examples/c++):

git clone --depth=1 https://github.com/imatix/zguide.git

I tried to compile hwclient.cpp using g++ but I get a bunch of errors, I assume because I cannot find the included zmq.hpp anywhere on my system (used locate zmq.hpp). Here are the errors:

/tmp/ccsb8olx.o: In function `zmq::error_t::error_t()':
hwclient.cpp:(.text._ZN3zmq7error_tC2Ev[_ZN3zmq7error_tC5Ev]+0x26): undefined reference to `zmq_errno'
/tmp/ccsb8olx.o: In function `zmq::error_t::what() const':
hwclient.cpp:(.text._ZNK3zmq7error_t4whatEv[_ZNK3zmq7error_t4whatEv]+0x16): undefined reference to `zmq_strerror'
/tmp/ccsb8olx.o: In function `zmq::message_t::message_t()':
hwclient.cpp:(.text._ZN3zmq9message_tC2Ev[_ZN3zmq9message_tC5Ev]+0x23): undefined reference to `zmq_msg_init'
/tmp/ccsb8olx.o: In function `zmq::message_t::message_t(unsigned long)':
hwclient.cpp:(.text._ZN3zmq9message_tC2Em[_ZN3zmq9message_tC5Em]+0x2e): undefined reference to `zmq_msg_init_size'
/tmp/ccsb8olx.o: In function `zmq::message_t::~message_t()':
hwclient.cpp:(.text._ZN3zmq9message_tD2Ev[_ZN3zmq9message_tD5Ev]+0x14): undefined reference to `zmq_msg_close'
/tmp/ccsb8olx.o: In function `zmq::message_t::data()':
hwclient.cpp:(.text._ZN3zmq9message_t4dataEv[_ZN3zmq9message_t4dataEv]+0x14): undefined reference to `zmq_msg_data'
/tmp/ccsb8olx.o: In function `zmq::context_t::context_t(int)':
hwclient.cpp:(.text._ZN3zmq9context_tC2Ei[_ZN3zmq9context_tC5Ei]+0x18): undefined reference to `zmq_init'
/tmp/ccsb8olx.o: In function `zmq::context_t::~context_t()':
hwclient.cpp:(.text._ZN3zmq9context_tD2Ev[_ZN3zmq9context_tD5Ev]+0x23): undefined reference to `zmq_term'
/tmp/ccsb8olx.o: In function `zmq::socket_t::socket_t(zmq::context_t&, int)':
hwclient.cpp:(.text._ZN3zmq8socket_tC2ERNS_9context_tEi[_ZN3zmq8socket_tC5ERNS_9context_tEi]+0x26): undefined reference to `zmq_socket'
/tmp/ccsb8olx.o: In function `zmq::socket_t::close()':
hwclient.cpp:(.text._ZN3zmq8socket_t5closeEv[_ZN3zmq8socket_t5closeEv]+0x26): undefined reference to `zmq_close'
/tmp/ccsb8olx.o: In function `zmq::socket_t::connect(char const*)':
hwclient.cpp:(.text._ZN3zmq8socket_t7connectEPKc[_ZN3zmq8socket_t7connectEPKc]+0x25): undefined reference to `zmq_connect'
/tmp/ccsb8olx.o: In function `zmq::socket_t::send(zmq::message_t&, int)':
hwclient.cpp:(.text._ZN3zmq8socket_t4sendERNS_9message_tEi[_ZN3zmq8socket_t4sendERNS_9message_tEi]+0x2b): undefined reference to `zmq_send'
hwclient.cpp:(.text._ZN3zmq8socket_t4sendERNS_9message_tEi[_ZN3zmq8socket_t4sendERNS_9message_tEi]+0x46): undefined reference to `zmq_errno'
/tmp/ccsb8olx.o: In function `zmq::socket_t::recv(zmq::message_t*, int)':
hwclient.cpp:(.text._ZN3zmq8socket_t4recvEPNS_9message_tEi[_ZN3zmq8socket_t4recvEPNS_9message_tEi]+0x2b): undefined reference to `zmq_recv'
hwclient.cpp:(.text._ZN3zmq8socket_t4recvEPNS_9message_tEi[_ZN3zmq8socket_t4recvEPNS_9message_tEi]+0x46): undefined reference to `zmq_errno'
collect2: error: ld returned 1 exit status

And for convenience, here is the hwclient.cpp code:

//
//  Hello World client in C++
//  Connects REQ socket to tcp://localhost:5555
//  Sends "Hello" to server, expects "World" back
//
#include <zmq.hpp>
#include <string>
#include <iostream>

int main ()
{
    //  Prepare our context and socket
    zmq::context_t context (1);
    zmq::socket_t socket (context, ZMQ_REQ);

    std::cout << "Connecting to hello world server..." << std::endl;
    socket.connect ("tcp://localhost:5555");

    //  Do 10 requests, waiting each time for a response
    for (int request_nbr = 0; request_nbr != 10; request_nbr++) {
        zmq::message_t request (5);
        memcpy (request.data (), "Hello", 5);
        std::cout << "Sending Hello " << request_nbr << "..." << std::endl;
        socket.send (request);

        //  Get the reply.
        zmq::message_t reply;
        socket.recv (&reply);
        std::cout << "Received World " << request_nbr << std::endl;
    }
    return 0;
}

I'm trying to figure out why zmq.hpp was not being installed.

Can anyone offer any advice on what I might be doing wrong?

Thanks.

Community
  • 1
  • 1
Matt Corby
  • 11,984
  • 3
  • 12
  • 19

1 Answers1

3

As discussed over the comments, you need to give the correct linking parameter to g++

g++ hwclient.cpp -lzmq

Explanation:
g++ compilation works in phases, the last of which is "linking", where your file is linked with "libraries" containing the pre-compiled "definitions" (of for example, functions that you're calling).

This is in contrast to the "pre-processing" stage that handles including of header files. Header files (most of the time) contain the "declarations" of functions.

Long story short:
if you see undefined reference to errors, you're missing some library during linking.

user3666197
  • 1
  • 6
  • 50
  • 92
  • Right, I thought the errors stemmed from zmq.hpp not existing in my /usr/include dir. Is that not the case? – Matt Corby Dec 29 '17 at 16:20
  • @MattCorby _"Is that not the case?"_ Obviously not. That would have been a totally different error message then. Something like `Cannot find 'zmq.hpp'`. – user0042 Dec 29 '17 at 16:22
  • Okay. If you don't mind, could I also get an explanation of what each flag in -lzmp does? I don't see them in the manpage for g++. – Matt Corby Dec 29 '17 at 16:24
  • That would have given another error message, something like "zmq.hpp not found". There are quite a few include paths that g++ searches by default, clearly one of them has zmp.hpp. How to find which one: I'd have to google... – Parakram Majumdar Dec 29 '17 at 16:24
  • the flag is just -l. zmq is the argument to the flag. If you don't find -l in the documentation then something is very very wrong :P – Parakram Majumdar Dec 29 '17 at 16:25
  • So I guess -l is the same as -L? There doesn't appear to be a very good explanation of what it does... Also, the file I needed was zmq.hpp, and I passed zmp as per your example ... shouldn't it have been zmq? – Matt Corby Dec 29 '17 at 16:33
  • Oh I see... it passes a library for the linker. I also checked my command history and it appears I did pass -lzmq and not -lzmp. Thank you for being patient with my simple questions :) – Matt Corby Dec 29 '17 at 16:40
  • -l and-L are definitely not the same. -l is used for specifying the library name and -L specifies directories in which to look for those libraries – schrödinbug May 26 '18 at 00:56