Message ID | 20191101092724.7650-2-nicolas.iooss@m4x.org (mailing list archive) |
---|---|
State | Rejected |
Headers | show |
Series | [1/3] Makefile: fix cleaning files that starts with "-" | expand |
On 11/1/19 5:27 AM, Nicolas Iooss wrote: > libselinux currently uses "gcc -aux-info" in order to generate glue code > for its Python bindings that throws an exception when a function returns > a negative integer value. This causes issues when another compiler than > gcc is used (such as clang or icc), as option -aux-info is specific to > gcc. > > Replace "gcc -aux-info" with a command that parses the content of header > files using "sed". As this is more fragile (because the declaration of > functions is not normalized), add a new target to the Makefile in order > to test that the new method does not produce different results with > "make CC=gcc test". > > When reverting commit cfe487409307 ("libselinux: mark all exported > function "extern""), "make test" now fails as expected: > > bash -e exception.sh test > Error ensuring that all exported functions that return an int are handled by exception.sh. > Here are functions that were not found in "gcc -aux-info" but that were collected by "sed": > Here are functions in "gcc -aux-info" that may be missing "extern" in header file: > selinuxfs_exists > make: *** [Makefile:202: test] Error 1 > > Original thread: https://lore.kernel.org/selinux/20191012172357.GB19655@imap.altlinux.org/T/#ma78bd7fe71fb5784387a8c0cebd867d6c02ee6e4 I'm not excited about moving to a more fragile method of generating this glue code. Would it perhaps suffice for us to pre-generate the files and keep them in-tree (or package them as part of the tar file distributions) so that downstream users without gcc can just use the generated files? > > Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org> > Cc: Michael Shigorin <mike@altlinux.org> > --- > libselinux/Makefile | 1 + > libselinux/src/Makefile | 5 ++++- > libselinux/src/exception.sh | 38 +++++++++++++++++++++++++++++++------ > 3 files changed, 37 insertions(+), 7 deletions(-) > > diff --git a/libselinux/Makefile b/libselinux/Makefile > index 16531fe95bf5..c0ae884f8ede 100644 > --- a/libselinux/Makefile > +++ b/libselinux/Makefile > @@ -67,3 +67,4 @@ clean-rubywrap: > $(MAKE) -C src clean-rubywrap $@ > > test: > + $(MAKE) -C src test > diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile > index 63d6b0eda270..c12230a17b1d 100644 > --- a/libselinux/src/Makefile > +++ b/libselinux/src/Makefile > @@ -198,7 +198,10 @@ clean: clean-pywrap clean-rubywrap > distclean: clean > rm -f $(GENERATED) $(SWIGFILES) > > +test: > + bash -e exception.sh test > + > indent: > ../../scripts/Lindent $(filter-out $(GENERATED),$(wildcard *.[ch])) > > -.PHONY: all clean clean-pywrap clean-rubywrap pywrap rubywrap swigify install install-pywrap install-rubywrap distclean > +.PHONY: all clean clean-pywrap clean-rubywrap pywrap rubywrap swigify install install-pywrap install-rubywrap distclean test indent > diff --git a/libselinux/src/exception.sh b/libselinux/src/exception.sh > index d6c8c71713ad..adbb632c2f04 100755 > --- a/libselinux/src/exception.sh > +++ b/libselinux/src/exception.sh > @@ -1,11 +1,12 @@ > +#!/bin/bash -e > function except() { > -case $1 in > +case "$1" in > selinux_file_context_cmp) # ignore > ;; > *) > echo " > %exception $1 { > - \$action > + \$action > if (result < 0) { > PyErr_SetFromErrno(PyExc_OSError); > SWIG_fail; > @@ -15,10 +16,35 @@ echo " > ;; > esac > } > -if ! ${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h > + > +if [ $# -eq 1 ] && [ "$1" = "test" ] > then > - # clang does not support -aux-info so fall back to gcc > - gcc -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h > + # Ensure that "gcc -aux-info" produces the same list of functions as the sed command. > + # The main difference between these way of producing the list of exported > + # functions is that "gcc -aux-info" automatically inserts "extern" to all > + # declarations and writes each one on a single line. > + # clang does not support -aux-info, so skip the test if generating the aux file failed. > + if ${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h > + then > + FCT_FROM_AUX="$(awk '/<stdin>.*extern int/ { print $6 }' temp.aux | sort -u)" > + FCT_FROM_SED="$(sed -n 's/^extern \+int \+\([0-9A-Za-z_]\+\) *(.*$/\1/p' < ../include/selinux/selinux.h | sort -u)" > + if [ "$FCT_FROM_AUX" != "$FCT_FROM_SED" ] > + then > + echo >&2 'Error ensuring that all exported functions that return an int are handled by exception.sh.' > + echo >&2 'Here are functions that were not found in "gcc -aux-info" but that were collected by "sed":' > + comm -13 <(echo "$FCT_FROM_AUX") <(echo "$FCT_FROM_SED") > + echo >&2 'Here are functions in "gcc -aux-info" that may be missing "extern" in header file:' > + comm -23 <(echo "$FCT_FROM_AUX") <(echo "$FCT_FROM_SED") > + exit 1 > + fi > + fi > + rm -f -- temp.aux -.o > + exit > fi > -for i in `awk '/<stdin>.*extern int/ { print $6 }' temp.aux`; do except $i ; done > + > +# shellcheck disable=SC2013 > +for i in $(sed -n 's/^extern \+int \+\([0-9A-Za-z_]\+\) *(.*$/\1/p' < ../include/selinux/selinux.h) > +do > + except "$i" > +done > rm -f -- temp.aux -.o >
diff --git a/libselinux/Makefile b/libselinux/Makefile index 16531fe95bf5..c0ae884f8ede 100644 --- a/libselinux/Makefile +++ b/libselinux/Makefile @@ -67,3 +67,4 @@ clean-rubywrap: $(MAKE) -C src clean-rubywrap $@ test: + $(MAKE) -C src test diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile index 63d6b0eda270..c12230a17b1d 100644 --- a/libselinux/src/Makefile +++ b/libselinux/src/Makefile @@ -198,7 +198,10 @@ clean: clean-pywrap clean-rubywrap distclean: clean rm -f $(GENERATED) $(SWIGFILES) +test: + bash -e exception.sh test + indent: ../../scripts/Lindent $(filter-out $(GENERATED),$(wildcard *.[ch])) -.PHONY: all clean clean-pywrap clean-rubywrap pywrap rubywrap swigify install install-pywrap install-rubywrap distclean +.PHONY: all clean clean-pywrap clean-rubywrap pywrap rubywrap swigify install install-pywrap install-rubywrap distclean test indent diff --git a/libselinux/src/exception.sh b/libselinux/src/exception.sh index d6c8c71713ad..adbb632c2f04 100755 --- a/libselinux/src/exception.sh +++ b/libselinux/src/exception.sh @@ -1,11 +1,12 @@ +#!/bin/bash -e function except() { -case $1 in +case "$1" in selinux_file_context_cmp) # ignore ;; *) echo " %exception $1 { - \$action + \$action if (result < 0) { PyErr_SetFromErrno(PyExc_OSError); SWIG_fail; @@ -15,10 +16,35 @@ echo " ;; esac } -if ! ${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h + +if [ $# -eq 1 ] && [ "$1" = "test" ] then - # clang does not support -aux-info so fall back to gcc - gcc -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h + # Ensure that "gcc -aux-info" produces the same list of functions as the sed command. + # The main difference between these way of producing the list of exported + # functions is that "gcc -aux-info" automatically inserts "extern" to all + # declarations and writes each one on a single line. + # clang does not support -aux-info, so skip the test if generating the aux file failed. + if ${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h + then + FCT_FROM_AUX="$(awk '/<stdin>.*extern int/ { print $6 }' temp.aux | sort -u)" + FCT_FROM_SED="$(sed -n 's/^extern \+int \+\([0-9A-Za-z_]\+\) *(.*$/\1/p' < ../include/selinux/selinux.h | sort -u)" + if [ "$FCT_FROM_AUX" != "$FCT_FROM_SED" ] + then + echo >&2 'Error ensuring that all exported functions that return an int are handled by exception.sh.' + echo >&2 'Here are functions that were not found in "gcc -aux-info" but that were collected by "sed":' + comm -13 <(echo "$FCT_FROM_AUX") <(echo "$FCT_FROM_SED") + echo >&2 'Here are functions in "gcc -aux-info" that may be missing "extern" in header file:' + comm -23 <(echo "$FCT_FROM_AUX") <(echo "$FCT_FROM_SED") + exit 1 + fi + fi + rm -f -- temp.aux -.o + exit fi -for i in `awk '/<stdin>.*extern int/ { print $6 }' temp.aux`; do except $i ; done + +# shellcheck disable=SC2013 +for i in $(sed -n 's/^extern \+int \+\([0-9A-Za-z_]\+\) *(.*$/\1/p' < ../include/selinux/selinux.h) +do + except "$i" +done rm -f -- temp.aux -.o
libselinux currently uses "gcc -aux-info" in order to generate glue code for its Python bindings that throws an exception when a function returns a negative integer value. This causes issues when another compiler than gcc is used (such as clang or icc), as option -aux-info is specific to gcc. Replace "gcc -aux-info" with a command that parses the content of header files using "sed". As this is more fragile (because the declaration of functions is not normalized), add a new target to the Makefile in order to test that the new method does not produce different results with "make CC=gcc test". When reverting commit cfe487409307 ("libselinux: mark all exported function "extern""), "make test" now fails as expected: bash -e exception.sh test Error ensuring that all exported functions that return an int are handled by exception.sh. Here are functions that were not found in "gcc -aux-info" but that were collected by "sed": Here are functions in "gcc -aux-info" that may be missing "extern" in header file: selinuxfs_exists make: *** [Makefile:202: test] Error 1 Original thread: https://lore.kernel.org/selinux/20191012172357.GB19655@imap.altlinux.org/T/#ma78bd7fe71fb5784387a8c0cebd867d6c02ee6e4 Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org> Cc: Michael Shigorin <mike@altlinux.org> --- libselinux/Makefile | 1 + libselinux/src/Makefile | 5 ++++- libselinux/src/exception.sh | 38 +++++++++++++++++++++++++++++++------ 3 files changed, 37 insertions(+), 7 deletions(-)