google/fruit

Can't Build as static library for ARM Cortex-M (arm-none-eabi)

RonAmihai opened this issue · 7 comments

I'm trying to build the library for usage in embedded Cortex-M project (Zephyr RTOS).
Using Ubuntu 18.04 (WSL), the latest version of Fruit (v3.4.0) & arm-none-eabi-g++ (9.2.1) compiler.

I've followed the instructions mentioned in this issue.

CMake generation goes fine with the following output:

$ LDFLAGS=--specs=nosys.specs cmake -H. -B_build -DCMAKE_TOOLCHAIN_FILE=arm-toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=False -DFRUIT_USES_BOOST=False

-- The C compiler identification is GNU 9.2.1
-- The CXX compiler identification is GNU 9.2.1
-- Check for working C compiler: /opt/toolchains/gcc-arm-none-eabi/bin/arm-none-eabi-gcc
-- Check for working C compiler: /opt/toolchains/gcc-arm-none-eabi/bin/arm-none-eabi-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /opt/toolchains/gcc-arm-none-eabi/bin/arm-none-eabi-g++
-- Check for working CXX compiler: /opt/toolchains/gcc-arm-none-eabi/bin/arm-none-eabi-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test FRUIT_TRIVIAL_SOURCE_COMPILES
-- Performing Test FRUIT_TRIVIAL_SOURCE_COMPILES - Success
-- Performing Test FRUIT_HAS_CLANG_ARBITRARY_OVERLOAD_RESOLUTION_BUG
-- Performing Test FRUIT_HAS_CLANG_ARBITRARY_OVERLOAD_RESOLUTION_BUG - Failed
-- Performing Test FRUIT_HAS_HAS_TRIVIAL_COPY
-- Performing Test FRUIT_HAS_HAS_TRIVIAL_COPY - Success
-- Performing Test FRUIT_HAS_IS_TRIVIALLY_COPYABLE
-- Performing Test FRUIT_HAS_IS_TRIVIALLY_COPYABLE - Success
-- Performing Test FRUIT_HAS_MAX_ALIGN_T
-- Performing Test FRUIT_HAS_MAX_ALIGN_T - Success
-- Performing Test FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE
-- Performing Test FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE - Success
-- Performing Test FRUIT_HAS_STD_IS_TRIVIALLY_COPY_CONSTRUCTIBLE
-- Performing Test FRUIT_HAS_STD_IS_TRIVIALLY_COPY_CONSTRUCTIBLE - Success
-- Performing Test FRUIT_HAS_STD_MAX_ALIGN_T
-- Performing Test FRUIT_HAS_STD_MAX_ALIGN_T - Success
-- Performing Test FRUIT_HAS_TYPEID
-- Performing Test FRUIT_HAS_TYPEID - Success
-- Performing Test FRUIT_HAS_CONSTEXPR_TYPEID
-- Performing Test FRUIT_HAS_CONSTEXPR_TYPEID - Success
-- Performing Test FRUIT_HAS_CXA_DEMANGLE
-- Performing Test FRUIT_HAS_CXA_DEMANGLE - Success
-- Performing Test FRUIT_HAS_ALWAYS_INLINE_ATTRIBUTE
-- Performing Test FRUIT_HAS_ALWAYS_INLINE_ATTRIBUTE - Success
-- Performing Test FRUIT_HAS_FORCEINLINE
-- Performing Test FRUIT_HAS_FORCEINLINE - Failed
-- Performing Test FRUIT_HAS_ATTRIBUTE_DEPRECATED
-- Performing Test FRUIT_HAS_ATTRIBUTE_DEPRECATED - Success
-- Performing Test FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED
-- Performing Test FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED - Success
-- Performing Test FRUIT_HAS_DECLSPEC_DEPRECATED
-- Performing Test FRUIT_HAS_DECLSPEC_DEPRECATED - Failed
-- Performing Test FRUIT_HAS_MSVC_ASSUME
-- Performing Test FRUIT_HAS_MSVC_ASSUME - Failed
-- Performing Test FRUIT_HAS_BUILTIN_UNREACHABLE
-- Performing Test FRUIT_HAS_BUILTIN_UNREACHABLE - Success
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/c/Users/ronam/Downloads/fruit-3.4.0/_build

However, build fails with the following output:

$ cmake --build _build

Scanning dependencies of target fruit
[ 14%] Building CXX object src/CMakeFiles/fruit.dir/memory_pool.cpp.obj
[ 14%] Building CXX object src/CMakeFiles/fruit.dir/binding_normalization.cpp.obj
In file included from /mnt/c/Users/ronam/Downloads/fruit-3.4.0/src/binding_normalization.cpp:27:
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.h:137:8: error: 'recursive_mutex' in namespace std' does not name a type
137 | std::recursive_mutex mutex;
| ^~~~~~~~~~~~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.h:29:1: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
28 | #include
+++ |+#include
29 |
In file included from /mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.h:284,
from /mnt/c/Users/ronam/Downloads/fruit-3.4.0/src/binding_normalization.cpp:27:
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h: In member function 'fruit::impl::InjectorStorage::RemoveAnnotations fruit::impl::InjectorStorage::get()':
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:234:24: error: 'recursive_mutex' is not a member of 'std'
234 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~~~~~~~~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:32:1: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
31 | #include <fruit/impl/injector/injector_storage.h>
+++ |+#include
32 |
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:234:24: error: 'recursive_mutex' is not a member of 'std'
234 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~~~~~~~~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:234:24: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:234:39: error: template argument 1 is invalid
234 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:234:46: error: 'mutex' was not declared in this scope
234 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h: In member function 'T fruit::impl::InjectorStorage::get(fruit::impl::SemistaticGraph<fruit::impl::TypeId, fruit::impl::NormalizedBinding>::node_iterator)':
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:242:24: error: 'recursive_mutex' is not a member of 'std'
242 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~~~~~~~~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:242:24: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:242:24: error: 'recursive_mutex' is not a member of 'std'
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:242:24: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:242:39: error: template argument 1 is invalid
242 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:242:46: error: 'mutex' was not declared in this scope
242 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h: In member function 'fruit::impl::InjectorStorage::RemoveAnnotations* fruit::impl::InjectorStorage::unsafeGet()':
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:272:24: error: 'recursive_mutex' is not a member of 'std'
272 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~~~~~~~~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:272:24: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:272:24: error: 'recursive_mutex' is not a member of 'std'
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:272:24: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:272:39: error: template argument 1 is invalid
272 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:272:46: error: 'mutex' was not declared in this scope
272 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h: In member function 'const std::vector<typename fruit::impl::meta::DoEval<fruit::impl::meta::RemoveAnnotations(fruit::impl::meta::Type)>::type::type*>& fruit::impl::InjectorStorage::getMultibindings()':
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:292:24: error: 'recursive_mutex' is not a member of 'std'
292 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~~~~~~~~~~~
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:292:24: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:292:24: error: 'recursive_mutex' is not a member of 'std'
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:292:24: note: 'std::recursive_mutex' is defined in header ''; did you forget to '#include '?
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:292:39: error: template argument 1 is invalid
292 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^
/mnt/c/Users/ronam/Downloads/fruit-3.4.0/include/fruit/impl/injector/injector_storage.defn.h:292:46: error: 'mutex' was not declared in this scope
292 | std::lock_guardstd::recursive_mutex lock(mutex);
| ^~~~~
At global scope:
cc1plus: warning: unrecognized command line option '-Wno-unknown-warning-option'
src/CMakeFiles/fruit.dir/build.make:75: recipe for target 'src/CMakeFiles/fruit.dir/binding_normalization.cpp.obj' failed
make[2]: *** [src/CMakeFiles/fruit.dir/binding_normalization.cpp.obj] Error 1
CMakeFiles/Makefile2:115: recipe for target 'src/CMakeFiles/fruit.dir/all' failed
make[1]: *** [src/CMakeFiles/fruit.dir/all] Error 2
Makefile:129: recipe for target 'all' failed
make: *** [all] Error 2

Building with Fruit v3.1.1 & cherry-pick 155b57e (as mentioned in the above issue) works fine.

"
On Ubuntu 15.10 and above, if your build fails because the cross-compiler does not seem to support C++11 threads (you get errors such as "httpserver.cpp:69:10: error: ‘mutex’ in namespace ‘std’ does not name a type) you may have to select the posix versions of gcc-mingw-w64 and g++-mingw-w64:

  |   |  
  |   | sudo update-alternatives --config x86_64-w64-mingw32-gcc
  |   | sudo update-alternatives --config x86_64-w64-mingw32-g++
  |   |  
  |   | And select the posix version of the compiler.

"

From https://github.com/bitcoin/bitcoin/pull/8653/files

Does that work for you?

"

On Ubuntu 15.10 and above, if your build fails because the cross-compiler does not seem to support C++11 threads (you get errors such as "httpserver.cpp:69:10: error: ‘mutex’ in namespace ‘std’ does not name a type) you may have to select the posix versions of gcc-mingw-w64 and g++-mingw-w64:
  |   |  
  |   | sudo update-alternatives --config x86_64-w64-mingw32-gcc
  |   | sudo update-alternatives --config x86_64-w64-mingw32-g++
  |   |  
  |   | And select the posix version of the compiler.

"

From https://github.com/bitcoin/bitcoin/pull/8653/files

Does that work for you?

I didn't manage to understand how to change the POSIX version of ARM-NONE-EABI's GCC/G++.
(I've installed ARM-NONE-EABI with the official binaries)

It also seems that ARM-NONE-EABI compilers support only single thread-model.

This is the compiler's details if it helps:
$ arm-none-eabi-g++ -v

Using built-in specs.
COLLECT_GCC=arm-none-eabi-g++
COLLECT_LTO_WRAPPER=/opt/toolchains/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/9.2.1/lto-wrapper
Target: arm-none-eabi
Configured with: /mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/src/gcc/configure --target=arm-none-eabi --prefix=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/install-native --libexecdir=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/install-native/lib --infodir=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/install-native/share/doc/gcc-arm-none-eabi/info --mandir=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/install-native/share/doc/gcc-arm-none-eabi/man --htmldir=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/install-native/share/doc/gcc-arm-none-eabi/html --pdfdir=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/install-native/share/doc/gcc-arm-none-eabi/pdf --enable-languages=c,c++ --enable-plugins --disable-decimal-float --disable-libffi --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-tls --with-gnu-as --with-gnu-ld --with-newlib --with-headers=yes --with-python-dir=share/gcc-arm-none-eabi --with-sysroot=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/install-native/arm-none-eabi --build=x86_64-linux-gnu --host=x86_64-linux-gnu --with-gmp=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/build-native/host-libs/usr --with-mpfr=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/build-native/host-libs/usr --with-mpc=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/build-native/host-libs/usr --with-isl=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/build-native/host-libs/usr --with-libelf=/mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/build-native/host-libs/usr --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --with-pkgversion='GNU Tools for Arm Embedded Processors 9-2019-q4-major' --with-multilib-list=rmprofile
Thread model: single
gcc version 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] (GNU Tools for Arm Embedded Processors 9-2019-q4-major)

The following links may be related:

I've added the following lines to Fruit's top CMakeLists.txt:
set(FRUIT_ADDITIONAL_COMPILE_FLAGS "${FRUIT_ADDITIONAL_CXX_FLAGS} -ffreestanding -flto")
set(FRUIT_ADDITIONAL_LINKER_FLAGS "${FRUIT_ADDITIONAL_LINKER_FLAGS} --specs=nosys.specs -flto -ffreestanding -nostdlib")

Didn't help much... Same results

tt4g commented

I think this is because the C++ STL std::recursive_mutex does not exist in the mutex header.
But I don't know why your build target doesn't support it.

Can you install gcc-arm-none-eabi using apt-get?
That's what I used when trying to reproduce the other issue.
Using that compiler should allow you to cross-compile Fruit (and binaries using it) for ARM.

As you mentioned (and as the -v output above shows) the compiler binary you're using was built disabling multi-threading functionality (among other things), which makes it not C++11-compliant (std::recursive_mutex is part of the standard) and therefore not compatible with Fruit.

Can you install gcc-arm-none-eabi using apt-get?
That's what I used when trying to reproduce the other issue.
Using that compiler should allow you to cross-compile Fruit (and binaries using it) for ARM.

As you mentioned (and as the -v output above shows) the compiler binary you're using was built disabling multi-threading functionality (among other things), which makes it not C++11-compliant (std::recursive_mutex is part of the standard) and therefore not compatible with Fruit.

It did help, Thank you.