termux-packages icon indicating copy to clipboard operation
termux-packages copied to clipboard

libc++ cmath math functions not found because of -isystem $PREFIX/include added by CMake

Open joakim-noah opened this issue 7 years ago • 21 comments

Nice work switching everything over to libc++, I've been recompiling llvm and the latest ldc to use it, mostly no problems so far. However, there is an older pure C++ version of ldc that we maintain and it has a problem compiling a C++ file that calls some llvm headers that ultimately invoke cmath:

In file included from /data/data/com.termux/files/home/src/ldc/dmd2/mars.h:70:
In file included from /data/data/com.termux/files/home/src/llvm-4.0.1.src/include/llvm/ADT/Triple.h:13:
In file included from /data/data/com.termux/files/home/src/llvm-4.0.1.src/include/llvm/ADT/Twine.h:13:
In file included from /data/data/com.termux/files/home/src/llvm-4.0.1.src/include/llvm/ADT/SmallVector.h:20:
In file included from /data/data/com.termux/files/home/src/llvm-4.0.1.src/include/llvm/Support/MathExtras.h:18:
In file included from /data/data/com.termux/files/home/src/llvm-4.0.1.src/include/llvm/Support/SwapByteOrder.h:19:
In file included from /data/data/com.termux/files/home/src/llvm-4.0.1.src/build/include/llvm/Support/DataTypes.h:33:
/data/data/com.termux/files/usr/bin/../include/c++/v1/cmath:319:9: error: no
      member named 'isgreater' in the global namespace
using ::isgreater;
      ~~^                                                                       /data/data/com.termux/files/usr/bin/../include/c++/v1/cmath:320:9: error: no
      member named 'isgreaterequal' in the global namespace                     using ::isgreaterequal;
      ~~^
/data/data/com.termux/files/usr/bin/../include/c++/v1/cmath:321:9: error: no
      member named 'isless' in the global namespace
using ::isless;
      ~~^                                                                       /data/data/com.termux/files/usr/bin/../include/c++/v1/cmath:322:9: error: no
      member named 'islessequal' in the global namespace
using ::islessequal;
      ~~^
/data/data/com.termux/files/usr/bin/../include/c++/v1/cmath:323:9: error: no
      member named 'islessgreater' in the global namespace                      using ::islessgreater;
      ~~^                                                                       /data/data/com.termux/files/usr/bin/../include/c++/v1/cmath:324:9: error: no
      member named 'isunordered' in the global namespace
using ::isunordered;
      ~~^
/data/data/com.termux/files/usr/bin/../include/c++/v1/cmath:325:9: error: no
      member named 'isunordered' in the global namespace                        using ::isunordered;
      ~~^
11 errors generated.

Tracking this down, I found that the CXX_INCLUDES generated by CMake has this definition, removing it fixes the problem:

-isystem /data/data/com.termux/files/usr/include

I can't find much info on how CXX_INCLUDES is generated. What's weird is that I don't see that particular -isystem flag for ldc 1.3 when compiling in Termux, so CMake seems to be behaving differently there.

I can reproduce with this sample file compiled in Termux:

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    double number, squareRoot;
    cout << "Enter a number: ";
    cin >> number;

    // sqrt() is a library function to calculate square root
    squareRoot = sqrt(number);
    cout << "Square root of " << number << " = " << squareRoot;
    return 0;
}

Normal compilation, clang++ foo.cpp, works, but this doesn't:

clang++ -isystem /data/data/com.termux/files/usr/include foo.cpp

I'm not sure if that should work or if CMake shouldn't be adding that flag, let me know.

joakim-noah avatar Jul 18 '17 11:07 joakim-noah

yeah for c++ the first include should be include/c++/4.9.0 or include/c++/v1 or some variation. What can occur is that c++ includes in same dir as include. Cmake is changing the first include dir to onclude. Before we changed to libc++_shared cmake doing this likely had no effect so you wouldn't notice as it would find the right headers either first or second time round.

Then again i could be wrong...

its-pointless avatar Jul 18 '17 11:07 its-pointless

Yeah, @its-pointless got it. It would try to get these functions from $PREFIX/include/c++/v1/math.h normally, but with -isystem $PREFIX/include appended, it's picking up the other math.h from there first. I'll dig into why CMake is adding that extra -isystem and see if it can be removed.

joakim-noah avatar Jul 18 '17 17:07 joakim-noah

Does the recent update to cmake 3.9 improve things?

fornwall avatar Jul 20 '17 22:07 fornwall

No, no difference with CMake 3.9.0. My guess is that CMake generates CXX_INCLUDES by searching for header files and adds that directory automatically for the C++ version of ldc, but not for the mostly D version, which doesn't call those header files.

I just tried it on another phone on which I haven't upgraded Termux to use the latest ndk and libc++. It wasn't completely clean, as I didn't have an old CMake installed on there, so I had to install CMake 3.9 and libc++ but not the updated ndk packages, and I didn't hit this error there. Looks like CMake was adding -isystem $PREFIX/include back then, but there was no math.h in the C++ includes for clang to get confused by, only $PREFIX/include/math.h and another $PREFIX/include/libandroid-support/math.h that wasn't picked up.

It appears this issue is a consequence of adding another $PREFIX/include/c++/v1/math.h when switching ndk-stl over to libc++ and how that collides with this -isystem $PREFIX/include that CMake always added, but is only causing a problem now.

joakim-noah avatar Jul 21 '17 12:07 joakim-noah

@joakim-noah Does the patch in https://github.com/android-ndk/ndk/issues/467 fix the problem?

fornwall avatar Jul 23 '17 21:07 fornwall

I don't think it will make a difference, as I originally ran into this problem with CMake 3.8.2 and his problem is that /usr/include of the host system is being pulled into a cross-compile, whereas I'm natively compiling in Termux. I think the cause is having two different math.h headers that are readily available now, I'll look into that.

joakim-noah avatar Jul 24 '17 09:07 joakim-noah

Alright, spent some time tracking this down. The issue is that ldc's CMakeLists.txt finds and includes the directory where libconfig.h is located, which is $PREFIX/include, since it uses the libconfig-dev Termux package. It doesn't happen with the newer ldc 1.3, because an ldc contributor removed the dependency on libconfig by now.

As explained in android-ndk/ndk#452, adding that include_directories in the old C++ version of ldc causes problems because it's placed first in the include search path, which the libc++ cmath doesn't expect (the GNU STL cmath didn't care, which is why it didn't matter before the switch). I tried setting CMAKE_SYSROOT and CMAKE_SYSROOT_COMPILE manually from the command-line, eg cmake -DCMAKE_SYSROOT=/data/data/com.termux/files, and that makes CMake filter out CMAKE_SYSROOT/usr/include from the CXX_INCLUDES it generates, but it then fails because it adds a --sysroot=CMAKE_SYSROOT.

I could work around this issue by simply removing the include_directories line where $PREFIX/include is added, but that's a hack, which will be a pain for others using CMake. Ideally, CMake should be able to filter out this path, we just need to figure out a way to make it do so, which won't break in other ways.

joakim-noah avatar Jul 28 '17 22:07 joakim-noah

I no longer see this issue when compiling llvm but still see it with cmake, can anyone else confirm?

stephengroat avatar Nov 29 '17 17:11 stephengroat

Never saw it with llvm but with ldc, which was pulling in cmath from an llvm header, but yeah, still happening with CMake.

joakim-noah avatar Nov 30 '17 06:11 joakim-noah

I am seeing this issue while trying to compile opencv from their master on github. Removing -isystem /data/data/com.termux/files/usr/include from the compiler command line fixes the issue but I can't find where cmake inserts it. My cmake is 3.10.1.

johncant avatar Dec 25 '17 23:12 johncant

In my case, it is because of this line in the CmakeLists.txt for the older C++ version of the project I'm building, which ends up trying to include /data/data/com.termux/files/usr/include so it can use the libconfig-dev header, as noted above. Commenting out that line fixes the issue for me, as it gets the header anyway.

Ideally, I guess CMake for Termux would be patched to ignore that system directory.

joakim-noah avatar Dec 26 '17 04:12 joakim-noah

I just pushed out an updated version 16-4 of the ndk-stl package, which includes the following diff: https://github.com/termux/termux-packages/blob/master/packages/ndk-stl/math-header.diff

@joakim-noah @johncant @stephengroat @its-pointless Could you try it out and see if it fixes the problem here without causing new ones?

fornwall avatar Jan 03 '18 00:01 fornwall

@fornwall, looks like that error is fixed now:

bash-4.4$ clang++ -isystem /data/data/com.termux/files/usr/include test.cpp
bash-4.4$ ./a.out
Enter a number: ^C

ghost avatar Jan 03 '18 11:01 ghost

@fornwall i'm still getting the error on #1169 build system

[  0%] Building CXX object lib/TableGen/CMakeFiles/LLVMTableGen.dir/Error.cpp.o
Scanning dependencies of target LLVMMC
In file included from /home/builder/.termux-build/libllvm/src/lib/BinaryFormat/Dwarf.cpp:14:
In file included from /home/builder/.termux-build/libllvm/src/include/llvm/BinaryFormat/Dwarf.h:24:
In file included from /home/builder/.termux-build/libllvm/build/include/llvm/Support/DataTypes.h:33:
/home/builder/.termux-build/_lib/16-aarch64-21-v3/lib/gcc/aarch64-linux-android/4.9.x/../../../../include/c++/4.9.x/cmath:313:9: error: no member named 'signbit' in
      the global namespace
using ::signbit;
      ~~^

stephengroat avatar Jan 04 '18 02:01 stephengroat

This patch fixes the issue for me with ldc, but it's just a workaround for the bigger issue: CMake needs to filter out the Termux $PREFIX/include when that include path is given higher priority by a CMakeLists.txt. Otherwise, conflicts other than this math.h one will likely crop up elsewhere.

joakim-noah avatar Jan 05 '18 06:01 joakim-noah

on current system (as of 1/21/2018)

-- The C compiler identification is GNU 7.2.0
-- The CXX compiler identification is GNU 7.2.0
-- The ASM compiler identification is GNU
-- Found assembler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- broken
CMake Error at /home/builder/.termux-build/_cache/cmake-3.10.2/share/cmake-3.10/Modules/CMakeTestCCompiler.cmake:52 (message):
  The C compiler

    "/usr/bin/cc"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: /home/builder/.termux-build/libllvm/host-build/CMakeFiles/CMakeTmp

    Run Build Command:"/usr/bin/make" "cmTC_d6752/fast"
    /usr/bin/make -f CMakeFiles/cmTC_d6752.dir/build.make CMakeFiles/cmTC_d6752.dir/build
    make[1]: Entering directory '/home/builder/.termux-build/libllvm/host-build/CMakeFiles/CMakeTmp'
    Building C object CMakeFiles/cmTC_d6752.dir/testCCompiler.c.o
    /usr/bin/cc    -o CMakeFiles/cmTC_d6752.dir/testCCompiler.c.o   -c /home/builder/.termux-build/libllvm/host-build/CMakeFiles/CMakeTmp/testCCompiler.c
    Linking C executable cmTC_d6752
    /home/builder/.termux-build/_cache/cmake-3.10.2/bin/cmake -E cmake_link_script CMakeFiles/cmTC_d6752.dir/link.txt --verbose=1
    /usr/bin/cc      CMakeFiles/cmTC_d6752.dir/testCCompiler.c.o  -o cmTC_d6752
    collect2: fatal error: ld terminated with signal 11 [Segmentation fault]
    compilation terminated.
    CMakeFiles/cmTC_d6752.dir/build.make:97: recipe for target 'cmTC_d6752' failed
    make[1]: *** [cmTC_d6752] Error 1
    make[1]: Leaving directory '/home/builder/.termux-build/libllvm/host-build/CMakeFiles/CMakeTmp'
    Makefile:126: recipe for target 'cmTC_d6752/fast' failed
    make: *** [cmTC_d6752/fast] Error 2




  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:54 (project)


-- Configuring incomplete, errors occurred!
See also "/home/builder/.termux-build/libllvm/host-build/CMakeFiles/CMakeOutput.log".
See also "/home/builder/.termux-build/libllvm/host-build/CMakeFiles/CMakeError.log".

stephengroat avatar Jan 21 '18 21:01 stephengroat

This broke with the latest NDK update, @its-pointless forgot to move the patch over to ndk-sysroot?

finagolfin avatar Mar 23 '19 14:03 finagolfin

@buttaface #3562 is this the only file that needs to be patched?

its-pointless avatar Mar 24 '19 00:03 its-pointless

i guess this illustrates the benefits of regression testing.

its-pointless avatar Mar 24 '19 00:03 its-pointless

Two math C++ includes, you got them both now.

finagolfin avatar Mar 24 '19 01:03 finagolfin

This issue/PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 18 '21 20:11 stale[bot]

Is this issue still relevant?

twaik avatar Mar 14 '24 18:03 twaik

I don't think so, as I recently removed the workaround for this, 395e1c9a7, and nobody complained.

finagolfin avatar Mar 15 '24 01:03 finagolfin