cpr icon indicating copy to clipboard operation
cpr copied to clipboard

cpr fails to compile when using submodules or FetchContent and Clang 11 on a Raspberry Pi 3B+

Open LunarWatcher opened this issue 1 year ago • 4 comments

Description

cpr detects my Raspberry Pi 3B+ as ARMv6, which is wrong. 3B+ is ARMv8, but because Raspbian didn't support 64 bit back when I installed it, the OS identifies it as ARMv7l. The correct identification for this device is consequently ARMv7/ARMv7l, which is also how the device self-identifies in all commands.

lscpu, lsb_release, and uname all pick up armv7 or armv7l. Additionally, one of the errors are about not supporting NEON, which from what I can tell, my CPU most certainly does. I assume this is down to how Clang interacts with the wrong architecture picked up by presumably cpr. That said, the compile errors seem to suggest this is CPR's fault (CMake seems to do the identifying, and zlib uses make), though I'm not entirely sure if it is, much less how.

Relevant output from cmake ..:

-- Arch detected: 'armv6'
-- Basearch of 'armv6' has been detected as: 'arm'

Conan picks up ARMv7, and forces its use across the board. GCC 8 also successfully compiles it for some reason, so not sure why Clang is an outlier here. It's definitely related to the incorrect ARMv6 identification, as Clang 11 when using Conan compiles everything correctly, without complaints.

Also not sure if this is in any way relevant:

CMake Warning at src/CMakeLists.txt:5 (add_executable):                                                                                                                                                                                        
Cannot generate a safe runtime search path for target cprtest because files                                                                                                                                                                  
in some directories may conflict with libraries in implicit directories:                                                                                                                                                                                                                                                                                                                                                                                                                    
runtime library [libz.so.1] in /usr/lib/arm-linux-gnueabihf may be hidden by files in:                                                                                                                                                         
/home/pi/build/cprtest/build/bin                                                                                                                                                                                                                                                                                                                                                                                                                                                      
Some of these libraries may not be found correctly.

Expected Behavior

cpr should compile

Actual Behavior

cpr doesn't compile

$ make
[  1%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/adler32.c.o
[  1%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/chunkset.c.o
[  2%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/compare258.c.o
[  2%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/compress.c.o
[  3%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/crc32.c.o
[  3%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/crc32_comb.c.o
[  4%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/deflate.c.o
[  4%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/deflate_fast.c.o
[  4%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/deflate_medium.c.o
[  5%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/deflate_quick.c.o
[  5%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/deflate_slow.c.o
[  6%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/functable.c.o
[  6%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/infback.c.o
[  7%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/inffast.c.o
[  7%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/inflate.c.o
[  8%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/inftrees.c.o
[  8%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/insert_string.c.o
[  9%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/trees.c.o
[  9%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/uncompr.c.o
[ 10%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/zutil.c.o
[ 10%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/arch/arm/armfeature.c.o
[ 11%] Building C object _deps/zlib-build/CMakeFiles/zlib.dir/arch/arm/adler32_neon.c.o
In file included from /home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:11:
/usr/lib/llvm-11/lib/clang/11.0.1/include/arm_neon.h:32:2: error: "NEON support not enabled"
#error "NEON support not enabled"
 ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:23:5: error: unknown type name 'uint32x2_t'; did you mean 'uint32_t'?
    uint32x2_t adacc2, s2acc2, as;
    ^~~~~~~~~~
    uint32_t
/usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h:26:20: note: 'uint32_t' declared here
typedef __uint32_t uint32_t;
                   ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:24:5: error: unknown type name 'uint8x16_t'; did you mean 'uint16_t'?
    uint8x16_t t0 = vld1q_u8(taps), t1 = vld1q_u8(taps + 16);
    ^~~~~~~~~~
    uint16_t
/usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h:25:20: note: 'uint16_t' declared here
typedef __uint16_t uint16_t;
                   ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:24:21: warning: implicit declaration of function 'vld1q_u8' is invalid in C99 [-Wimplicit-function-declaration]
    uint8x16_t t0 = vld1q_u8(taps), t1 = vld1q_u8(taps + 16);
                    ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:26:5: error: unknown type name 'uint32x4_t'; did you mean 'uint32_t'?
    uint32x4_t adacc = vdupq_n_u32(0), s2acc = vdupq_n_u32(0);
    ^~~~~~~~~~
    uint32_t
/usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h:26:20: note: 'uint32_t' declared here
typedef __uint32_t uint32_t;
                   ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:26:24: warning: implicit declaration of function 'vdupq_n_u32' is invalid in C99 [-Wimplicit-function-declaration]
    uint32x4_t adacc = vdupq_n_u32(0), s2acc = vdupq_n_u32(0);
                       ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:27:13: warning: implicit declaration of function 'vsetq_lane_u32' is invalid in C99 [-Wimplicit-function-declaration]
    adacc = vsetq_lane_u32(s[0], adacc, 0);
            ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:31:9: error: unknown type name 'uint8x16_t'; did you mean 'uint16_t'?
        uint8x16_t d0 = vld1q_u8(buf), d1 = vld1q_u8(buf + 16);
        ^~~~~~~~~~
        uint16_t
/usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h:25:20: note: 'uint16_t' declared here
typedef __uint16_t uint16_t;
                   ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:32:9: error: unknown type name 'uint16x8_t'; did you mean 'uint16_t'?
        uint16x8_t adler, sum2;
        ^~~~~~~~~~
        uint16_t
/usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h:25:20: note: 'uint16_t' declared here
typedef __uint16_t uint16_t;
                   ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:33:17: warning: implicit declaration of function 'vaddq_u32' is invalid in C99 [-Wimplicit-function-declaration]
        s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 5));
                ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:33:34: warning: implicit declaration of function 'vshlq_n_u32' is invalid in C99 [-Wimplicit-function-declaration]
        s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 5));
                                 ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:34:17: warning: implicit declaration of function 'vpaddlq_u8' is invalid in C99 [-Wimplicit-function-declaration]
        adler = vpaddlq_u8(       d0);
                ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:35:17: warning: implicit declaration of function 'vpadalq_u8' is invalid in C99 [-Wimplicit-function-declaration]
        adler = vpadalq_u8(adler, d1);
                ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:36:16: warning: implicit declaration of function 'vmull_u8' is invalid in C99 [-Wimplicit-function-declaration]
        sum2 = vmull_u8(      vget_low_u8(t0), vget_low_u8(d0));
               ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:36:31: warning: implicit declaration of function 'vget_low_u8' is invalid in C99 [-Wimplicit-function-declaration]
        sum2 = vmull_u8(      vget_low_u8(t0), vget_low_u8(d0));
                              ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:37:16: warning: implicit declaration of function 'vmlal_u8' is invalid in C99 [-Wimplicit-function-declaration]
        sum2 = vmlal_u8(sum2, vget_high_u8(t0), vget_high_u8(d0));
               ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:37:31: warning: implicit declaration of function 'vget_high_u8' is invalid in C99 [-Wimplicit-function-declaration]
        sum2 = vmlal_u8(sum2, vget_high_u8(t0), vget_high_u8(d0));
                              ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:40:17: warning: implicit declaration of function 'vpadalq_u16' is invalid in C99 [-Wimplicit-function-declaration]
        adacc = vpadalq_u16(adacc, adler);
                ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:47:9: error: unknown type name 'uint8x16_t'; did you mean 'uint16_t'?
        uint8x16_t d0 = vld1q_u8(buf);
        ^~~~~~~~~~
        uint16_t
/usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h:25:20: note: 'uint16_t' declared here
typedef __uint16_t uint16_t;
                   ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:48:9: error: unknown type name 'uint16x8_t'; did you mean 'uint16_t'?
        uint16x8_t adler, sum2;
        ^~~~~~~~~~
        uint16_t
/usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h:25:20: note: 'uint16_t' declared here
typedef __uint16_t uint16_t;
                   ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:49:17: warning: implicit declaration of function 'vaddq_u32' is invalid in C99 [-Wimplicit-function-declaration]
        s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 4));
                ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:49:34: warning: implicit declaration of function 'vshlq_n_u32' is invalid in C99 [-Wimplicit-function-declaration]
        s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 4));
                                 ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:50:17: warning: implicit declaration of function 'vpaddlq_u8' is invalid in C99 [-Wimplicit-function-declaration]
        adler = vpaddlq_u8(d0);
                ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:51:16: warning: implicit declaration of function 'vmull_u8' is invalid in C99 [-Wimplicit-function-declaration]
        sum2 = vmull_u8(      vget_low_u8(t1), vget_low_u8(d0));
               ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:51:31: warning: implicit declaration of function 'vget_low_u8' is invalid in C99 [-Wimplicit-function-declaration]
        sum2 = vmull_u8(      vget_low_u8(t1), vget_low_u8(d0));
                              ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:52:16: warning: implicit declaration of function 'vmlal_u8' is invalid in C99 [-Wimplicit-function-declaration]
        sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d0));
               ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:52:31: warning: implicit declaration of function 'vget_high_u8' is invalid in C99 [-Wimplicit-function-declaration]
        sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d0));
                              ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:53:17: warning: implicit declaration of function 'vpadalq_u16' is invalid in C99 [-Wimplicit-function-declaration]
        adacc = vpadalq_u16(adacc, adler);
                ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:59:14: warning: implicit declaration of function 'vpadd_u32' is invalid in C99 [-Wimplicit-function-declaration]
    adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc));
             ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:59:24: warning: implicit declaration of function 'vget_low_u32' is invalid in C99 [-Wimplicit-function-declaration]
    adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc));
                       ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:59:45: warning: implicit declaration of function 'vget_high_u32' is invalid in C99 [-Wimplicit-function-declaration]
    adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc));
                                            ^
/home/pi/build/cprtest/build/_deps/zlib-src/arch/arm/adler32_neon.c:62:12: warning: implicit declaration of function 'vget_lane_u32' is invalid in C99 [-Wimplicit-function-declaration]
    s[0] = vget_lane_u32(as, 0);
           ^
24 warnings and 8 errors generated.
make[2]: *** [_deps/zlib-build/CMakeFiles/zlib.dir/build.make:355: _deps/zlib-build/CMakeFiles/zlib.dir/arch/arm/adler32_neon.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:234: _deps/zlib-build/CMakeFiles/zlib.dir/all] Error 2
make: *** [Makefile:149: all] Error 2

Possible Fix

N/A

Steps to Reproduce

  1. Code: CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(cprtest)

set (CMAKE_CXX_STANDARD 11)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

include(FetchContent)
FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git
                         GIT_TAG 871ed52d350214a034f6ef8a3b8f51c5ce1bd400) # The commit hash for 1.9.0. Replace with the latest from: https://github.com/libcpr/cpr/releases
FetchContent_MakeAvailable(cpr)

add_subdirectory(src)
# vim:ft=cmake

src/CMakeLists.txt:

set (SOURCE_FILES
    cprtest/Main.cpp
)

add_executable(cprtest ${SOURCE_FILES})
target_include_directories(cprtest PUBLIC ./)

target_link_libraries(cprtest PUBLIC cpr::cpr)

# vim:ft=cmake

src/cprtest/Main.cpp:

#include<iostream>

#include <cpr/cpr.h>

int main() {
    std::cout << "Hello, World!" << std::endl;
}
  1. mkdir build && cd build && cmake .., with CXX=clang++ CC=clang, where clang++ and clang refer to Clang 11
  2. Lo and behold as the build explodes

Your Environment

  • Version used: 1.9.0, 1.9.1, master
  • Where did you get it from (e.g. conan, vcpkg, master, ...): master/1.9.1 (as a submodule), 1.9.0 (FetchContent). 1.9.0 via Conan compiles fine
  • Operating System and version: Raspbian (Debian Buster 10)
  • Link to a small example: the code is included in the issue; this is about the cpr dependency itself, and not an execution error in either my or cpr's non-buildscript code.

LunarWatcher avatar Aug 13 '22 15:08 LunarWatcher

Thanks for your well written issue! It looks to me like this is an issue of zlib-ng, we are using as a faster drop in replacement for curl. Until I have time to investigate this deeper, you can disable zlib support via the following options:

https://github.com/libcpr/cpr/blob/ab6ec0be798c511552e389276fe8e36e408ddf99/CMakeLists.txt#L215-L223

COM8 avatar Aug 14 '22 08:08 COM8

Good to know. Conan still picks the right version though, so rolling with it for now (though I'm gonna drop conan again for this particular project as soon as I can; trying to keep it minimal).

Thanks for mentioning zlib-ng; did some quick investigation on my own, and tracked it down to zlib-ng's CMake script:

https://github.com/zlib-ng/zlib-ng/blob/a406284705a462939c7a634119884a31b87d6af9/cmake/detect-arch.cmake#L21-L46

On that note, I have noticed some shockingly inconsistent use of macros in a different project of mine. I used a nasty hack where I treat __ARM__ as ARMv7, though I cannot recommend that to any large-scale application that may actually run on ARMv6.

I dug back into the macros defined by the compiler, just on the off chance it's relevant. It most definitely is:

❯  echo | g++ -dM -E -x c++ - | grep -i arm                                                                                                                                                                                                  
#define __ARM_SIZEOF_WCHAR_T 4                                                                                                                                                                                                               
#define __ARM_FEATURE_SAT 1                                                                                                                                                                                                                  
#define __ARM_ARCH_ISA_ARM 1                                                                                                                                                                                                                 
#define __ARMEL__ 1                                                                                                                                                                                                                          
#define __ARM_FEATURE_UNALIGNED 1                                                                                                                                                                                                            
#define __ARM_FP 12                                                                                                                                                                                                                          
#define __ARM_SIZEOF_MINIMAL_ENUM 4                                                                                                                                                                                                          
#define __ARM_PCS_VFP 1                                                                                                                                                                                                                      
#define __ARM_FEATURE_LDREX 4                                                                                                                                                                                                                
#define __ARM_FEATURE_QBIT 1                                                                                                                                                                                                                 
#define __ARM_ARCH_6__ 1                                                                                                                                                                                                                     
#define __ARM_32BIT_STATE 1                                                                                                                                                                                                                  
#define __ARM_FEATURE_CLZ 1                                                                                                                                                                                                                  
#define __ARM_ARCH_ISA_THUMB 1                                                                                                                                                                                                               
#define __ARM_ARCH 6                                                                                                                                                                                                                         
#define __arm__ 1                                                                                                                                                                                                                            
#define __ARM_FEATURE_SIMD32 1                                                                                                                                                                                                               
#define __ARM_FEATURE_COPROC 15                                                                                                                                                                                                              
#define __ARM_EABI__ 1                                                                                                                                                                                                                       
#define __ARM_FEATURE_DSP 1
❯ echo | clang++ -dM -E -x c++ - | grep -i arm
#define __ARMEL__ 1
#define __ARM_32BIT_STATE 1
#define __ARM_ACLE 200
#define __ARM_ARCH 6
#define __ARM_ARCH_6K__ 1
#define __ARM_ARCH_ISA_ARM 1
#define __ARM_ARCH_ISA_THUMB 1
#define __ARM_EABI__ 1
#define __ARM_FEATURE_CLZ 1
#define __ARM_FEATURE_DSP 1
#define __ARM_FEATURE_LDREX 0xf
#define __ARM_FEATURE_QBIT 1
#define __ARM_FEATURE_SAT 1
#define __ARM_FEATURE_SIMD32 1
#define __ARM_FP 0xc
#define __ARM_FP16_ARGS 1
#define __ARM_FP16_FORMAT_IEEE 1
#define __ARM_PCS 1
#define __ARM_PCS_VFP 1
#define __ARM_SIZEOF_MINIMAL_ENUM 4
#define __ARM_SIZEOF_WCHAR_T 4
#define __ARM_VFPV2__ 1
#define __arm 1
#define __arm__ 1

I assumed ARMv7 was undefined for some reason, or that I was missing a macro for ARMv7l when I messed around in similar territory. I guess I should've checked.

I compiled Clang 11 on my own IIRC, but GCC 8 was pre-installed, and I haven't touched it. I cannot comprehend why it reports ARMv6 through built-in macros in both when it clearly isn't. I do have the stock version of libstdc++-8-dev as well. To add insult to injury... this is by design? Incredibly annoying

LunarWatcher avatar Aug 14 '22 14:08 LunarWatcher

And the rabbit hole goes deeper.

I installed Raspbian when it was still running on a Debian 10 base without 64 bit support. Not only has 64 bit support since been released, but an update to Raspbian's base has been made, that I can't seem to get without a full reinstall. My version of Raspbian is now classified as the legacy version as well.

So, it might not be worth putting much dev effort into fixing this. It's easier for me to bite the bullet and upgrade when I'm back to being near my RPi in around a week. With this version of Raspbian being a legacy version, there's not going to be (m)any new installs. The problem might be gone in the new version of Raspbian, including in the 32 bit version. I'm unable to test this at the moment, however. I also can't tell which arch the OS is compiled for from Raspberry Pi's website, though it does say the non-legacy 32 bit version supports all devices, so might still be compiled for ARMv6? There's a single image variant on their website, so that does seem plausible. If that's the case, fixing it is suddenly relevant again

LunarWatcher avatar Aug 14 '22 15:08 LunarWatcher

Interesting... Later this week I will try to play around with it on my own since a own quite a couple of PIs, so I can quickly evaluate stuff there.

COM8 avatar Aug 15 '22 08:08 COM8