Как импортировать библиотеки zeromq в cmake?

Я только начинаю учиться работать с zeromq библиотеки и их использование в разных проектах на C++. Пример кода, который я написал (скопировал оттуда учебники)это:

//  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;
}

и, построив вывод этого файла с помощью команды ниже:

g++ main.cpp -o test -lzmq

файл будет сгенерирован без проблем.

проблема в том, что я хочу создать файл с помощью CMake.Таким образом, я написал как ниже:

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})

часть, которую я думал, будет достаточно, чтобы построить программу -lzmq но даже этот кусок включен, я получаю следующие сообщения об ошибках:

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'

должен ли я установить другой вид переменной в файле CMake или я установил библиотеку в неправильном каталоге? или есть что-то еще, о чем я должен был упомянуть? и системная ведьма, над которой я работаю, - это Ubuntu 14.04

3 ответов


CMake не включает прямую поддержку для 0mq и 0mq не включает прямую поддержку для CMake. Но, 0mq поддерживает pkg-config и мы можем использовать это, чтобы помочь нам. Поскольку вы упомянули, что находитесь на Ubuntu 14.04, убедитесь, что вы сделали sudo apt-get install libzmq3-dev для установки библиотек 0mq, заголовков и pkg-config .

затем используйте следующие CMakeLists.txt который я изменил из вашей версии выше. (Я прокомментировал все свои изменения inline.)

## 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})

теперь вы можете make ваш проект.

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

если вы хотите увидеть, что происходит под капотом, сделайте подробный make.

❯ 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

если вы посмотрите на строку компиляции, вы заметите, что

  1. добавлена поддержка C++11 (с помощью -std=gnu++11 флаг)
  2. нет -I/path/to/zmq флаг. Это потому, что Ubuntu dumps zmq.hpp на /usr/include и CMake достаточно умен, чтобы знать, что это путь по умолчанию, так что он ничего не делает

если вы посмотрите на линии связи вы заметите, что libzmq.так было включено через его полный путь. Некоторые люди не любят этого (включая меня) и предпочитают -L/lib/dir -lmylib вместо. Использование полного пути - это "путь CMake", и вы действительно оцените его, когда вы растете с CMake и используете его для более крупных и сложных проектов (вам все равно может не понравиться это.)

также обратите внимание, что, поскольку вы находитесь на Ubuntu, мы могли бы обмануть и использовать dpkg -L libzmq3-dev, чтобы найти расположение файлов мы заинтересованы в затем добавил их в свой оригинальный CMAKE_CXX_FLAGS линии, но это обман и, что более важно, не портативный.


недавно в репозиторий libzmq github был добавлен конфигурационный файл cmake здесь.

Это еще не включено в последнюю версию (4.2.1), но я полагаю, что это должно быть в следующей версии.

Я установил головную версию с помощью cmake, а затем установил cppzmq, который использует find_package(ZeroMQ REQUIRED) найти libzmq. Все сработало как по волшебству.


Это тоже работает

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