web-dev-qa-db-fra.com

Comment importer des bibliothèques zeromq dans cmake?

Je commence tout juste à apprendre à utiliser les bibliothèques zeromq et à les utiliser dans différents projets C++. Le code exemple que j'ai écrit (en fait copié à partir de leurs tutoriels) est le suivant:

//  file: main.cpp
//  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;
}

et en construisant la sortie de ce fichier avec la commande ci-dessous:

g++ main.cpp -o test -lzmq

le fichier sera généré sans problème.

Le problème que j'ai est que je veux construire le fichier en utilisant CMake.Ainsi, j'ai écrit un fichier CMakeLists.txt comme ci-dessous:

cmake_minimum_required(VERSION 3.6)
project(test2)


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lzmq")


set(SOURCE_FILES main.cpp)
add_executable(test2 ${SOURCE_FILES})

La partie que je pensais suffisante pour construire le programme est -lzmq mais même avec cette partie incluse, je reçois les messages d'erreur suivants:

CMakeFiles/test2.dir/main.cpp.o: In function `zmq::error_t::error_t()':
/usr/include/zmq.hpp:62: undefined reference to `zmq_errno'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::error_t::what() const':
/usr/include/zmq.hpp:66: undefined reference to `zmq_strerror'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::message_t::message_t()':
/usr/include/zmq.hpp:107: undefined reference to `zmq_msg_init'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::message_t::message_t(unsigned long)':
/usr/include/zmq.hpp:114: undefined reference to `zmq_msg_init_size'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::message_t::~message_t()':
/usr/include/zmq.hpp:129: undefined reference to `zmq_msg_close'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::message_t::data()':
/usr/include/zmq.hpp:180: undefined reference to `zmq_msg_data'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::context_t::context_t(int)':
/usr/include/zmq.hpp:204: undefined reference to `zmq_init'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::context_t::~context_t()':
/usr/include/zmq.hpp:225: undefined reference to `zmq_term'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::socket_t(zmq::context_t&, int)':
/usr/include/zmq.hpp:251: undefined reference to `zmq_socket'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::close()':
/usr/include/zmq.hpp:283: undefined reference to `zmq_close'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::connect(char const*)':
/usr/include/zmq.hpp:314: undefined reference to `zmq_connect'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::send(zmq::message_t&, int)':
/usr/include/zmq.hpp:321: undefined reference to `zmq_send'
/usr/include/zmq.hpp:324: undefined reference to `zmq_errno'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::recv(zmq::message_t*, int)':
/usr/include/zmq.hpp:331: undefined reference to `zmq_recv'
/usr/include/zmq.hpp:334: undefined reference to `zmq_errno'

Devrais-je définir un autre type de variable dans le fichier CMake ou dois-je installer la bibliothèque dans un mauvais répertoire? ou y a-t-il autre chose que j'aurais dû mentionner? et le système sur lequel je travaille est Ubuntu 14.04

8
Omid N

CMake n'inclut pas le support direct pour 0mq et 0mq n'inclut pas le support direct pour CMake. Mais 0mq supporte pkg-config et nous pouvons l'utiliser pour nous aider. Puisque vous avez mentionné être sur Ubuntu 14.04, assurez-vous d’avoir installé Sudo apt-get install libzmq3-dev pour installer les bibliothèques 0mq, les en-têtes et le fichier pkg-config.pc.

Ensuite, utilisez le CMakeLists.txt suivant que j'ai modifié à partir de votre version ci-dessus. (J'ai commenté tous mes changements en ligne.)

## i have cmake 3.5
cmake_minimum_required(VERSION 3.5)
project(test2)

## use this to globally use C++11 with in our project
set(CMAKE_CXX_STANDARD 11)

## load in pkg-config support
find_package(PkgConfig)
## use pkg-config to get hints for 0mq locations
pkg_check_modules(PC_ZeroMQ QUIET zmq)

## use the hint from above to find where 'zmq.hpp' is located
find_path(ZeroMQ_INCLUDE_DIR
        NAMES zmq.hpp
        PATHS ${PC_ZeroMQ_INCLUDE_DIRS}
        )

## use the hint from about to find the location of libzmq
find_library(ZeroMQ_LIBRARY
        NAMES zmq
        PATHS ${PC_ZeroMQ_LIBRARY_DIRS}
        )

set(SOURCE_FILES main.cpp)
add_executable(test2 ${SOURCE_FILES})

## add the include directory to our compile directives
target_include_directories(test2 PUBLIC ${ZeroMQ_INCLUDE_DIR})
## at the 0mq library to our link directive
target_link_libraries(test2 PUBLIC ${ZeroMQ_LIBRARY})

Maintenant, vous pouvez make votre projet.

❯ make
[ 50%] Building CXX object CMakeFiles/test2.dir/main.cpp.o
[100%] Linking CXX executable test2
[100%] Built target test2

Si vous voulez voir ce qui se passe sous le capot, faites un make verbose.

❯ make VERBOSE=1
/usr/bin/cmake -H/home/nega/foo -B/home/nega/foo/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/nega/foo/build/CMakeFiles /home/nega/foo/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/nega/foo/build'
make -f CMakeFiles/test2.dir/build.make CMakeFiles/test2.dir/depend
make[2]: Entering directory '/home/nega/foo/build'
cd /home/nega/foo/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/nega/foo /home/nega/foo /home/nega/foo/build /home/nega/foo/build /home/nega/foo/build/CMakeFiles/test2.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/nega/foo/build'
make -f CMakeFiles/test2.dir/build.make CMakeFiles/test2.dir/build
make[2]: Entering directory '/home/nega/foo/build'
[ 50%] Building CXX object CMakeFiles/test2.dir/main.cpp.o
/usr/bin/c++     -std=gnu++11 -o CMakeFiles/test2.dir/main.cpp.o -c /home/nega/foo/main.cpp
[100%] Linking CXX executable test2
/usr/bin/cmake -E cmake_link_script CMakeFiles/test2.dir/link.txt --verbose=1
/usr/bin/c++      CMakeFiles/test2.dir/main.cpp.o  -o test2 /usr/lib/x86_64-linux-gnu/libzmq.so 
make[2]: Leaving directory '/home/nega/foo/build'
[100%] Built target test2
make[1]: Leaving directory '/home/nega/foo/build'
/usr/bin/cmake -E cmake_progress_start /home/nega/foo/build/CMakeFiles 0

Si vous regardez la ligne de compilation, vous remarquerez que

  1. La prise en charge de C++ 11 a été ajoutée (avec l'indicateur -std=gnu++11)
  2. Il n'y a pas d'indicateur -I/path/to/zmq. C'est parce que Ubuntu vide zmq.hpp dans /usr/include et que CMake est assez intelligent pour savoir que c'est un chemin par défaut, donc cela ne fait rien

Si vous regardez la ligne de lien, vous remarquerez que libzmq.so a été inclus via son chemin complet. Certaines personnes n'aiment pas cela (moi-même inclus) et préfèrent plutôt -L/lib/dir -lmylib. Utiliser le chemin complet est "à la manière de CMake", et vous en arriverez à l'apprécier à mesure que vous grandissez avec CMake et que vous l'utiliserez pour des projets plus volumineux et compliqués (vous pourriez ne pas l'aimer quand même.)

Notez également que puisque vous êtes sur Ubuntu, nous aurions pu tricher et utiliser dpkg -L libzmq3-dev pour trouver les emplacements des fichiers qui nous intéressaient, puis les ajouter à votre ligne CMAKE_CXX_FLAGS d'origine, mais c'est de la triche et, ce qui est plus important, non portable.

17
nega

Un fichier de configuration cmake a été ajouté au référentiel libzmq github le 7 janv. 2017 ici .

Ceci n'est pas encore inclus dans la dernière version (4.2.1), mais je pense que cela devrait l'être dans la prochaine version.

J'ai installé la version principale à l'aide de cmake puis installé cppzmq , qui utilise find_package(ZeroMQ REQUIRED) pour localiser libzmq. Tout a fonctionné comme un charme.

EDIT: Le fichier de configuration de cmake est inclus dans la version 4.2.2 ici . Ensuite, il a été déplacé vers le répertoire builds/cmake à la sortie 4.2.4 . Je ne l'ai pas testé à nouveau, mais find_package(ZeroMQ REQUIRED) devrait simplement fonctionner depuis ibzmq 4.2.2.

7
Danqi Wang

Cela fonctionne aussi bien

 cmake_minimum_required(VERSION 3.6)
 project(test)     
 add_executable(c main.cpp)
 target_link_libraries(c zmq)
0
Nischit Pradhan