tc-cpp-is-true doesn't work correctly when building with clang. This leads to problems when ebuilds get the wrong result, in my case I'm seeing a build failure in dev-python/m2crypto-0.31.0-r2 when cross-compiling for ARM with clang. That setup takes effort to reproduce though, so I'll spare you the details but provide an artificial repro: # CC=/usr/lib/llvm/8/bin/clang bash -x -c '. eclass/toolchain-funcs.eclass; tc-cpp-is-true "defined(__FILE__)"; echo $?' + . eclass/toolchain-funcs.eclass ++ [[ -z '' ]] ++ _TOOLCHAIN_FUNCS_ECLASS=1 ++ inherit multilib eclass/toolchain-funcs.eclass: line 18: inherit: command not found + tc-cpp-is-true 'defined(__FILE__)' + local 'CONDITION=defined(__FILE__)' + shift +++ tc-getTARGET_CPP +++ [[ -n '' ]] +++ tc-getCPP +++ tc-getPROG CPP '/usr/lib/llvm/8/bin/clang -E' +++ _tc-getPROG CHOST CPP '/usr/lib/llvm/8/bin/clang -E' +++ local tuple=CHOST +++ local v var vars=CPP +++ prog=($3) +++ local prog +++ var=CPP +++ for v in ${vars} +++ [[ -n '' ]] +++ local search= +++ [[ -n '' ]] +++ [[ -z '' ]] +++ [[ -n '' ]] +++ [[ -n '' ]] +++ export 'CPP=/usr/lib/llvm/8/bin/clang -E' +++ CPP='/usr/lib/llvm/8/bin/clang -E' +++ echo '/usr/lib/llvm/8/bin/clang -E' ++ /usr/lib/llvm/8/bin/clang -E -P - + local 'RESULT= true' + [[ true == true ]] + echo 1 1 Note the newline in the RESULT variable which ultimately leads to the wrong result. Here's the difference in behavior between gcc and clang: # echo -e "#ifdef __FILE__\ntrue\n#endif" | gcc -E -P - true # echo -e "#ifdef __FILE__\ntrue\n#endif" | /usr/lib/llvm/8/bin/clang -E -P - true Reproducible: Always Steps to Reproduce: CC=/usr/lib/llvm/8/bin/clang bash -x -c '. eclass/toolchain-funcs.eclass; tc-cpp-is-true "defined(__FILE__)"; echo $?' Actual Results: Last line of the output is 1. Expected Results: Should print 0 in the last line since __FILE__ is always defined.
Proposed fix: https://github.com/gentoo/gentoo/pull/13497
Yeah, I agree it's a bug. Reliance on whitespace has always been the problem of these macros. It works even worse when you pass something like -ggdb3 as part of CC: $ echo -e "#ifdef __FILE__\ntrue\n#endif" | gcc -ggdb3 -E -P - ... #define __STDC_IEC_559_COMPLEX__ 1 #define __STDC_ISO_10646__ 201706L true Arguably it should almost never happen but in practice it's convenient sometimes. I wounder if it would be better to rely on exit code of preprocessor itself and inject the error there. Something like: $ clang -ggdb3 -E -P - <<< $(echo -e "#ifdef __FILE1__\ntrue\n#else\n#error Nooooooo\n#endif") >/dev/null 2>&1 && echo ok $ clang -ggdb3 -E -P - <<< $(echo -e "#ifdef __FILE__\ntrue\n#else\n#error Nooooooo\n#endif") >/dev/null 2>&1 && echo ok ok
Also, we used to grep for ^true$ to avoid the case of -ggdb3: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=f3f183dd42463b42d1aac27debb04c75c616dae7
Updated the fix to use preprocessor exit status as suggested on the pull request: https://github.com/gentoo/gentoo/commit/2ff07a14c230f2e225bc605e9d93e6031e169a34
The bug has been closed via the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=8f02136721af40dd89a09101504750fb28f8142e commit 8f02136721af40dd89a09101504750fb28f8142e Author: Sergei Trofimovich <slyfox@gentoo.org> AuthorDate: 2019-11-06 22:40:18 +0000 Commit: Sergei Trofimovich <slyfox@gentoo.org> CommitDate: 2019-11-06 22:44:34 +0000 eclass/tests/toolchain-funcs.sh add test for 'tc-cpp-is-true()' With patch from bug #698912 reverted we observe failures as: * Testing tc-cpp-is-true (gcc, defined) ... [ ok ] * Testing tc-cpp-is-true (gcc, not defined) ... [ ok ] * Testing tc-cpp-is-true (gcc, defined on -ggdb3) ... [ !! ] * Testing tc-cpp-is-true (clang, defined) ... [ !! ] * Testing tc-cpp-is-true (clang, not defined) ... [ ok ] * Testing tc-cpp-is-true (clang, defined on -ggdb3) ... [ !! ] Closes: https://bugs.gentoo.org/698912 Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> eclass/tests/toolchain-funcs.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) Additionally, it has been referenced in the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=3ef6b33339da7bb04afd77e1bc5db011b02d658a commit 3ef6b33339da7bb04afd77e1bc5db011b02d658a Author: Mattias Nissler <mnissler@chromium.org> AuthorDate: 2019-11-04 10:11:20 +0000 Commit: Sergei Trofimovich <slyfox@gentoo.org> CommitDate: 2019-11-06 22:44:33 +0000 toolchain-funcs.eclass: fix tc-cpp-is-true() to work with clang Clang's preprocessor likes to output a leading newline, which makes the comparison always fail. GCC generates additional output with certain flags (e.g. -ggdb3) as well. Hence, switch the test to trigger a preprocessor error when the condition is not true and examine the exit code. Bug: https://bugs.gentoo.org/698912 Signed-off-by: Mattias Nissler <mnissler@chromium.org> Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> eclass/toolchain-funcs.eclass | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)