[libcamera-devel,v1,2/2] libcamera: base: utils: Support C libraries lacking locale support
diff mbox series

Message ID 20230108214357.12641-3-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • libcamera Fix compilation with uClibc
Related show

Commit Message

Laurent Pinchart Jan. 8, 2023, 9:43 p.m. UTC
Not all C libraries include support for locale objects (locale_t) and
the strto*_l() family of functions. A notable example is uClibc that can
be compiled with a hardcoded "C" locale. Compilation then fails as the
newlocale(), freelocale() and strtod_l() functions are not defined.

Fix the compilation breakage by checking for the availability of
newlocale(), and fall back to strtod() when the function isn't
available. This may not lead to the correct result if support for locale
objects isn't available and the locale isn't hardcoded to "C", but that
is such a corner case that we will likely never encounter it.

Fixes: e8ae254970cf ("libcamera: yaml_parser: Use C locale")
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 meson.build                  |  4 ++++
 src/libcamera/base/utils.cpp | 12 ++++++++++++
 2 files changed, 16 insertions(+)

Comments

Kieran Bingham Jan. 8, 2023, 11:22 p.m. UTC | #1
Quoting Laurent Pinchart via libcamera-devel (2023-01-08 21:43:57)
> Not all C libraries include support for locale objects (locale_t) and
> the strto*_l() family of functions. A notable example is uClibc that can
> be compiled with a hardcoded "C" locale. Compilation then fails as the
> newlocale(), freelocale() and strtod_l() functions are not defined.
> 
> Fix the compilation breakage by checking for the availability of
> newlocale(), and fall back to strtod() when the function isn't
> available. This may not lead to the correct result if support for locale
> objects isn't available and the locale isn't hardcoded to "C", but that
> is such a corner case that we will likely never encounter it.

Agreed.

And this is fine by me, as long as it all compiles. I'm not yet aware of
anyone actually using libcamera with uClibc (I'd love to hear if anyone
is using it ...) - so I think this is just to maintain compatibility for
now.

Does the same issue happen in musl - or does that have locale support ?

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> Fixes: e8ae254970cf ("libcamera: yaml_parser: Use C locale")
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  meson.build                  |  4 ++++
>  src/libcamera/base/utils.cpp | 12 ++++++++++++
>  2 files changed, 16 insertions(+)
> 
> diff --git a/meson.build b/meson.build
> index e86673dd5c0c..7dcd34d3e6b3 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -72,6 +72,10 @@ if cc.has_header_symbol('unistd.h', 'issetugid')
>      config_h.set('HAVE_ISSETUGID', 1)
>  endif
>  
> +if cc.has_header_symbol('locale.h', 'newlocale', prefix : '#define _GNU_SOURCE')
> +    config_h.set('HAVE_NEWLOCALE', 1)
> +endif
> +
>  if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOURCE')
>      config_h.set('HAVE_SECURE_GETENV', 1)
>  endif
> diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
> index 4a239427a4d9..ac3e1311995e 100644
> --- a/src/libcamera/base/utils.cpp
> +++ b/src/libcamera/base/utils.cpp
> @@ -464,6 +464,8 @@ std::string toAscii(const std::string &str)
>   * \a b
>   */
>  
> +#if HAVE_NEWLOCALE
> +
>  namespace {
>  
>  /*
> @@ -493,6 +495,8 @@ Locale cLocale("C");
>  
>  } /* namespace */
>  
> +#endif /* HAVE_NEWLOCALE */
> +
>  /**
>   * \brief Convert a string to a double independently of the current locale
>   * \param[in] nptr The string to convert
> @@ -506,7 +510,15 @@ Locale cLocale("C");
>   */
>  double strtod(const char *__restrict nptr, char **__restrict endptr)
>  {
> +#if HAVE_NEWLOCALE
>         return strtod_l(nptr, endptr, cLocale.locale());
> +#else
> +       /*
> +        * If the libc implementation doesn't provide locale object support,
> +        * assume that strtod() is locale-independent.
> +        */
> +       return strtod(nptr, endptr);
> +#endif
>  }
>  
>  } /* namespace utils */
> -- 
> Regards,
> 
> Laurent Pinchart
>
Laurent Pinchart Jan. 8, 2023, 11:40 p.m. UTC | #2
On Sun, Jan 08, 2023 at 11:22:37PM +0000, Kieran Bingham wrote:
> Quoting Laurent Pinchart via libcamera-devel (2023-01-08 21:43:57)
> > Not all C libraries include support for locale objects (locale_t) and
> > the strto*_l() family of functions. A notable example is uClibc that can
> > be compiled with a hardcoded "C" locale. Compilation then fails as the
> > newlocale(), freelocale() and strtod_l() functions are not defined.
> > 
> > Fix the compilation breakage by checking for the availability of
> > newlocale(), and fall back to strtod() when the function isn't
> > available. This may not lead to the correct result if support for locale
> > objects isn't available and the locale isn't hardcoded to "C", but that
> > is such a corner case that we will likely never encounter it.
> 
> Agreed.
> 
> And this is fine by me, as long as it all compiles. I'm not yet aware of
> anyone actually using libcamera with uClibc (I'd love to hear if anyone
> is using it ...) - so I think this is just to maintain compatibility for
> now.
> 
> Does the same issue happen in musl - or does that have locale support ?

No, musl has locale object support.

> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> > Fixes: e8ae254970cf ("libcamera: yaml_parser: Use C locale")
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  meson.build                  |  4 ++++
> >  src/libcamera/base/utils.cpp | 12 ++++++++++++
> >  2 files changed, 16 insertions(+)
> > 
> > diff --git a/meson.build b/meson.build
> > index e86673dd5c0c..7dcd34d3e6b3 100644
> > --- a/meson.build
> > +++ b/meson.build
> > @@ -72,6 +72,10 @@ if cc.has_header_symbol('unistd.h', 'issetugid')
> >      config_h.set('HAVE_ISSETUGID', 1)
> >  endif
> >  
> > +if cc.has_header_symbol('locale.h', 'newlocale', prefix : '#define _GNU_SOURCE')
> > +    config_h.set('HAVE_NEWLOCALE', 1)
> > +endif
> > +
> >  if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOURCE')
> >      config_h.set('HAVE_SECURE_GETENV', 1)
> >  endif
> > diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
> > index 4a239427a4d9..ac3e1311995e 100644
> > --- a/src/libcamera/base/utils.cpp
> > +++ b/src/libcamera/base/utils.cpp
> > @@ -464,6 +464,8 @@ std::string toAscii(const std::string &str)
> >   * \a b
> >   */
> >  
> > +#if HAVE_NEWLOCALE
> > +
> >  namespace {
> >  
> >  /*
> > @@ -493,6 +495,8 @@ Locale cLocale("C");
> >  
> >  } /* namespace */
> >  
> > +#endif /* HAVE_NEWLOCALE */
> > +
> >  /**
> >   * \brief Convert a string to a double independently of the current locale
> >   * \param[in] nptr The string to convert
> > @@ -506,7 +510,15 @@ Locale cLocale("C");
> >   */
> >  double strtod(const char *__restrict nptr, char **__restrict endptr)
> >  {
> > +#if HAVE_NEWLOCALE
> >         return strtod_l(nptr, endptr, cLocale.locale());
> > +#else
> > +       /*
> > +        * If the libc implementation doesn't provide locale object support,
> > +        * assume that strtod() is locale-independent.
> > +        */
> > +       return strtod(nptr, endptr);
> > +#endif
> >  }
> >  
> >  } /* namespace utils */
Jacopo Mondi Jan. 10, 2023, 8:13 a.m. UTC | #3
Hi Laurent

On Sun, Jan 08, 2023 at 11:43:57PM +0200, Laurent Pinchart via libcamera-devel wrote:
> Not all C libraries include support for locale objects (locale_t) and
> the strto*_l() family of functions. A notable example is uClibc that can
> be compiled with a hardcoded "C" locale. Compilation then fails as the
> newlocale(), freelocale() and strtod_l() functions are not defined.
>
> Fix the compilation breakage by checking for the availability of
> newlocale(), and fall back to strtod() when the function isn't
> available. This may not lead to the correct result if support for locale
> objects isn't available and the locale isn't hardcoded to "C", but that
> is such a corner case that we will likely never encounter it.
>
> Fixes: e8ae254970cf ("libcamera: yaml_parser: Use C locale")
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  meson.build                  |  4 ++++
>  src/libcamera/base/utils.cpp | 12 ++++++++++++
>  2 files changed, 16 insertions(+)
>
> diff --git a/meson.build b/meson.build
> index e86673dd5c0c..7dcd34d3e6b3 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -72,6 +72,10 @@ if cc.has_header_symbol('unistd.h', 'issetugid')
>      config_h.set('HAVE_ISSETUGID', 1)
>  endif
>
> +if cc.has_header_symbol('locale.h', 'newlocale', prefix : '#define _GNU_SOURCE')
> +    config_h.set('HAVE_NEWLOCALE', 1)
> +endif
> +
>  if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOURCE')
>      config_h.set('HAVE_SECURE_GETENV', 1)
>  endif
> diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
> index 4a239427a4d9..ac3e1311995e 100644
> --- a/src/libcamera/base/utils.cpp
> +++ b/src/libcamera/base/utils.cpp
> @@ -464,6 +464,8 @@ std::string toAscii(const std::string &str)
>   * \a b
>   */
>
> +#if HAVE_NEWLOCALE
> +

Just bikeshedding on the NEWLOCALE symbol. "New" to implies there's an
old vs new version, while you're just here checking that locale is
supported. Maybe just HAVE_LOCALE ?

Apart from this:
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

Thanks
  j

>  namespace {
>
>  /*
> @@ -493,6 +495,8 @@ Locale cLocale("C");
>
>  } /* namespace */
>
> +#endif /* HAVE_NEWLOCALE */
> +
>  /**
>   * \brief Convert a string to a double independently of the current locale
>   * \param[in] nptr The string to convert
> @@ -506,7 +510,15 @@ Locale cLocale("C");
>   */
>  double strtod(const char *__restrict nptr, char **__restrict endptr)
>  {
> +#if HAVE_NEWLOCALE
>  	return strtod_l(nptr, endptr, cLocale.locale());
> +#else
> +	/*
> +	 * If the libc implementation doesn't provide locale object support,
> +	 * assume that strtod() is locale-independent.
> +	 */
> +	return strtod(nptr, endptr);
> +#endif
>  }
>
>  } /* namespace utils */
> --
> Regards,
>
> Laurent Pinchart
>
Laurent Pinchart Jan. 10, 2023, 8:50 a.m. UTC | #4
Hi Jacopo,

On Tue, Jan 10, 2023 at 09:13:53AM +0100, Jacopo Mondi wrote:
> On Sun, Jan 08, 2023 at 11:43:57PM +0200, Laurent Pinchart via libcamera-devel wrote:
> > Not all C libraries include support for locale objects (locale_t) and
> > the strto*_l() family of functions. A notable example is uClibc that can
> > be compiled with a hardcoded "C" locale. Compilation then fails as the
> > newlocale(), freelocale() and strtod_l() functions are not defined.
> >
> > Fix the compilation breakage by checking for the availability of
> > newlocale(), and fall back to strtod() when the function isn't
> > available. This may not lead to the correct result if support for locale
> > objects isn't available and the locale isn't hardcoded to "C", but that
> > is such a corner case that we will likely never encounter it.
> >
> > Fixes: e8ae254970cf ("libcamera: yaml_parser: Use C locale")
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  meson.build                  |  4 ++++
> >  src/libcamera/base/utils.cpp | 12 ++++++++++++
> >  2 files changed, 16 insertions(+)
> >
> > diff --git a/meson.build b/meson.build
> > index e86673dd5c0c..7dcd34d3e6b3 100644
> > --- a/meson.build
> > +++ b/meson.build
> > @@ -72,6 +72,10 @@ if cc.has_header_symbol('unistd.h', 'issetugid')
> >      config_h.set('HAVE_ISSETUGID', 1)
> >  endif
> >
> > +if cc.has_header_symbol('locale.h', 'newlocale', prefix : '#define _GNU_SOURCE')
> > +    config_h.set('HAVE_NEWLOCALE', 1)
> > +endif
> > +
> >  if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOURCE')
> >      config_h.set('HAVE_SECURE_GETENV', 1)
> >  endif
> > diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
> > index 4a239427a4d9..ac3e1311995e 100644
> > --- a/src/libcamera/base/utils.cpp
> > +++ b/src/libcamera/base/utils.cpp
> > @@ -464,6 +464,8 @@ std::string toAscii(const std::string &str)
> >   * \a b
> >   */
> >
> > +#if HAVE_NEWLOCALE
> > +
> 
> Just bikeshedding on the NEWLOCALE symbol. "New" to implies there's an
> old vs new version, while you're just here checking that locale is
> supported. Maybe just HAVE_LOCALE ?

It comes directly from the name of the function being checked in
meson.build, newlocale(). I could replace that with a check for the
locale_t type and use HAVE_LOCALE_T if preferred.

> Apart from this:
> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> 
> >  namespace {
> >
> >  /*
> > @@ -493,6 +495,8 @@ Locale cLocale("C");
> >
> >  } /* namespace */
> >
> > +#endif /* HAVE_NEWLOCALE */
> > +
> >  /**
> >   * \brief Convert a string to a double independently of the current locale
> >   * \param[in] nptr The string to convert
> > @@ -506,7 +510,15 @@ Locale cLocale("C");
> >   */
> >  double strtod(const char *__restrict nptr, char **__restrict endptr)
> >  {
> > +#if HAVE_NEWLOCALE
> >  	return strtod_l(nptr, endptr, cLocale.locale());
> > +#else
> > +	/*
> > +	 * If the libc implementation doesn't provide locale object support,
> > +	 * assume that strtod() is locale-independent.
> > +	 */
> > +	return strtod(nptr, endptr);
> > +#endif
> >  }
> >
> >  } /* namespace utils */

Patch
diff mbox series

diff --git a/meson.build b/meson.build
index e86673dd5c0c..7dcd34d3e6b3 100644
--- a/meson.build
+++ b/meson.build
@@ -72,6 +72,10 @@  if cc.has_header_symbol('unistd.h', 'issetugid')
     config_h.set('HAVE_ISSETUGID', 1)
 endif
 
+if cc.has_header_symbol('locale.h', 'newlocale', prefix : '#define _GNU_SOURCE')
+    config_h.set('HAVE_NEWLOCALE', 1)
+endif
+
 if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOURCE')
     config_h.set('HAVE_SECURE_GETENV', 1)
 endif
diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
index 4a239427a4d9..ac3e1311995e 100644
--- a/src/libcamera/base/utils.cpp
+++ b/src/libcamera/base/utils.cpp
@@ -464,6 +464,8 @@  std::string toAscii(const std::string &str)
  * \a b
  */
 
+#if HAVE_NEWLOCALE
+
 namespace {
 
 /*
@@ -493,6 +495,8 @@  Locale cLocale("C");
 
 } /* namespace */
 
+#endif /* HAVE_NEWLOCALE */
+
 /**
  * \brief Convert a string to a double independently of the current locale
  * \param[in] nptr The string to convert
@@ -506,7 +510,15 @@  Locale cLocale("C");
  */
 double strtod(const char *__restrict nptr, char **__restrict endptr)
 {
+#if HAVE_NEWLOCALE
 	return strtod_l(nptr, endptr, cLocale.locale());
+#else
+	/*
+	 * If the libc implementation doesn't provide locale object support,
+	 * assume that strtod() is locale-independent.
+	 */
+	return strtod(nptr, endptr);
+#endif
 }
 
 } /* namespace utils */