diff mbox series

[for-4.15] autoconf: check endian.h include path

Message ID 20210204093833.91190-1-roger.pau@citrix.com (mailing list archive)
State New
Headers show
Series [for-4.15] autoconf: check endian.h include path | expand

Commit Message

Roger Pau Monné Feb. 4, 2021, 9:38 a.m. UTC
Introduce an autoconf macro to check for the include path of certain
headers that can be different between OSes.

Use such macro to find the correct path for the endian.h header, and
modify the users of endian.h to use the output of such check.

Suggested-by: Ian Jackson <iwj@xenproject.org>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
Please re-run autogen after applying.

The biggest risk for this would be some kind of configure or build
failure, and we should be able to catch it in either osstest or the
gitlab build tests.
---
 m4/header.m4                                      | 13 +++++++++++++
 tools/configure.ac                                |  3 +++
 tools/libs/guest/xg_dom_decompress_unsafe_lzo1x.c |  2 +-
 tools/libs/guest/xg_dom_decompress_unsafe_xz.c    |  2 +-
 tools/libs/guest/xg_dom_decompress_unsafe_zstd.c  |  2 +-
 tools/xenstore/include/xenstore_state.h           |  6 +-----
 6 files changed, 20 insertions(+), 8 deletions(-)
 create mode 100644 m4/header.m4

Comments

Jan Beulich Feb. 4, 2021, 9:46 a.m. UTC | #1
On 04.02.2021 10:38, Roger Pau Monne wrote:
> --- a/tools/configure.ac
> +++ b/tools/configure.ac
> @@ -74,6 +74,7 @@ m4_include([../m4/ax_compare_version.m4])
>  m4_include([../m4/paths.m4])
>  m4_include([../m4/systemd.m4])
>  m4_include([../m4/golang.m4])
> +m4_include([../m4/header.m4])
>  
>  AX_XEN_EXPAND_CONFIG()
>  
> @@ -517,4 +518,6 @@ AC_ARG_ENABLE([pvshim],
>  ])
>  AC_SUBST(pvshim)
>  
> +AX_FIND_HEADER([INCLUDE_ENDIAN_H], [endian.h sys/endian.h])

Instead of a new macro, can't you use AC_CHECK_HEADERS()?

I'm also not certain about the order of checks - what if both
exist?

Jan
Roger Pau Monné Feb. 4, 2021, 9:59 a.m. UTC | #2
On Thu, Feb 04, 2021 at 10:46:58AM +0100, Jan Beulich wrote:
> On 04.02.2021 10:38, Roger Pau Monne wrote:
> > --- a/tools/configure.ac
> > +++ b/tools/configure.ac
> > @@ -74,6 +74,7 @@ m4_include([../m4/ax_compare_version.m4])
> >  m4_include([../m4/paths.m4])
> >  m4_include([../m4/systemd.m4])
> >  m4_include([../m4/golang.m4])
> > +m4_include([../m4/header.m4])
> >  
> >  AX_XEN_EXPAND_CONFIG()
> >  
> > @@ -517,4 +518,6 @@ AC_ARG_ENABLE([pvshim],
> >  ])
> >  AC_SUBST(pvshim)
> >  
> > +AX_FIND_HEADER([INCLUDE_ENDIAN_H], [endian.h sys/endian.h])
> 
> Instead of a new macro, can't you use AC_CHECK_HEADERS()?

AC_CHECK_HEADERS doesn't do what we want here: it will instead produce
a HAVE_header-file define for each header on the list that's present,
and the action-if-found doesn't get passed the path of the found
header according to the documentation.

Here I want the variable to be set to the include path of the first
header on the list that's present on the system.

> I'm also not certain about the order of checks - what if both
> exist?

With my macro the first one will be picked.

Thanks, Roger.
Jan Beulich Feb. 4, 2021, 10:13 a.m. UTC | #3
On 04.02.2021 10:59, Roger Pau Monné wrote:
> On Thu, Feb 04, 2021 at 10:46:58AM +0100, Jan Beulich wrote:
>> On 04.02.2021 10:38, Roger Pau Monne wrote:
>>> --- a/tools/configure.ac
>>> +++ b/tools/configure.ac
>>> @@ -74,6 +74,7 @@ m4_include([../m4/ax_compare_version.m4])
>>>  m4_include([../m4/paths.m4])
>>>  m4_include([../m4/systemd.m4])
>>>  m4_include([../m4/golang.m4])
>>> +m4_include([../m4/header.m4])
>>>  
>>>  AX_XEN_EXPAND_CONFIG()
>>>  
>>> @@ -517,4 +518,6 @@ AC_ARG_ENABLE([pvshim],
>>>  ])
>>>  AC_SUBST(pvshim)
>>>  
>>> +AX_FIND_HEADER([INCLUDE_ENDIAN_H], [endian.h sys/endian.h])
>>
>> Instead of a new macro, can't you use AC_CHECK_HEADERS()?
> 
> AC_CHECK_HEADERS doesn't do what we want here: it will instead produce
> a HAVE_header-file define for each header on the list that's present,
> and the action-if-found doesn't get passed the path of the found
> header according to the documentation.
> 
> Here I want the variable to be set to the include path of the first
> header on the list that's present on the system.

I was thinking of

#if defined(HAVE_SYS_ENDIAN_H)
# include <sys/endian.h>
#elif defined(HAVE_ENDIAN_H)
# include <endian.h>
#else
# error ...
#endif

>> I'm also not certain about the order of checks - what if both
>> exist?
> 
> With my macro the first one will be picked.

And which one is to be the first one? IOW how likely is it that
on a system having both the first one is what we're after vs
the second one?

Jan
Roger Pau Monné Feb. 4, 2021, 10:21 a.m. UTC | #4
On Thu, Feb 04, 2021 at 11:13:43AM +0100, Jan Beulich wrote:
> On 04.02.2021 10:59, Roger Pau Monné wrote:
> > On Thu, Feb 04, 2021 at 10:46:58AM +0100, Jan Beulich wrote:
> >> On 04.02.2021 10:38, Roger Pau Monne wrote:
> >>> --- a/tools/configure.ac
> >>> +++ b/tools/configure.ac
> >>> @@ -74,6 +74,7 @@ m4_include([../m4/ax_compare_version.m4])
> >>>  m4_include([../m4/paths.m4])
> >>>  m4_include([../m4/systemd.m4])
> >>>  m4_include([../m4/golang.m4])
> >>> +m4_include([../m4/header.m4])
> >>>  
> >>>  AX_XEN_EXPAND_CONFIG()
> >>>  
> >>> @@ -517,4 +518,6 @@ AC_ARG_ENABLE([pvshim],
> >>>  ])
> >>>  AC_SUBST(pvshim)
> >>>  
> >>> +AX_FIND_HEADER([INCLUDE_ENDIAN_H], [endian.h sys/endian.h])
> >>
> >> Instead of a new macro, can't you use AC_CHECK_HEADERS()?
> > 
> > AC_CHECK_HEADERS doesn't do what we want here: it will instead produce
> > a HAVE_header-file define for each header on the list that's present,
> > and the action-if-found doesn't get passed the path of the found
> > header according to the documentation.
> > 
> > Here I want the variable to be set to the include path of the first
> > header on the list that's present on the system.
> 
> I was thinking of
> 
> #if defined(HAVE_SYS_ENDIAN_H)
> # include <sys/endian.h>
> #elif defined(HAVE_ENDIAN_H)
> # include <endian.h>
> #else
> # error ...
> #endif

I think having to replicate this logic in all places that include
endian.h is cumbersome.

> >> I'm also not certain about the order of checks - what if both
> >> exist?
> > 
> > With my macro the first one will be picked.
> 
> And which one is to be the first one? IOW how likely is it that
> on a system having both the first one is what we're after vs
> the second one?

Not sure, but the same will happen with your proposal above: in your
chunk sys/endian.h will be picked over endian.h. If we think that's
the right precedence I can adjust AX_FIND_HEADER to be:

AX_FIND_HEADER([INCLUDE_ENDIAN_H], [sys/endian.h endian.h])

Which will achieve the same as your proposed snipped.

I can also add a comment to the macro that the first match will be the
one that gets set.

Thanks, Roger.
Jan Beulich Feb. 4, 2021, 10:32 a.m. UTC | #5
On 04.02.2021 11:21, Roger Pau Monné wrote:
> On Thu, Feb 04, 2021 at 11:13:43AM +0100, Jan Beulich wrote:
>> On 04.02.2021 10:59, Roger Pau Monné wrote:
>>> On Thu, Feb 04, 2021 at 10:46:58AM +0100, Jan Beulich wrote:
>>>> On 04.02.2021 10:38, Roger Pau Monne wrote:
>>>>> --- a/tools/configure.ac
>>>>> +++ b/tools/configure.ac
>>>>> @@ -74,6 +74,7 @@ m4_include([../m4/ax_compare_version.m4])
>>>>>  m4_include([../m4/paths.m4])
>>>>>  m4_include([../m4/systemd.m4])
>>>>>  m4_include([../m4/golang.m4])
>>>>> +m4_include([../m4/header.m4])
>>>>>  
>>>>>  AX_XEN_EXPAND_CONFIG()
>>>>>  
>>>>> @@ -517,4 +518,6 @@ AC_ARG_ENABLE([pvshim],
>>>>>  ])
>>>>>  AC_SUBST(pvshim)
>>>>>  
>>>>> +AX_FIND_HEADER([INCLUDE_ENDIAN_H], [endian.h sys/endian.h])
>>>>
>>>> Instead of a new macro, can't you use AC_CHECK_HEADERS()?
>>>
>>> AC_CHECK_HEADERS doesn't do what we want here: it will instead produce
>>> a HAVE_header-file define for each header on the list that's present,
>>> and the action-if-found doesn't get passed the path of the found
>>> header according to the documentation.
>>>
>>> Here I want the variable to be set to the include path of the first
>>> header on the list that's present on the system.
>>
>> I was thinking of
>>
>> #if defined(HAVE_SYS_ENDIAN_H)
>> # include <sys/endian.h>
>> #elif defined(HAVE_ENDIAN_H)
>> # include <endian.h>
>> #else
>> # error ...
>> #endif
> 
> I think having to replicate this logic in all places that include
> endian.h is cumbersome.

Right - I would further encapsulate this in a local header.

>>>> I'm also not certain about the order of checks - what if both
>>>> exist?
>>>
>>> With my macro the first one will be picked.
>>
>> And which one is to be the first one? IOW how likely is it that
>> on a system having both the first one is what we're after vs
>> the second one?
> 
> Not sure, but the same will happen with your proposal above: in your
> chunk sys/endian.h will be picked over endian.h.

Oh, sure - the two points are entirely orthogonal. And I'm
also not certain at all whether checking sys/ first is
better, equal, or worse. I simply don't know what the
conventions are. As a result I wonder whether we shouldn't
check that the header provides what we need.

Jan

> If we think that's
> the right precedence I can adjust AX_FIND_HEADER to be:
> 
> AX_FIND_HEADER([INCLUDE_ENDIAN_H], [sys/endian.h endian.h])
> 
> Which will achieve the same as your proposed snipped.
> 
> I can also add a comment to the macro that the first match will be the
> one that gets set.
> 
> Thanks, Roger.
>
Roger Pau Monné Feb. 4, 2021, 10:48 a.m. UTC | #6
On Thu, Feb 04, 2021 at 11:32:41AM +0100, Jan Beulich wrote:
> On 04.02.2021 11:21, Roger Pau Monné wrote:
> > On Thu, Feb 04, 2021 at 11:13:43AM +0100, Jan Beulich wrote:
> >> On 04.02.2021 10:59, Roger Pau Monné wrote:
> >>> On Thu, Feb 04, 2021 at 10:46:58AM +0100, Jan Beulich wrote:
> >>>> On 04.02.2021 10:38, Roger Pau Monne wrote:
> >>>>> --- a/tools/configure.ac
> >>>>> +++ b/tools/configure.ac
> >>>>> @@ -74,6 +74,7 @@ m4_include([../m4/ax_compare_version.m4])
> >>>>>  m4_include([../m4/paths.m4])
> >>>>>  m4_include([../m4/systemd.m4])
> >>>>>  m4_include([../m4/golang.m4])
> >>>>> +m4_include([../m4/header.m4])
> >>>>>  
> >>>>>  AX_XEN_EXPAND_CONFIG()
> >>>>>  
> >>>>> @@ -517,4 +518,6 @@ AC_ARG_ENABLE([pvshim],
> >>>>>  ])
> >>>>>  AC_SUBST(pvshim)
> >>>>>  
> >>>>> +AX_FIND_HEADER([INCLUDE_ENDIAN_H], [endian.h sys/endian.h])
> >>>>
> >>>> Instead of a new macro, can't you use AC_CHECK_HEADERS()?
> >>>
> >>> AC_CHECK_HEADERS doesn't do what we want here: it will instead produce
> >>> a HAVE_header-file define for each header on the list that's present,
> >>> and the action-if-found doesn't get passed the path of the found
> >>> header according to the documentation.
> >>>
> >>> Here I want the variable to be set to the include path of the first
> >>> header on the list that's present on the system.
> >>
> >> I was thinking of
> >>
> >> #if defined(HAVE_SYS_ENDIAN_H)
> >> # include <sys/endian.h>
> >> #elif defined(HAVE_ENDIAN_H)
> >> # include <endian.h>
> >> #else
> >> # error ...
> >> #endif
> > 
> > I think having to replicate this logic in all places that include
> > endian.h is cumbersome.
> 
> Right - I would further encapsulate this in a local header.

IMO encapsulating in configure achieves the same purpose.

> >>>> I'm also not certain about the order of checks - what if both
> >>>> exist?
> >>>
> >>> With my macro the first one will be picked.
> >>
> >> And which one is to be the first one? IOW how likely is it that
> >> on a system having both the first one is what we're after vs
> >> the second one?
> > 
> > Not sure, but the same will happen with your proposal above: in your
> > chunk sys/endian.h will be picked over endian.h.
> 
> Oh, sure - the two points are entirely orthogonal. And I'm
> also not certain at all whether checking sys/ first is
> better, equal, or worse. I simply don't know what the
> conventions are.

I'm not sure either. For the specific case of endian.h I would
expect only one to be present, and I think we should first check for
top level (ie: endian.h) before checking for subfolders (ie: sys/), as
top level should have precedence.

I really don't have a strong opinion either way, so if there's an
argument to do it the other way around that would also be fine.

> As a result I wonder whether we shouldn't
> check that the header provides what we need.

Right, that would be a step forward I think. I'm not opposed to it,
but I also don't have plans to implement myself. Just checking the
path seem to be fine for the purpose here.

It could be expanded to also use AC_CHECK_DECLS to check for specific
declarations once the header path is found.

Thanks, Roger.
Ian Jackson Feb. 4, 2021, 11:34 a.m. UTC | #7
Roger Pau Monne writes ("[PATCH for-4.15] autoconf: check endian.h include path"):
> Introduce an autoconf macro to check for the include path of certain
> headers that can be different between OSes.
> 
> Use such macro to find the correct path for the endian.h header, and
> modify the users of endian.h to use the output of such check.
> 
> Suggested-by: Ian Jackson <iwj@xenproject.org>
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>

Reviewed-by: Ian Jackson <iwj@xenproject.org>

> Please re-run autogen after applying.
> 
> The biggest risk for this would be some kind of configure or build
> failure, and we should be able to catch it in either osstest or the
> gitlab build tests.

Thanks.  I agree.

Release-Acked-by: Ian Jackson <iwj@xenproject.org>
Ian Jackson Feb. 4, 2021, 11:37 a.m. UTC | #8
Roger Pau Monné writes ("Re: [PATCH for-4.15] autoconf: check endian.h include path"):
> On Thu, Feb 04, 2021 at 11:32:41AM +0100, Jan Beulich wrote:
> > On 04.02.2021 11:21, Roger Pau Monné wrote:
> > > I think having to replicate this logic in all places that include
> > > endian.h is cumbersome.
> > 
> > Right - I would further encapsulate this in a local header.
> 
> IMO encapsulating in configure achieves the same purpose.

I like the way Roger has done it.

> > >> And which one is to be the first one? IOW how likely is it that
> > >> on a system having both the first one is what we're after vs
> > >> the second one?
> > > 
> > > Not sure, but the same will happen with your proposal above: in your
> > > chunk sys/endian.h will be picked over endian.h.
> > 
> > Oh, sure - the two points are entirely orthogonal. And I'm
> > also not certain at all whether checking sys/ first is
> > better, equal, or worse. I simply don't know what the
> > conventions are.
> 
> I'm not sure either. For the specific case of endian.h I would
> expect only one to be present, and I think we should first check for
> top level (ie: endian.h) before checking for subfolders (ie: sys/), as
> top level should have precedence.
> 
> I really don't have a strong opinion either way, so if there's an
> argument to do it the other way around that would also be fine.

I don't think it matters much here, but in general I would say that
checking the more general location first is a good idea.  Checking the
more specific location might in some cases find us a file that's
actually an implementation detail.

Ian.
diff mbox series

Patch

diff --git a/m4/header.m4 b/m4/header.m4
new file mode 100644
index 0000000000..81d1d65194
--- /dev/null
+++ b/m4/header.m4
@@ -0,0 +1,13 @@ 
+AC_DEFUN([AX_FIND_HEADER], [
+ax_found=0
+m4_foreach_w([header], $2, [
+    AS_IF([test "$ax_found" = "0"], [
+        AC_CHECK_HEADER(header, [
+            AC_DEFINE($1, [<header>], [Header path for $1])
+            ax_found=1])
+    ])
+])
+AS_IF([test "$ax_found" = "0"], [
+    AC_MSG_ERROR([No header found from list $2])
+])
+])
diff --git a/tools/configure.ac b/tools/configure.ac
index 5b328700e0..3a3e7b4b2b 100644
--- a/tools/configure.ac
+++ b/tools/configure.ac
@@ -74,6 +74,7 @@  m4_include([../m4/ax_compare_version.m4])
 m4_include([../m4/paths.m4])
 m4_include([../m4/systemd.m4])
 m4_include([../m4/golang.m4])
+m4_include([../m4/header.m4])
 
 AX_XEN_EXPAND_CONFIG()
 
@@ -517,4 +518,6 @@  AC_ARG_ENABLE([pvshim],
 ])
 AC_SUBST(pvshim)
 
+AX_FIND_HEADER([INCLUDE_ENDIAN_H], [endian.h sys/endian.h])
+
 AC_OUTPUT()
diff --git a/tools/libs/guest/xg_dom_decompress_unsafe_lzo1x.c b/tools/libs/guest/xg_dom_decompress_unsafe_lzo1x.c
index a4f8ebd42d..e58c1b95ed 100644
--- a/tools/libs/guest/xg_dom_decompress_unsafe_lzo1x.c
+++ b/tools/libs/guest/xg_dom_decompress_unsafe_lzo1x.c
@@ -1,7 +1,7 @@ 
 #include <stdio.h>
 #include <stdlib.h>
 #include <inttypes.h>
-#include <endian.h>
+#include INCLUDE_ENDIAN_H
 #include <stdint.h>
 
 #include "xg_private.h"
diff --git a/tools/libs/guest/xg_dom_decompress_unsafe_xz.c b/tools/libs/guest/xg_dom_decompress_unsafe_xz.c
index ff6824b38d..fc48198741 100644
--- a/tools/libs/guest/xg_dom_decompress_unsafe_xz.c
+++ b/tools/libs/guest/xg_dom_decompress_unsafe_xz.c
@@ -1,5 +1,5 @@ 
 #include <stdio.h>
-#include <endian.h>
+#include INCLUDE_ENDIAN_H
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdint.h>
diff --git a/tools/libs/guest/xg_dom_decompress_unsafe_zstd.c b/tools/libs/guest/xg_dom_decompress_unsafe_zstd.c
index 52558d2ffc..01eafaaaa6 100644
--- a/tools/libs/guest/xg_dom_decompress_unsafe_zstd.c
+++ b/tools/libs/guest/xg_dom_decompress_unsafe_zstd.c
@@ -1,5 +1,5 @@ 
 #include <stdio.h>
-#include <endian.h>
+#include INCLUDE_ENDIAN_H
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdint.h>
diff --git a/tools/xenstore/include/xenstore_state.h b/tools/xenstore/include/xenstore_state.h
index f7e4da2b2c..ae0d053c8f 100644
--- a/tools/xenstore/include/xenstore_state.h
+++ b/tools/xenstore/include/xenstore_state.h
@@ -21,11 +21,7 @@ 
 #ifndef XENSTORE_STATE_H
 #define XENSTORE_STATE_H
 
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-#include <sys/endian.h>
-#else
-#include <endian.h>
-#endif
+#include INCLUDE_ENDIAN_H
 #include <sys/types.h>
 
 #ifndef htobe32