Use nanomsg instead of std{in,out} for communication between dist and writer.
authorCarl Hetherington <cth@carlh.net>
Mon, 23 Mar 2020 00:35:51 +0000 (01:35 +0100)
committerCarl Hetherington <cth@carlh.net>
Sat, 28 Mar 2020 18:47:28 +0000 (19:47 +0100)
platform/windows/dcpomatic2_dist_debug.bat [new file with mode: 0644]
platform/windows/wscript
src/lib/copy_to_drive_job.cc
src/lib/copy_to_drive_job.h
src/lib/nanomsg.cc [new file with mode: 0644]
src/lib/nanomsg.h [new file with mode: 0644]
src/lib/wscript
src/tools/dcpomatic_dist.cc
src/tools/dcpomatic_dist_writer.cc
src/tools/wscript
wscript

diff --git a/platform/windows/dcpomatic2_dist_debug.bat b/platform/windows/dcpomatic2_dist_debug.bat
new file mode 100644 (file)
index 0000000..9893ccf
--- /dev/null
@@ -0,0 +1 @@
+gdb.exe -x gdb_script dcpomatic2_dist.exe > %HOMEPATH%/Documents/dcpomatic_debug_log.txt
index ab0333db215c2454dcaa98339f30ea6f8050ead2..d7b754fb2a015c13b68217ab1f8b2e67bbb585b8 100644 (file)
@@ -156,6 +156,7 @@ File "%static_deps%/bin/libwebp-7.dll"
 File "%static_deps%/bin/libcrypto-1_1-x64.dll"
 File "%static_deps%/bin/libltdl-7.dll"
 File "%static_deps%/bin/libdl.dll"
+File "%static_deps%/bin/libnanomsg.dll"
 
 File "%cdist_deps%/bin/asdcp-carl.dll"
 File "%cdist_deps%/bin/kumu-carl.dll"
index ef7c09060e01d154a94cbde2de6b3459867d2914..68055f7e9d8e2c9970074820f40f4afe22e7bbe9 100644 (file)
@@ -23,6 +23,7 @@
 #include "compose.hpp"
 #include "exceptions.h"
 #include <dcp/raw_convert.h>
+#include <nanomsg/nn.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -38,12 +39,11 @@ using std::min;
 using boost::shared_ptr;
 using dcp::raw_convert;
 
-CopyToDriveJob::CopyToDriveJob (boost::filesystem::path dcp, Drive drive, boost::process::opstream& to_writer, boost::process::ipstream& from_writer)
+CopyToDriveJob::CopyToDriveJob (boost::filesystem::path dcp, Drive drive, Nanomsg& nanomsg)
        : Job (shared_ptr<Film>())
        , _dcp (dcp)
        , _drive (drive)
-       , _to_writer (to_writer)
-       , _from_writer (from_writer)
+       , _nanomsg (nanomsg)
 {
 
 }
@@ -63,25 +63,19 @@ CopyToDriveJob::json_name () const
 void
 CopyToDriveJob::run ()
 {
-       _to_writer << _dcp.string() << "\n";
-       _to_writer << _drive.internal_name() << "\n";
-       _to_writer.flush ();
+       _nanomsg.send(String::compose("%1\n%2\n", _dcp.string(), _drive.internal_name()));
 
        while (true) {
-               string s;
-               getline (_from_writer, s);
+               string s = _nanomsg.blocking_get ();
                if (s == DIST_WRITER_OK) {
                        set_state (FINISHED_OK);
                        return;
                } else if (s == DIST_WRITER_ERROR) {
-                       string m;
-                       getline (_from_writer, m);
-                       string n;
-                       getline (_from_writer, n);
+                       string const m = _nanomsg.blocking_get ();
+                       string const n = _nanomsg.blocking_get ();
                        throw CopyError (m, raw_convert<int>(n));
                } else if (s == DIST_WRITER_PROGRESS) {
-                       string p;
-                       getline (_from_writer, p);
+                       string p = _nanomsg.blocking_get();
                        set_progress (raw_convert<float>(p));
                }
        }
index 7b0bf830af4d72784afd10bf7485d9b114d17b9f..1a1a99f442f3a6707a074430cc65222fec3f2196 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2019-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
 #include "cross.h"
 #include "job.h"
-#include <boost/process.hpp>
+#include "nanomsg.h"
 
 class CopyToDriveJob : public Job
 {
 public:
-       CopyToDriveJob (boost::filesystem::path dcp, Drive drive, boost::process::opstream& to_writer, boost::process::ipstream& from_writer);
+       CopyToDriveJob (boost::filesystem::path dcp, Drive drive, Nanomsg& nanomsg);
 
        std::string name () const;
        std::string json_name () const;
@@ -36,6 +36,5 @@ private:
        void copy (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total);
        boost::filesystem::path _dcp;
        Drive _drive;
-       boost::process::opstream& _to_writer;
-       boost::process::ipstream& _from_writer;
+       Nanomsg& _nanomsg;
 };
diff --git a/src/lib/nanomsg.cc b/src/lib/nanomsg.cc
new file mode 100644 (file)
index 0000000..b98c393
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+    Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "nanomsg.h"
+#include "dcpomatic_log.h"
+#include <nanomsg/nn.h>
+#include <nanomsg/pair.h>
+#include <stdexcept>
+#include <cerrno>
+
+using std::string;
+using std::runtime_error;
+using boost::optional;
+
+#define NANOMSG_URL "ipc:///tmp/dcpomatic.ipc"
+
+Nanomsg::Nanomsg (bool server)
+{
+       _socket = nn_socket (AF_SP, NN_PAIR);
+       if (_socket < 0) {
+               throw runtime_error("Could not set up nanomsg socket");
+       }
+       if (server) {
+               if (nn_bind(_socket, NANOMSG_URL) < 0) {
+                       throw runtime_error(String::compose("Could not bind nanomsg socket (%1)", errno));
+               }
+       } else {
+               if (nn_connect(_socket, NANOMSG_URL) < 0) {
+                       throw runtime_error(String::compose("Could not connect nanomsg socket (%1)", errno));
+               }
+       }
+}
+
+void
+Nanomsg::send (string s)
+{
+       int const r = nn_send (_socket, s.c_str(), s.length(), 0);
+       if (r < 0) {
+               throw runtime_error(String::compose("Could not send to nanomsg socket (%1)", errno));
+       } else if (r != int(s.length())) {
+               throw runtime_error("Could not send to nanomsg socket (message too big)");
+       }
+}
+
+optional<string>
+Nanomsg::get_from_pending ()
+{
+       if (_pending.empty()) {
+               return optional<string>();
+       }
+
+       string const l = _pending.back();
+       _pending.pop_back();
+       return l;
+}
+
+void
+Nanomsg::recv_and_parse (bool blocking)
+{
+       char* buf = 0;
+       int const received = nn_recv (_socket, &buf, NN_MSG, blocking ? 0 : NN_DONTWAIT);
+       if (received < 0)
+       {
+               if (!blocking && errno == EAGAIN) {
+                       return;
+               }
+
+               throw runtime_error ("Could not communicate with subprocess");
+       }
+
+       char* p = buf;
+       for (int i = 0; i < received; ++i) {
+               if (*p == '\n') {
+                       _pending.push_front (_current);
+                       _current = "";
+               } else {
+                       _current += *p;
+               }
+               ++p;
+       }
+       nn_freemsg (buf);
+}
+
+string
+Nanomsg::blocking_get ()
+{
+       optional<string> l = get_from_pending ();
+       if (l) {
+               return *l;
+       }
+
+       recv_and_parse (true);
+
+       l = get_from_pending ();
+       if (!l) {
+               throw runtime_error ("Could not communicate with subprocess");
+       }
+
+       return *l;
+}
+
+optional<string>
+Nanomsg::nonblocking_get ()
+{
+       optional<string> l = get_from_pending ();
+       if (l) {
+               return *l;
+       }
+
+       recv_and_parse (false);
+       return get_from_pending ();
+}
diff --git a/src/lib/nanomsg.h b/src/lib/nanomsg.h
new file mode 100644 (file)
index 0000000..26db2d2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+    Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <string>
+#include <list>
+#include <boost/optional.hpp>
+#include <boost/noncopyable.hpp>
+
+class Nanomsg : public boost::noncopyable
+{
+public:
+       explicit Nanomsg (bool server);
+
+       void send (std::string s);
+       std::string blocking_get ();
+       boost::optional<std::string> nonblocking_get ();
+
+private:
+       boost::optional<std::string> get_from_pending ();
+       void recv_and_parse (bool blocking);
+
+       int _socket;
+       std::list<std::string> _pending;
+       std::string _current;
+};
+
index fce323e0f0c44335e1fb3fe46c54e137be22b667..f2ad9714e29d349e30bf5d58b2d7c7426e480058 100644 (file)
@@ -127,6 +127,7 @@ sources = """
           log_entry.cc
           mid_side_decoder.cc
           monitor_checker.cc
+          nanomsg.cc
           overlaps.cc
           player.cc
           player_text.cc
@@ -192,7 +193,7 @@ def build(bld):
                  AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE
                  BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2 BOOST_REGEX
                  SAMPLERATE POSTPROC TIFF SSH DCP CXML GLIB LZMA XML++
-                 CURL ZIP FONTCONFIG PANGOMM CAIROMM XMLSEC SUB ICU NETTLE PNG LWEXT4 POLKIT
+                 CURL ZIP FONTCONFIG PANGOMM CAIROMM XMLSEC SUB ICU NETTLE PNG
                  """
 
     if bld.env.TARGET_OSX:
@@ -205,6 +206,9 @@ def build(bld):
 
     if bld.env.ENABLE_DIST:
         obj.source += ' copy_to_drive_job.cc'
+        obj.uselib += ' LWEXT4 NANOMSG'
+        if bld.env.TARGET_LINUX:
+            obj.uselib += ' POLKIT'
 
     if bld.env.TARGET_WINDOWS:
         obj.uselib += ' WINSOCK2 DBGHELP SHLWAPI MSWSOCK BOOST_LOCALE SETUPAPI'
index 433dcd2097a3fc682777d245f352f8513c3bb19d..a9d8f9bdaeaf1ab8b203481924003b234f49d4eb 100644 (file)
@@ -30,6 +30,8 @@
 #include "lib/cross.h"
 #include "lib/copy_to_drive_job.h"
 #include "lib/job_manager.h"
+#include <nanomsg/nn.h>
+#include <nanomsg/pair.h>
 #include <wx/wx.h>
 #include <boost/process.hpp>
 #ifdef __WXOSX__
@@ -40,6 +42,7 @@ using std::string;
 using std::exception;
 using std::cout;
 using std::cerr;
+using std::runtime_error;
 using boost::shared_ptr;
 
 class DOMFrame : public wxFrame
@@ -47,6 +50,7 @@ class DOMFrame : public wxFrame
 public:
        explicit DOMFrame (wxString const & title)
                : wxFrame (0, -1, title)
+               , _nanomsg (true)
                , _sizer (new wxBoxSizer(wxVERTICAL))
        {
                /* Use a panel as the only child of the Frame so that we avoid
@@ -96,7 +100,7 @@ public:
                _sizer->Add (grid, 1, wxALL | wxEXPAND, DCPOMATIC_DIALOG_BORDER);
                overall_panel->SetSizer (_sizer);
                Fit ();
-               SetSize (512, GetSize().GetHeight() + 32);
+               SetSize (768, GetSize().GetHeight() + 32);
 
                /* XXX: this is a hack, but I expect we'll need logs and I'm not sure if there's
                 * a better place to put them.
@@ -109,7 +113,7 @@ public:
 
                Bind (wxEVT_SIZE, boost::bind (&DOMFrame::sized, this, _1));
 
-               _writer = new boost::process::child ("dcpomatic2_dist_writer", boost::process::std_in < _to_writer, boost::process::std_out > _from_writer);
+               _writer = new boost::process::child ("dcpomatic2_dist_writer");
        }
 
 private:
@@ -148,7 +152,7 @@ private:
                        return;
                }
 
-               JobManager::instance()->add(shared_ptr<Job>(new CopyToDriveJob(*_dcp_path, _drives[_drive->GetSelection()], _to_writer, _from_writer)));
+               JobManager::instance()->add(shared_ptr<Job>(new CopyToDriveJob(*_dcp_path, _drives[_drive->GetSelection()], _nanomsg)));
        }
 
        void drive_refresh ()
@@ -193,8 +197,7 @@ private:
        boost::optional<boost::filesystem::path> _dcp_path;
        std::vector<Drive> _drives;
        boost::process::child* _writer;
-       boost::process::opstream _to_writer;
-       boost::process::ipstream _from_writer;
+       Nanomsg _nanomsg;
        wxSizer* _sizer;
 };
 
index 7f76c9ba44f48c7fbe808028f499553e18b7d317..c965666e691c527d9e74644003f830f422b9c4b5 100644 (file)
@@ -25,6 +25,7 @@
 #include "lib/digester.h"
 #include "lib/file_log.h"
 #include "lib/dcpomatic_log.h"
+#include "lib/nanomsg.h"
 extern "C" {
 #include <lwext4/ext4_mbr.h>
 #include <lwext4/ext4_fs.h>
@@ -65,10 +66,11 @@ extern "C" {
 #include <boost/filesystem.hpp>
 #include <iostream>
 
-using std::cout;
 using std::cin;
 using std::min;
 using std::string;
+using std::runtime_error;
+using boost::optional;
 
 #ifdef DCPOMATIC_LINUX
 static PolkitAuthority* polkit_authority = 0;
@@ -76,6 +78,7 @@ static PolkitAuthority* polkit_authority = 0;
 static boost::filesystem::path dcp_path;
 static std::string device;
 static uint64_t const block_size = 4096;
+static Nanomsg* nanomsg = 0;
 
 static
 void
@@ -139,8 +142,7 @@ write (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total
                }
                remaining -= this_time;
                total_remaining -= this_time;
-               cout << DIST_WRITER_PROGRESS "\n" << (1 - float(total_remaining) / total) << "\n";
-               cout.flush ();
+               nanomsg->send(String::compose(DIST_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)));
        }
 
        fclose (in);
@@ -177,8 +179,7 @@ read (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_
                digester.add (buffer, this_time);
                remaining -= this_time;
                total_remaining -= this_time;
-               cout << DIST_WRITER_PROGRESS "\n" << (1 - float(total_remaining) / total) << "\n";
-               cout.flush ();
+               nanomsg->send(String::compose(DIST_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)));
        }
 
        ext4_fclose (&in);
@@ -195,13 +196,9 @@ static
 void
 copy (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total)
 {
-       using namespace boost::filesystem;
+       LOG_DIST ("Copy %1 -> %2", from.string(), to.string());
 
-       /* XXX: this is a hack.  We are going to "treat" every byte twice; write it, and then verify it.  Double the
-        * bytes totals so that progress works itself out (assuming write is the same speed as read).
-        */
-       total_remaining *= 2;
-       total *= 2;
+       using namespace boost::filesystem;
 
        path const cr = to / from.filename();
 
@@ -216,7 +213,9 @@ copy (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_
                }
        } else {
                string const write_digest = write (from, cr, total_remaining, total);
+               LOG_DIST ("Wrote %1 %2 with %3", from.string(), cr.string(), write_digest);
                string const read_digest = read (from, cr, total_remaining, total);
+               LOG_DIST ("Read %1 %2 with %3", from.string(), cr.string(), write_digest);
                if (write_digest != read_digest) {
                        throw VerifyError ("Hash of written data is incorrect", 0);
                }
@@ -230,7 +229,7 @@ try
 {
 //     ext4_dmask_set (DEBUG_ALL);
 
-       cout << "U\n";
+       nanomsg->send("U\n");
 
        /* We rely on static initialization for these */
        static struct ext4_fs fs;
@@ -250,6 +249,7 @@ try
        if (!bd) {
                throw CopyError ("Failed to open drive", 0);
        }
+       LOG_DIST_NC ("Opened drive");
 
        struct ext4_mbr_parts parts;
        parts.division[0] = 100;
@@ -267,6 +267,7 @@ try
        if (r) {
                throw CopyError ("Failed to write MBR", r);
        }
+       LOG_DIST_NC ("Wrote MBR");
 
 #ifdef DCPOMATIC_WINDOWS
        struct ext4_mbr_bdevs bdevs;
@@ -300,25 +301,33 @@ try
        if (!bd) {
                throw CopyError ("Failed to open partition", 0);
        }
+       LOG_DIST_NC ("Opened partition");
 
        r = ext4_mkfs(&fs, bd, &info, F_SET_EXT4);
        if (r != EOK) {
                throw CopyError ("Failed to make filesystem", r);
        }
+       LOG_DIST_NC ("Made filesystem");
 
        r = ext4_device_register(bd, "ext4_fs");
        if (r != EOK) {
                throw CopyError ("Failed to register device", r);
        }
+       LOG_DIST_NC ("Registered device");
 
        r = ext4_mount("ext4_fs", "/mp/", false);
        if (r != EOK) {
                throw CopyError ("Failed to mount device", r);
        }
+       LOG_DIST_NC ("Mounted device");
 
        uint64_t total_bytes = 0;
        count (dcp_path, total_bytes);
 
+       /* XXX: this is a hack.  We are going to "treat" every byte twice; write it, and then verify it.  Double the
+        * bytes totals so that progress works itself out (assuming write is the same speed as read).
+        */
+       total_bytes *= 2;
        copy (dcp_path, "/mp", total_bytes, total_bytes);
 
        r = ext4_umount("/mp/");
@@ -326,14 +335,11 @@ try
                throw CopyError ("Failed to unmount device", r);
        }
 
-       cout << DIST_WRITER_OK "\n";
-       cout.flush ();
+       nanomsg->send(DIST_WRITER_OK "\n");
 } catch (CopyError& e) {
-       cout << DIST_WRITER_ERROR "\n" << e.message() << "\n" << e.number() << "\n";
-       cout.flush ();
+       nanomsg->send(String::compose(DIST_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number()));
 } catch (VerifyError& e) {
-       cout << DIST_WRITER_ERROR "\n" << e.message() << "\n" << e.number() << "\n";
-       cout.flush ();
+       nanomsg->send(String::compose(DIST_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number()));
 }
 
 #ifdef DCPOMATIC_LINUX
@@ -354,41 +360,25 @@ polkit_callback (GObject *, GAsyncResult* res, gpointer)
 bool
 idle ()
 {
-#ifdef DCPOMATIC_POSIX
-       struct pollfd input[1] = { { fd: 0, events: POLLIN, revents: 0 } };
-       int const r = poll (input, 1, 0);
-       if (r > 0 && (input[0].revents & POLLIN)) {
-#else
-       DWORD num;
-       LOG_DIST ("now handle in is %1", reinterpret_cast<uint64_t>(GetStdHandle(STD_INPUT_HANDLE)));
-       if (!GetNumberOfConsoleInputEvents(GetStdHandle(STD_INPUT_HANDLE), &num)) {
-               LOG_DIST ("Could not check console: %1", GetLastError());
+       optional<string> s = nanomsg->nonblocking_get ();
+       if (!s) {
+               return true;
        }
 
-       LOG_DIST ("%1 console events", num);
-       if (num) {
-#endif
-               string s;
-               getline (cin, s);
-               if (s.empty()) {
-                       return true;
-               }
-               dcp_path = s;
-               getline (cin, s);
-               device = "/dev/" + s;
+       dcp_path = *s;
+       device = "/dev/" + nanomsg->blocking_get ();
 
-               LOG_DIST ("Here we go writing %1 to %2", dcp_path, device);
+       LOG_DIST ("Here we go writing %1 to %2", dcp_path, device);
 
 #ifdef DCPOMATIC_LINUX
-               polkit_authority = polkit_authority_get_sync (0, 0);
-               PolkitSubject* subject = polkit_unix_process_new (getppid());
-               polkit_authority_check_authorization (
+       polkit_authority = polkit_authority_get_sync (0, 0);
+       PolkitSubject* subject = polkit_unix_process_new (getppid());
+       polkit_authority_check_authorization (
                        polkit_authority, subject, "com.dcpomatic.write-drive", 0, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, 0, polkit_callback, 0
                        );
 #else
-               write ();
+       write ();
 #endif
-       }
        return true;
 }
 
@@ -402,23 +392,12 @@ main ()
        dcpomatic_log->set_types (dcpomatic_log->types() | LogEntry::TYPE_DIST);
        LOG_DIST_NC("dcpomatic_dist_writer started");
 
-#ifdef DCPOMATIC_WINDOWS
-       FreeConsole ();
-       AllocConsole ();
-
-       HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
-       int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT);
-       FILE* hf_out = _fdopen(hCrt, "w");
-       setvbuf(hf_out, NULL, _IONBF, 1);
-       *stdout = *hf_out;
-
-       HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE);
-       LOG_DIST ("handle_in is %1", reinterpret_cast<uint64_t>(handle_in));
-       hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT);
-       FILE* hf_in = _fdopen(hCrt, "r");
-       setvbuf(hf_in, NULL, _IONBF, 128);
-       *stdin = *hf_in;
-#endif
+       try {
+               nanomsg = new Nanomsg (false);
+       } catch (runtime_error& e) {
+               LOG_DIST_NC("Could not set up nanomsg socket");
+               exit (EXIT_FAILURE);
+       }
 
        Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create ();
        Glib::signal_timeout().connect(sigc::ptr_fun(&idle), 500);
index 8a6bc60c539f4832c7caf99c1605c240c1409719..8ab5831124ae607d1b7468164908e41e01fd3fe0 100644 (file)
@@ -32,11 +32,10 @@ def build(bld):
     uselib += 'AVUTIL SWSCALE SWRESAMPLE POSTPROC CURL BOOST_FILESYSTEM SSH ZIP CAIROMM FONTCONFIG PANGOMM SUB '
     uselib += 'SNDFILE SAMPLERATE BOOST_REGEX ICU NETTLE RTAUDIO PNG '
 
-    if bld.env.TARGET_LINUX:
-        uselib += 'POLKIT '
-
     if bld.env.ENABLE_DIST:
-        uselib += 'LWEXT4 '
+        if bld.env.TARGET_LINUX:
+            uselib += 'POLKIT '
+        uselib += 'LWEXT4 NANOMSG '
 
     if bld.env.TARGET_WINDOWS:
         uselib += 'WINSOCK2 DBGHELP SHLWAPI MSWSOCK BOOST_LOCALE WINSOCK2 OLE32 DSOUND WINMM KSUSER '
diff --git a/wscript b/wscript
index 67e429d8d038664fd0f07d2ef6389d79836739de..12012ad30d6d242030780dbe91367ee8e8ea29f4 100644 (file)
--- a/wscript
+++ b/wscript
@@ -383,6 +383,10 @@ def configure(conf):
     if conf.env.TARGET_LINUX and conf.options.enable_dist:
         conf.check_cfg(package='polkit-gobject-1', args='--cflags --libs', uselib_store='POLKIT', mandatory=True)
 
+    # nanomsg
+    if conf.options.enable_dist:
+        conf.check_cfg(package='libnanomsg', args='--cflags --libs', uselib_store='NANOMSG', mandatory=True)
+
     # FFmpeg
     if conf.options.static_ffmpeg:
         names = ['avformat', 'avfilter', 'avcodec', 'avutil', 'swscale', 'postproc', 'swresample']