[{"id":1520,"web_url":"https://patchwork.libcamera.org/comment/1520/","msgid":"<c726293a-e9a9-fb83-e440-d7852271509c@ideasonboard.com>","date":"2019-04-27T13:58:29","subject":"Re: [libcamera-devel] [PATCH] libcamera: Make libudev optional","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Laurent,\n\nOn 27/04/2019 04:16, Laurent Pinchart wrote:\n> libcamera depends on libudev for device enumeration. It is however\n> useful to allow building documentation without requiring the dependency\n> to be installed. Make the libudev dependency optional and compile the\n> udev-based device enumerator out when libudev is not present.\n> \n> Note that will libcamera will compile without libudev, it will not be\n\ns/Note that will/Note that while/\n\n> able to enumerate devices. A sysfs-based device enumerator is planned as\n> a fallback but not implemented yet.\n\nI think being able to build the documentation standalone is certainly a\ngood thing.\n\nI'd possibly have looked at the route of providing a meson configuration\noption to enable only the documentation, as we might find that a\nplatform without libudev now doesn't work correctly - but as that will\nbe fixed separately I'm not going to block this on that point.\n\n\n\nIgnoring the documentation requirement, this does step a long way to\ngetting configurable device enumeration methods (with the benefit of\nletting us build our documentation without requiring libudev) so:\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n\n\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  Documentation/Doxyfile.in                     |   4 +-\n>  meson.build                                   |   3 +-\n>  src/libcamera/camera_manager.cpp              |   2 +-\n>  src/libcamera/device_enumerator.cpp           | 157 +----------------\n>  src/libcamera/device_enumerator_udev.cpp      | 163 ++++++++++++++++++\n>  src/libcamera/include/device_enumerator.h     |  24 ---\n>  .../include/device_enumerator_udev.h          |  42 +++++\n>  src/libcamera/meson.build                     |  10 +-\n>  8 files changed, 223 insertions(+), 182 deletions(-)\n>  create mode 100644 src/libcamera/device_enumerator_udev.cpp\n>  create mode 100644 src/libcamera/include/device_enumerator_udev.h\n> \n> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> index 3e2b7fd9da0e..950ad4fef40e 100644\n> --- a/Documentation/Doxyfile.in\n> +++ b/Documentation/Doxyfile.in\n> @@ -833,7 +833,9 @@ RECURSIVE              = YES\n>  # Note that relative paths are relative to the directory from which doxygen is\n>  # run.\n>  \n> -EXCLUDE                = ../src/libcamera/pipeline/\n> +EXCLUDE                = ../src/libcamera/device_enumerator_udev.cpp \\\n> +\t\t\t ../src/libcamera/include/device_enumerator_udev.h \\\n> +\t\t\t ../src/libcamera/pipeline/\n>  \n>  # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n>  # directories that are symbolic links (a Unix file system feature) are excluded\n> diff --git a/meson.build b/meson.build\n> index 3434dd7c1b66..d272ff33b100 100644\n> --- a/meson.build\n> +++ b/meson.build\n> @@ -19,7 +19,6 @@ config_h = configuration_data()\n>  if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix: '#define _GNU_SOURCE')\n>      config_h.set('HAVE_SECURE_GETENV', 1)\n>  endif\n> -configure_file(output: 'config.h', configuration: config_h)\n>  \n>  common_arguments = [\n>      '-Wno-unused-parameter',\n> @@ -49,6 +48,8 @@ if get_option('tests')\n>    subdir('test')\n>  endif\n>  \n> +configure_file(output: 'config.h', configuration: config_h)\n> +\n>  pkg_mod = import('pkgconfig')\n>  pkg_mod.generate(libraries : libcamera,\n>                   version : '1.0',\n> diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\n> index 40a39bd2a6d9..cf881ce2e641 100644\n> --- a/src/libcamera/camera_manager.cpp\n> +++ b/src/libcamera/camera_manager.cpp\n> @@ -80,7 +80,7 @@ int CameraManager::start()\n>  \t\treturn -EBUSY;\n>  \n>  \tenumerator_ = DeviceEnumerator::create();\n> -\tif (enumerator_->enumerate())\n> +\tif (!enumerator_ || enumerator_->enumerate())\n>  \t\treturn -ENODEV;\n>  \n>  \t/*\n> diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp\n> index 49467546bab8..f6878b3d58b3 100644\n> --- a/src/libcamera/device_enumerator.cpp\n> +++ b/src/libcamera/device_enumerator.cpp\n> @@ -6,14 +6,9 @@\n>   */\n>  \n>  #include \"device_enumerator.h\"\n> +#include \"device_enumerator_udev.h\"\n>  \n> -#include <fcntl.h>\n> -#include <libudev.h>\n>  #include <string.h>\n> -#include <sys/ioctl.h>\n> -#include <unistd.h>\n> -\n> -#include <libcamera/event_notifier.h>\n>  \n>  #include \"log.h\"\n>  #include \"media_device.h\"\n> @@ -148,13 +143,11 @@ std::unique_ptr<DeviceEnumerator> DeviceEnumerator::create()\n>  {\n>  \tstd::unique_ptr<DeviceEnumerator> enumerator;\n>  \n> -\t/**\n> -\t * \\todo Add compile time checks to only try udev enumerator if libudev\n> -\t * is available.\n> -\t */\n> +#ifdef HAVE_LIBUDEV\n>  \tenumerator = utils::make_unique<DeviceEnumeratorUdev>();\n>  \tif (!enumerator->init())\n>  \t\treturn enumerator;\n> +#endif\n>  \n>  \t/*\n>  \t * Either udev is not available or udev initialization failed. Fall back\n> @@ -327,148 +320,4 @@ std::shared_ptr<MediaDevice> DeviceEnumerator::search(const DeviceMatch &dm)\n>   * fails\n>   */\n>  \n> -/**\n> - * \\class DeviceEnumeratorUdev\n> - * \\brief Device enumerator based on libudev\n> - */\n> -\n> -DeviceEnumeratorUdev::DeviceEnumeratorUdev()\n> -\t: udev_(nullptr)\n> -{\n> -}\n> -\n> -DeviceEnumeratorUdev::~DeviceEnumeratorUdev()\n> -{\n> -\tdelete notifier_;\n> -\n> -\tif (monitor_)\n> -\t\tudev_monitor_unref(monitor_);\n> -\tif (udev_)\n> -\t\tudev_unref(udev_);\n> -}\n> -\n> -int DeviceEnumeratorUdev::init()\n> -{\n> -\tint ret;\n> -\n> -\tif (udev_)\n> -\t\treturn -EBUSY;\n> -\n> -\tudev_ = udev_new();\n> -\tif (!udev_)\n> -\t\treturn -ENODEV;\n> -\n> -\tmonitor_ = udev_monitor_new_from_netlink(udev_, \"udev\");\n> -\tif (!monitor_)\n> -\t\treturn -ENODEV;\n> -\n> -\tret = udev_monitor_filter_add_match_subsystem_devtype(monitor_, \"media\",\n> -\t\t\t\t\t\t\t      nullptr);\n> -\tif (ret < 0)\n> -\t\treturn ret;\n> -\n> -\treturn 0;\n> -}\n> -\n> -int DeviceEnumeratorUdev::enumerate()\n> -{\n> -\tstruct udev_enumerate *udev_enum = nullptr;\n> -\tstruct udev_list_entry *ents, *ent;\n> -\tint ret;\n> -\n> -\tudev_enum = udev_enumerate_new(udev_);\n> -\tif (!udev_enum)\n> -\t\treturn -ENOMEM;\n> -\n> -\tret = udev_enumerate_add_match_subsystem(udev_enum, \"media\");\n> -\tif (ret < 0)\n> -\t\tgoto done;\n> -\n> -\tret = udev_enumerate_scan_devices(udev_enum);\n> -\tif (ret < 0)\n> -\t\tgoto done;\n> -\n> -\tents = udev_enumerate_get_list_entry(udev_enum);\n> -\tif (!ents)\n> -\t\tgoto done;\n> -\n> -\tudev_list_entry_foreach(ent, ents) {\n> -\t\tstruct udev_device *dev;\n> -\t\tconst char *devnode;\n> -\t\tconst char *syspath = udev_list_entry_get_name(ent);\n> -\n> -\t\tdev = udev_device_new_from_syspath(udev_, syspath);\n> -\t\tif (!dev) {\n> -\t\t\tLOG(DeviceEnumerator, Warning)\n> -\t\t\t\t<< \"Failed to get device for '\"\n> -\t\t\t\t<< syspath << \"', skipping\";\n> -\t\t\tcontinue;\n> -\t\t}\n> -\n> -\t\tdevnode = udev_device_get_devnode(dev);\n> -\t\tif (!devnode) {\n> -\t\t\tudev_device_unref(dev);\n> -\t\t\tret = -ENODEV;\n> -\t\t\tgoto done;\n> -\t\t}\n> -\n> -\t\taddDevice(devnode);\n> -\n> -\t\tudev_device_unref(dev);\n> -\t}\n> -done:\n> -\tudev_enumerate_unref(udev_enum);\n> -\tif (ret < 0)\n> -\t\treturn ret;\n> -\n> -\tret = udev_monitor_enable_receiving(monitor_);\n> -\tif (ret < 0)\n> -\t\treturn ret;\n> -\n> -\tint fd = udev_monitor_get_fd(monitor_);\n> -\tnotifier_ = new EventNotifier(fd, EventNotifier::Read);\n> -\tnotifier_->activated.connect(this, &DeviceEnumeratorUdev::udevNotify);\n> -\n> -\treturn 0;\n> -}\n> -\n> -std::string DeviceEnumeratorUdev::lookupDeviceNode(int major, int minor)\n> -{\n> -\tstruct udev_device *device;\n> -\tconst char *name;\n> -\tdev_t devnum;\n> -\tstd::string deviceNode = std::string();\n> -\n> -\tdevnum = makedev(major, minor);\n> -\tdevice = udev_device_new_from_devnum(udev_, 'c', devnum);\n> -\tif (!device)\n> -\t\treturn std::string();\n> -\n> -\tname = udev_device_get_devnode(device);\n> -\tif (name)\n> -\t\tdeviceNode = name;\n> -\n> -\tudev_device_unref(device);\n> -\n> -\treturn deviceNode;\n> -}\n> -\n> -void DeviceEnumeratorUdev::udevNotify(EventNotifier *notifier)\n> -{\n> -\tstruct udev_device *dev = udev_monitor_receive_device(monitor_);\n> -\tstd::string action(udev_device_get_action(dev));\n> -\tstd::string deviceNode(udev_device_get_devnode(dev));\n> -\n> -\tLOG(DeviceEnumerator, Debug)\n> -\t\t<< action << \" device \" << udev_device_get_devnode(dev);\n> -\n> -\tif (action == \"add\") {\n> -\t\taddDevice(deviceNode);\n> -\t} else if (action == \"remove\") {\n> -\t\tremoveDevice(deviceNode);\n> -\t}\n> -\n> -\tudev_device_unref(dev);\n> -}\n> -\n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/device_enumerator_udev.cpp b/src/libcamera/device_enumerator_udev.cpp\n\nI like that the udev specific code is moved out to it's own unit.\n\n\n\n> new file mode 100644\n> index 000000000000..cb2d21b90506\n> --- /dev/null\n> +++ b/src/libcamera/device_enumerator_udev.cpp\n> @@ -0,0 +1,163 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2018-2019, Google Inc.\n> + *\n> + * device_enumerator_udev.cpp - udev-based device enumerator\n> + */\n> +\n> +#include \"device_enumerator_udev.h\"\n> +\n> +#include <fcntl.h>\n> +#include <libudev.h>\n> +#include <string.h>\n> +#include <sys/ioctl.h>\n> +#include <unistd.h>\n> +\n> +#include <libcamera/event_notifier.h>\n> +\n> +#include \"log.h\"\n> +\n> +namespace libcamera {\n> +\n> +LOG_DECLARE_CATEGORY(DeviceEnumerator)\n> +\n> +DeviceEnumeratorUdev::DeviceEnumeratorUdev()\n> +\t: udev_(nullptr)\n> +{\n> +}\n> +\n> +DeviceEnumeratorUdev::~DeviceEnumeratorUdev()\n> +{\n> +\tdelete notifier_;\n> +\n> +\tif (monitor_)\n> +\t\tudev_monitor_unref(monitor_);\n> +\tif (udev_)\n> +\t\tudev_unref(udev_);\n> +}\n> +\n> +int DeviceEnumeratorUdev::init()\n> +{\n> +\tint ret;\n> +\n> +\tif (udev_)\n> +\t\treturn -EBUSY;\n> +\n> +\tudev_ = udev_new();\n> +\tif (!udev_)\n> +\t\treturn -ENODEV;\n> +\n> +\tmonitor_ = udev_monitor_new_from_netlink(udev_, \"udev\");\n> +\tif (!monitor_)\n> +\t\treturn -ENODEV;\n> +\n> +\tret = udev_monitor_filter_add_match_subsystem_devtype(monitor_, \"media\",\n> +\t\t\t\t\t\t\t      nullptr);\n> +\tif (ret < 0)\n> +\t\treturn ret;\n> +\n> +\treturn 0;\n> +}\n> +\n> +int DeviceEnumeratorUdev::enumerate()\n> +{\n> +\tstruct udev_enumerate *udev_enum = nullptr;\n> +\tstruct udev_list_entry *ents, *ent;\n> +\tint ret;\n> +\n> +\tudev_enum = udev_enumerate_new(udev_);\n> +\tif (!udev_enum)\n> +\t\treturn -ENOMEM;\n> +\n> +\tret = udev_enumerate_add_match_subsystem(udev_enum, \"media\");\n> +\tif (ret < 0)\n> +\t\tgoto done;\n> +\n> +\tret = udev_enumerate_scan_devices(udev_enum);\n> +\tif (ret < 0)\n> +\t\tgoto done;\n> +\n> +\tents = udev_enumerate_get_list_entry(udev_enum);\n> +\tif (!ents)\n> +\t\tgoto done;\n> +\n> +\tudev_list_entry_foreach(ent, ents) {\n> +\t\tstruct udev_device *dev;\n> +\t\tconst char *devnode;\n> +\t\tconst char *syspath = udev_list_entry_get_name(ent);\n> +\n> +\t\tdev = udev_device_new_from_syspath(udev_, syspath);\n> +\t\tif (!dev) {\n> +\t\t\tLOG(DeviceEnumerator, Warning)\n> +\t\t\t\t<< \"Failed to get device for '\"\n> +\t\t\t\t<< syspath << \"', skipping\";\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n> +\t\tdevnode = udev_device_get_devnode(dev);\n> +\t\tif (!devnode) {\n> +\t\t\tudev_device_unref(dev);\n> +\t\t\tret = -ENODEV;\n> +\t\t\tgoto done;\n> +\t\t}\n> +\n> +\t\taddDevice(devnode);\n> +\n> +\t\tudev_device_unref(dev);\n> +\t}\n> +done:\n> +\tudev_enumerate_unref(udev_enum);\n> +\tif (ret < 0)\n> +\t\treturn ret;\n> +\n> +\tret = udev_monitor_enable_receiving(monitor_);\n> +\tif (ret < 0)\n> +\t\treturn ret;\n> +\n> +\tint fd = udev_monitor_get_fd(monitor_);\n> +\tnotifier_ = new EventNotifier(fd, EventNotifier::Read);\n> +\tnotifier_->activated.connect(this, &DeviceEnumeratorUdev::udevNotify);\n> +\n> +\treturn 0;\n> +}\n> +\n> +std::string DeviceEnumeratorUdev::lookupDeviceNode(int major, int minor)\n> +{\n> +\tstruct udev_device *device;\n> +\tconst char *name;\n> +\tdev_t devnum;\n> +\tstd::string deviceNode = std::string();\n> +\n> +\tdevnum = makedev(major, minor);\n> +\tdevice = udev_device_new_from_devnum(udev_, 'c', devnum);\n> +\tif (!device)\n> +\t\treturn std::string();\n> +\n> +\tname = udev_device_get_devnode(device);\n> +\tif (name)\n> +\t\tdeviceNode = name;\n> +\n> +\tudev_device_unref(device);\n> +\n> +\treturn deviceNode;\n> +}\n> +\n> +void DeviceEnumeratorUdev::udevNotify(EventNotifier *notifier)\n> +{\n> +\tstruct udev_device *dev = udev_monitor_receive_device(monitor_);\n> +\tstd::string action(udev_device_get_action(dev));\n> +\tstd::string deviceNode(udev_device_get_devnode(dev));\n> +\n> +\tLOG(DeviceEnumerator, Debug)\n> +\t\t<< action << \" device \" << udev_device_get_devnode(dev);\n> +\n> +\tif (action == \"add\") {\n> +\t\taddDevice(deviceNode);\n> +\t} else if (action == \"remove\") {\n> +\t\tremoveDevice(deviceNode);\n> +\t}\n> +\n> +\tudev_device_unref(dev);\n> +}\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h\n> index 2801861864b8..02aec3bc50c6 100644\n> --- a/src/libcamera/include/device_enumerator.h\n> +++ b/src/libcamera/include/device_enumerator.h\n> @@ -7,19 +7,14 @@\n>  #ifndef __LIBCAMERA_DEVICE_ENUMERATOR_H__\n>  #define __LIBCAMERA_DEVICE_ENUMERATOR_H__\n>  \n> -#include <map>\n>  #include <memory>\n>  #include <string>\n>  #include <vector>\n>  \n>  #include <linux/media.h>\n>  \n> -struct udev;\n> -struct udev_monitor;\n> -\n>  namespace libcamera {\n>  \n> -class EventNotifier;\n>  class MediaDevice;\n>  \n>  class DeviceMatch\n> @@ -58,25 +53,6 @@ private:\n>  \tvirtual std::string lookupDeviceNode(int major, int minor) = 0;\n>  };\n>  \n> -class DeviceEnumeratorUdev: public DeviceEnumerator\n> -{\n> -public:\n> -\tDeviceEnumeratorUdev();\n> -\t~DeviceEnumeratorUdev();\n> -\n> -\tint init() final;\n> -\tint enumerate() final;\n> -\n> -private:\n> -\tstruct udev *udev_;\n> -\tstruct udev_monitor *monitor_;\n> -\tEventNotifier *notifier_;\n> -\n> -\tstd::string lookupDeviceNode(int major, int minor) final;\n> -\n> -\tvoid udevNotify(EventNotifier *notifier);\n> -};\n> -\n>  } /* namespace libcamera */\n>  \n>  #endif\t/* __LIBCAMERA_DEVICE_ENUMERATOR_H__ */\n> diff --git a/src/libcamera/include/device_enumerator_udev.h b/src/libcamera/include/device_enumerator_udev.h\n> new file mode 100644\n> index 000000000000..80f9372bca36\n> --- /dev/null\n> +++ b/src/libcamera/include/device_enumerator_udev.h\n> @@ -0,0 +1,42 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2018-2019, Google Inc.\n> + *\n> + * device_enumerator_udev.h - udev-based device enumerator\n> + */\n> +#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__\n> +#define __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__\n> +\n> +#include <string>\n> +\n> +#include \"device_enumerator.h\"\n> +\n> +struct udev;\n> +struct udev_monitor;\n> +\n> +namespace libcamera {\n> +\n> +class EventNotifier;\n> +\n> +class DeviceEnumeratorUdev : public DeviceEnumerator\n> +{\n> +public:\n> +\tDeviceEnumeratorUdev();\n> +\t~DeviceEnumeratorUdev();\n> +\n> +\tint init() final;\n> +\tint enumerate() final;\n> +\n> +private:\n> +\tstruct udev *udev_;\n> +\tstruct udev_monitor *monitor_;\n> +\tEventNotifier *notifier_;\n> +\n> +\tstd::string lookupDeviceNode(int major, int minor) final;\n> +\n> +\tvoid udevNotify(EventNotifier *notifier);\n> +};\n> +\n> +} /* namespace libcamera */\n> +\n> +#endif\t/* __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__ */\n> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n> index cf4edec05755..2b678237b64f 100644\n> --- a/src/libcamera/meson.build\n> +++ b/src/libcamera/meson.build\n> @@ -26,6 +26,7 @@ libcamera_sources = files([\n>  libcamera_headers = files([\n>      'include/camera_sensor.h',\n>      'include/device_enumerator.h',\n> +    'include/device_enumerator_udev.h',\n>      'include/event_dispatcher_poll.h',\n>      'include/formats.h',\n>      'include/log.h',\n> @@ -46,7 +47,14 @@ includes = [\n>  \n>  subdir('pipeline')\n>  \n> -libudev = dependency('libudev')\n> +libudev = dependency('libudev', required: false)\n> +\n> +if libudev.found()\n> +    config_h.set('HAVE_LIBUDEV', 1)\n> +    libcamera_sources += files([\n> +        'device_enumerator_udev.cpp',\n> +    ])\n> +endif\n>  \n>  libcamera = shared_library('camera',\n>                             libcamera_sources,\n>","headers":{"Return-Path":"<kieran.bingham@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 46B7860004\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 27 Apr 2019 15:58:33 +0200 (CEST)","from [192.168.1.6] (net-37-182-44-227.cust.vodafonedsl.it\n\t[37.182.44.227])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 719655F;\n\tSat, 27 Apr 2019 15:58:32 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1556373512;\n\tbh=IdASdaFF881NaBC+BmzlXZ/3hecu/pirYzDwmDYBFQM=;\n\th=Reply-To:Subject:To:References:From:Date:In-Reply-To:From;\n\tb=WRLli4lUYPGEFkqrF7HLXzQ3b8EqWJ1NCSeCH4sc8+AEZAQHXvGudFhrPUfcfL2FE\n\ttc9BTI75uIEF1Co5UB+ntNBsq16jauiTNMSF6LAAAcuAl76tuL7YvoqEvqoJcJ1N5H\n\tDt7bGJKA2apCJAVioOItJ9Z2HRR4IRtL/R3iYzxk=","Reply-To":"kieran.bingham@ideasonboard.com","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20190427021631.15252-1-laurent.pinchart@ideasonboard.com>","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Openpgp":"preference=signencrypt","Autocrypt":"addr=kieran.bingham@ideasonboard.com; keydata=\n\t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\n\tsbsRB8KNNvVXBOVNwko86rQqF9drZuw=","Organization":"Ideas on Board","Message-ID":"<c726293a-e9a9-fb83-e440-d7852271509c@ideasonboard.com>","Date":"Sat, 27 Apr 2019 15:58:29 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101\n\tThunderbird/60.6.1","MIME-Version":"1.0","In-Reply-To":"<20190427021631.15252-1-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=utf-8","Content-Language":"en-GB","Content-Transfer-Encoding":"8bit","Subject":"Re: [libcamera-devel] [PATCH] libcamera: Make libudev optional","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sat, 27 Apr 2019 13:58:33 -0000"}},{"id":1521,"web_url":"https://patchwork.libcamera.org/comment/1521/","msgid":"<20190427141043.GB4690@pendragon.ideasonboard.com>","date":"2019-04-27T14:10:43","subject":"Re: [libcamera-devel] [PATCH] libcamera: Make libudev optional","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Kieran,\n\nOn Sat, Apr 27, 2019 at 03:58:29PM +0200, Kieran Bingham wrote:\n> On 27/04/2019 04:16, Laurent Pinchart wrote:\n> > libcamera depends on libudev for device enumeration. It is however\n> > useful to allow building documentation without requiring the dependency\n> > to be installed. Make the libudev dependency optional and compile the\n> > udev-based device enumerator out when libudev is not present.\n> > \n> > Note that will libcamera will compile without libudev, it will not be\n> \n> s/Note that will/Note that while/\n> \n> > able to enumerate devices. A sysfs-based device enumerator is planned as\n> > a fallback but not implemented yet.\n> \n> I think being able to build the documentation standalone is certainly a\n> good thing.\n> \n> I'd possibly have looked at the route of providing a meson configuration\n> option to enable only the documentation, as we might find that a\n> platform without libudev now doesn't work correctly - but as that will\n> be fixed separately I'm not going to block this on that point.\n\nI think it would be useful too, but given that we plan to have a\nsysfs-based enumerator for platforms without libudev, I think this patch\ngoes in the right direction anyway.\n\n> Ignoring the documentation requirement, this does step a long way to\n> getting configurable device enumeration methods (with the benefit of\n> letting us build our documentation without requiring libudev) so:\n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\nThank you.\n\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  Documentation/Doxyfile.in                     |   4 +-\n> >  meson.build                                   |   3 +-\n> >  src/libcamera/camera_manager.cpp              |   2 +-\n> >  src/libcamera/device_enumerator.cpp           | 157 +----------------\n> >  src/libcamera/device_enumerator_udev.cpp      | 163 ++++++++++++++++++\n> >  src/libcamera/include/device_enumerator.h     |  24 ---\n> >  .../include/device_enumerator_udev.h          |  42 +++++\n> >  src/libcamera/meson.build                     |  10 +-\n> >  8 files changed, 223 insertions(+), 182 deletions(-)\n> >  create mode 100644 src/libcamera/device_enumerator_udev.cpp\n> >  create mode 100644 src/libcamera/include/device_enumerator_udev.h\n> > \n> > diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> > index 3e2b7fd9da0e..950ad4fef40e 100644\n> > --- a/Documentation/Doxyfile.in\n> > +++ b/Documentation/Doxyfile.in\n> > @@ -833,7 +833,9 @@ RECURSIVE              = YES\n> >  # Note that relative paths are relative to the directory from which doxygen is\n> >  # run.\n> >  \n> > -EXCLUDE                = ../src/libcamera/pipeline/\n> > +EXCLUDE                = ../src/libcamera/device_enumerator_udev.cpp \\\n> > +\t\t\t ../src/libcamera/include/device_enumerator_udev.h \\\n> > +\t\t\t ../src/libcamera/pipeline/\n> >  \n> >  # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n> >  # directories that are symbolic links (a Unix file system feature) are excluded\n> > diff --git a/meson.build b/meson.build\n> > index 3434dd7c1b66..d272ff33b100 100644\n> > --- a/meson.build\n> > +++ b/meson.build\n> > @@ -19,7 +19,6 @@ config_h = configuration_data()\n> >  if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix: '#define _GNU_SOURCE')\n> >      config_h.set('HAVE_SECURE_GETENV', 1)\n> >  endif\n> > -configure_file(output: 'config.h', configuration: config_h)\n> >  \n> >  common_arguments = [\n> >      '-Wno-unused-parameter',\n> > @@ -49,6 +48,8 @@ if get_option('tests')\n> >    subdir('test')\n> >  endif\n> >  \n> > +configure_file(output: 'config.h', configuration: config_h)\n> > +\n> >  pkg_mod = import('pkgconfig')\n> >  pkg_mod.generate(libraries : libcamera,\n> >                   version : '1.0',\n> > diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\n> > index 40a39bd2a6d9..cf881ce2e641 100644\n> > --- a/src/libcamera/camera_manager.cpp\n> > +++ b/src/libcamera/camera_manager.cpp\n> > @@ -80,7 +80,7 @@ int CameraManager::start()\n> >  \t\treturn -EBUSY;\n> >  \n> >  \tenumerator_ = DeviceEnumerator::create();\n> > -\tif (enumerator_->enumerate())\n> > +\tif (!enumerator_ || enumerator_->enumerate())\n> >  \t\treturn -ENODEV;\n> >  \n> >  \t/*\n> > diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp\n> > index 49467546bab8..f6878b3d58b3 100644\n> > --- a/src/libcamera/device_enumerator.cpp\n> > +++ b/src/libcamera/device_enumerator.cpp\n> > @@ -6,14 +6,9 @@\n> >   */\n> >  \n> >  #include \"device_enumerator.h\"\n> > +#include \"device_enumerator_udev.h\"\n> >  \n> > -#include <fcntl.h>\n> > -#include <libudev.h>\n> >  #include <string.h>\n> > -#include <sys/ioctl.h>\n> > -#include <unistd.h>\n> > -\n> > -#include <libcamera/event_notifier.h>\n> >  \n> >  #include \"log.h\"\n> >  #include \"media_device.h\"\n> > @@ -148,13 +143,11 @@ std::unique_ptr<DeviceEnumerator> DeviceEnumerator::create()\n> >  {\n> >  \tstd::unique_ptr<DeviceEnumerator> enumerator;\n> >  \n> > -\t/**\n> > -\t * \\todo Add compile time checks to only try udev enumerator if libudev\n> > -\t * is available.\n> > -\t */\n> > +#ifdef HAVE_LIBUDEV\n> >  \tenumerator = utils::make_unique<DeviceEnumeratorUdev>();\n> >  \tif (!enumerator->init())\n> >  \t\treturn enumerator;\n> > +#endif\n> >  \n> >  \t/*\n> >  \t * Either udev is not available or udev initialization failed. Fall back\n> > @@ -327,148 +320,4 @@ std::shared_ptr<MediaDevice> DeviceEnumerator::search(const DeviceMatch &dm)\n> >   * fails\n> >   */\n> >  \n> > -/**\n> > - * \\class DeviceEnumeratorUdev\n> > - * \\brief Device enumerator based on libudev\n> > - */\n> > -\n> > -DeviceEnumeratorUdev::DeviceEnumeratorUdev()\n> > -\t: udev_(nullptr)\n> > -{\n> > -}\n> > -\n> > -DeviceEnumeratorUdev::~DeviceEnumeratorUdev()\n> > -{\n> > -\tdelete notifier_;\n> > -\n> > -\tif (monitor_)\n> > -\t\tudev_monitor_unref(monitor_);\n> > -\tif (udev_)\n> > -\t\tudev_unref(udev_);\n> > -}\n> > -\n> > -int DeviceEnumeratorUdev::init()\n> > -{\n> > -\tint ret;\n> > -\n> > -\tif (udev_)\n> > -\t\treturn -EBUSY;\n> > -\n> > -\tudev_ = udev_new();\n> > -\tif (!udev_)\n> > -\t\treturn -ENODEV;\n> > -\n> > -\tmonitor_ = udev_monitor_new_from_netlink(udev_, \"udev\");\n> > -\tif (!monitor_)\n> > -\t\treturn -ENODEV;\n> > -\n> > -\tret = udev_monitor_filter_add_match_subsystem_devtype(monitor_, \"media\",\n> > -\t\t\t\t\t\t\t      nullptr);\n> > -\tif (ret < 0)\n> > -\t\treturn ret;\n> > -\n> > -\treturn 0;\n> > -}\n> > -\n> > -int DeviceEnumeratorUdev::enumerate()\n> > -{\n> > -\tstruct udev_enumerate *udev_enum = nullptr;\n> > -\tstruct udev_list_entry *ents, *ent;\n> > -\tint ret;\n> > -\n> > -\tudev_enum = udev_enumerate_new(udev_);\n> > -\tif (!udev_enum)\n> > -\t\treturn -ENOMEM;\n> > -\n> > -\tret = udev_enumerate_add_match_subsystem(udev_enum, \"media\");\n> > -\tif (ret < 0)\n> > -\t\tgoto done;\n> > -\n> > -\tret = udev_enumerate_scan_devices(udev_enum);\n> > -\tif (ret < 0)\n> > -\t\tgoto done;\n> > -\n> > -\tents = udev_enumerate_get_list_entry(udev_enum);\n> > -\tif (!ents)\n> > -\t\tgoto done;\n> > -\n> > -\tudev_list_entry_foreach(ent, ents) {\n> > -\t\tstruct udev_device *dev;\n> > -\t\tconst char *devnode;\n> > -\t\tconst char *syspath = udev_list_entry_get_name(ent);\n> > -\n> > -\t\tdev = udev_device_new_from_syspath(udev_, syspath);\n> > -\t\tif (!dev) {\n> > -\t\t\tLOG(DeviceEnumerator, Warning)\n> > -\t\t\t\t<< \"Failed to get device for '\"\n> > -\t\t\t\t<< syspath << \"', skipping\";\n> > -\t\t\tcontinue;\n> > -\t\t}\n> > -\n> > -\t\tdevnode = udev_device_get_devnode(dev);\n> > -\t\tif (!devnode) {\n> > -\t\t\tudev_device_unref(dev);\n> > -\t\t\tret = -ENODEV;\n> > -\t\t\tgoto done;\n> > -\t\t}\n> > -\n> > -\t\taddDevice(devnode);\n> > -\n> > -\t\tudev_device_unref(dev);\n> > -\t}\n> > -done:\n> > -\tudev_enumerate_unref(udev_enum);\n> > -\tif (ret < 0)\n> > -\t\treturn ret;\n> > -\n> > -\tret = udev_monitor_enable_receiving(monitor_);\n> > -\tif (ret < 0)\n> > -\t\treturn ret;\n> > -\n> > -\tint fd = udev_monitor_get_fd(monitor_);\n> > -\tnotifier_ = new EventNotifier(fd, EventNotifier::Read);\n> > -\tnotifier_->activated.connect(this, &DeviceEnumeratorUdev::udevNotify);\n> > -\n> > -\treturn 0;\n> > -}\n> > -\n> > -std::string DeviceEnumeratorUdev::lookupDeviceNode(int major, int minor)\n> > -{\n> > -\tstruct udev_device *device;\n> > -\tconst char *name;\n> > -\tdev_t devnum;\n> > -\tstd::string deviceNode = std::string();\n> > -\n> > -\tdevnum = makedev(major, minor);\n> > -\tdevice = udev_device_new_from_devnum(udev_, 'c', devnum);\n> > -\tif (!device)\n> > -\t\treturn std::string();\n> > -\n> > -\tname = udev_device_get_devnode(device);\n> > -\tif (name)\n> > -\t\tdeviceNode = name;\n> > -\n> > -\tudev_device_unref(device);\n> > -\n> > -\treturn deviceNode;\n> > -}\n> > -\n> > -void DeviceEnumeratorUdev::udevNotify(EventNotifier *notifier)\n> > -{\n> > -\tstruct udev_device *dev = udev_monitor_receive_device(monitor_);\n> > -\tstd::string action(udev_device_get_action(dev));\n> > -\tstd::string deviceNode(udev_device_get_devnode(dev));\n> > -\n> > -\tLOG(DeviceEnumerator, Debug)\n> > -\t\t<< action << \" device \" << udev_device_get_devnode(dev);\n> > -\n> > -\tif (action == \"add\") {\n> > -\t\taddDevice(deviceNode);\n> > -\t} else if (action == \"remove\") {\n> > -\t\tremoveDevice(deviceNode);\n> > -\t}\n> > -\n> > -\tudev_device_unref(dev);\n> > -}\n> > -\n> >  } /* namespace libcamera */\n> > diff --git a/src/libcamera/device_enumerator_udev.cpp b/src/libcamera/device_enumerator_udev.cpp\n> \n> I like that the udev specific code is moved out to it's own unit.\n> \n> \n> \n> > new file mode 100644\n> > index 000000000000..cb2d21b90506\n> > --- /dev/null\n> > +++ b/src/libcamera/device_enumerator_udev.cpp\n> > @@ -0,0 +1,163 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2018-2019, Google Inc.\n> > + *\n> > + * device_enumerator_udev.cpp - udev-based device enumerator\n> > + */\n> > +\n> > +#include \"device_enumerator_udev.h\"\n> > +\n> > +#include <fcntl.h>\n> > +#include <libudev.h>\n> > +#include <string.h>\n> > +#include <sys/ioctl.h>\n> > +#include <unistd.h>\n> > +\n> > +#include <libcamera/event_notifier.h>\n> > +\n> > +#include \"log.h\"\n> > +\n> > +namespace libcamera {\n> > +\n> > +LOG_DECLARE_CATEGORY(DeviceEnumerator)\n> > +\n> > +DeviceEnumeratorUdev::DeviceEnumeratorUdev()\n> > +\t: udev_(nullptr)\n> > +{\n> > +}\n> > +\n> > +DeviceEnumeratorUdev::~DeviceEnumeratorUdev()\n> > +{\n> > +\tdelete notifier_;\n> > +\n> > +\tif (monitor_)\n> > +\t\tudev_monitor_unref(monitor_);\n> > +\tif (udev_)\n> > +\t\tudev_unref(udev_);\n> > +}\n> > +\n> > +int DeviceEnumeratorUdev::init()\n> > +{\n> > +\tint ret;\n> > +\n> > +\tif (udev_)\n> > +\t\treturn -EBUSY;\n> > +\n> > +\tudev_ = udev_new();\n> > +\tif (!udev_)\n> > +\t\treturn -ENODEV;\n> > +\n> > +\tmonitor_ = udev_monitor_new_from_netlink(udev_, \"udev\");\n> > +\tif (!monitor_)\n> > +\t\treturn -ENODEV;\n> > +\n> > +\tret = udev_monitor_filter_add_match_subsystem_devtype(monitor_, \"media\",\n> > +\t\t\t\t\t\t\t      nullptr);\n> > +\tif (ret < 0)\n> > +\t\treturn ret;\n> > +\n> > +\treturn 0;\n> > +}\n> > +\n> > +int DeviceEnumeratorUdev::enumerate()\n> > +{\n> > +\tstruct udev_enumerate *udev_enum = nullptr;\n> > +\tstruct udev_list_entry *ents, *ent;\n> > +\tint ret;\n> > +\n> > +\tudev_enum = udev_enumerate_new(udev_);\n> > +\tif (!udev_enum)\n> > +\t\treturn -ENOMEM;\n> > +\n> > +\tret = udev_enumerate_add_match_subsystem(udev_enum, \"media\");\n> > +\tif (ret < 0)\n> > +\t\tgoto done;\n> > +\n> > +\tret = udev_enumerate_scan_devices(udev_enum);\n> > +\tif (ret < 0)\n> > +\t\tgoto done;\n> > +\n> > +\tents = udev_enumerate_get_list_entry(udev_enum);\n> > +\tif (!ents)\n> > +\t\tgoto done;\n> > +\n> > +\tudev_list_entry_foreach(ent, ents) {\n> > +\t\tstruct udev_device *dev;\n> > +\t\tconst char *devnode;\n> > +\t\tconst char *syspath = udev_list_entry_get_name(ent);\n> > +\n> > +\t\tdev = udev_device_new_from_syspath(udev_, syspath);\n> > +\t\tif (!dev) {\n> > +\t\t\tLOG(DeviceEnumerator, Warning)\n> > +\t\t\t\t<< \"Failed to get device for '\"\n> > +\t\t\t\t<< syspath << \"', skipping\";\n> > +\t\t\tcontinue;\n> > +\t\t}\n> > +\n> > +\t\tdevnode = udev_device_get_devnode(dev);\n> > +\t\tif (!devnode) {\n> > +\t\t\tudev_device_unref(dev);\n> > +\t\t\tret = -ENODEV;\n> > +\t\t\tgoto done;\n> > +\t\t}\n> > +\n> > +\t\taddDevice(devnode);\n> > +\n> > +\t\tudev_device_unref(dev);\n> > +\t}\n> > +done:\n> > +\tudev_enumerate_unref(udev_enum);\n> > +\tif (ret < 0)\n> > +\t\treturn ret;\n> > +\n> > +\tret = udev_monitor_enable_receiving(monitor_);\n> > +\tif (ret < 0)\n> > +\t\treturn ret;\n> > +\n> > +\tint fd = udev_monitor_get_fd(monitor_);\n> > +\tnotifier_ = new EventNotifier(fd, EventNotifier::Read);\n> > +\tnotifier_->activated.connect(this, &DeviceEnumeratorUdev::udevNotify);\n> > +\n> > +\treturn 0;\n> > +}\n> > +\n> > +std::string DeviceEnumeratorUdev::lookupDeviceNode(int major, int minor)\n> > +{\n> > +\tstruct udev_device *device;\n> > +\tconst char *name;\n> > +\tdev_t devnum;\n> > +\tstd::string deviceNode = std::string();\n> > +\n> > +\tdevnum = makedev(major, minor);\n> > +\tdevice = udev_device_new_from_devnum(udev_, 'c', devnum);\n> > +\tif (!device)\n> > +\t\treturn std::string();\n> > +\n> > +\tname = udev_device_get_devnode(device);\n> > +\tif (name)\n> > +\t\tdeviceNode = name;\n> > +\n> > +\tudev_device_unref(device);\n> > +\n> > +\treturn deviceNode;\n> > +}\n> > +\n> > +void DeviceEnumeratorUdev::udevNotify(EventNotifier *notifier)\n> > +{\n> > +\tstruct udev_device *dev = udev_monitor_receive_device(monitor_);\n> > +\tstd::string action(udev_device_get_action(dev));\n> > +\tstd::string deviceNode(udev_device_get_devnode(dev));\n> > +\n> > +\tLOG(DeviceEnumerator, Debug)\n> > +\t\t<< action << \" device \" << udev_device_get_devnode(dev);\n> > +\n> > +\tif (action == \"add\") {\n> > +\t\taddDevice(deviceNode);\n> > +\t} else if (action == \"remove\") {\n> > +\t\tremoveDevice(deviceNode);\n> > +\t}\n> > +\n> > +\tudev_device_unref(dev);\n> > +}\n> > +\n> > +} /* namespace libcamera */\n> > diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h\n> > index 2801861864b8..02aec3bc50c6 100644\n> > --- a/src/libcamera/include/device_enumerator.h\n> > +++ b/src/libcamera/include/device_enumerator.h\n> > @@ -7,19 +7,14 @@\n> >  #ifndef __LIBCAMERA_DEVICE_ENUMERATOR_H__\n> >  #define __LIBCAMERA_DEVICE_ENUMERATOR_H__\n> >  \n> > -#include <map>\n> >  #include <memory>\n> >  #include <string>\n> >  #include <vector>\n> >  \n> >  #include <linux/media.h>\n> >  \n> > -struct udev;\n> > -struct udev_monitor;\n> > -\n> >  namespace libcamera {\n> >  \n> > -class EventNotifier;\n> >  class MediaDevice;\n> >  \n> >  class DeviceMatch\n> > @@ -58,25 +53,6 @@ private:\n> >  \tvirtual std::string lookupDeviceNode(int major, int minor) = 0;\n> >  };\n> >  \n> > -class DeviceEnumeratorUdev: public DeviceEnumerator\n> > -{\n> > -public:\n> > -\tDeviceEnumeratorUdev();\n> > -\t~DeviceEnumeratorUdev();\n> > -\n> > -\tint init() final;\n> > -\tint enumerate() final;\n> > -\n> > -private:\n> > -\tstruct udev *udev_;\n> > -\tstruct udev_monitor *monitor_;\n> > -\tEventNotifier *notifier_;\n> > -\n> > -\tstd::string lookupDeviceNode(int major, int minor) final;\n> > -\n> > -\tvoid udevNotify(EventNotifier *notifier);\n> > -};\n> > -\n> >  } /* namespace libcamera */\n> >  \n> >  #endif\t/* __LIBCAMERA_DEVICE_ENUMERATOR_H__ */\n> > diff --git a/src/libcamera/include/device_enumerator_udev.h b/src/libcamera/include/device_enumerator_udev.h\n> > new file mode 100644\n> > index 000000000000..80f9372bca36\n> > --- /dev/null\n> > +++ b/src/libcamera/include/device_enumerator_udev.h\n> > @@ -0,0 +1,42 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2018-2019, Google Inc.\n> > + *\n> > + * device_enumerator_udev.h - udev-based device enumerator\n> > + */\n> > +#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__\n> > +#define __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__\n> > +\n> > +#include <string>\n> > +\n> > +#include \"device_enumerator.h\"\n> > +\n> > +struct udev;\n> > +struct udev_monitor;\n> > +\n> > +namespace libcamera {\n> > +\n> > +class EventNotifier;\n> > +\n> > +class DeviceEnumeratorUdev : public DeviceEnumerator\n> > +{\n> > +public:\n> > +\tDeviceEnumeratorUdev();\n> > +\t~DeviceEnumeratorUdev();\n> > +\n> > +\tint init() final;\n> > +\tint enumerate() final;\n> > +\n> > +private:\n> > +\tstruct udev *udev_;\n> > +\tstruct udev_monitor *monitor_;\n> > +\tEventNotifier *notifier_;\n> > +\n> > +\tstd::string lookupDeviceNode(int major, int minor) final;\n> > +\n> > +\tvoid udevNotify(EventNotifier *notifier);\n> > +};\n> > +\n> > +} /* namespace libcamera */\n> > +\n> > +#endif\t/* __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__ */\n> > diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n> > index cf4edec05755..2b678237b64f 100644\n> > --- a/src/libcamera/meson.build\n> > +++ b/src/libcamera/meson.build\n> > @@ -26,6 +26,7 @@ libcamera_sources = files([\n> >  libcamera_headers = files([\n> >      'include/camera_sensor.h',\n> >      'include/device_enumerator.h',\n> > +    'include/device_enumerator_udev.h',\n> >      'include/event_dispatcher_poll.h',\n> >      'include/formats.h',\n> >      'include/log.h',\n> > @@ -46,7 +47,14 @@ includes = [\n> >  \n> >  subdir('pipeline')\n> >  \n> > -libudev = dependency('libudev')\n> > +libudev = dependency('libudev', required: false)\n> > +\n> > +if libudev.found()\n> > +    config_h.set('HAVE_LIBUDEV', 1)\n> > +    libcamera_sources += files([\n> > +        'device_enumerator_udev.cpp',\n> > +    ])\n> > +endif\n> >  \n> >  libcamera = shared_library('camera',\n> >                             libcamera_sources,","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1C8856174F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 27 Apr 2019 16:10:55 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(net-37-182-44-227.cust.vodafonedsl.it [37.182.44.227])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 7C50C5F;\n\tSat, 27 Apr 2019 16:10:54 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1556374254;\n\tbh=a657iG9/nIM26haz4tByzLVeXZmAzIRn/EbjfAssaNE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=MRdwwEdhJyqW8JN8/dBh8+zE2mHL6nRK5OcO0TKeryzca/j3NfChQ5auK85eKeSkb\n\tIXJ3nowrH/rEBz1C2rHbxZhh+ihZ/IAQ0zLmbE6v3aVb2LTwdmxDGRLUFvCcwoeq/0\n\tATDEWt5hstBSZDEW8fL5TO8HVnL/2iEkPALBEOs8=","Date":"Sat, 27 Apr 2019 17:10:43 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190427141043.GB4690@pendragon.ideasonboard.com>","References":"<20190427021631.15252-1-laurent.pinchart@ideasonboard.com>\n\t<c726293a-e9a9-fb83-e440-d7852271509c@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<c726293a-e9a9-fb83-e440-d7852271509c@ideasonboard.com>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH] libcamera: Make libudev optional","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sat, 27 Apr 2019 14:10:55 -0000"}}]