diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-15 01:34:51 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-15 01:34:51 +0000 |
commit | 609ffbb4dfa85fbc2acaf31a682506aa642520c7 (patch) | |
tree | 61d841dc12f982b1afaf7956176f05df58a9d98c | |
parent | 57123c8a2477a4d99cb68c53d195e9fb428dd535 (diff) | |
parent | dc953bece52b53bac740d46d32c74be1a4cf1b7c (diff) | |
download | google-fruit-android12-mainline-tethering-release.tar.gz |
Snap for 7550844 from dc953bece52b53bac740d46d32c74be1a4cf1b7c to mainline-tethering-releaseandroid-mainline-12.0.0_r95android-mainline-12.0.0_r82android-mainline-12.0.0_r66android-mainline-12.0.0_r53android-mainline-12.0.0_r38android-mainline-12.0.0_r18android-mainline-12.0.0_r125android-mainline-12.0.0_r110aml_tet_311811050android12-mainline-tethering-release
Change-Id: Icf9620c5a00336121c242e2fb08408460e221a62
149 files changed, 2829 insertions, 1374 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..912b302 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.py linguist-detectable=false @@ -16,3 +16,6 @@ bench_results /*.vcxproj.filters /CMakeSettings.json /*.vcxproj.user +/out/build/x64-Debug +/out/build/x64-Debug cxx-17 +/extras/bazel_usage_example/bazel-* diff --git a/.travis.yml b/.travis.yml index 9e1c79f..50045e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,44 +4,65 @@ branches: only: - master -dist: trusty +dist: xenial language: cpp matrix: fast_finish: true include: - compiler: gcc - env: COMPILER=gcc-9 UBUNTU=19.04 TEST=ReleasePlain - install: export OS=linux; export COMPILER='gcc-9'; export UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=gcc-10 UBUNTU=20.10 TEST=ReleasePlain + install: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='gcc-9'; export UBUNTU='19.04'; extras/scripts/postsubmit.sh + script: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.10'; extras/scripts/postsubmit.sh ReleasePlain - compiler: gcc - env: COMPILER=gcc-9 UBUNTU=19.04 TEST=DebugPlain - install: export OS=linux; export COMPILER='gcc-9'; export UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=gcc-10 UBUNTU=20.10 TEST=DebugPlain + install: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='gcc-9'; export UBUNTU='19.04'; extras/scripts/postsubmit.sh + script: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.10'; extras/scripts/postsubmit.sh DebugPlain - compiler: clang - env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=19.04 TEST=ReleasePlain + env: COMPILER=clang-8.0 STL=libstdc++ UBUNTU=20.10 TEST=ReleasePlain + install: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/postsubmit.sh ReleasePlain + - compiler: clang + env: COMPILER=clang-8.0 STL=libstdc++ UBUNTU=20.10 TEST=DebugAsanUbsan + install: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/postsubmit.sh DebugAsanUbsan + - compiler: clang + env: COMPILER=clang-8.0 STL=libstdc++ UBUNTU=20.10 TEST=DebugPlain + install: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/postsubmit.sh DebugPlain + - compiler: clang + env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=20.04 TEST=ReleasePlain install: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh os: linux script: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/postsubmit.sh ReleasePlain + export UBUNTU='20.04'; extras/scripts/postsubmit.sh ReleasePlain - compiler: clang - env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=19.04 TEST=DebugAsanUbsan + env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=20.04 TEST=DebugAsanUbsan install: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh os: linux script: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/postsubmit.sh DebugAsanUbsan + export UBUNTU='20.04'; extras/scripts/postsubmit.sh DebugAsanUbsan - compiler: clang - env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=19.04 TEST=DebugPlain + env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=20.04 TEST=DebugPlain install: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh os: linux script: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/postsubmit.sh DebugPlain + export UBUNTU='20.04'; extras/scripts/postsubmit.sh DebugPlain - compiler: gcc env: COMPILER=bazel UBUNTU=18.04 install: export OS=linux; export COMPILER='bazel'; export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh @@ -49,101 +70,115 @@ matrix: script: export OS=linux; export COMPILER='bazel'; export UBUNTU='18.04'; extras/scripts/postsubmit.sh DebugPlain - compiler: gcc - env: COMPILER=gcc-9 TEST=DebugPlain - install: export OS=osx; export COMPILER='gcc-9'; extras/scripts/travis_ci_install_osx.sh - os: osx - osx_image: xcode11.4 - script: export OS=osx; export COMPILER='gcc-9'; extras/scripts/postsubmit.sh DebugPlain - - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=DebugPlain - install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh - os: osx - osx_image: xcode10.3 - script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugPlain - - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=DebugPlain - install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh - os: osx - osx_image: xcode11.4 - script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugPlain + env: COMPILER=gcc-7 UBUNTU=20.10 TEST=ReleasePlain + install: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.10'; extras/scripts/postsubmit.sh + ReleasePlain + - compiler: gcc + env: COMPILER=gcc-7 UBUNTU=20.10 TEST=DebugAsanUbsan + install: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.10'; extras/scripts/postsubmit.sh + DebugAsanUbsan + - compiler: gcc + env: COMPILER=gcc-10 UBUNTU=20.10 TEST=DebugAsanUbsan + install: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.10'; extras/scripts/postsubmit.sh + DebugAsanUbsan - compiler: clang - env: COMPILER=clang-8.0 STL=libstdc++ UBUNTU=19.04 TEST=ReleasePlainNoPch - install: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=clang-11.0 STL=libstdc++ UBUNTU=20.10 TEST=ReleasePlain + install: export OS=linux; export COMPILER='clang-11.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/postsubmit.sh ReleasePlainNoPch + script: export OS=linux; export COMPILER='clang-11.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/postsubmit.sh ReleasePlain - compiler: clang - env: COMPILER=clang-8.0 STL=libstdc++ UBUNTU=19.04 TEST=DebugAsanUbsanNoPch - install: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=clang-11.0 STL=libstdc++ UBUNTU=20.10 TEST=DebugAsanUbsan + install: export OS=linux; export COMPILER='clang-11.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='clang-8.0'; export STL='libstdc++'; - export UBUNTU='19.04'; extras/scripts/postsubmit.sh DebugAsanUbsanNoPch + script: export OS=linux; export COMPILER='clang-11.0'; export STL='libstdc++'; + export UBUNTU='20.10'; extras/scripts/postsubmit.sh DebugAsanUbsan - compiler: clang - env: COMPILER=clang-8.0 STL=libc++ UBUNTU=19.04 TEST=ReleasePlainNoPch - install: export OS=linux; export COMPILER='clang-8.0'; export STL='libc++'; export - UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=clang-11.0 STL=libc++ UBUNTU=20.10 TEST=ReleasePlain + install: export OS=linux; export COMPILER='clang-11.0'; export STL='libc++'; export + UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='clang-8.0'; export STL='libc++'; export - UBUNTU='19.04'; extras/scripts/postsubmit.sh ReleasePlainNoPch + script: export OS=linux; export COMPILER='clang-11.0'; export STL='libc++'; export + UBUNTU='20.10'; extras/scripts/postsubmit.sh ReleasePlain - compiler: clang - env: COMPILER=clang-8.0 STL=libc++ UBUNTU=19.04 TEST=DebugAsanUbsanNoPch - install: export OS=linux; export COMPILER='clang-8.0'; export STL='libc++'; export - UBUNTU='19.04'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=clang-11.0 STL=libc++ UBUNTU=20.10 TEST=DebugAsanUbsan + install: export OS=linux; export COMPILER='clang-11.0'; export STL='libc++'; export + UBUNTU='20.10'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='clang-11.0'; export STL='libc++'; export + UBUNTU='20.10'; extras/scripts/postsubmit.sh DebugAsanUbsan + - compiler: gcc + env: COMPILER=gcc-7 UBUNTU=20.04 TEST=ReleasePlain + install: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.04'; extras/scripts/postsubmit.sh + ReleasePlain + - compiler: gcc + env: COMPILER=gcc-7 UBUNTU=20.04 TEST=DebugAsanUbsan + install: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='clang-8.0'; export STL='libc++'; export - UBUNTU='19.04'; extras/scripts/postsubmit.sh DebugAsanUbsanNoPch + script: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.04'; extras/scripts/postsubmit.sh + DebugAsanUbsan - compiler: gcc - env: COMPILER=gcc-8 UBUNTU=18.10 TEST=ReleasePlain - install: export OS=linux; export COMPILER='gcc-8'; export UBUNTU='18.10'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=gcc-5 UBUNTU=18.04 TEST=ReleasePlain + install: export OS=linux; export COMPILER='gcc-5'; export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='gcc-8'; export UBUNTU='18.10'; extras/scripts/postsubmit.sh + script: export OS=linux; export COMPILER='gcc-5'; export UBUNTU='18.04'; extras/scripts/postsubmit.sh ReleasePlain - compiler: gcc - env: COMPILER=gcc-8 UBUNTU=18.10 TEST=DebugPlain - install: export OS=linux; export COMPILER='gcc-8'; export UBUNTU='18.10'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=gcc-5 UBUNTU=18.04 TEST=DebugPlain + install: export OS=linux; export COMPILER='gcc-5'; export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='gcc-8'; export UBUNTU='18.10'; extras/scripts/postsubmit.sh + script: export OS=linux; export COMPILER='gcc-5'; export UBUNTU='18.04'; extras/scripts/postsubmit.sh + DebugPlain + - compiler: gcc + env: COMPILER=gcc-8 UBUNTU=18.04 TEST=ReleasePlain + install: export OS=linux; export COMPILER='gcc-8'; export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='gcc-8'; export UBUNTU='18.04'; extras/scripts/postsubmit.sh + ReleasePlain + - compiler: gcc + env: COMPILER=gcc-8 UBUNTU=18.04 TEST=DebugPlain + install: export OS=linux; export COMPILER='gcc-8'; export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh + os: linux + script: export OS=linux; export COMPILER='gcc-8'; export UBUNTU='18.04'; extras/scripts/postsubmit.sh DebugPlain - compiler: clang - env: COMPILER=clang-4.0 STL=libstdc++ UBUNTU=18.10 TEST=ReleasePlain - install: export OS=linux; export COMPILER='clang-4.0'; export STL='libstdc++'; - export UBUNTU='18.10'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=clang-3.9 STL=libstdc++ UBUNTU=18.04 TEST=ReleasePlain + install: export OS=linux; export COMPILER='clang-3.9'; export STL='libstdc++'; + export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='clang-4.0'; export STL='libstdc++'; - export UBUNTU='18.10'; extras/scripts/postsubmit.sh ReleasePlain + script: export OS=linux; export COMPILER='clang-3.9'; export STL='libstdc++'; + export UBUNTU='18.04'; extras/scripts/postsubmit.sh ReleasePlain - compiler: clang - env: COMPILER=clang-4.0 STL=libstdc++ UBUNTU=18.10 TEST=DebugAsanUbsan - install: export OS=linux; export COMPILER='clang-4.0'; export STL='libstdc++'; - export UBUNTU='18.10'; extras/scripts/travis_ci_install_linux.sh + env: COMPILER=clang-3.9 STL=libstdc++ UBUNTU=18.04 TEST=DebugAsanUbsan + install: export OS=linux; export COMPILER='clang-3.9'; export STL='libstdc++'; + export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh os: linux - script: export OS=linux; export COMPILER='clang-4.0'; export STL='libstdc++'; - export UBUNTU='18.10'; extras/scripts/postsubmit.sh DebugAsanUbsan + script: export OS=linux; export COMPILER='clang-3.9'; export STL='libstdc++'; + export UBUNTU='18.04'; extras/scripts/postsubmit.sh DebugAsanUbsan - compiler: clang - env: COMPILER=clang-7.0 STL=libstdc++ UBUNTU=18.10 TEST=ReleasePlainNoPch + env: COMPILER=clang-7.0 STL=libstdc++ UBUNTU=18.04 TEST=ReleasePlainNoPch install: export OS=linux; export COMPILER='clang-7.0'; export STL='libstdc++'; - export UBUNTU='18.10'; extras/scripts/travis_ci_install_linux.sh + export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh os: linux script: export OS=linux; export COMPILER='clang-7.0'; export STL='libstdc++'; - export UBUNTU='18.10'; extras/scripts/postsubmit.sh ReleasePlainNoPch + export UBUNTU='18.04'; extras/scripts/postsubmit.sh ReleasePlainNoPch - compiler: clang - env: COMPILER=clang-7.0 STL=libstdc++ UBUNTU=18.10 TEST=DebugAsanUbsanNoPch + env: COMPILER=clang-7.0 STL=libstdc++ UBUNTU=18.04 TEST=DebugAsanUbsanNoPch install: export OS=linux; export COMPILER='clang-7.0'; export STL='libstdc++'; - export UBUNTU='18.10'; extras/scripts/travis_ci_install_linux.sh + export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh os: linux script: export OS=linux; export COMPILER='clang-7.0'; export STL='libstdc++'; - export UBUNTU='18.10'; extras/scripts/postsubmit.sh DebugAsanUbsanNoPch - - compiler: gcc - env: COMPILER=bazel UBUNTU=16.04 - install: export OS=linux; export COMPILER='bazel'; export UBUNTU='16.04'; extras/scripts/travis_ci_install_linux.sh - os: linux - script: export OS=linux; export COMPILER='bazel'; export UBUNTU='16.04'; extras/scripts/postsubmit.sh - DebugPlain + export UBUNTU='18.04'; extras/scripts/postsubmit.sh DebugAsanUbsanNoPch - compiler: gcc env: COMPILER=gcc-5 UBUNTU=16.04 TEST=ReleasePlain install: export OS=linux; export COMPILER='gcc-5'; export UBUNTU='16.04'; extras/scripts/travis_ci_install_linux.sh @@ -185,122 +220,109 @@ matrix: script: export OS=linux; export COMPILER='clang-3.9'; export STL='libstdc++'; export UBUNTU='16.04'; extras/scripts/postsubmit.sh DebugPlain - compiler: gcc - env: COMPILER=gcc-6 TEST=ReleasePlain - install: export OS=osx; export COMPILER='gcc-6'; extras/scripts/travis_ci_install_osx.sh + env: COMPILER=gcc-6 TEST=ReleasePlainNoClangTidy + install: export OS=osx; export COMPILER='gcc-6'; travis_wait extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode11.4 - script: export OS=osx; export COMPILER='gcc-6'; extras/scripts/postsubmit.sh ReleasePlain + script: export OS=osx; export COMPILER='gcc-6'; extras/scripts/postsubmit.sh ReleasePlainNoClangTidy - compiler: gcc - env: COMPILER=gcc-6 TEST=DebugPlain - install: export OS=osx; export COMPILER='gcc-6'; extras/scripts/travis_ci_install_osx.sh + env: COMPILER=gcc-6 TEST=DebugPlainNoClangTidy + install: export OS=osx; export COMPILER='gcc-6'; travis_wait extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode11.4 - script: export OS=osx; export COMPILER='gcc-6'; extras/scripts/postsubmit.sh DebugPlain + script: export OS=osx; export COMPILER='gcc-6'; extras/scripts/postsubmit.sh DebugPlainNoClangTidy - compiler: gcc - env: COMPILER=gcc-9 TEST=ReleasePlain - install: export OS=osx; export COMPILER='gcc-9'; extras/scripts/travis_ci_install_osx.sh + env: COMPILER=gcc-9 TEST=ReleasePlainNoPchNoClangTidy + install: export OS=osx; export COMPILER='gcc-9'; travis_wait extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode11.4 - script: export OS=osx; export COMPILER='gcc-9'; extras/scripts/postsubmit.sh ReleasePlain - - compiler: clang - env: COMPILER=clang-4.0 STL=libc++ TEST=ReleasePlain - install: export OS=osx; export COMPILER='clang-4.0'; export STL='libc++'; extras/scripts/travis_ci_install_osx.sh + script: export OS=osx; export COMPILER='gcc-9'; extras/scripts/postsubmit.sh ReleasePlainNoPchNoClangTidy + - compiler: gcc + env: COMPILER=gcc-9 TEST=DebugPlainNoPchNoClangTidy + install: export OS=osx; export COMPILER='gcc-9'; travis_wait extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode11.4 - script: export OS=osx; export COMPILER='clang-4.0'; export STL='libc++'; extras/scripts/postsubmit.sh - ReleasePlain + script: export OS=osx; export COMPILER='gcc-9'; extras/scripts/postsubmit.sh DebugPlainNoPchNoClangTidy - compiler: clang - env: COMPILER=clang-4.0 STL=libc++ TEST=DebugAsanUbsan - install: export OS=osx; export COMPILER='clang-4.0'; export STL='libc++'; extras/scripts/travis_ci_install_osx.sh + env: COMPILER=clang-6.0 STL=libc++ TEST=ReleasePlainNoClangTidy + install: export OS=osx; export COMPILER='clang-6.0'; export STL='libc++'; travis_wait + extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode11.4 - script: export OS=osx; export COMPILER='clang-4.0'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugAsanUbsan + script: export OS=osx; export COMPILER='clang-6.0'; export STL='libc++'; extras/scripts/postsubmit.sh + ReleasePlainNoClangTidy - compiler: clang - env: COMPILER=clang-8.0 STL=libc++ TEST=ReleasePlainNoPch - install: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; extras/scripts/travis_ci_install_osx.sh + env: COMPILER=clang-6.0 STL=libc++ TEST=DebugAsanUbsanNoClangTidy + install: export OS=osx; export COMPILER='clang-6.0'; export STL='libc++'; travis_wait + extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode11.4 - script: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; extras/scripts/postsubmit.sh - ReleasePlainNoPch + script: export OS=osx; export COMPILER='clang-6.0'; export STL='libc++'; extras/scripts/postsubmit.sh + DebugAsanUbsanNoClangTidy - compiler: clang - env: COMPILER=clang-8.0 STL=libc++ TEST=DebugAsanUbsanNoPch - install: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; extras/scripts/travis_ci_install_osx.sh + env: COMPILER=clang-8.0 STL=libc++ TEST=ReleasePlainNoPchNoClangTidy + install: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; travis_wait + extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode11.4 script: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugAsanUbsanNoPch + ReleasePlainNoPchNoClangTidy - compiler: clang - env: COMPILER=clang-8.0 STL=libc++ TEST=DebugPlainNoPch - install: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; extras/scripts/travis_ci_install_osx.sh + env: COMPILER=clang-8.0 STL=libc++ TEST=DebugAsanUbsanNoPchNoClangTidy + install: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; travis_wait + extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode11.4 script: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugPlainNoPch + DebugAsanUbsanNoPchNoClangTidy - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=ReleasePlain - install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; + env: COMPILER=clang-8.0 STL=libc++ TEST=DebugPlainNoPchNoClangTidy + install: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; travis_wait extras/scripts/travis_ci_install_osx.sh os: osx - osx_image: xcode8.3 - script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - ReleasePlain - - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=DebugAsan - install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh - os: osx - osx_image: xcode8.3 - script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugAsan + osx_image: xcode11.4 + script: export OS=osx; export COMPILER='clang-8.0'; export STL='libc++'; extras/scripts/postsubmit.sh + DebugPlainNoPchNoClangTidy - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=ReleasePlain + env: COMPILER=clang-default STL=libc++ TEST=ReleasePlainNoClangTidy install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh + travis_wait extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode9.4 script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - ReleasePlain + ReleasePlainNoClangTidy - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=DebugAsanUbsan + env: COMPILER=clang-default STL=libc++ TEST=DebugAsanUbsanNoClangTidy install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh + travis_wait extras/scripts/travis_ci_install_osx.sh os: osx osx_image: xcode9.4 script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugAsanUbsan + DebugAsanUbsanNoClangTidy - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=ReleasePlain + env: COMPILER=clang-default STL=libc++ TEST=ReleasePlainNoPchNoClangTidy install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh + travis_wait extras/scripts/travis_ci_install_osx.sh os: osx - osx_image: xcode10.3 + osx_image: xcode11.3 script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - ReleasePlain + ReleasePlainNoPchNoClangTidy - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=DebugAsanUbsan + env: COMPILER=clang-default STL=libc++ TEST=DebugAsanUbsanNoPchNoClangTidy install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh + travis_wait extras/scripts/travis_ci_install_osx.sh os: osx - osx_image: xcode10.3 + osx_image: xcode11.3 script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugAsanUbsan + DebugAsanUbsanNoPchNoClangTidy - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=ReleasePlain + env: COMPILER=clang-default STL=libc++ TEST=DebugPlainNoPchNoClangTidy install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh + travis_wait extras/scripts/travis_ci_install_osx.sh os: osx - osx_image: xcode11.4 + osx_image: xcode11.3 script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - ReleasePlain - - compiler: clang - env: COMPILER=clang-default STL=libc++ TEST=DebugAsanUbsan - install: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; - extras/scripts/travis_ci_install_osx.sh - os: osx - osx_image: xcode11.4 - script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh - DebugAsanUbsan + DebugPlainNoPchNoClangTidy services: - docker sudo: required @@ -14,11 +14,39 @@ // Simply '#include <fruit/fruit.h>' to get started. // See https://github.com/google/fruit/wiki for more details. +package { + default_applicable_licenses: ["external_google-fruit_license"], +} + +// Added automatically by a large-scale-change +// +// large-scale-change included anything that looked like it might be a license +// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc. +// +// Please consider removing redundant or irrelevant files from 'license_text:'. +// See: http://go/android-license-faq +license { + name: "external_google-fruit_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "COPYING", + "LICENSE", + ], +} + cc_library { name: "libfruit", host_supported: true, + vendor_available: true, export_include_dirs: ["include", "configuration/android"], srcs: ["src/**/*.cpp", ], + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], } // TODO: tests written in python+pytest that calls back into compiler. unclear how to best proceed. @@ -6,8 +6,9 @@ filegroup( name = "fruit_headers", srcs = glob([ "include/**/*.h", - "configuration/bazel/**/*.h", - ]), + ]) + [ + "//third_party/fruit/configuration/bazel:fruit-config-base", + ], ) cc_library( @@ -15,9 +16,12 @@ cc_library( srcs = glob([ "src/*.cpp", "include/fruit/impl/**/*.h", - "configuration/bazel/**/*.h"]), + ]), hdrs = glob(["include/fruit/*.h"]), includes = ["include", "configuration/bazel"], - deps = [], + deps = [ + "@boost//:unordered", + "//third_party/fruit/configuration/bazel:fruit-config-base", + ], linkopts = ["-lm"], ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20e5ba0..7efcf7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,22 @@ -project(Fruit) -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.2) + +project(Fruit VERSION 3.6.0 LANGUAGES CXX) + +set(FRUIT_IS_BEING_BUILT_BY_CONAN FALSE CACHE BOOL "This is set in Conan builds.") +if("${FRUIT_IS_BEING_BUILT_BY_CONAN}") + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() +endif() if (POLICY CMP0054) cmake_policy(SET CMP0054 NEW) endif() +if ("${CMAKE_CXX_STANDARD}" STREQUAL "") + set(CMAKE_CXX_STANDARD 11) +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) + # CMake on OSX likes to see this set explicitly, otherwise it outputs a warning. set(CMAKE_MACOSX_RPATH 1) @@ -17,10 +29,6 @@ option(BUILD_SHARED_LIBS "Build shared library" ON) # The Visual Studio CMake generators default to multiple configurations, but Fruit doesn't support multi-configuration build directories. set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}") -if(NOT "${RUNTIME_OUTPUT_DIRECTORY}") - set(RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -endif() - set(FRUIT_ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX compiler flags." FORCE) set(FRUIT_ADDITIONAL_COMPILE_FLAGS "${FRUIT_ADDITIONAL_CXX_FLAGS}") @@ -43,7 +51,8 @@ elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(MSVC)$") # The warning C4577 is disabled because we don't need a termination guarantee on exceptions for functions marked with # 'noexcept'. # The warning C4530 is disabled because it's triggered by MSVC's STL. - set(FRUIT_ADDITIONAL_COMPILE_FLAGS "${FRUIT_ADDITIONAL_COMPILE_FLAGS} /nologo /FS /W4 /wd4324 /wd4709 /wd4459 /wd4141 /wd4714 /wd4577 /wd4530 /D_SCL_SECURE_NO_WARNINGS") + # The warning C5205 is disabled, MSVC emits it for abstract classes in example code with non-virtual destructors, but we never call delete on those (even though std::default_delete<Scaler> is instantiated for those types). + set(FRUIT_ADDITIONAL_COMPILE_FLAGS "${FRUIT_ADDITIONAL_COMPILE_FLAGS} /nologo /FS /W4 /wd4324 /wd4709 /wd4459 /wd4141 /wd4714 /wd4577 /wd4530 /wd5205 /D_SCL_SECURE_NO_WARNINGS") endif() option(FRUIT_ENABLE_COVERAGE "Enable collection of test coverage. This is meant to be used by Fruit developers. It's only supported when using GCC on Linux." OFF) @@ -58,14 +67,19 @@ set(FRUIT_USES_BOOST TRUE CACHE BOOL "Whether to use Boost (specifically, boost::unordered_set and boost::unordered_map). If this is false, Fruit will use std::unordered_set and std::unordered_map instead (however this causes injection to be a bit slower).") -set(FRUIT_IS_BEING_BUILT_BY_CONAN FALSE CACHE BOOL "This is set in Conan builds.") +if(${FRUIT_USES_BOOST}) -if("${WIN32}" AND "${FRUIT_USES_BOOST}" AND NOT "${FRUIT_IS_BEING_BUILT_BY_CONAN}") - set(BOOST_DIR "" CACHE PATH "The directory where the boost library is installed, e.g. C:\\boost\\boost_1_62_0.") - if("${BOOST_DIR}" STREQUAL "") - message(FATAL_ERROR "Please re-run CMake, specifying the boost library path as BOOST_DIR, e.g. -DBOOST_DIR=C:\\boost\\boost_1_62_0, or specify -DFRUIT_USES_BOOST=False to not use boost.") + if(DEFINED BOOST_DIR) + message(DEPRECATION "BOOST_DIR is deprecated. Use Boost_INCLUDE_DIR instead.") + set(Boost_INCLUDE_DIR "${BOOST_DIR}" CACHE PATH "") + endif() + + find_package(Boost) + if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + else() + message(FATAL_ERROR "Please re-run CMake, specifying the boost library path as Boost_INCLUDE_DIR, e.g. -DBoost_INCLUDE_DIR=C:\\boost\\boost_1_62_0, or specify -DFRUIT_USES_BOOST=False to not use boost.") endif() - include_directories("${BOOST_DIR}") endif() set(RUN_TESTS_UNDER_VALGRIND FALSE CACHE BOOL "Whether to run Fruit tests under valgrind") @@ -87,6 +101,18 @@ else() set(FRUIT_COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} ${FRUIT_ADDITIONAL_COMPILE_FLAGS}") endif() +set(FRUIT_CLANG_TIDY_CHECKS + bugprone*,-bugprone-reserved-identifier,-bugprone-exception-escape,clang-analyzer*,performance*,google*,-google-readability*,-google-runtime-references,clang-diagnostic-unused-command-line-argument,misc-macro-parentheses,-clang-diagnostic-dtor-name) + +set(FRUIT_ENABLE_CLANG_TIDY FALSE CACHE BOOL "Whether to run clang-tidy on the Fruit codebase during the build") +if(${FRUIT_ENABLE_CLANG_TIDY}) + set(CMAKE_CXX_CLANG_TIDY + clang-tidy; + -header-filter=fruit; + -checks=${FRUIT_CLANG_TIDY_CHECKS}; + -warnings-as-errors=*;) +endif() + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) @@ -94,34 +120,29 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) # of the user-friendly default that hides Fruit internals). #add_definitions(-DFRUIT_DEEP_TEMPLATE_INSTANTIATION_STACKTRACES_FOR_ERRORS=1) -set(INSTALL_INCLUDE_DIR include/fruit CACHE PATH "Installation directory for headers") -set(INSTALL_LIBRARY_DIR lib CACHE PATH "Installation directory for libraries") - -set(FRUIT_VERSION "3.4.0") +include(GNUInstallDirs) add_subdirectory(configuration) add_subdirectory(src) -if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - # Do not exclude these from "make all" in debug mode, they must build. - add_subdirectory(examples) - add_subdirectory(tests) -else() - add_subdirectory(examples EXCLUDE_FROM_ALL) - add_subdirectory(tests) -endif() +if(NOT "${FRUIT_IS_BEING_BUILT_BY_CONAN}") + if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + # Do not exclude these from "make all" in debug mode, they must build. + add_subdirectory(examples) + add_subdirectory(tests) + else() + add_subdirectory(examples EXCLUDE_FROM_ALL) + add_subdirectory(tests) + endif() -add_subdirectory(extras EXCLUDE_FROM_ALL) + add_subdirectory(extras EXCLUDE_FROM_ALL) +endif() install(DIRECTORY include/fruit/ - DESTINATION "${INSTALL_INCLUDE_DIR}" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fruit FILES_MATCHING PATTERN "*.h") set(CPACK_PACKAGE_NAME "Fruit") set(CPACK_PACKAGE_VENDOR "Marco Poletti") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Fruit - Dependency Injection Framework For C++") -string(REGEX REPLACE "([^.]*)\\.([^.]*)\\.([^.]*)" "\\1" CPACK_PACKAGE_VERSION_MAJOR "${FRUIT_VERSION}") -string(REGEX REPLACE "([^.]*)\\.([^.]*)\\.([^.]*)" "\\2" CPACK_PACKAGE_VERSION_MINOR "${FRUIT_VERSION}") -string(REGEX REPLACE "([^.]*)\\.([^.]*)\\.([^.]*)" "\\3" CPACK_PACKAGE_VERSION_PATCH "${FRUIT_VERSION}") -set(CPACK_PACKAGE_VERSION "${FRUIT_VERSION}") set(CPACK_PACKAGE_INSTALL_DIRECTORY "Fruit") diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 89a3fca..1415516 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ Example commands to build a development version of Fruit using CMake (with all a cd $PATH_TO_FRUIT mkdir build-debug cd build-debug -cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Werror -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1" +cmake .. -DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="-Werror -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1" make -j 16 cd tests py.test-3 -n auto @@ -104,43 +104,30 @@ For example, if you installed Boost in `C:\boost\boost_1_62_0`, you can put this // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. "configurations": [ { - "name": "x86-Debug", - "generator": "Visual Studio 15 2017", - "configurationType": "Debug", - "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", - "cmakeCommandArgs": "-DBOOST_DIR=C:\\boost\\boost_1_62_0 -DCMAKE_BUILD_TYPE=Debug -DFRUIT_ADDITIONAL_CXX_FLAGS=/Z7", - "buildCommandArgs": "-m -v:minimal" + "name": "x64-Debug", + "generator": "Visual Studio 16 2019 Win64", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "cmakeCommandArgs": "-DBoost_INCLUDE_DIR=C:\\boost\\boost_1_62_0 -DCMAKE_BUILD_TYPE=Debug -DFRUIT_ADDITIONAL_CXX_FLAGS=/Z7", + "buildCommandArgs": "-m -v:minimal", + "intelliSenseMode": "windows-msvc-x64" }, { - "name": "x86-Release", - "generator": "Visual Studio 15 2017", - "configurationType": "Release", - "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", - "cmakeCommandArgs": "-DBOOST_DIR=C:\\boost\\boost_1_62_0 -DCMAKE_BUILD_TYPE=Release", - "buildCommandArgs": "-m -v:minimal" - }, - { - "name": "x64-Debug", - "generator": "Visual Studio 15 2017 Win64", - "configurationType": "Debug", - "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", - "cmakeCommandArgs": "-DBOOST_DIR=C:\\boost\\boost_1_62_0 -DCMAKE_BUILD_TYPE=Debug -DFRUIT_ADDITIONAL_CXX_FLAGS=/Z7", - "buildCommandArgs": "-m -v:minimal" - }, - { - "name": "x64-Release", - "generator": "Visual Studio 15 2017 Win64", - "configurationType": "Release", - "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", - "cmakeCommandArgs": "-DBOOST_DIR=C:\\boost\\boost_1_62_0 -DCMAKE_BUILD_TYPE=Release", - "buildCommandArgs": "-m -v:minimal" + "name": "x64-Debug-noboost", + "generator": "Visual Studio 16 2019 Win64", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "cmakeCommandArgs": "-DFRUIT_USES_BOOST=False -DCMAKE_BUILD_TYPE=Debug -DFRUIT_ADDITIONAL_CXX_FLAGS=/Z7", + "buildCommandArgs": "-m -v:minimal", + "intelliSenseMode": "windows-msvc-x64" } + ] } The `/Z7` flag instructs Visual Studio to use the C7 format for debugging information, which allows Fruit's tests to run in parallel without interfering with each other. -If you don't want to use Boost, you can replace the `-DBOOST_DIR=...` flags above with `-DFRUIT_USES_BOOST=False`. +If you don't want to use Boost, you can replace the `-DBoost_INCLUDE_DIR=...` flags above with `-DFRUIT_USES_BOOST=False`. You can now run CMake within Visual Studio (from the menu: CMake -> Cache -> Generate -> CMakeLists.txt) and build Fruit (from the menu: CMake -> Build All). @@ -148,8 +135,9 @@ You can also run tests, but *only* from the command-line (after building Fruit f To do that, you'll need python3 installed (you can download it [here](https://www.python.org/downloads/)). -You'll also the `pytest` and `pytest-xdist` packages. You can install them with: +You'll also some Python packages. You can install them with: + pip install absl-py pip install pytest pip install pytest-xdist @@ -9,11 +9,11 @@ third_party { type: GIT value: "https://github.com/google/fruit.git" } - version: "bb1fc3b3abe3eda0f093fb1d45f9be96c6af6366" + version: "70f7c06e305ad7c9e4e99b87672aaa1061d914d6" license_type: NOTICE last_upgrade_date { - year: 2019 - month: 9 - day: 3 + year: 2020 + month: 11 + day: 30 } } @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2014 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. @@ -1 +1,2 @@ +hhb@google.com iam@google.com diff --git a/appveyor.yml b/appveyor.yml index bc9a449..2406142 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,23 +3,48 @@ clone_folder: C:\Fruit environment: PYTHON3_PATH: C:\Python36 matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - CMAKE_GENERATOR: 'Visual Studio 14 2015 Win64' - VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC' - ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX /DFRUIT_DEBUG /DFRUIT_EXTRA_DEBUG /D_ITERATOR_DEBUG_LEVEL=2" -T host=x64' + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + CMAKE_GENERATOR: 'Visual Studio 16 2019' + VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build' + ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX /DFRUIT_DEBUG /DFRUIT_EXTRA_DEBUG /D_ITERATOR_DEBUG_LEVEL=2" -T host=x64 -A x64 -DCMAKE_CXX_STANDARD=17' + CONFIGURATION: Debug + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + CMAKE_GENERATOR: 'Visual Studio 16 2019' + VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build' + ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX /DFRUIT_DEBUG /DFRUIT_EXTRA_DEBUG /D_ITERATOR_DEBUG_LEVEL=2" -T host=x64 -A x64' CONFIGURATION: Debug - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 CMAKE_GENERATOR: 'Visual Studio 15 2017 Win64' VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build' ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX /DFRUIT_DEBUG /DFRUIT_EXTRA_DEBUG /D_ITERATOR_DEBUG_LEVEL=2" -T host=x64' CONFIGURATION: Debug + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + CMAKE_GENERATOR: 'Visual Studio 16 2019' + VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build' + ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64 -A x64' + CONFIGURATION: Release + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + CMAKE_GENERATOR: 'Visual Studio 15 2017 Win64' + VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build' + ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64' + CONFIGURATION: Release + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + CMAKE_GENERATOR: 'Visual Studio 16 2019' + VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build' + ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DBUILD_SHARED_LIBS=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64 -A x64' + CONFIGURATION: Release + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + CMAKE_GENERATOR: 'Visual Studio 15 2017 Win64' + VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build' + ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DBUILD_SHARED_LIBS=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64' + CONFIGURATION: Release + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 MINGW_PATH: 'C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin' CMAKE_GENERATOR: 'MinGW Makefiles' VCVARSALL_DIR: '' ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="-Werror -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1"' CONFIGURATION: Debug - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 MINGW_PATH: 'C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin' CMAKE_GENERATOR: 'MinGW Makefiles' @@ -30,33 +55,13 @@ environment: MINGW_PATH: 'C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin' CMAKE_GENERATOR: 'MinGW Makefiles' VCVARSALL_DIR: '' - ADDITIONAL_CMAKE_ARGS: '-DBOOST_DIR=C:\Libraries\boost_1_64_0 -DCMAKE_CXX_FLAGS="-Werror"' - CONFIGURATION: Release - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - CMAKE_GENERATOR: 'Visual Studio 15 2017 Win64' - VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build' - ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64' - CONFIGURATION: Release - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - CMAKE_GENERATOR: 'Visual Studio 14 2015 Win64' - VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC' - ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64' + ADDITIONAL_CMAKE_ARGS: '-DBoost_INCLUDE_DIR=C:\Libraries\boost_1_69_0 -DCMAKE_CXX_FLAGS="-Werror"' CONFIGURATION: Release - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 MINGW_PATH: 'C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin' CMAKE_GENERATOR: 'MinGW Makefiles' VCVARSALL_DIR: '' - ADDITIONAL_CMAKE_ARGS: '-DBOOST_DIR=C:\Libraries\boost_1_64_0 -DBUILD_SHARED_LIBS=False -DCMAKE_CXX_FLAGS="-Werror"' - CONFIGURATION: Release - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - CMAKE_GENERATOR: 'Visual Studio 15 2017 Win64' - VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build' - ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DBUILD_SHARED_LIBS=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64' - CONFIGURATION: Release - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - CMAKE_GENERATOR: 'Visual Studio 14 2015 Win64' - VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC' - ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DBUILD_SHARED_LIBS=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64' + ADDITIONAL_CMAKE_ARGS: '-DBoost_INCLUDE_DIR=C:\Libraries\boost_1_69_0 -DBUILD_SHARED_LIBS=False -DCMAKE_CXX_FLAGS="-Werror"' CONFIGURATION: Release build_script: - cmd: cmd /c C:\Fruit\extras\scripts\postsubmit.bat diff --git a/cmake-modules/FindFruit.cmake b/cmake-modules/FindFruit.cmake index a6155cd..3b4fc24 100644 --- a/cmake-modules/FindFruit.cmake +++ b/cmake-modules/FindFruit.cmake @@ -2,23 +2,23 @@ # set(ENV{FRUIT_INSTALLED_DIR} "/path/to/fruit/build") find_path(FRUIT_INCLUDE_DIR fruit.h - HINTS ( - FRUIT_INSTALLED_DIR - /usr - /usr/local - ) - PATH_SUFFIXES include/fruit include fruit -) + HINTS ( + ${FRUIT_INSTALLED_DIR} + /usr + /usr/local + ) + PATH_SUFFIXES include/fruit + ) find_library(FRUIT_LIBRARY - NAMES fruit - HINTS ( - FRUIT_INSTALLED_DIR - /usr - /usr/local - ) - PATH_SUFFIXES lib ${FRUIT_INSTALLED_DIR} -) + NAMES fruit + HINTS ( + ${FRUIT_INSTALLED_DIR} + /usr + /usr/local + ) + PATH_SUFFIXES lib lib64 + ) include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(fruit DEFAULT_MSG FRUIT_LIBRARY FRUIT_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Fruit DEFAULT_MSG FRUIT_LIBRARY FRUIT_INCLUDE_DIR) diff --git a/conanfile.py b/conanfile.py index 46bd1ce..a96d39c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -5,7 +5,7 @@ import os class FruitConan(ConanFile): name = "fruit" - version = "3.4.0" + version = "3.6.0" license = "Apache" url = "https://github.com/google/fruit" homepage = "https://github.com/google/fruit" @@ -16,6 +16,7 @@ class FruitConan(ConanFile): generators = "cmake" exports = "COPYING" _source_subfolder = "source_subfolder" + _cmake = None def configure(self): min_version = { @@ -32,37 +33,30 @@ class FruitConan(ConanFile): self.settings.compiler.version, min_version)) - def requirements(self): + def build_requirements(self): if self.options.use_boost: - self.requires("boost/1.68.0@conan/stable") + self.build_requires("boost/1.68.0@conan/stable") def source(self): tools.get("{0}/archive/v{1}.tar.gz".format(self.homepage, self.version)) extracted_dir = self.name + "-" + self.version os.rename(extracted_dir, self._source_subfolder) - # This small hack might be useful to guarantee proper /MT /MD linkage - # in MSVC if the packaged project doesn't have variables to set it - # properly - tools.replace_in_file(os.path.join(self._source_subfolder, "CMakeLists.txt"), - "project(Fruit)", - '''PROJECT(Myfruit) -include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) -conan_basic_setup()''') def _configure_cmake(self): - cmake = CMake(self) - cmake.definitions["FRUIT_IS_BEING_BUILT_BY_CONAN"] = "YES" - cmake.definitions["BUILD_SHARED_LIBS"] = "YES" if self.options.shared else "NO" - if self.options.use_boost: + if not self._cmake: + self._cmake = CMake(self) + self._cmake.definitions["FRUIT_IS_BEING_BUILT_BY_CONAN"] = "YES" + self._cmake.definitions["BUILD_SHARED_LIBS"] = "YES" if self.options.shared else "NO" + self._cmake.definitions["FRUIT_USES_BOOST"] = self.options.use_boost + if self.options.use_boost: + self._cmake.definitions["Boost_INCLUDE_DIR"] = os.path.join( + self.deps_cpp_info["boost"].rootpath, "include") if self.settings.os == "Windows": - cmake.definitions["BOOST_DIR"] = "." - else: - cmake.definitions["FRUIT_USES_BOOST"] = "NO" - if self.settings.os == "Windows": - cmake.definitions["FRUIT_TESTS_USE_PRECOMPILED_HEADERS"] = "NO" - cmake.definitions["CMAKE_BUILD_TYPE"] = self.settings.build_type - cmake.configure(source_folder=self._source_subfolder) - return cmake + self._cmake.definitions["FRUIT_TESTS_USE_PRECOMPILED_HEADERS"] = "NO" + self._cmake.definitions["CMAKE_BUILD_TYPE"] = self.settings.build_type + self._cmake.configure(source_folder=self._source_subfolder) + + return self._cmake def build(self): cmake = self._configure_cmake() @@ -76,5 +70,4 @@ conan_basic_setup()''') src=self._source_subfolder) def package_info(self): - self.cpp_info.includedirs = ["include"] - self.cpp_info.libs = ["fruit"] + self.cpp_info.libs = tools.collect_libs(self) diff --git a/configuration/CMakeLists.txt b/configuration/CMakeLists.txt index b18a463..11d8445 100644 --- a/configuration/CMakeLists.txt +++ b/configuration/CMakeLists.txt @@ -218,4 +218,4 @@ endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fruit-config-base.h.in ${CMAKE_CURRENT_BINARY_DIR}/../include/fruit/impl/fruit-config-base.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/../include/fruit/impl/fruit-config-base.h - DESTINATION ${INSTALL_INCLUDE_DIR}/impl) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fruit/impl) diff --git a/configuration/bazel/BUILD b/configuration/bazel/BUILD new file mode 100644 index 0000000..a207462 --- /dev/null +++ b/configuration/bazel/BUILD @@ -0,0 +1,8 @@ +load("//third_party/fruit/configuration/bazel:build_defs.bzl", "generate_fruit_config") + +package(default_visibility = ["//third_party/fruit:__subpackages__"]) + +generate_fruit_config( + name = "fruit-config-base", + check_sources = glob(["*.cpp"]) +) diff --git a/configuration/bazel/always_inline_attribute.cpp b/configuration/bazel/always_inline_attribute.cpp new file mode 100644 index 0000000..e6215af --- /dev/null +++ b/configuration/bazel/always_inline_attribute.cpp @@ -0,0 +1,7 @@ +__attribute__((always_inline)) +void f() { +} + +int main() { + return 0; +} diff --git a/configuration/bazel/attribute_deprecated.cpp b/configuration/bazel/attribute_deprecated.cpp new file mode 100644 index 0000000..245519d --- /dev/null +++ b/configuration/bazel/attribute_deprecated.cpp @@ -0,0 +1,5 @@ +[[deprecated]] void f(); + +int main() { + return 0; +} diff --git a/configuration/bazel/build_defs.bzl b/configuration/bazel/build_defs.bzl new file mode 100644 index 0000000..28c3b17 --- /dev/null +++ b/configuration/bazel/build_defs.bzl @@ -0,0 +1,103 @@ +load("@rules_cc//cc:action_names.bzl", "C_COMPILE_ACTION_NAME") +load("@rules_cc//cc:toolchain_utils.bzl", "find_cpp_toolchain") + +def _generate_fruit_config_impl(ctx): + cc_toolchain = find_cpp_toolchain(ctx) + + feature_configuration = cc_common.configure_features( + ctx = ctx, + cc_toolchain = cc_toolchain, + requested_features = ctx.features, + unsupported_features = ctx.disabled_features, + ) + c_compiler_path = cc_common.get_tool_for_action( + feature_configuration = feature_configuration, + action_name = C_COMPILE_ACTION_NAME, + ) + + check_output_files = [] + for check_source in ctx.files.check_sources: + check_name = check_source.path[:-len(".cpp")].split('/')[-1].split('\\')[-1] + + output_file = ctx.actions.declare_file(check_name + ".o") + + c_compile_variables = cc_common.create_compile_variables( + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + user_compile_flags = ctx.fragments.cpp.copts + ctx.fragments.cpp.conlyopts, + source_file = check_source.path, + output_file = output_file.path, + ) + command_line = cc_common.get_memory_inefficient_command_line( + feature_configuration = feature_configuration, + action_name = C_COMPILE_ACTION_NAME, + variables = c_compile_variables, + ) + env = cc_common.get_environment_variables( + feature_configuration = feature_configuration, + action_name = C_COMPILE_ACTION_NAME, + variables = c_compile_variables, + ) + + check_define = 'FRUIT_HAS_%s' % check_name.upper() + check_output_file = ctx.actions.declare_file(check_name + ".h") + + ctx.actions.run_shell( + command = '"$@" &>/dev/null && echo "#define %s 1" >"%s" || echo "#define %s 0" >"%s"; touch "%s"' % ( + check_define, check_output_file.path, check_define, check_output_file.path, output_file.path + ), + arguments = [c_compiler_path] + command_line, + env = env, + inputs = depset( + [check_source], + transitive = [cc_toolchain.all_files], + ), + outputs = [output_file, check_output_file], + ) + check_output_files.append(check_output_file) + + merged_output_file = ctx.actions.declare_file("fruit/impl/fruit-config-base.h") + ctx.actions.run_shell( + command = '\n'.join([ + '(', + 'echo "#ifndef FRUIT_CONFIG_BASE_H"', + 'echo "#define FRUIT_CONFIG_BASE_H"', + 'echo "#define FRUIT_USES_BOOST 1"', + 'cat %s' % ' '.join([check_output_file.path for check_output_file in check_output_files]), + 'echo "#endif"', + ')>%s' % merged_output_file.path + ]), + inputs = check_output_files, + outputs = [merged_output_file], + ) + + compilation_context, compilation_outputs = cc_common.compile( + actions = ctx.actions, + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + public_hdrs = [merged_output_file], + name = "%s_link" % ctx.label.name, + ) + + linking_context, linking_outputs = cc_common.create_linking_context_from_compilation_outputs( + actions = ctx.actions, + feature_configuration = feature_configuration, + compilation_outputs = compilation_outputs, + cc_toolchain = cc_toolchain, + name = "%s_link" % ctx.label.name, + ) + + return [ + DefaultInfo(files = depset([merged_output_file]), runfiles = ctx.runfiles(files = [merged_output_file])), + CcInfo(compilation_context=compilation_context, linking_context=linking_context), + ] + +generate_fruit_config = rule( + implementation = _generate_fruit_config_impl, + attrs = { + "check_sources": attr.label_list(allow_files = True), + "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), + }, + toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], + fragments = ["cpp"], +)
\ No newline at end of file diff --git a/configuration/bazel/builtin_unreachable.cpp b/configuration/bazel/builtin_unreachable.cpp new file mode 100644 index 0000000..11d20cf --- /dev/null +++ b/configuration/bazel/builtin_unreachable.cpp @@ -0,0 +1,13 @@ +int f() { + static int x = 1; + if (x == 1) { + return 0; + } else { + __builtin_unreachable(); + // Note: the lack of return here is intentional + } +} + +int main() { + return f(); +} diff --git a/configuration/bazel/clang_arbitrary_overload_resolution_bug.cpp b/configuration/bazel/clang_arbitrary_overload_resolution_bug.cpp new file mode 100644 index 0000000..67b4317 --- /dev/null +++ b/configuration/bazel/clang_arbitrary_overload_resolution_bug.cpp @@ -0,0 +1,11 @@ +template <typename T, typename U> +struct Pair {}; + +struct Map : public Pair<int, float>, Pair<int, char> {}; + +template <typename Value> +Value f(Pair<int, Value>*) { return Value(); } + +int main() { + f((Map*)0); +} diff --git a/configuration/bazel/constexpr_typeid.cpp b/configuration/bazel/constexpr_typeid.cpp new file mode 100644 index 0000000..a793377 --- /dev/null +++ b/configuration/bazel/constexpr_typeid.cpp @@ -0,0 +1,6 @@ +#include <typeinfo> +int main() { + constexpr static const std::type_info& x = typeid(int); + (void) x; + return 0; +} diff --git a/configuration/bazel/cxa_demangle.cpp b/configuration/bazel/cxa_demangle.cpp new file mode 100644 index 0000000..3e4f57f --- /dev/null +++ b/configuration/bazel/cxa_demangle.cpp @@ -0,0 +1,6 @@ +#include <cxxabi.h> +int main() { + auto* p = abi::__cxa_demangle; + (void) p; + return 0; +} diff --git a/configuration/bazel/declspec_deprecated.cpp b/configuration/bazel/declspec_deprecated.cpp new file mode 100644 index 0000000..79a9f43 --- /dev/null +++ b/configuration/bazel/declspec_deprecated.cpp @@ -0,0 +1,5 @@ +__declspec(deprecated) void f(); + +int main() { + return 0; +} diff --git a/configuration/bazel/force_inline.cpp b/configuration/bazel/force_inline.cpp new file mode 100644 index 0000000..fab42d2 --- /dev/null +++ b/configuration/bazel/force_inline.cpp @@ -0,0 +1,7 @@ +__forceinline +void f() { +} + +int main() { + return 0; +} diff --git a/configuration/bazel/fruit/impl/fruit-config-base.h b/configuration/bazel/fruit/impl/fruit-config-base.h deleted file mode 100644 index 8e7af1d..0000000 --- a/configuration/bazel/fruit/impl/fruit-config-base.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2014 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FRUIT_CONFIG_BASE_H -#define FRUIT_CONFIG_BASE_H - -// Needed for all Clang versions (as of January 2016), not needed for GCC. -// This can also be defined for GCC, but it slightly slows down compile time of code using Fruit. -#define FRUIT_HAS_CLANG_ARBITRARY_OVERLOAD_RESOLUTION_BUG 1 - -// Whether the compiler defines std::max_align_t. -#define FRUIT_HAS_STD_MAX_ALIGN_T 1 - -// Whether the compiler defines ::max_align_t. -// Ignored if FRUIT_HAS_STD_MAX_ALIGN_T is set. -#define FRUIT_HAS_MAX_ALIGN_T 1 - -// Whether the compiler defines std::is_trivially_copyable. -#define FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE 1 - -// Whether the compiler defines __has_trivial_copy. -// Ignored if FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE is set. -#define FRUIT_HAS_HAS_TRIVIAL_COPY 1 - -// Whether the compiler defines __is_trivially_copyable. -// Ignored if FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE is set. -#define FRUIT_HAS_IS_TRIVIALLY_COPYABLE 1 - -// Whether the compiler defines std::is_trivially_copy_constructible. -#define FRUIT_HAS_STD_IS_TRIVIALLY_COPY_CONSTRUCTIBLE 1 - -// Whether typeid() is available. Typically, it is unless RTTI is disabled. -#define FRUIT_HAS_TYPEID 1 - -// Whether typeid() is constexpr. Typically, it is except in MSVC. -#define FRUIT_HAS_CONSTEXPR_TYPEID 1 - -// Whether abi::__cxa_demangle() is available after including cxxabi.h. -#define FRUIT_HAS_CXA_DEMANGLE 1 - -#define FRUIT_USES_BOOST 1 - -#define FRUIT_HAS_ALWAYS_INLINE_ATTRIBUTE 1 - -#define FRUIT_HAS_FORCEINLINE 0 - -#define FRUIT_HAS_ATTRIBUTE_DEPRECATED 0 - -#define FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED 1 - -#define FRUIT_HAS_DECLSPEC_DEPRECATED 0 - -#define FRUIT_HAS_MSVC_ASSUME 0 - -#define FRUIT_HAS_BUILTIN_UNREACHABLE 1 - -#endif // FRUIT_CONFIG_BASE_H diff --git a/configuration/bazel/gcc_attribute_deprecated.cpp b/configuration/bazel/gcc_attribute_deprecated.cpp new file mode 100644 index 0000000..6d0bf5f --- /dev/null +++ b/configuration/bazel/gcc_attribute_deprecated.cpp @@ -0,0 +1,5 @@ +void f() __attribute__((deprecated)); + +int main() { + return 0; +} diff --git a/configuration/bazel/has_trivial_copy.cpp b/configuration/bazel/has_trivial_copy.cpp new file mode 100644 index 0000000..b9da7d1 --- /dev/null +++ b/configuration/bazel/has_trivial_copy.cpp @@ -0,0 +1,5 @@ +int main() { + bool b = __has_trivial_copy(int); + (void) b; + return 0; +} diff --git a/configuration/bazel/is_trivially_copyable.cpp b/configuration/bazel/is_trivially_copyable.cpp new file mode 100644 index 0000000..b8b7379 --- /dev/null +++ b/configuration/bazel/is_trivially_copyable.cpp @@ -0,0 +1,5 @@ +int main() { + bool b = __is_trivially_copyable(int); + (void) b; + return 0; +} diff --git a/configuration/bazel/max_align_t.cpp b/configuration/bazel/max_align_t.cpp new file mode 100644 index 0000000..37342f1 --- /dev/null +++ b/configuration/bazel/max_align_t.cpp @@ -0,0 +1,5 @@ +#include <cstddef> +using X = max_align_t; +int main() { + return 0; +} diff --git a/configuration/bazel/msvc_assume.cpp b/configuration/bazel/msvc_assume.cpp new file mode 100644 index 0000000..cd9f6ed --- /dev/null +++ b/configuration/bazel/msvc_assume.cpp @@ -0,0 +1,13 @@ +int f() { + static int x = 1; + if (x == 1) { + return 0; + } else { + __assume(0); + // Note: the lack of return here is intentional + } +} + +int main() { + return f(); +} diff --git a/configuration/bazel/std_is_trivially_copy_constructible.cpp b/configuration/bazel/std_is_trivially_copy_constructible.cpp new file mode 100644 index 0000000..7cb8d5b --- /dev/null +++ b/configuration/bazel/std_is_trivially_copy_constructible.cpp @@ -0,0 +1,6 @@ +#include <type_traits> +int main() { + bool b = std::is_trivially_copy_constructible<int>::value; + (void) b; + return 0; +} diff --git a/configuration/bazel/std_is_trivially_copyable.cpp b/configuration/bazel/std_is_trivially_copyable.cpp new file mode 100644 index 0000000..871b793 --- /dev/null +++ b/configuration/bazel/std_is_trivially_copyable.cpp @@ -0,0 +1,6 @@ +#include <type_traits> +int main() { + bool b = std::is_trivially_copyable<int>::value; + (void) b; + return 0; +} diff --git a/configuration/bazel/std_max_align_t.cpp b/configuration/bazel/std_max_align_t.cpp new file mode 100644 index 0000000..acec695 --- /dev/null +++ b/configuration/bazel/std_max_align_t.cpp @@ -0,0 +1,5 @@ +#include <cstddef> +using X = std::max_align_t; +int main() { + return 0; +} diff --git a/configuration/bazel/typeid.cpp b/configuration/bazel/typeid.cpp new file mode 100644 index 0000000..9621d03 --- /dev/null +++ b/configuration/bazel/typeid.cpp @@ -0,0 +1,5 @@ +#include <typeinfo> +int main() { + (void) typeid(int); + return 0; +} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a00f93c..200118d 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,4 +1,13 @@ +# This is a restricted set compared to Fruit's code, the bar for Fruit code is higher. +if(${FRUIT_ENABLE_CLANG_TIDY}) + set(CMAKE_CXX_CLANG_TIDY + clang-tidy; + -header-filter=fruit; + -checks=${FRUIT_CLANG_TIDY_CHECKS},-google-explicit-constructor,-google-build-using-namespace; + -warnings-as-errors=*;) +endif() + add_subdirectory(simple_injection) add_subdirectory(hello_world) diff --git a/extras/bazel_root/WORKSPACE b/extras/bazel_root/WORKSPACE index 8622415..d74dafe 100644 --- a/extras/bazel_root/WORKSPACE +++ b/extras/bazel_root/WORKSPACE @@ -6,3 +6,13 @@ git_repository( # GTest HEAD as of August 2018. commit = "9c96f500a39df6915f8f1ab53b60be9889f1572b", ) + +git_repository( + name = "com_github_nelhage_rules_boost", + commit = "1e3a69bf2d5cd10c34b74f066054cd335d033d71", + remote = "https://github.com/nelhage/rules_boost", + shallow_since = "1591047380 -0700", +) + +load("@com_github_nelhage_rules_boost//:boost/boost.bzl", "boost_deps") +boost_deps() diff --git a/extras/bazel_root/third_party/fruit/build b/extras/bazel_root/third_party/fruit/build deleted file mode 120000 index 388dc92..0000000 --- a/extras/bazel_root/third_party/fruit/build +++ /dev/null @@ -1 +0,0 @@ -../../../../BUILD
\ No newline at end of file diff --git a/extras/bazel_usage_example/BUILD b/extras/bazel_usage_example/BUILD new file mode 100644 index 0000000..47934aa --- /dev/null +++ b/extras/bazel_usage_example/BUILD @@ -0,0 +1,8 @@ + +licenses(["notice"]) + +cc_binary( + name = "hello_world", + srcs = ["main.cpp"], + deps = ["@com_google_fruit//third_party/fruit"], +) diff --git a/extras/bazel_usage_example/WORKSPACE b/extras/bazel_usage_example/WORKSPACE new file mode 100644 index 0000000..e037168 --- /dev/null +++ b/extras/bazel_usage_example/WORKSPACE @@ -0,0 +1,19 @@ +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + +git_repository( + name = "com_github_nelhage_rules_boost", + branch = "master", + remote = "https://github.com/nelhage/rules_boost", +) + +load("@com_github_nelhage_rules_boost//:boost/boost.bzl", "boost_deps") +boost_deps() + +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + +git_repository( + name = "com_google_fruit", + remote = "https://github.com/google/fruit", + branch = "master", + strip_prefix = "extras/bazel_root", +) diff --git a/extras/bazel_usage_example/main.cpp b/extras/bazel_usage_example/main.cpp new file mode 100644 index 0000000..4364993 --- /dev/null +++ b/extras/bazel_usage_example/main.cpp @@ -0,0 +1,55 @@ + +#include <fruit/fruit.h> +#include <iostream> + +using fruit::Component; +using fruit::Injector; + +class Writer { +public: + virtual void write(std::string s) = 0; +}; + +class StdoutWriter : public Writer { +public: + // Like "StdoutWriter() = default;" but also marks this constructor as the + // one to use for injection. + INJECT(StdoutWriter()) = default; + + virtual void write(std::string s) override { + std::cout << s; + } +}; + +class Greeter { +public: + virtual void greet() = 0; +}; + +class GreeterImpl : public Greeter { +private: + Writer* writer; + +public: + // Like "GreeterImpl(Writer* writer) {...}" but also marks this constructor + // as the one to use for injection. + INJECT(GreeterImpl(Writer* writer)) : writer(writer) {} + + virtual void greet() override { + writer->write("Hello world!\n"); + } +}; + +Component<Greeter> getGreeterComponent() { + return fruit::createComponent().bind<Writer, StdoutWriter>().bind<Greeter, GreeterImpl>(); +} + +int main() { + + Injector<Greeter> injector(getGreeterComponent); + Greeter* greeter = injector.get<Greeter*>(); + + greeter->greet(); + + return 0; +} diff --git a/extras/benchmark/boost_di_source_generator.py b/extras/benchmark/boost_di_source_generator.py index 6a3f91f..d2858a1 100644 --- a/extras/benchmark/boost_di_source_generator.py +++ b/extras/benchmark/boost_di_source_generator.py @@ -11,23 +11,27 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from typing import List -def generate_files(injection_graph, generate_runtime_bench_code): +import networkx as nx + + +def generate_files(injection_graph: nx.DiGraph, generate_runtime_bench_code: bool): file_content_by_name = dict() - for node_id in injection_graph.nodes_iter(): - deps = injection_graph.successors(node_id) + for node_id in injection_graph.nodes: + deps = list(injection_graph.successors(node_id)) file_content_by_name['component%s.h' % node_id] = _generate_component_header(node_id, deps) file_content_by_name['component%s.cpp' % node_id] = _generate_component_source(node_id, deps) [toplevel_node] = [node_id - for node_id in injection_graph.nodes_iter() - if not injection_graph.predecessors(node_id)] + for node_id in injection_graph.nodes + if not any(True for p in injection_graph.predecessors(node_id))] file_content_by_name['main.cpp'] = _generate_main(injection_graph, toplevel_node, generate_runtime_bench_code) return file_content_by_name -def _generate_component_header(component_index, deps): +def _generate_component_header(component_index: int, deps: List[int]): fields = ''.join(['std::shared_ptr<Interface%s> x%s;\n' % (dep, dep) for dep in deps]) component_deps = ''.join([', std::shared_ptr<Interface%s>' % dep for dep in deps]) @@ -39,7 +43,7 @@ def _generate_component_header(component_index, deps): #define COMPONENT{component_index}_H #include <boost/di.hpp> -#include <boost/di/extension/scopes/scoped_scope.hpp> +#include <boost/di/extension/scopes/scoped.hpp> #include <memory> // Example include that the code might use @@ -69,7 +73,7 @@ auto x{component_index}Component = [] {{ """ return template.format(**locals()) -def _generate_component_source(component_index, deps): +def _generate_component_source(component_index: int, deps: List[int]): param_initializers = ', '.join('x%s(x%s)' % (dep, dep) for dep in deps) if param_initializers: @@ -86,12 +90,12 @@ X{component_index}::X{component_index}({component_deps}) """ return template.format(**locals()) -def _generate_main(injection_graph, toplevel_component, generate_runtime_bench_code): +def _generate_main(injection_graph: nx.DiGraph, toplevel_component: int, generate_runtime_bench_code: bool): include_directives = ''.join('#include "component%s.h"\n' % index - for index in injection_graph.nodes_iter()) + for index in injection_graph.nodes) injector_params = ', '.join('x%sComponent()' % index - for index in injection_graph.nodes_iter()) + for index in injection_graph.nodes) if generate_runtime_bench_code: template = """ diff --git a/extras/benchmark/format_bench_results.py b/extras/benchmark/format_bench_results.py index 49c4893..614db07 100755 --- a/extras/benchmark/format_bench_results.py +++ b/extras/benchmark/format_bench_results.py @@ -15,30 +15,47 @@ import argparse import json +from typing import Tuple, List, Dict, Union, Callable, Any, Sequence, Set, Iterable + import yaml from collections import defaultdict -def extract_results(bench_results, fixed_benchmark_params, column_dimension, row_dimension, result_dimension): - table_data = defaultdict(lambda: dict()) +def extract_results(bench_results: List[Dict[str, Dict[Any, Any]]], + fixed_benchmark_params: Dict[str, Union[str, Tuple[str, ...]]], + column_dimension: str, + row_dimension: str, + result_dimension: str) -> Tuple[Dict[str, Dict[str, Dict[str, Any]]], + Set[Tuple[List[Tuple[str, str]], ...]], + Set[Tuple[Tuple[List[Tuple[str, str]], ...], + str]]]: + table_data = defaultdict(lambda: dict()) # type: Dict[str, Dict[str, Dict[str, Any]]] remaining_dimensions_by_row_column = dict() + used_bench_results = set() # type: Set[Tuple[List[Tuple[str, str]], ...]] + used_bench_result_values = set() # type: Set[Tuple[Tuple[List[Tuple[str, str]], ...], str]] for bench_result in bench_results: try: params = {dimension_name: make_immutable(dimension_value) for dimension_name, dimension_value in bench_result['benchmark'].items()} + original_params = dict(params) results = bench_result['results'] + matches = True + if result_dimension not in results: + # result_dimension not found in this result, skip + matches = False for param_name, param_value in fixed_benchmark_params.items(): - if params.get(param_name) != param_value: + if (isinstance(param_value, tuple) and params.get(param_name) in param_value) or (params.get(param_name) == param_value): + pass + else: # fixed_benchmark_params not satisfied by this result, skip - break - if result_dimension not in results: - # result_dimension not found in this result, skip - break - params.pop(param_name) - else: + matches = False + if matches: # fixed_benchmark_params were satisfied by these params (and were removed) assert row_dimension in params.keys(), '%s not in %s' % (row_dimension, params.keys()) assert column_dimension in params.keys(), '%s not in %s' % (column_dimension, params.keys()) assert result_dimension in results, '%s not in %s' % (result_dimension, results) + used_bench_results.add(tuple(sorted(original_params.items()))) + used_bench_result_values.add((tuple(sorted(original_params.items())), + result_dimension)) row_value = params[row_dimension] column_value = params[column_dimension] remaining_dimensions = params.copy() @@ -48,21 +65,16 @@ def extract_results(bench_results, fixed_benchmark_params, column_dimension, row previous_remaining_dimensions = remaining_dimensions_by_row_column[(row_value, column_value)] raise Exception( 'Found multiple benchmark results with the same fixed benchmark params, benchmark param for row and benchmark param for column, so a result can\'t be uniquely determined. ' - + 'Consider adding additional values in fixed_benchmark_params. Remaining dimensions: %s vs %s' % ( + + 'Consider adding additional values in fixed_benchmark_params. Remaining dimensions:\n%s\nvs\n%s' % ( remaining_dimensions, previous_remaining_dimensions)) table_data[row_value][column_value] = results[result_dimension] remaining_dimensions_by_row_column[(row_value, column_value)] = remaining_dimensions except Exception as e: raise Exception('While processing %s' % bench_result) from e - return table_data - - -def identity(x): - return x - + return table_data, used_bench_results, used_bench_result_values # Takes a 2-dimensional array (list of lists) and prints a markdown table with that content. -def print_markdown_table(table_data): +def print_markdown_table(table_data: List[List[str]]) -> None: max_content_length_by_column = [max([len(str(row[column_index])) for row in table_data]) for column_index in range(len(table_data[0]))] for row_index in range(len(table_data)): @@ -81,7 +93,11 @@ def print_markdown_table(table_data): for column_index in range(len(row))]) + '-|') -def compute_min_max(table_data, row_headers, column_headers): +# A sequence of length 2, with the lower and upper bound of the interval. +# TODO: use a class instead. +Interval = Sequence[float] + +def compute_min_max(table_data, row_headers: List[str], column_headers: List[str]) -> Interval: values_by_row = {row_header: [table_data[row_header][column_header] for column_header in column_headers if column_header in table_data[row_header]] @@ -93,8 +109,7 @@ def compute_min_max(table_data, row_headers, column_headers): for row_header in row_headers]) return (min_in_table, max_in_table) - -def pretty_print_percentage_difference(baseline_value, current_value): +def pretty_print_percentage_difference(baseline_value: Interval, current_value: Interval): baseline_min = baseline_value[0] baseline_max = baseline_value[1] current_min = current_value[0] @@ -108,6 +123,10 @@ def pretty_print_percentage_difference(baseline_value, current_value): else: return "%s - %s" % (percentage_min_s, percentage_max_s) +DimensionPrettyPrinter = Callable[[Any], str] + +IntervalPrettyPrinter = Callable[[Interval, float, float], str] + # Takes a table as a dict of dicts (where each table_data[row_key][column_key] is a confidence interval) and prints it as a markdown table using # the specified pretty print functions for column keys, row keys and values respectively. @@ -117,18 +136,19 @@ def pretty_print_percentage_difference(baseline_value, current_value): def print_confidence_intervals_table(table_name, table_data, baseline_table_data, - column_header_pretty_printer=identity, - row_header_pretty_printer=identity, - value_pretty_printer=identity): + column_header_pretty_printer: DimensionPrettyPrinter, + row_header_pretty_printer: DimensionPrettyPrinter, + value_pretty_printer: IntervalPrettyPrinter, + row_sort_key: Callable[[Any], Any]): if table_data == {}: print('%s: (no data)' % table_name) return - row_headers = sorted(list(table_data.keys())) + row_headers = sorted(list(table_data.keys()), key=row_sort_key) # We need to compute the union of the headers of all rows; some rows might be missing values for certain columns. column_headers = sorted(set().union(*[list(row_values.keys()) for row_values in table_data.values()])) if baseline_table_data: - baseline_row_headers = sorted(list(baseline_table_data.keys())) + baseline_row_headers = sorted(list(baseline_table_data.keys()), key=row_sort_key) baseline_column_headers = sorted(set().union(*[list(row_values.keys()) for row_values in baseline_table_data.values()])) unmached_baseline_column_headers = set(baseline_row_headers) - set(row_headers) if unmached_baseline_column_headers: @@ -166,15 +186,20 @@ def print_confidence_intervals_table(table_name, print_markdown_table(table_content) -def format_string_pretty_printer(format_string): - def pretty_print(s): +def format_string_pretty_printer(format_string: str) -> Callable[[str], str]: + def pretty_print(s: str): return format_string % s return pretty_print +def float_to_str(x: float) -> str: + if x > 100: + return str(int(x)) + else: + return '%.2g' % x -def interval_pretty_printer(interval, unit, multiplier): - interval = interval.copy() +def interval_pretty_printer(interval: Interval, unit: str, multiplier: float) -> str: + interval = list(interval) # type: List[Any] interval[0] *= multiplier interval[1] *= multiplier @@ -184,11 +209,11 @@ def interval_pretty_printer(interval, unit, multiplier): if int(interval[0]) == interval[0] and interval[0] >= 10: interval[0] = int(interval[0]) else: - interval[0] = '%.3g' % interval[0] + interval[0] = float_to_str(interval[0]) if int(interval[1]) == interval[1] and interval[1] >= 10: interval[1] = int(interval[1]) else: - interval[1] = '%.3g' % interval[1] + interval[1] = float_to_str(interval[1]) if interval[0] == interval[1]: return '%s %s' % (interval[0], unit) @@ -198,7 +223,7 @@ def interval_pretty_printer(interval, unit, multiplier): # Finds the best unit to represent values in the range [min_value, max_value]. # The units must be specified as an ordered list [multiplier1, ..., multiplierN] -def find_best_unit(units, min_value, max_value): +def find_best_unit(units: List[float], min_value: float, max_value: float) -> float: assert min_value <= max_value if max_value <= units[0]: return units[0] @@ -222,7 +247,7 @@ def find_best_unit(units, min_value, max_value): return units[0] -def time_interval_pretty_printer(time_interval, min_in_table, max_in_table): +def time_interval_pretty_printer(time_interval: Interval, min_in_table: float, max_in_table: float) -> str: sec = 1 milli = 0.001 micro = milli * milli @@ -235,7 +260,7 @@ def time_interval_pretty_printer(time_interval, min_in_table, max_in_table): return interval_pretty_printer(time_interval, unit=unit_name, multiplier=1 / unit) -def file_size_interval_pretty_printer(file_size_interval, min_in_table, max_in_table): +def file_size_interval_pretty_printer(file_size_interval: Interval, min_in_table: float, max_in_table: float) -> str: byte = 1 kb = 1024 mb = kb * kb @@ -254,11 +279,11 @@ def make_immutable(x): return x -def dict_pretty_printer(dict_data): +def dict_pretty_printer(dict_data: List[Dict[str, Union[str, Tuple[str]]]]) -> Callable[[Union[str, Tuple[str]]], str]: if isinstance(dict_data, list): dict_data = {make_immutable(mapping['from']): mapping['to'] for mapping in dict_data} - def pretty_print(s): + def pretty_print(s: Union[str, Tuple[str]]) -> str: if s in dict_data: return dict_data[s] else: @@ -267,7 +292,8 @@ def dict_pretty_printer(dict_data): return pretty_print -def determine_column_pretty_printer(pretty_printer_definition): + +def determine_column_pretty_printer(pretty_printer_definition: Dict[str, Any]) -> DimensionPrettyPrinter: if 'format_string' in pretty_printer_definition: return format_string_pretty_printer(pretty_printer_definition['format_string']) @@ -276,19 +302,23 @@ def determine_column_pretty_printer(pretty_printer_definition): raise Exception("Unrecognized pretty printer description: %s" % pretty_printer_definition) - -def determine_row_pretty_printer(pretty_printer_definition): +def determine_row_pretty_printer(pretty_printer_definition: Dict[str, Any]) -> DimensionPrettyPrinter: return determine_column_pretty_printer(pretty_printer_definition) +def determine_row_sort_key(pretty_printer_definition: Dict[str, Any]) -> Callable[[Any], Any]: + if 'fixed_map' in pretty_printer_definition: + indexes = {x: i for i, x in enumerate(pretty_printer_definition['fixed_map'].keys())} + return lambda s: indexes[s] -def determine_value_pretty_printer(unit): + return lambda x: x + +def determine_value_pretty_printer(unit: str) -> IntervalPrettyPrinter: if unit == "seconds": return time_interval_pretty_printer if unit == "bytes": return file_size_interval_pretty_printer raise Exception("Unrecognized unit: %s" % unit) - def main(): parser = argparse.ArgumentParser(description='Runs all the benchmarks whose results are on the Fruit website.') parser.add_argument('--benchmark-results', @@ -314,17 +344,23 @@ def main(): baseline_bench_results = None with open(args.benchmark_tables_definition, 'r') as f: - for table_definition in yaml.load(f)["tables"]: + used_bench_results = set() + # Set of (Benchmark definition, Benchmark result name) pairs + used_bench_result_values = set() + config = yaml.full_load(f) + for table_definition in config["tables"]: try: fixed_benchmark_params = {dimension_name: make_immutable(dimension_value) for dimension_name, dimension_value in table_definition['benchmark_filter'].items()} - table_data = extract_results( + table_data, last_used_bench_results, last_used_bench_result_values = extract_results( bench_results, fixed_benchmark_params=fixed_benchmark_params, column_dimension=table_definition['columns']['dimension'], row_dimension=table_definition['rows']['dimension'], result_dimension=table_definition['results']['dimension']) + used_bench_results = used_bench_results.union(last_used_bench_results) + used_bench_result_values = used_bench_result_values.union(last_used_bench_result_values) if baseline_bench_results: - baseline_table_data = extract_results( + baseline_table_data, _, _ = extract_results( baseline_bench_results, fixed_benchmark_params=fixed_benchmark_params, column_dimension=table_definition['columns']['dimension'], @@ -340,13 +376,29 @@ def main(): baseline_table_data, column_header_pretty_printer=determine_column_pretty_printer(columns_pretty_printer_definition), row_header_pretty_printer=determine_row_pretty_printer(rows_pretty_printer_definition), - value_pretty_printer=determine_value_pretty_printer(results_unit)) + value_pretty_printer=determine_value_pretty_printer(results_unit), + row_sort_key=determine_row_sort_key(rows_pretty_printer_definition)) print() print() except Exception as e: - print('While processing table:\n' + table_definition) + print('While processing table:\n%s' % table_definition) print() raise e + allowed_unused_benchmarks = set(config.get('allowed_unused_benchmarks', [])) + allowed_unused_benchmark_results = set(config.get('allowed_unused_benchmark_results', [])) + for bench_result in bench_results: + params = {dimension_name: make_immutable(dimension_value) + for dimension_name, dimension_value in bench_result['benchmark'].items()} + benchmark_defn = tuple(sorted(params.items())) + if benchmark_defn not in used_bench_results: + if params['name'] not in allowed_unused_benchmarks: + print('Warning: benchmark result did not match any tables: %s' % params) + else: + unused_result_dimensions = {result_dimension + for result_dimension in bench_result['results'].keys() + if (benchmark_defn, result_dimension) not in used_bench_result_values and result_dimension not in allowed_unused_benchmark_results} + if unused_result_dimensions: + print('Warning: unused result dimensions %s in benchmark result %s' % (unused_result_dimensions, params)) if __name__ == "__main__": diff --git a/extras/benchmark/fruit_source_generator.py b/extras/benchmark/fruit_source_generator.py index 894bd28..f7bc786 100644 --- a/extras/benchmark/fruit_source_generator.py +++ b/extras/benchmark/fruit_source_generator.py @@ -11,29 +11,32 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from typing import List +import networkx as nx -def generate_files(injection_graph, generate_runtime_bench_code, use_normalized_component=False): + +def generate_files(injection_graph: nx.DiGraph, generate_runtime_bench_code: bool, use_normalized_component: bool=False): if use_normalized_component: assert not generate_runtime_bench_code file_content_by_name = dict() - for node_id in injection_graph.nodes_iter(): + for node_id in injection_graph.nodes: file_content_by_name['component%s.h' % node_id] = _generate_component_header(node_id) - file_content_by_name['component%s.cpp' % node_id] = _generate_component_source(node_id, injection_graph.successors(node_id)) + file_content_by_name['component%s.cpp' % node_id] = _generate_component_source(node_id, list(injection_graph.successors(node_id))) [toplevel_node] = [node_id - for node_id in injection_graph.nodes_iter() - if not injection_graph.predecessors(node_id)] + for node_id in injection_graph.nodes + if not any(True for p in injection_graph.predecessors(node_id))] file_content_by_name['main.cpp'] = _generate_main(toplevel_node, generate_runtime_bench_code) return file_content_by_name -def _get_component_type(component_index): +def _get_component_type(component_index: int): return 'fruit::Component<Interface{component_index}>'.format(**locals()) -def _generate_component_header(component_index): +def _generate_component_header(component_index: int): component_type = _get_component_type(component_index) template = """ #ifndef COMPONENT{component_index}_H @@ -54,7 +57,7 @@ struct Interface{component_index} {{ """ return template.format(**locals()) -def _generate_component_source(component_index, deps): +def _generate_component_source(component_index: int, deps: List[int]): include_directives = ''.join(['#include "component%s.h"\n' % index for index in deps + [component_index]]) fields = ''.join(['Interface%s& x%s;\n' % (dep, dep) @@ -95,7 +98,7 @@ struct X{component_index} : public Interface{component_index} {{ return template.format(**locals()) -def _generate_main(toplevel_component, generate_runtime_bench_code): +def _generate_main(toplevel_component: int, generate_runtime_bench_code: bool): if generate_runtime_bench_code: template = """ #include "component{toplevel_component}.h" diff --git a/extras/benchmark/generate_benchmark.py b/extras/benchmark/generate_benchmark.py index cee0017..411e9a6 100755 --- a/extras/benchmark/generate_benchmark.py +++ b/extras/benchmark/generate_benchmark.py @@ -24,9 +24,9 @@ import argparse import networkx as nx -def generate_injection_graph(num_components_with_no_deps, - num_components_with_deps, - num_deps): +def generate_injection_graph(num_components_with_no_deps: int, + num_components_with_deps: int, + num_deps: int): injection_graph = nx.DiGraph() num_used_ids = 0 @@ -71,23 +71,23 @@ def generate_injection_graph(num_components_with_no_deps, return injection_graph def generate_benchmark( - di_library, - compiler, - cxx_std, - output_dir, - num_components_with_no_deps, - num_components_with_deps, - num_deps, - generate_runtime_bench_code, - use_exceptions=True, - use_rtti=True, - fruit_build_dir=None, - fruit_sources_dir=None, - boost_di_sources_dir=None, - generate_debuginfo=False, - use_new_delete=False, - use_interfaces=False, - use_normalized_component=False): + di_library: str, + compiler: str, + cxx_std: str, + output_dir: str, + num_components_with_no_deps: int, + num_components_with_deps: int, + num_deps: int, + generate_runtime_bench_code: bool, + use_exceptions: bool=True, + use_rtti: bool=True, + fruit_build_dir: str=None, + fruit_sources_dir: str=None, + boost_di_sources_dir: str=None, + generate_debuginfo: bool=False, + use_new_delete: bool=False, + use_interfaces: bool=False, + use_normalized_component: bool=False): """Generates a sample codebase using the specified DI library, meant for benchmarking. :param boost_di_sources_dir: this is only used if di_library=='boost_di', it can be None otherwise. @@ -135,8 +135,8 @@ def generate_benchmark( other_compile_flags.append('-fno-exceptions') if not use_rtti: other_compile_flags.append('-fno-rtti') - compile_command = '%s -std=%s -MMD -MP -O2 -W -Wall -Werror -DNDEBUG -ftemplate-depth=10000 %s %s' % (compiler, cxx_std, include_flags, ' '.join(other_compile_flags)) - link_command = '%s -std=%s -O2 -W -Wall -Werror %s %s' % (compiler, cxx_std, rpath_flags, library_dirs_flags) + compile_command = '%s -std=%s -MMD -MP -O2 -W -Wall -DNDEBUG -ftemplate-depth=10000 %s %s' % (compiler, cxx_std, include_flags, ' '.join(other_compile_flags)) + link_command = '%s -std=%s -O2 -W -Wall %s %s' % (compiler, cxx_std, rpath_flags, library_dirs_flags) # GCC requires passing the -lfruit flag *after* all object files to be linked for some reason. link_command_suffix = link_libraries_flags diff --git a/extras/benchmark/makefile_generator.py b/extras/benchmark/makefile_generator.py index 083fd36..7781a6e 100644 --- a/extras/benchmark/makefile_generator.py +++ b/extras/benchmark/makefile_generator.py @@ -11,23 +11,30 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from typing import List -def generate_makefile(cpp_files, executable_name, compile_command, link_command, link_command_suffix): +def generate_makefile(cpp_files: List[str], executable_name: str, compile_command: str, link_command: str, link_command_suffix: str): assert executable_name + '.cpp' in cpp_files, '%s.cpp in %s' % (executable_name, cpp_files) link_rule_template = """ {executable_name}: {object_files} \t{link_command} {object_files} -o {executable_name} {link_command_suffix} + +{executable_name}_ram.txt: {object_files_ram_txt} +\t(cat {object_files_ram_txt}; /bin/time -v {link_command} {object_files} -o {executable_name}.tmp {link_command_suffix} 2>&1 | fgrep 'Maximum resident set size' | sed 's|.*: ||') >{executable_name}_ram.txt """ compile_rule_template = """ {name}.o: {name}.cpp \t{compile_command} -c {name}.cpp -o {name}.o + +{name}.o_ram.txt: {name}.cpp +\t/bin/time -v {compile_command} -c {name}.cpp -o {name}.o 2>&1 | fgrep 'Maximum resident set size' | sed 's|.*: ||' >{name}.o_ram.txt """ clean_rule_template = """ clean: -\trm -f {object_files} {dep_files} {executable_name} +\trm -f {object_files} {dep_files} {executable_name} {executable_name}_ram.txt {object_files_ram_txt} """ dep_file_deps = """ @@ -40,6 +47,7 @@ include {dep_files} compile_rules = [] object_files = [] + object_files_ram_txt = [] dep_files = [] for cpp_file in cpp_files: assert cpp_file.endswith('.cpp') @@ -50,16 +58,19 @@ include {dep_files} compile_command=compile_command) compile_rules.append(compile_rule) object_files.append('%s.o' % source) + object_files_ram_txt.append('%s.o_ram.txt' % source) dep_files.append('%s.d' % source) link_rule = link_rule_template.format( object_files=' '.join(object_files), + object_files_ram_txt=' '.join(object_files_ram_txt), link_command=link_command, link_command_suffix=link_command_suffix, executable_name=executable_name) clean_rule = clean_rule_template.format( object_files=' '.join(object_files), + object_files_ram_txt=' '.join(object_files_ram_txt), executable_name=executable_name, dep_files=' '.join(dep_files)) diff --git a/extras/benchmark/new_delete_benchmark.cpp b/extras/benchmark/new_delete_benchmark.cpp index 8131eac..d30d835 100644 --- a/extras/benchmark/new_delete_benchmark.cpp +++ b/extras/benchmark/new_delete_benchmark.cpp @@ -29,6 +29,9 @@ #elif MULTIPLIER == 100 #define REPEAT(X) REPEAT_100(X, _) +#elif MULTIPLIER == 250 +#define REPEAT(X) REPEAT_250(X, _) + #elif MULTIPLIER == 1000 #define REPEAT(X) REPEAT_1000(X, _) @@ -48,12 +51,21 @@ R PLACEHOLDER(X, I##5) R PLACEHOLDER(X, I##6) R PLACEHOLDER(X, I##7) R PLACEHOLDER(X, I##8) \ R PLACEHOLDER(X, I##9) +#define META_REPEAT_5(R, X, I) \ + R PLACEHOLDER(X, I##0) R PLACEHOLDER(X, I##1) R PLACEHOLDER(X, I##2) R PLACEHOLDER(X, I##3) R PLACEHOLDER(X, I##4) + #define REPEAT_1(X, I) X(I) +#define REPEAT_5(X, I) META_REPEAT_5(REPEAT_1, X, I) + #define REPEAT_10(X, I) META_REPEAT_10(REPEAT_1, X, I) +#define REPEAT_25(X, I) META_REPEAT_5(REPEAT_5, X, I) + #define REPEAT_100(X, I) META_REPEAT_10(REPEAT_10, X, I) +#define REPEAT_250(X, I) META_REPEAT_10(REPEAT_25, X, I) + #define REPEAT_1000(X, I) META_REPEAT_10(REPEAT_100, X, I) using namespace std; diff --git a/extras/benchmark/no_di_library_source_generator.py b/extras/benchmark/no_di_library_source_generator.py index 2d91d04..65046a2 100644 --- a/extras/benchmark/no_di_library_source_generator.py +++ b/extras/benchmark/no_di_library_source_generator.py @@ -12,13 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. import itertools +from typing import List + import networkx as nx -def generate_files(injection_graph, use_new_delete, use_interfaces, generate_runtime_bench_code): +def generate_files(injection_graph: nx.DiGraph, use_new_delete: bool, use_interfaces: bool, generate_runtime_bench_code: bool): file_content_by_name = dict() - for node_id in injection_graph.nodes_iter(): - deps = injection_graph.successors(node_id) + for node_id in injection_graph.nodes: + deps = list(injection_graph.successors(node_id)) if use_interfaces: file_content_by_name['class%s_interface.h' % node_id] = _generate_class_interface_header(node_id) file_content_by_name['class%s.h' % node_id] = _generate_class_header_with_interfaces(node_id, deps) @@ -31,7 +33,7 @@ def generate_files(injection_graph, use_new_delete, use_interfaces, generate_run return file_content_by_name -def _generate_class_interface_header(class_index): +def _generate_class_interface_header(class_index: int): template = """ #ifndef CLASS{class_index}_INTERFACE_H #define CLASS{class_index}_INTERFACE_H @@ -48,7 +50,7 @@ struct Interface{class_index} {{ """ return template.format(**locals()) -def _generate_class_header_with_interfaces(class_index, deps): +def _generate_class_header_with_interfaces(class_index: int, deps: List[int]): include_directives = ''.join('#include "class%s_interface.h"\n' % index for index in itertools.chain(deps, (class_index,))) fields = ''.join('Interface%s& x%s;\n' % (index, index) @@ -75,7 +77,7 @@ struct Class{class_index} : public Interface{class_index} {{ """ return template.format(**locals()) -def _generate_class_header_without_interfaces(class_index, deps): +def _generate_class_header_without_interfaces(class_index: int, deps: List[int]): include_directives = ''.join('#include "class%s.h"\n' % index for index in deps) fields = ''.join('Class%s& x%s;\n' % (index, index) @@ -101,7 +103,7 @@ struct Class{class_index} {{ """ return template.format(**locals()) -def _generate_class_cpp_file_with_interfaces(class_index, deps): +def _generate_class_cpp_file_with_interfaces(class_index: int, deps: List[int]): constructor_params = ', '.join('Interface%s& x%s' % (index, index) for index in deps) field_initializers = ', '.join('x%s(x%s)' % (index, index) @@ -127,7 +129,7 @@ Class{class_index}::~Class{class_index}() {{ """ return template.format(**locals()) -def _generate_class_cpp_file_without_interfaces(class_index, deps): +def _generate_class_cpp_file_without_interfaces(class_index: int, deps: List[int]): constructor_params = ', '.join('Class%s& x%s' % (index, index) for index in deps) field_initializers = ', '.join('x%s(x%s)' % (index, index) @@ -145,14 +147,14 @@ Class{class_index}::Class{class_index}({constructor_params}) return template.format(**locals()) -def _generate_main(injection_graph, use_interfaces, use_new_delete, generate_runtime_bench_code): +def _generate_main(injection_graph: nx.DiGraph, use_interfaces: bool, use_new_delete: bool, generate_runtime_bench_code: bool): [toplevel_class_index] = [node_id - for node_id in injection_graph.nodes_iter() - if not injection_graph.predecessors(node_id)] + for node_id in injection_graph.nodes + if not any(True for p in injection_graph.predecessors(node_id))] if use_interfaces: include_directives = ''.join('#include "class%s.h"\n' % index - for index in injection_graph.nodes_iter()) + for index in injection_graph.nodes) else: include_directives = '#include "class%s.h"\n' % toplevel_class_index @@ -171,7 +173,7 @@ def _generate_main(injection_graph, use_interfaces, use_new_delete, generate_run for class_index in reversed(list(nx.topological_sort(injection_graph)))) void_casts = ''.join('(void) x%s;\n' % index - for index in injection_graph.nodes_iter()) + for index in injection_graph.nodes) if generate_runtime_bench_code: template = """ diff --git a/extras/benchmark/run_benchmarks.py b/extras/benchmark/run_benchmarks.py index d19232b..1fc3fd4 100755 --- a/extras/benchmark/run_benchmarks.py +++ b/extras/benchmark/run_benchmarks.py @@ -22,13 +22,15 @@ import tempfile import os import shutil import itertools +import traceback +from typing import Dict, List, Tuple, Optional, Any, TypeVar, Callable, Iterable + import numpy import subprocess import yaml from numpy import floor, log10 import scipy import multiprocessing -import sh import json import statsmodels.stats.api as stats from generate_benchmark import generate_benchmark @@ -36,7 +38,7 @@ import git from functools import lru_cache as memoize class CommandFailedException(Exception): - def __init__(self, command, stdout, stderr, error_code): + def __init__(self, command: List[str], stdout: str, stderr: str, error_code: str): self.command = command self.stdout = stdout self.stderr = stderr @@ -53,7 +55,7 @@ class CommandFailedException(Exception): {stderr} ''').format(command=self.command, error_code=self.error_code, stdout=self.stdout, stderr=self.stderr) -def run_command(executable, args=[], cwd=None, env=None): +def run_command(executable: str, args: List[Any]=[], cwd: str=None, env: Dict[str, str]=None) -> Tuple[str, str]: args = [str(arg) for arg in args] command = [executable] + args try: @@ -70,7 +72,7 @@ compile_flags = ['-O2', '-DNDEBUG'] make_args = ['-j', multiprocessing.cpu_count() + 1] -def parse_results(result_lines): +def parse_results(result_lines: List[str]) -> Dict[str, float]: """ Parses results from the format: ['Dimension name1 = 123', @@ -89,7 +91,7 @@ def parse_results(result_lines): # We memoize the result since this might be called repeatedly and it's somewhat expensive. @memoize(maxsize=None) -def determine_compiler_name(compiler_executable_name): +def determine_compiler_name(compiler_executable_name: str) -> str: tmpdir = tempfile.gettempdir() + '/fruit-determine-compiler-version-dir' ensure_empty_dir(tmpdir) with open(tmpdir + '/CMakeLists.txt', 'w') as file: @@ -112,7 +114,7 @@ def determine_compiler_name(compiler_executable_name): # Returns a pair (sha256_hash, version_name), where version_name will be None if no version tag was found at HEAD. @memoize(maxsize=None) -def git_repo_info(repo_path): +def git_repo_info(repo_path: str) -> Tuple[str, str]: repo = git.Repo(repo_path) head_tags = [tag.name for tag in repo.tags if tag.commit == repo.head.commit and re.match('v[0-9].*', tag.name)] if head_tags == []: @@ -129,7 +131,7 @@ def git_repo_info(repo_path): # We put the compiler name/version in the results because the same 'compiler' value might refer to different compiler versions # (e.g. if GCC 6.0.0 is installed when benchmarks are run, then it's updated to GCC 6.0.1 and finally the results are formatted, we # want the formatted results to say "GCC 6.0.0" instead of "GCC 6.0.1"). -def add_synthetic_benchmark_parameters(original_benchmark_parameters, path_to_code_under_test): +def add_synthetic_benchmark_parameters(original_benchmark_parameters: Dict[str, Any], path_to_code_under_test: Optional[str]): benchmark_params = original_benchmark_parameters.copy() benchmark_params['compiler_name'] = determine_compiler_name(original_benchmark_parameters['compiler']) if path_to_code_under_test is not None: @@ -140,8 +142,13 @@ def add_synthetic_benchmark_parameters(original_benchmark_parameters, path_to_co return benchmark_params -class SimpleNewDeleteRunTimeBenchmark: - def __init__(self, benchmark_definition, fruit_benchmark_sources_dir): +class Benchmark: + def prepare(self) -> None: ... + def run(self) -> Dict[str, float]: ... + def describe(self) -> str: ... + +class SimpleNewDeleteRunTimeBenchmark(Benchmark): + def __init__(self, benchmark_definition: Dict[str, Any], fruit_benchmark_sources_dir: str): self.benchmark_definition = add_synthetic_benchmark_parameters(benchmark_definition, path_to_code_under_test=None) self.fruit_benchmark_sources_dir = fruit_benchmark_sources_dir @@ -170,8 +177,8 @@ class SimpleNewDeleteRunTimeBenchmark: return self.benchmark_definition -class FruitSingleFileCompileTimeBenchmark: - def __init__(self, benchmark_definition, fruit_sources_dir, fruit_build_dir, fruit_benchmark_sources_dir): +class FruitSingleFileCompileTimeBenchmark(Benchmark): + def __init__(self, benchmark_definition: Dict[str, Any], fruit_sources_dir: str, fruit_build_dir: str, fruit_benchmark_sources_dir: str): self.benchmark_definition = add_synthetic_benchmark_parameters(benchmark_definition, path_to_code_under_test=fruit_sources_dir) self.fruit_sources_dir = fruit_sources_dir self.fruit_build_dir = fruit_build_dir @@ -207,7 +214,7 @@ class FruitSingleFileCompileTimeBenchmark: return self.benchmark_definition -def ensure_empty_dir(dirname): +def ensure_empty_dir(dirname: str): # We start by creating the directory instead of just calling rmtree with ignore_errors=True because that would ignore # all errors, so we might otherwise go ahead even if the directory wasn't properly deleted. os.makedirs(dirname, exist_ok=True) @@ -215,7 +222,7 @@ def ensure_empty_dir(dirname): os.makedirs(dirname) -class GenericGeneratedSourcesBenchmark: +class GenericGeneratedSourcesBenchmark(Benchmark): def __init__(self, di_library, benchmark_definition, @@ -258,6 +265,10 @@ class GenericGeneratedSourcesBenchmark: self.arbitrary_files = [files[i * (len(files) // (num_files_changed + 2))] for i in range(1, num_files_changed + 1)] + def prepare_compile_memory_benchmark(self): + self.prepare_compile_benchmark() + self.run_compile_memory_benchmark() + def prepare_runtime_benchmark(self): self.prepare_compile_benchmark() self.run_make_build() @@ -289,6 +300,16 @@ class GenericGeneratedSourcesBenchmark: result = {'incremental_compile_time': end - start} return result + def run_compile_memory_benchmark(self): + run_command('make', args=make_args + ['clean'], cwd=self.tmpdir) + run_command('make', args=make_args + ['main_ram.txt'], cwd=self.tmpdir) + with open(self.tmpdir + '/main_ram.txt') as f: + ram_usages = [int(n)*1024 for n in f.readlines()] + return { + 'total_max_ram_usage': sum(ram_usages), + 'max_ram_usage': max(ram_usages), + } + def run_runtime_benchmark(self): num_classes = self.benchmark_definition['num_classes'] loop_factor = self.benchmark_definition['loop_factor'] @@ -340,6 +361,17 @@ class IncrementalCompileTimeBenchmark(GenericGeneratedSourcesBenchmark): def run(self): return self.run_incremental_compile_benchmark() +class CompileMemoryBenchmark(GenericGeneratedSourcesBenchmark): + def __init__(self, **kwargs): + super().__init__(generate_runtime_bench_code=False, + **kwargs) + + def prepare(self): + self.prepare_compile_memory_benchmark() + + def run(self): + return self.run_compile_memory_benchmark() + class StartupTimeBenchmark(GenericGeneratedSourcesBenchmark): def __init__(self, **kwargs): super().__init__(generate_runtime_bench_code=False, @@ -395,6 +427,13 @@ class FruitIncrementalCompileTimeBenchmark(IncrementalCompileTimeBenchmark): fruit_sources_dir=fruit_sources_dir, **kwargs) +class FruitCompileMemoryBenchmark(CompileMemoryBenchmark): + def __init__(self, fruit_sources_dir, **kwargs): + super().__init__(di_library='fruit', + path_to_code_under_test=fruit_sources_dir, + fruit_sources_dir=fruit_sources_dir, + **kwargs) + class FruitRunTimeBenchmark(RunTimeBenchmark): def __init__(self, fruit_sources_dir, **kwargs): super().__init__(di_library='fruit', @@ -444,6 +483,13 @@ class BoostDiIncrementalCompileTimeBenchmark(IncrementalCompileTimeBenchmark): boost_di_sources_dir=boost_di_sources_dir, **kwargs) +class BoostDiCompileMemoryBenchmark(CompileMemoryBenchmark): + def __init__(self, boost_di_sources_dir, **kwargs): + super().__init__(di_library='boost_di', + path_to_code_under_test=boost_di_sources_dir, + boost_di_sources_dir=boost_di_sources_dir, + **kwargs) + class BoostDiRunTimeBenchmark(RunTimeBenchmark): def __init__(self, boost_di_sources_dir, **kwargs): super().__init__(di_library='boost_di', @@ -484,6 +530,11 @@ class SimpleDiIncrementalCompileTimeBenchmark(IncrementalCompileTimeBenchmark): super().__init__(di_library='none', **kwargs) +class SimpleDiCompileMemoryBenchmark(CompileMemoryBenchmark): + def __init__(self, **kwargs): + super().__init__(di_library='none', + **kwargs) + class SimpleDiRunTimeBenchmark(RunTimeBenchmark): def __init__(self, **kwargs): super().__init__(di_library='none', @@ -514,6 +565,10 @@ class SimpleDiWithInterfacesIncrementalCompileTimeBenchmark(SimpleDiIncrementalC def __init__(self, **kwargs): super().__init__(use_interfaces=True, **kwargs) +class SimpleDiWithInterfacesCompileMemoryBenchmark(SimpleDiCompileMemoryBenchmark): + def __init__(self, **kwargs): + super().__init__(use_interfaces=True, **kwargs) + class SimpleDiWithInterfacesRunTimeBenchmark(SimpleDiRunTimeBenchmark): def __init__(self, **kwargs): super().__init__(use_interfaces=True, **kwargs) @@ -540,6 +595,10 @@ class SimpleDiWithInterfacesAndNewDeleteIncrementalCompileTimeBenchmark(SimpleDi def __init__(self, **kwargs): super().__init__(use_new_delete=True, **kwargs) +class SimpleDiWithInterfacesAndNewDeleteCompileMemoryBenchmark(SimpleDiWithInterfacesCompileMemoryBenchmark): + def __init__(self, **kwargs): + super().__init__(use_new_delete=True, **kwargs) + class SimpleDiWithInterfacesAndNewDeleteRunTimeBenchmark(SimpleDiWithInterfacesRunTimeBenchmark): def __init__(self, **kwargs): super().__init__(use_new_delete=True, **kwargs) @@ -559,13 +618,13 @@ class SimpleDiWithInterfacesAndNewDeleteExecutableSizeBenchmarkWithoutExceptions super().__init__(use_new_delete=True, **kwargs) -def round_to_significant_digits(n, num_significant_digits): +def round_to_significant_digits(n: float, num_significant_digits: int) -> float: if n <= 0: # We special-case this, otherwise the log10 below will fail. return 0 return round(n, num_significant_digits - int(floor(log10(n))) - 1) -def run_benchmark(benchmark, max_runs, timeout_hours, output_file, min_runs=3): +def run_benchmark(benchmark: Benchmark, max_runs: int, timeout_hours: int, output_file: str, min_runs: int=3) -> None: def run_benchmark_once(): print('Running benchmark... ', end='', flush=True) result = benchmark.run() @@ -627,7 +686,7 @@ def run_benchmark(benchmark, max_runs, timeout_hours, output_file, min_runs=3): print() -def expand_benchmark_definition(benchmark_definition): +def expand_benchmark_definition(benchmark_definition: Dict[str, Any]) -> List[Dict[str, Tuple[Any]]]: """ Takes a benchmark definition, e.g.: [{name: 'foo', compiler: ['g++-5', 'g++-6']}, @@ -650,12 +709,15 @@ def expand_benchmark_definition(benchmark_definition): for value_combination in value_combinations] -def expand_benchmark_definitions(benchmark_definitions): +def expand_benchmark_definitions(benchmark_definitions: List[Dict[str, Any]]): return list(itertools.chain(*[expand_benchmark_definition(benchmark_definition) for benchmark_definition in benchmark_definitions])) -def group_by(l, element_to_key): - """Takes a list and returns a dict of sublists, where the elements are grouped using the provided function""" - result = defaultdict(list) +T = TypeVar('T') +K = TypeVar('K') + +def group_by(l: List[T], element_to_key: Callable[[T], K]) -> Iterable[Tuple[K, List[T]]]: + """Takes a list and returns a list of sublists, where the elements are grouped using the provided function""" + result = defaultdict(list) # type: Dict[K, List[T]] for elem in l: result[element_to_key(elem)].append(elem) return result.items() @@ -690,7 +752,7 @@ def main(): fruit_build_dir = tempfile.gettempdir() + '/fruit-benchmark-build-dir' with open(args.benchmark_definition, 'r') as f: - yaml_file_content = yaml.load(f) + yaml_file_content = yaml.full_load(f) global_definitions = yaml_file_content['global'] benchmark_definitions = expand_benchmark_definitions(yaml_file_content['benchmarks']) @@ -702,24 +764,28 @@ def main(): (benchmark_definition['compiler'], tuple(benchmark_definition['additional_cmake_args']))): print('Preparing for benchmarks with the compiler %s, with additional CMake args %s' % (compiler_executable_name, additional_cmake_args)) - # We compute this here (and memoize the result) so that the benchmark's describe() will retrieve the cached - # value instantly. - determine_compiler_name(compiler_executable_name) - - # Build Fruit in fruit_build_dir, so that fruit_build_dir points to a built Fruit (useful for e.g. the config header). - shutil.rmtree(fruit_build_dir, ignore_errors=True) - os.makedirs(fruit_build_dir) - modified_env = os.environ.copy() - modified_env['CXX'] = compiler_executable_name - run_command('cmake', - args=[ - args.fruit_sources_dir, - '-DCMAKE_BUILD_TYPE=Release', - *additional_cmake_args, - ], - cwd=fruit_build_dir, - env=modified_env) - run_command('make', args=make_args, cwd=fruit_build_dir) + try: + # We compute this here (and memoize the result) so that the benchmark's describe() will retrieve the cached + # value instantly. + determine_compiler_name(compiler_executable_name) + + # Build Fruit in fruit_build_dir, so that fruit_build_dir points to a built Fruit (useful for e.g. the config header). + shutil.rmtree(fruit_build_dir, ignore_errors=True) + os.makedirs(fruit_build_dir) + modified_env = os.environ.copy() + modified_env['CXX'] = compiler_executable_name + run_command('cmake', + args=[ + args.fruit_sources_dir, + '-DCMAKE_BUILD_TYPE=Release', + *additional_cmake_args, + ], + cwd=fruit_build_dir, + env=modified_env) + run_command('make', args=make_args, cwd=fruit_build_dir) + except Exception as e: + print('Exception while preparing for benchmarks with the compiler %s, with additional CMake args %s.\n%s\nGoing ahead with the rest.' % (compiler_executable_name, additional_cmake_args, traceback.format_exc())) + continue for benchmark_definition in benchmark_definitions_with_current_config: benchmark_index += 1 @@ -744,6 +810,7 @@ def main(): benchmark_class = { 'fruit_compile_time': FruitCompileTimeBenchmark, 'fruit_incremental_compile_time': FruitIncrementalCompileTimeBenchmark, + 'fruit_compile_memory': FruitCompileMemoryBenchmark, 'fruit_run_time': FruitRunTimeBenchmark, 'fruit_startup_time': FruitStartupTimeBenchmark, 'fruit_startup_time_with_normalized_component': FruitStartupTimeWithNormalizedComponentBenchmark, @@ -758,6 +825,7 @@ def main(): benchmark_class = { 'boost_di_compile_time': BoostDiCompileTimeBenchmark, 'boost_di_incremental_compile_time': BoostDiIncrementalCompileTimeBenchmark, + 'boost_di_compile_memory': BoostDiCompileMemoryBenchmark, 'boost_di_run_time': BoostDiRunTimeBenchmark, 'boost_di_startup_time': BoostDiStartupTimeBenchmark, 'boost_di_executable_size': BoostDiExecutableSizeBenchmark, @@ -770,18 +838,21 @@ def main(): benchmark_class = { 'simple_di_compile_time': SimpleDiCompileTimeBenchmark, 'simple_di_incremental_compile_time': SimpleDiIncrementalCompileTimeBenchmark, + 'simple_di_compile_memory': SimpleDiCompileMemoryBenchmark, 'simple_di_run_time': SimpleDiRunTimeBenchmark, 'simple_di_startup_time': SimpleDiStartupTimeBenchmark, 'simple_di_executable_size': SimpleDiExecutableSizeBenchmark, 'simple_di_executable_size_without_exceptions_and_rtti': SimpleDiExecutableSizeBenchmarkWithoutExceptionsAndRtti, 'simple_di_with_interfaces_compile_time': SimpleDiWithInterfacesCompileTimeBenchmark, 'simple_di_with_interfaces_incremental_compile_time': SimpleDiWithInterfacesIncrementalCompileTimeBenchmark, + 'simple_di_with_interfaces_compile_memory': SimpleDiWithInterfacesCompileMemoryBenchmark, 'simple_di_with_interfaces_run_time': SimpleDiWithInterfacesRunTimeBenchmark, 'simple_di_with_interfaces_startup_time': SimpleDiWithInterfacesStartupTimeBenchmark, 'simple_di_with_interfaces_executable_size': SimpleDiWithInterfacesExecutableSizeBenchmark, 'simple_di_with_interfaces_executable_size_without_exceptions_and_rtti': SimpleDiWithInterfacesExecutableSizeBenchmarkWithoutExceptionsAndRtti, 'simple_di_with_interfaces_and_new_delete_compile_time': SimpleDiWithInterfacesAndNewDeleteCompileTimeBenchmark, 'simple_di_with_interfaces_and_new_delete_incremental_compile_time': SimpleDiWithInterfacesAndNewDeleteIncrementalCompileTimeBenchmark, + 'simple_di_with_interfaces_and_new_delete_compile_memory': SimpleDiWithInterfacesAndNewDeleteCompileMemoryBenchmark, 'simple_di_with_interfaces_and_new_delete_run_time': SimpleDiWithInterfacesAndNewDeleteRunTimeBenchmark, 'simple_di_with_interfaces_and_new_delete_startup_time': SimpleDiWithInterfacesAndNewDeleteStartupTimeBenchmark, 'simple_di_with_interfaces_and_new_delete_executable_size': SimpleDiWithInterfacesAndNewDeleteExecutableSizeBenchmark, @@ -795,11 +866,14 @@ def main(): if benchmark.describe() in previous_run_completed_benchmarks: print("Skipping benchmark that was already run previously (due to --continue-benchmark):", benchmark.describe()) continue - - run_benchmark(benchmark, - output_file=args.output_file, - max_runs=global_definitions['max_runs'], - timeout_hours=global_definitions['max_hours_per_combination']) + + try: + run_benchmark(benchmark, + output_file=args.output_file, + max_runs=global_definitions['max_runs'], + timeout_hours=global_definitions['max_hours_per_combination']) + except Exception as e: + print('Exception while running benchmark: %s.\n%s\nGoing ahead with the rest.' % (benchmark.describe(), traceback.format_exc())) if __name__ == "__main__": diff --git a/extras/benchmark/suites/boost_di.yml b/extras/benchmark/suites/boost_di.yml index 815991c..458d11e 100644 --- a/extras/benchmark/suites/boost_di.yml +++ b/extras/benchmark/suites/boost_di.yml @@ -19,18 +19,21 @@ global: # These values are ignored, they are here just to be referenced below. constants: compilers: &compilers - - "g++-8" - - "clang++-6.0" + - "g++-9" + - "clang++-10" benchmarks: - name: - "boost_di_compile_time" + - "boost_di_compile_memory" - "boost_di_incremental_compile_time" - "boost_di_run_time" + - "boost_di_startup_time" - "boost_di_executable_size" loop_factor: 1.0 num_classes: - 100 + - 250 - 1000 compiler: *compilers cxx_std: "c++14" @@ -38,3 +41,18 @@ benchmarks: - [] benchmark_generation_flags: - [] + + - name: + - "boost_di_executable_size_without_exceptions_and_rtti" + loop_factor: 1.0 + num_classes: + - 100 + - 250 + - 1000 + compiler: *compilers + cxx_std: "c++14" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] + diff --git a/extras/benchmark/suites/debug.yml b/extras/benchmark/suites/debug.yml index 13d6c0b..c31d4d5 100644 --- a/extras/benchmark/suites/debug.yml +++ b/extras/benchmark/suites/debug.yml @@ -22,12 +22,12 @@ global: # These values are ignored, they are here just to be referenced below. constants: compilers: &compilers - - "g++-7" - - "clang++-4.0" + - "g++-9" + - "clang++-10" gcc: &gcc - - "g++-7" + - "g++-9" clang: &clang - - "clang++-4.0" + - "clang++-10" benchmarks: - name: "fruit_single_file_compile_time" @@ -43,16 +43,19 @@ benchmarks: - name: - "new_delete_run_time" - "simple_di_compile_time" + - "simple_di_compile_memory" - "simple_di_incremental_compile_time" - "simple_di_run_time" - "simple_di_startup_time" - "simple_di_executable_size" - "simple_di_with_interfaces_compile_time" + - "simple_di_with_interfaces_compile_memory" - "simple_di_with_interfaces_incremental_compile_time" - "simple_di_with_interfaces_run_time" - "simple_di_with_interfaces_startup_time" - "simple_di_with_interfaces_executable_size" - "simple_di_with_interfaces_and_new_delete_compile_time" + - "simple_di_with_interfaces_and_new_delete_compile_memory" - "simple_di_with_interfaces_and_new_delete_incremental_compile_time" - "simple_di_with_interfaces_and_new_delete_run_time" - "simple_di_with_interfaces_and_new_delete_startup_time" @@ -68,7 +71,22 @@ benchmarks: - [] - name: + - "simple_di_executable_size_without_exceptions_and_rtti" + - "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti" + - "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti" + loop_factor: 0.01 + num_classes: + - 100 + compiler: *compilers + cxx_std: "c++11" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] + + - name: - "fruit_compile_time" + - "fruit_compile_memory" - "fruit_incremental_compile_time" - "fruit_run_time" - "fruit_startup_time" @@ -87,7 +105,22 @@ benchmarks: - [] - name: + - "fruit_executable_size_without_exceptions_and_rtti" + loop_factor: 0.01 + num_classes: + - 100 + compiler: *gcc + cxx_std: "c++11" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + - ['-DFRUIT_USES_BOOST=False', '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + - ["-DBUILD_SHARED_LIBS=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] + + - name: - "fruit_compile_time" + - "fruit_compile_memory" - "fruit_incremental_compile_time" - "fruit_run_time" - "fruit_startup_time" @@ -104,7 +137,20 @@ benchmarks: - [] - name: + - "fruit_executable_size_without_exceptions_and_rtti" + loop_factor: 0.01 + num_classes: + - 100 + compiler: *clang + cxx_std: "c++11" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] + + - name: - "boost_di_compile_time" + - "boost_di_compile_memory" - "boost_di_incremental_compile_time" - "boost_di_run_time" - "boost_di_startup_time" @@ -118,3 +164,15 @@ benchmarks: - [] benchmark_generation_flags: - [] + + - name: + - "boost_di_executable_size_without_exceptions_and_rtti" + loop_factor: 0.01 + num_classes: + - 100 + compiler: *compilers + cxx_std: "c++14" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] diff --git a/extras/benchmark/suites/fruit_full.yml b/extras/benchmark/suites/fruit_full.yml index 32ac6d1..9709291 100644 --- a/extras/benchmark/suites/fruit_full.yml +++ b/extras/benchmark/suites/fruit_full.yml @@ -19,10 +19,11 @@ global: # These values are ignored, they are here just to be referenced below. constants: compilers: &compilers - - "g++-8" - - "clang++-6.0" + - "g++-9" + - "clang++-10" num_classes: &num_classes - 100 + - 250 - 1000 benchmarks: @@ -39,10 +40,12 @@ benchmarks: - [] - name: - - "new_delete_run_time" - "fruit_compile_time" + - "fruit_compile_memory" - "fruit_incremental_compile_time" - "fruit_run_time" + - "fruit_startup_time" + - "fruit_startup_time_with_normalized_component" - "fruit_executable_size" loop_factor: 1.0 num_classes: *num_classes @@ -54,9 +57,23 @@ benchmarks: - [] - name: + - "fruit_executable_size_without_exceptions_and_rtti" + loop_factor: 1.0 + num_classes: *num_classes + compiler: *compilers + cxx_std: "c++11" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] + + - name: - "fruit_compile_time" + - "fruit_compile_memory" - "fruit_incremental_compile_time" - "fruit_run_time" + - "fruit_startup_time" + - "fruit_startup_time_with_normalized_component" - "fruit_executable_size" loop_factor: 1.0 num_classes: *num_classes @@ -67,3 +84,15 @@ benchmarks: - ["-DBUILD_SHARED_LIBS=False"] benchmark_generation_flags: - [] + + - name: + - "fruit_executable_size_without_exceptions_and_rtti" + loop_factor: 1.0 + num_classes: *num_classes + compiler: *compilers + cxx_std: "c++11" + additional_cmake_args: + - ['-DFRUIT_USES_BOOST=False', '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + - ["-DBUILD_SHARED_LIBS=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] diff --git a/extras/benchmark/suites/fruit_mostly_full.yml b/extras/benchmark/suites/fruit_mostly_full.yml index e212ac8..f1eac70 100644 --- a/extras/benchmark/suites/fruit_mostly_full.yml +++ b/extras/benchmark/suites/fruit_mostly_full.yml @@ -19,11 +19,10 @@ global: # These values are ignored, they are here just to be referenced below. constants: compilers: &compilers - - "g++-8" - - "clang++-6.0" + - "g++-9" + - "clang++-10" num_classes: &num_classes - 100 - - 1000 benchmarks: - name: "fruit_single_file_compile_time" @@ -38,10 +37,12 @@ benchmarks: - [] - name: - - "new_delete_run_time" - "fruit_compile_time" + - "fruit_compile_memory" - "fruit_incremental_compile_time" - "fruit_run_time" + - "fruit_startup_time" + - "fruit_startup_time_with_normalized_component" - "fruit_executable_size" loop_factor: 1.0 num_classes: *num_classes @@ -51,3 +52,14 @@ benchmarks: - [] benchmark_generation_flags: - [] + + - name: + - "fruit_executable_size_without_exceptions_and_rtti" + loop_factor: 1.0 + num_classes: *num_classes + compiler: *compilers + cxx_std: "c++11" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] diff --git a/extras/benchmark/suites/fruit_quick.yml b/extras/benchmark/suites/fruit_quick.yml index 002e7e8..fd64ae7 100644 --- a/extras/benchmark/suites/fruit_quick.yml +++ b/extras/benchmark/suites/fruit_quick.yml @@ -19,8 +19,8 @@ global: # These values are ignored, they are here just to be referenced below. constants: compilers: &compilers - - "g++-6" - - "clang++-4.0" + - "g++-9" + - "clang++-10" num_classes: &num_classes - 100 @@ -38,9 +38,13 @@ benchmarks: - name: - "fruit_compile_time" + - "fruit_compile_memory" - "fruit_incremental_compile_time" - "fruit_run_time" + - "fruit_startup_time" + - "fruit_startup_time_with_normalized_component" - "fruit_executable_size" + - "fruit_executable_size_without_exceptions_and_rtti" loop_factor: 1.0 num_classes: *num_classes compiler: *compilers diff --git a/extras/benchmark/suites/fruit_single.yml b/extras/benchmark/suites/fruit_single.yml index d269da9..e030c5e 100644 --- a/extras/benchmark/suites/fruit_single.yml +++ b/extras/benchmark/suites/fruit_single.yml @@ -21,7 +21,7 @@ global: # These values are ignored, they are here just to be referenced below. constants: compilers: &compilers - - "g++-7" + - "g++-9" benchmarks: - name: diff --git a/extras/benchmark/suites/simple_di_full.yml b/extras/benchmark/suites/simple_di_full.yml index 6ed8d0f..6c104aa 100644 --- a/extras/benchmark/suites/simple_di_full.yml +++ b/extras/benchmark/suites/simple_di_full.yml @@ -22,33 +22,52 @@ global: # These values are ignored, they are here just to be referenced below. constants: compilers: &compilers - - "g++-7" - - "clang++-4.0" + - "g++-9" + - "clang++-10" num_classes: &num_classes - 100 + - 250 - 1000 benchmarks: - name: - "new_delete_run_time" - "simple_di_compile_time" + - "simple_di_compile_memory" - "simple_di_incremental_compile_time" - "simple_di_run_time" + - "simple_di_startup_time" - "simple_di_executable_size" + - "simple_di_with_interfaces_compile_memory" - "simple_di_with_interfaces_compile_time" - "simple_di_with_interfaces_incremental_compile_time" - "simple_di_with_interfaces_run_time" + - "simple_di_with_interfaces_startup_time" - "simple_di_with_interfaces_executable_size" + - "simple_di_with_interfaces_and_new_delete_compile_memory" - "simple_di_with_interfaces_and_new_delete_compile_time" - "simple_di_with_interfaces_and_new_delete_incremental_compile_time" - "simple_di_with_interfaces_and_new_delete_run_time" + - "simple_di_with_interfaces_and_new_delete_startup_time" - "simple_di_with_interfaces_and_new_delete_executable_size" loop_factor: 1.0 - num_classes: - - 100 + num_classes: *num_classes compiler: *compilers cxx_std: "c++11" additional_cmake_args: - [] benchmark_generation_flags: - [] + + - name: + - "simple_di_executable_size_without_exceptions_and_rtti" + - "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti" + - "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti" + loop_factor: 1.0 + num_classes: *num_classes + compiler: *compilers + cxx_std: "c++11" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] diff --git a/extras/benchmark/suites/simple_di_mostly_full.yml b/extras/benchmark/suites/simple_di_mostly_full.yml index a833652..7ab0d00 100644 --- a/extras/benchmark/suites/simple_di_mostly_full.yml +++ b/extras/benchmark/suites/simple_di_mostly_full.yml @@ -22,8 +22,8 @@ global: # These values are ignored, they are here just to be referenced below. constants: compilers: &compilers - - "g++-7" - - "clang++-4.0" + - "g++-9" + - "clang++-10" num_classes: &num_classes - 100 @@ -31,16 +31,22 @@ benchmarks: - name: - "new_delete_run_time" - "simple_di_compile_time" + - "simple_di_compile_memory" - "simple_di_incremental_compile_time" - "simple_di_run_time" + - "simple_di_startup_time" - "simple_di_executable_size" - "simple_di_with_interfaces_compile_time" + - "simple_di_with_interfaces_compile_memory" - "simple_di_with_interfaces_incremental_compile_time" - "simple_di_with_interfaces_run_time" + - "simple_di_with_interfaces_startup_time" - "simple_di_with_interfaces_executable_size" - "simple_di_with_interfaces_and_new_delete_compile_time" + - "simple_di_with_interfaces_and_new_delete_compile_memory" - "simple_di_with_interfaces_and_new_delete_incremental_compile_time" - "simple_di_with_interfaces_and_new_delete_run_time" + - "simple_di_with_interfaces_and_new_delete_startup_time" - "simple_di_with_interfaces_and_new_delete_executable_size" loop_factor: 1.0 num_classes: @@ -51,3 +57,17 @@ benchmarks: - [] benchmark_generation_flags: - [] + + - name: + - "simple_di_executable_size_without_exceptions_and_rtti" + - "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti" + - "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti" + loop_factor: 1.0 + num_classes: + - 100 + compiler: *compilers + cxx_std: "c++11" + additional_cmake_args: + - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: + - [] diff --git a/extras/benchmark/tables/fruit_internal.yml b/extras/benchmark/tables/fruit_internal.yml index 48ac40e..dfc7a27 100644 --- a/extras/benchmark/tables/fruit_internal.yml +++ b/extras/benchmark/tables/fruit_internal.yml @@ -16,139 +16,283 @@ constants: pretty_printer: format_string: "%s" +allowed_unused_benchmarks: + - new_delete_run_time + - fruit_single_file_compile_time + +allowed_unused_benchmark_results: + - total_max_ram_usage + tables: - - name: "Fruit compile time (single file)" + + # Fruit vs Boost.DI and "no DI" + + - name: "Compile time (Clang)" benchmark_filter: - name: "fruit_single_file_compile_time" benchmark_generation_flags: [] additional_cmake_args: [] - columns: *num_bindings_column - rows: *compiler_name_row + compiler: "clang++-10" + name: [ + "fruit_compile_time", + "boost_di_compile_time", + "simple_di_compile_time", + "simple_di_with_interfaces_compile_time", + "simple_di_with_interfaces_and_new_delete_compile_time", + ] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_compile_time": "Fruit" + "boost_di_compile_time": "Boost.DI" + "simple_di_compile_time": "Simple DI" + "simple_di_with_interfaces_compile_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_compile_time": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column results: dimension: "compile_time" unit: "seconds" - - - name: "Fruit compile time" + + - name: "Compile time (GCC)" benchmark_filter: - name: "fruit_compile_time" benchmark_generation_flags: [] additional_cmake_args: [] + compiler: "g++-9" + name: [ + "fruit_compile_time", + "boost_di_compile_time", + "simple_di_compile_time", + "simple_di_with_interfaces_compile_time", + "simple_di_with_interfaces_and_new_delete_compile_time", + ] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_compile_time": "Fruit" + "boost_di_compile_time": "Boost.DI" + "simple_di_compile_time": "Simple DI" + "simple_di_with_interfaces_compile_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_compile_time": "Simple DI w/ interfaces, new/delete" columns: *num_classes_column - rows: *compiler_name_row results: dimension: "compile_time" unit: "seconds" - - name: "Fruit incremental compile time" + - name: "Incremental compile time (Clang)" benchmark_filter: - name: "fruit_incremental_compile_time" benchmark_generation_flags: [] additional_cmake_args: [] + compiler: "clang++-10" + name: [ + "fruit_incremental_compile_time", + "boost_di_incremental_compile_time", + "simple_di_incremental_compile_time", + "simple_di_with_interfaces_incremental_compile_time", + "simple_di_with_interfaces_and_new_delete_incremental_compile_time", + ] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_incremental_compile_time": "Fruit" + "boost_di_incremental_compile_time": "Boost.DI" + "simple_di_incremental_compile_time": "Simple DI" + "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete" columns: *num_classes_column - rows: *compiler_name_row results: - dimension: "compile_time" + dimension: "incremental_compile_time" unit: "seconds" - - name: "Fruit full injection time" + - name: "Incremental compile time (GCC)" benchmark_filter: - name: "fruit_run_time" benchmark_generation_flags: [] additional_cmake_args: [] + compiler: "g++-9" + name: [ + "fruit_incremental_compile_time", + "boost_di_incremental_compile_time", + "simple_di_incremental_compile_time", + "simple_di_with_interfaces_incremental_compile_time", + "simple_di_with_interfaces_and_new_delete_incremental_compile_time", + ] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_incremental_compile_time": "Fruit" + "boost_di_incremental_compile_time": "Boost.DI" + "simple_di_incremental_compile_time": "Simple DI" + "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete" columns: *num_classes_column - rows: *compiler_name_row results: - dimension: "Full injection time" + dimension: "incremental_compile_time" unit: "seconds" - - name: "Fruit component normalization time" + - name: "Compile memory (Clang)" benchmark_filter: - name: "fruit_run_time" benchmark_generation_flags: [] additional_cmake_args: [] + compiler: "clang++-10" + name: [ + "fruit_compile_memory", + "boost_di_compile_memory", + "simple_di_compile_memory", + "simple_di_with_interfaces_compile_memory", + "simple_di_with_interfaces_and_new_delete_compile_memory", + ] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_compile_memory": "Fruit" + "boost_di_compile_memory": "Boost.DI" + "simple_di_compile_memory": "Simple DI" + "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete" columns: *num_classes_column - rows: *compiler_name_row results: - dimension: "componentNormalizationTime" - unit: "seconds" + dimension: "max_ram_usage" + unit: "bytes" - - name: "Fruit setup time" + - name: "Compile memory (GCC)" benchmark_filter: - name: "fruit_run_time" benchmark_generation_flags: [] additional_cmake_args: [] + compiler: "g++-9" + name: [ + "fruit_compile_memory", + "boost_di_compile_memory", + "simple_di_compile_memory", + "simple_di_with_interfaces_compile_memory", + "simple_di_with_interfaces_and_new_delete_compile_memory", + ] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_compile_memory": "Fruit" + "boost_di_compile_memory": "Boost.DI" + "simple_di_compile_memory": "Simple DI" + "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete" columns: *num_classes_column - rows: *compiler_name_row results: - dimension: "Total for setup" - unit: "seconds" + dimension: "max_ram_usage" + unit: "bytes" - - name: "Fruit per-request time" + - name: "Startup time (Clang)" benchmark_filter: - name: "fruit_run_time" + compiler: "clang++-10" benchmark_generation_flags: [] additional_cmake_args: [] + name: [ + "fruit_startup_time", + "boost_di_startup_time", + "simple_di_startup_time", + "simple_di_with_interfaces_startup_time", + "simple_di_with_interfaces_and_new_delete_startup_time", + ] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_startup_time": "Fruit" + "boost_di_startup_time": "Boost.DI" + "simple_di_startup_time": "Simple DI" + "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete" columns: *num_classes_column - rows: *compiler_name_row results: - dimension: "Total per request" + dimension: "startup_time" unit: "seconds" - - - name: "New/delete time" - benchmark_filter: - name: "new_delete_run_time" + + - name: "Startup time (GCC)" + benchmark_filter: + compiler: "g++-9" benchmark_generation_flags: [] additional_cmake_args: [] + name: [ + "fruit_startup_time", + "boost_di_startup_time", + "simple_di_startup_time", + "simple_di_with_interfaces_startup_time", + "simple_di_with_interfaces_and_new_delete_startup_time", + ] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_startup_time": "Fruit" + "boost_di_startup_time": "Boost.DI" + "simple_di_startup_time": "Simple DI" + "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete" columns: *num_classes_column - rows: *compiler_name_row results: - dimension: "Total" + dimension: "startup_time" unit: "seconds" - - - name: "Compile time (100 classes)" + + - name: "Startup time with normalized component (Clang)" benchmark_filter: - num_classes: 100 + compiler: "clang++-10" benchmark_generation_flags: [] additional_cmake_args: [] - columns: + name: [ + "fruit_startup_time_with_normalized_component", + "boost_di_startup_time_with_normalized_component", + "simple_di_startup_time_with_normalized_component", + "simple_di_with_interfaces_startup_time_with_normalized_component", + "simple_di_with_interfaces_and_new_delete_startup_time_with_normalized_component", + ] + rows: dimension: "name" pretty_printer: fixed_map: - "fruit_compile_time": "Fruit" - "boost_di_compile_time": "Boost.DI" - "simple_di_incremental_compile_time": "Simple DI" - "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete" - rows: *compiler_name_row + "fruit_startup_time_with_normalized_component": "Fruit" + "boost_di_startup_time_with_normalized_component": "Boost.DI" + "simple_di_startup_time_with_normalized_component": "Simple DI" + "simple_di_with_interfaces_startup_time_with_normalized_component": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_startup_time_with_normalized_component": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column results: - dimension: "compile_time" + dimension: "fruit_startup_time_with_normalized_component" unit: "seconds" - - - name: "Incremental compile time (100 classes)" + + - name: "Startup time with normalized component (GCC)" benchmark_filter: - num_classes: 100 + compiler: "g++-9" benchmark_generation_flags: [] additional_cmake_args: [] - columns: + name: [ + "fruit_startup_time_with_normalized_component", + "boost_di_startup_time_with_normalized_component", + "simple_di_startup_time_with_normalized_component", + "simple_di_with_interfaces_startup_time_with_normalized_component", + "simple_di_with_interfaces_and_new_delete_startup_time_with_normalized_component", + ] + rows: dimension: "name" pretty_printer: fixed_map: - "fruit_incremental_compile_time": "Fruit" - "boost_di_incremental_compile_time": "Boost.DI" - "simple_di_incremental_compile_time": "Simple DI" - "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete" - rows: *compiler_name_row + "fruit_startup_time_with_normalized_component": "Fruit" + "boost_di_startup_time_with_normalized_component": "Boost.DI" + "simple_di_startup_time_with_normalized_component": "Simple DI" + "simple_di_with_interfaces_startup_time_with_normalized_component": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_startup_time_with_normalized_component": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column results: - dimension: "compile_time" + dimension: "fruit_startup_time_with_normalized_component" unit: "seconds" - - name: "Fruit full injection time (100 classes)" + - name: "Component normalization time (Clang)" benchmark_filter: - num_classes: 100 + compiler: "clang++-10" benchmark_generation_flags: [] additional_cmake_args: [] - columns: + rows: dimension: "name" pretty_printer: fixed_map: @@ -157,17 +301,17 @@ tables: "simple_di_incremental_run_time": "Simple DI" "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces" "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete" - rows: *compiler_name_row + columns: *num_classes_column results: - dimension: "Full injection time" + dimension: "componentNormalizationTime" unit: "seconds" - - name: "Fruit component normalization time (100 classes)" + - name: "Component normalization time (GCC)" benchmark_filter: - num_classes: 100 + compiler: "g++-9" benchmark_generation_flags: [] additional_cmake_args: [] - columns: + rows: dimension: "name" pretty_printer: fixed_map: @@ -176,65 +320,427 @@ tables: "simple_di_incremental_run_time": "Simple DI" "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces" "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete" - rows: *compiler_name_row + columns: *num_classes_column results: dimension: "componentNormalizationTime" unit: "seconds" - - - name: "Setup time (100 classes)" + - name: "Per-request time (Clang)" benchmark_filter: - num_classes: 100 + compiler: "clang++-10" benchmark_generation_flags: [] additional_cmake_args: [] - columns: + rows: dimension: "name" pretty_printer: fixed_map: "fruit_run_time": "Fruit" "boost_di_run_time": "Boost.DI" - "simple_di_incremental_run_time": "Simple DI" - "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete" - rows: *compiler_name_row + "simple_di_run_time": "Simple DI" + "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column results: - dimension: "Total for setup" + dimension: "Total per request" unit: "seconds" - - name: "Per-request time (100 classes)" + - name: "Per-request time (GCC)" benchmark_filter: - num_classes: 100 + compiler: "g++-9" benchmark_generation_flags: [] additional_cmake_args: [] - columns: + rows: dimension: "name" pretty_printer: fixed_map: "fruit_run_time": "Fruit" "boost_di_run_time": "Boost.DI" - "simple_di_incremental_run_time": "Simple DI" - "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete" - rows: *compiler_name_row + "simple_di_run_time": "Simple DI" + "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column results: dimension: "Total per request" unit: "seconds" - - - name: "Executable size (stripped, 100 classes)" + + - name: "Executable size (stripped, Clang)" benchmark_filter: - num_classes: 100 + compiler: "clang++-10" benchmark_generation_flags: [] additional_cmake_args: [] - columns: + rows: dimension: "name" pretty_printer: fixed_map: "fruit_executable_size": "Fruit" "boost_di_executable_size": "Boost.DI" - "simple_di_incremental_run_time": "Simple DI" - "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete" - rows: *compiler_name_row + "simple_di_executable_size": "Simple DI" + "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Executable size (stripped, GCC)" + benchmark_filter: + compiler: "g++-9" + benchmark_generation_flags: [] + additional_cmake_args: [] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_executable_size": "Fruit" + "boost_di_executable_size": "Boost.DI" + "simple_di_executable_size": "Simple DI" + "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Executable size (stripped, no exceptions/RTTI, Clang)" + benchmark_filter: + compiler: "clang++-10" + benchmark_generation_flags: [] + additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_executable_size_without_exceptions_and_rtti": "Fruit" + "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI" + "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI" + "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Executable size (stripped, no exceptions/RTTI, GCC)" + benchmark_filter: + compiler: "g++-9" + benchmark_generation_flags: [] + additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + rows: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_executable_size_without_exceptions_and_rtti": "Fruit" + "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI" + "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI" + "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete" + columns: *num_classes_column + results: + dimension: "num_bytes" + unit: "bytes" + + # Fruit: performance by default and with various compiler options. + + - name: "Fruit compile time (Clang)" + benchmark_filter: + benchmark_generation_flags: [] + compiler: "clang++-10" + name: "fruit_compile_time" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "compile_time" + unit: "seconds" + + - name: "Fruit compile time (GCC)" + benchmark_filter: + benchmark_generation_flags: [] + compiler: "g++-9" + name: "fruit_compile_time" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "compile_time" + unit: "seconds" + + - name: "Fruit incremental compile time (Clang)" + benchmark_filter: + benchmark_generation_flags: [] + compiler: "clang++-10" + name: "fruit_incremental_compile_time" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "incremental_compile_time" + unit: "seconds" + + - name: "Fruit incremental compile time (GCC)" + benchmark_filter: + benchmark_generation_flags: [] + compiler: "g++-9" + name: "fruit_incremental_compile_time" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "incremental_compile_time" + unit: "seconds" + + - name: "Fruit compile memory (Clang)" + benchmark_filter: + benchmark_generation_flags: [] + compiler: "clang++-10" + name: "fruit_compile_memory" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "max_ram_usage" + unit: "bytes" + + - name: "Fruit compile memory (GCC)" + benchmark_filter: + benchmark_generation_flags: [] + compiler: "g++-9" + name: "fruit_compile_memory" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "max_ram_usage" + unit: "bytes" + + - name: "Fruit startup time (Clang)" + benchmark_filter: + compiler: "clang++-10" + benchmark_generation_flags: [] + name: "fruit_startup_time" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "startup_time" + unit: "seconds" + + - name: "Fruit startup time (GCC)" + benchmark_filter: + compiler: "g++-9" + benchmark_generation_flags: [] + name: "fruit_startup_time" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "startup_time" + unit: "seconds" + + - name: "Fruit startup time with normalized component (Clang)" + benchmark_filter: + compiler: "clang++-10" + benchmark_generation_flags: [] + name: "fruit_startup_time_with_normalized_component" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "startup_time" + unit: "seconds" + + - name: "Fruit startup time with normalized component (GCC)" + benchmark_filter: + compiler: "g++-9" + benchmark_generation_flags: [] + name: "fruit_startup_time_with_normalized_component" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "startup_time" + unit: "seconds" + + - name: "Fruit component normalization time (Clang)" + benchmark_filter: + compiler: "clang++-10" + benchmark_generation_flags: [] + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "componentNormalizationTime" + unit: "seconds" + + - name: "Fruit component normalization time (GCC)" + benchmark_filter: + compiler: "g++-9" + benchmark_generation_flags: [] + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "componentNormalizationTime" + unit: "seconds" + + - name: "Fruit per-request time (Clang)" + benchmark_filter: + compiler: "clang++-10" + benchmark_generation_flags: [] + name: "fruit_run_time" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "Total per request" + unit: "seconds" + + - name: "Fruit per-request time (GCC)" + benchmark_filter: + compiler: "g++-9" + benchmark_generation_flags: [] + name: "fruit_run_time" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "Total per request" + unit: "seconds" + + - name: "Fruit executable size (stripped, Clang)" + benchmark_filter: + compiler: "clang++-10" + benchmark_generation_flags: [] + name: "fruit_executable_size" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Fruit executable size (stripped, GCC)" + benchmark_filter: + compiler: "g++-9" + benchmark_generation_flags: [] + name: "fruit_executable_size" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple []: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost" + columns: *num_classes_column + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Fruit executable size (stripped, no exceptions/RTTI, Clang)" + benchmark_filter: + compiler: "clang++-10" + benchmark_generation_flags: [] + name: "fruit_executable_size_without_exceptions_and_rtti" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "without boost" + columns: *num_classes_column + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Fruit executable size (stripped, no exceptions/RTTI, GCC)" + benchmark_filter: + compiler: "g++-9" + benchmark_generation_flags: [] + name: "fruit_executable_size_without_exceptions_and_rtti" + rows: + dimension: "additional_cmake_args" + pretty_printer: + fixed_map: + !!python/tuple ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "(defaults)" + !!python/tuple ["-DBUILD_SHARED_LIBS=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "statically linked" + !!python/tuple ["-DFRUIT_USES_BOOST=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "without boost" + columns: *num_classes_column results: dimension: "num_bytes" unit: "bytes" diff --git a/extras/benchmark/tables/fruit_wiki.yml b/extras/benchmark/tables/fruit_wiki.yml index 0af3b3e..28bdccf 100644 --- a/extras/benchmark/tables/fruit_wiki.yml +++ b/extras/benchmark/tables/fruit_wiki.yml @@ -41,26 +41,15 @@ tables: dimension: "compile_time" unit: "seconds" - - name: "Fruit full injection time" + - name: "Fruit startup time" benchmark_filter: - name: "fruit_run_time" + name: "fruit_startup_time" additional_cmake_args: [] benchmark_generation_flags: [] columns: *num_classes_column rows: *compiler_name_row results: - dimension: "Full injection time" - unit: "seconds" - - - name: "Fruit setup time" - benchmark_filter: - name: "fruit_run_time" - additional_cmake_args: [] - benchmark_generation_flags: [] - columns: *num_classes_column - rows: *compiler_name_row - results: - dimension: "Total for setup" + dimension: "startup_time" unit: "seconds" - name: "Fruit per-request time" @@ -92,6 +81,39 @@ tables: num_classes: 100 additional_cmake_args: [] benchmark_generation_flags: [] + name: [ + "fruit_compile_time", + "boost_di_compile_time", + "simple_di_compile_time", + "simple_di_with_interfaces_compile_time", + "simple_di_with_interfaces_and_new_delete_compile_time", + ] + columns: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_compile_time": "Fruit" + "boost_di_compile_time": "Boost.DI" + "simple_di_compile_time": "Simple DI" + "simple_di_with_interfaces_compile_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_compile_time": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "compile_time" + unit: "seconds" + + - name: "Compile time (250 classes)" + benchmark_filter: + num_classes: 250 + additional_cmake_args: [] + benchmark_generation_flags: [] + name: [ + "fruit_compile_time", + "boost_di_compile_time", + "simple_di_compile_time", + "simple_di_with_interfaces_compile_time", + "simple_di_with_interfaces_and_new_delete_compile_time", + ] columns: dimension: "name" pretty_printer: @@ -111,6 +133,13 @@ tables: num_classes: 1000 additional_cmake_args: [] benchmark_generation_flags: [] + name: [ + "fruit_compile_time", + "boost_di_compile_time", + "simple_di_compile_time", + "simple_di_with_interfaces_compile_time", + "simple_di_with_interfaces_and_new_delete_compile_time", + ] columns: dimension: "name" pretty_printer: @@ -130,6 +159,13 @@ tables: num_classes: 100 additional_cmake_args: [] benchmark_generation_flags: [] + name: [ + "fruit_incremental_compile_time", + "boost_di_incremental_compile_time", + "simple_di_incremental_compile_time", + "simple_di_with_interfaces_incremental_compile_time", + "simple_di_with_interfaces_and_new_delete_incremental_compile_time", + ] columns: dimension: "name" pretty_printer: @@ -141,7 +177,33 @@ tables: "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete" rows: *compiler_name_row results: - dimension: "compile_time" + dimension: "incremental_compile_time" + unit: "seconds" + + - name: "Incremental compile time (250 classes)" + benchmark_filter: + num_classes: 250 + additional_cmake_args: [] + benchmark_generation_flags: [] + name: [ + "fruit_incremental_compile_time", + "boost_di_incremental_compile_time", + "simple_di_incremental_compile_time", + "simple_di_with_interfaces_incremental_compile_time", + "simple_di_with_interfaces_and_new_delete_incremental_compile_time", + ] + columns: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_incremental_compile_time": "Fruit" + "boost_di_incremental_compile_time": "Boost.DI" + "simple_di_incremental_compile_time": "Simple DI" + "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "incremental_compile_time" unit: "seconds" - name: "Incremental compile time (1000 classes)" @@ -149,6 +211,13 @@ tables: num_classes: 1000 additional_cmake_args: [] benchmark_generation_flags: [] + name: [ + "fruit_incremental_compile_time", + "boost_di_incremental_compile_time", + "simple_di_incremental_compile_time", + "simple_di_with_interfaces_incremental_compile_time", + "simple_di_with_interfaces_and_new_delete_incremental_compile_time", + ] columns: dimension: "name" pretty_printer: @@ -160,48 +229,88 @@ tables: "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete" rows: *compiler_name_row results: - dimension: "compile_time" + dimension: "incremental_compile_time" unit: "seconds" - - name: "Full injection time (100 classes)" + - name: "Compile memory (100 classes)" benchmark_filter: num_classes: 100 additional_cmake_args: [] benchmark_generation_flags: [] + name: [ + "fruit_compile_memory", + "boost_di_compile_memory", + "simple_di_compile_memory", + "simple_di_with_interfaces_compile_memory", + "simple_di_with_interfaces_and_new_delete_compile_memory", + ] columns: dimension: "name" pretty_printer: fixed_map: - "fruit_run_time": "Fruit" - "boost_di_run_time": "Boost.DI" - "simple_di_run_time": "Simple DI" - "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete" + "fruit_compile_memory": "Fruit" + "boost_di_compile_memory": "Boost.DI" + "simple_di_compile_memory": "Simple DI" + "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete" rows: *compiler_name_row results: - dimension: "Full injection time" - unit: "seconds" + dimension: "max_ram_usage" + unit: "bytes" + + - name: "Compile memory (250 classes)" + benchmark_filter: + num_classes: 250 + additional_cmake_args: [] + benchmark_generation_flags: [] + name: [ + "fruit_compile_memory", + "boost_di_compile_memory", + "simple_di_compile_memory", + "simple_di_with_interfaces_compile_memory", + "simple_di_with_interfaces_and_new_delete_compile_memory", + ] + columns: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_compile_memory": "Fruit" + "boost_di_compile_memory": "Boost.DI" + "simple_di_compile_memory": "Simple DI" + "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "max_ram_usage" + unit: "bytes" - - name: "Full injection time (1000 classes)" + - name: "Compile memory (1000 classes)" benchmark_filter: num_classes: 1000 additional_cmake_args: [] benchmark_generation_flags: [] + name: [ + "fruit_compile_memory", + "boost_di_compile_memory", + "simple_di_compile_memory", + "simple_di_with_interfaces_compile_memory", + "simple_di_with_interfaces_and_new_delete_compile_memory", + ] columns: dimension: "name" pretty_printer: fixed_map: - "fruit_run_time": "Fruit" - "boost_di_run_time": "Boost.DI" - "simple_di_run_time": "Simple DI" - "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete" + "fruit_compile_memory": "Fruit" + "boost_di_compile_memory": "Boost.DI" + "simple_di_compile_memory": "Simple DI" + "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete" rows: *compiler_name_row results: - dimension: "Full injection time" - unit: "seconds" + dimension: "max_ram_usage" + unit: "bytes" - - name: "Setup time (100 classes)" + - name: "Startup time (100 classes)" benchmark_filter: num_classes: 100 additional_cmake_args: [] @@ -210,17 +319,38 @@ tables: dimension: "name" pretty_printer: fixed_map: - "fruit_run_time": "Fruit" - "boost_di_run_time": "Boost.DI" - "simple_di_run_time": "Simple DI" - "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete" + "fruit_startup_time": "Fruit" + "fruit_startup_time_with_normalized_component": "Fruit (with normalized component)" + "boost_di_startup_time": "Boost.DI" + "simple_di_startup_time": "Simple DI" + "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete" rows: *compiler_name_row results: - dimension: "Total for setup" + dimension: "startup_time" unit: "seconds" - - - name: "Setup time (1000 classes)" + + - name: "Startup time (250 classes)" + benchmark_filter: + num_classes: 250 + additional_cmake_args: [] + benchmark_generation_flags: [] + columns: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_startup_time": "Fruit" + "fruit_startup_time_with_normalized_component": "Fruit (with normalized component)" + "boost_di_startup_time": "Boost.DI" + "simple_di_startup_time": "Simple DI" + "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "startup_time" + unit: "seconds" + + - name: "Startup time (1000 classes)" benchmark_filter: num_classes: 1000 additional_cmake_args: [] @@ -229,6 +359,26 @@ tables: dimension: "name" pretty_printer: fixed_map: + "fruit_startup_time": "Fruit" + "fruit_startup_time_with_normalized_component": "Fruit (with normalized component)" + "boost_di_startup_time": "Boost.DI" + "simple_di_startup_time": "Simple DI" + "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "startup_time" + unit: "seconds" + + - name: "Per-request time (100 classes)" + benchmark_filter: + num_classes: 100 + additional_cmake_args: [] + benchmark_generation_flags: [] + columns: + dimension: "name" + pretty_printer: + fixed_map: "fruit_run_time": "Fruit" "boost_di_run_time": "Boost.DI" "simple_di_run_time": "Simple DI" @@ -236,12 +386,12 @@ tables: "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete" rows: *compiler_name_row results: - dimension: "Total for setup" + dimension: "Total per request" unit: "seconds" - - name: "Per-request time (100 classes)" + - name: "Per-request time (250 classes)" benchmark_filter: - num_classes: 100 + num_classes: 250 additional_cmake_args: [] benchmark_generation_flags: [] columns: @@ -288,9 +438,28 @@ tables: fixed_map: "fruit_executable_size": "Fruit" "boost_di_executable_size": "Boost.DI" - "simple_di_run_time": "Simple DI" - "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete" + "simple_di_executable_size": "Simple DI" + "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Executable size (stripped, 250 classes)" + benchmark_filter: + num_classes: 250 + additional_cmake_args: [] + benchmark_generation_flags: [] + columns: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_executable_size": "Fruit" + "boost_di_executable_size": "Boost.DI" + "simple_di_executable_size": "Simple DI" + "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete" rows: *compiler_name_row results: dimension: "num_bytes" @@ -307,9 +476,67 @@ tables: fixed_map: "fruit_executable_size": "Fruit" "boost_di_executable_size": "Boost.DI" - "simple_di_run_time": "Simple DI" - "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces" - "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete" + "simple_di_executable_size": "Simple DI" + "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "num_bytes" + unit: "bytes" + + + - name: "Executable size (stripped, 100 classes, no exceptions/rtti)" + benchmark_filter: + num_classes: 100 + additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: [] + columns: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_executable_size_without_exceptions_and_rtti": "Fruit" + "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI" + "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI" + "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Executable size (stripped, 250 classes, no exceptions/rtti)" + benchmark_filter: + num_classes: 250 + additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: [] + columns: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_executable_size_without_exceptions_and_rtti": "Fruit" + "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI" + "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI" + "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete" + rows: *compiler_name_row + results: + dimension: "num_bytes" + unit: "bytes" + + - name: "Executable size (stripped, 1000 classes, no exceptions/rtti)" + benchmark_filter: + num_classes: 1000 + additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti'] + benchmark_generation_flags: [] + columns: + dimension: "name" + pretty_printer: + fixed_map: + "fruit_executable_size_without_exceptions_and_rtti": "Fruit" + "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI" + "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI" + "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces" + "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete" rows: *compiler_name_row results: dimension: "num_bytes" @@ -338,10 +565,10 @@ tables: dimension: "compile_time" unit: "seconds" - - name: "Full injection time (100 classes)" + - name: "Startup time (100 classes)" benchmark_filter: num_classes: 100 - name: "fruit_run_time" + name: "fruit_startup_time" benchmark_generation_flags: [] columns: dimension: "additional_cmake_args" @@ -355,13 +582,13 @@ tables: to: "Statically-linking with Fruit" rows: *compiler_name_row results: - dimension: "Full injection time" + dimension: "startup_time" unit: "seconds" - - name: "Setup time (100 classes)" + - name: "Startup time (100 classes)" benchmark_filter: num_classes: 100 - name: "fruit_run_time" + name: "fruit_startup_time" benchmark_generation_flags: [] columns: dimension: "additional_cmake_args" @@ -375,7 +602,7 @@ tables: to: "Statically-linking with Fruit" rows: *compiler_name_row results: - dimension: "Total for setup" + dimension: "startup_time" unit: "seconds" - name: "Per-request time (100 classes)" diff --git a/extras/dockerfiles/.dockerignore b/extras/dockerfiles/.dockerignore new file mode 100644 index 0000000..4e1954c --- /dev/null +++ b/extras/dockerfiles/.dockerignore @@ -0,0 +1,2 @@ +Dockerfile.* +rebuild_all.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu-16.04 b/extras/dockerfiles/Dockerfile.ubuntu-16.04 deleted file mode 100644 index b53b883..0000000 --- a/extras/dockerfiles/Dockerfile.ubuntu-16.04 +++ /dev/null @@ -1,9 +0,0 @@ -FROM ubuntu:16.04 -MAINTAINER Marco Poletti <poletti.marco@gmail.com> - -COPY ubuntu-16.04_custom.list /etc/apt/sources.list.d/ -COPY common_install.sh common_cleanup.sh ubuntu-16.04_install.sh / - -RUN bash -x /common_install.sh && \ - bash -x /ubuntu-16.04_install.sh && \ - bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu-17.04 b/extras/dockerfiles/Dockerfile.ubuntu-17.04 deleted file mode 100644 index ee50dcc..0000000 --- a/extras/dockerfiles/Dockerfile.ubuntu-17.04 +++ /dev/null @@ -1,10 +0,0 @@ -FROM ubuntu:17.04 -MAINTAINER Marco Poletti <poletti.marco@gmail.com> - -COPY ubuntu-17.04_custom.list /etc/apt/sources.list.d/ -COPY common_install.sh common_cleanup.sh ubuntu-17.04_install.sh / - -RUN sed -i -re 's/([a-z]{2}\.)?archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list; \ - bash -x /common_install.sh && \ - bash -x /ubuntu-17.04_install.sh && \ - bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu-18.04 b/extras/dockerfiles/Dockerfile.ubuntu-18.04 index ec5d5cb..d458bb4 100644 --- a/extras/dockerfiles/Dockerfile.ubuntu-18.04 +++ b/extras/dockerfiles/Dockerfile.ubuntu-18.04 @@ -1,9 +1,53 @@ FROM ubuntu:18.04 MAINTAINER Marco Poletti <poletti.marco@gmail.com> +COPY common_install.sh common_cleanup.sh / + +RUN bash -x /common_install.sh +RUN apt-get install -y --no-install-recommends curl + +# For the Bazel repository +RUN curl https://bazel.build/bazel-release.pub.gpg | apt-key add - + +RUN echo 'deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8' >> /etc/apt/sources.list.d/bazel.list + COPY ubuntu-18.04_custom.list /etc/apt/sources.list.d/ -COPY common_install.sh common_cleanup.sh ubuntu-18.04_install.sh / -RUN bash -x /common_install.sh && \ - bash -x /ubuntu-18.04_install.sh && \ - bash -x /common_cleanup.sh +RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys F23C5A6CF475977595C89F51BA6932366A755776 + +RUN apt-get update -qq + +RUN apt-get remove -y python3-pip +RUN python3 -m easy_install pip + +RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ + g++-8 \ + g++-7 \ + g++-6 \ + g++-5 \ + clang-3.9 \ + clang-4.0 \ + clang-5.0 \ + clang-6.0 \ + clang-7 \ + clang-8 \ + clang-9 \ + clang-10 \ + bazel \ + git \ + python3.8 \ + clang-tidy \ + clang-format + +RUN python3.8 -m easy_install pip + +RUN pip3 install absl-py +RUN pip3 install bidict +RUN pip3 install pytest +RUN pip3 install pytest-xdist +RUN pip3 install sh +RUN pip3 install setuptools +RUN pip3 install networkx +RUN pip3 install wheel + +RUN bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu-18.10 b/extras/dockerfiles/Dockerfile.ubuntu-18.10 deleted file mode 100644 index 09bd008..0000000 --- a/extras/dockerfiles/Dockerfile.ubuntu-18.10 +++ /dev/null @@ -1,9 +0,0 @@ -FROM ubuntu:18.10 -MAINTAINER Marco Poletti <poletti.marco@gmail.com> - -COPY ubuntu-18.10_custom.list /etc/apt/sources.list.d/ -COPY common_install.sh common_cleanup.sh ubuntu-18.10_install.sh / - -RUN bash -x /common_install.sh && \ - bash -x /ubuntu-18.10_install.sh && \ - bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu-19.04 b/extras/dockerfiles/Dockerfile.ubuntu-19.04 deleted file mode 100644 index 7939990..0000000 --- a/extras/dockerfiles/Dockerfile.ubuntu-19.04 +++ /dev/null @@ -1,9 +0,0 @@ -FROM ubuntu:19.04 -MAINTAINER Marco Poletti <poletti.marco@gmail.com> - -COPY ubuntu-19.04_custom.list /etc/apt/sources.list.d/ -COPY common_install.sh common_cleanup.sh ubuntu-19.04_install.sh / - -RUN bash -x /common_install.sh && \ - bash -x /ubuntu-19.04_install.sh && \ - bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu-19.10 b/extras/dockerfiles/Dockerfile.ubuntu-19.10 new file mode 100644 index 0000000..ca6be96 --- /dev/null +++ b/extras/dockerfiles/Dockerfile.ubuntu-19.10 @@ -0,0 +1,40 @@ +FROM ubuntu:19.10 +MAINTAINER Marco Poletti <poletti.marco@gmail.com> + +COPY common_install.sh common_cleanup.sh / + +RUN bash -x /common_install.sh + +COPY ubuntu-19.10_custom.list /etc/apt/sources.list.d/ + +RUN apt-get update + +RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ + g++-7 \ + g++-8 \ + g++-9 \ + clang-6.0 \ + clang-7 \ + clang-8 \ + clang-9 \ + clang-10 \ + python3-sh \ + python3-typed-ast \ + python3-pip \ + python3-setuptools \ + python3-networkx \ + clang-tidy \ + clang-format + +RUN pip3 install --upgrade pip + +RUN pip3 install absl-py +RUN pip3 install bidict +RUN pip3 install pytest +RUN pip3 install pytest-xdist +RUN pip3 install sh +RUN pip3 install setuptools +RUN pip3 install networkx +RUN pip3 install wheel + +RUN bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu-20.04 b/extras/dockerfiles/Dockerfile.ubuntu-20.04 new file mode 100644 index 0000000..3ce7d9c --- /dev/null +++ b/extras/dockerfiles/Dockerfile.ubuntu-20.04 @@ -0,0 +1,41 @@ +FROM ubuntu:20.04 +MAINTAINER Marco Poletti <poletti.marco@gmail.com> + +COPY common_install.sh common_cleanup.sh / + +RUN bash -x /common_install.sh + +COPY ubuntu-20.04_custom.list /etc/apt/sources.list.d/ + +RUN apt-get update + +RUN apt-get remove -y python3-pip +RUN python3 -m easy_install pip + +RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ + g++-7 \ + g++-8 \ + g++-9 \ + g++-10 \ + clang-6.0 \ + clang-7 \ + clang-8 \ + clang-9 \ + clang-10 \ + python3.8 \ + python3.8-distutils \ + clang-tidy \ + clang-format + +RUN python3.8 -m easy_install pip + +RUN pip3 install absl-py +RUN pip3 install bidict +RUN pip3 install pytest +RUN pip3 install pytest-xdist +RUN pip3 install sh +RUN pip3 install setuptools +RUN pip3 install networkx +RUN pip3 install wheel + +RUN bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu-20.10 b/extras/dockerfiles/Dockerfile.ubuntu-20.10 new file mode 100644 index 0000000..6b4e52c --- /dev/null +++ b/extras/dockerfiles/Dockerfile.ubuntu-20.10 @@ -0,0 +1,40 @@ +FROM ubuntu:20.10 +MAINTAINER Marco Poletti <poletti.marco@gmail.com> + +COPY common_install.sh common_cleanup.sh / + +RUN bash -x /common_install.sh + +COPY ubuntu-20.10_custom.list /etc/apt/sources.list.d/ + +RUN apt-get update + +RUN apt-get remove -y python3-pip +RUN python3 -m easy_install pip + +RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ + g++-7 \ + g++-8 \ + g++-9 \ + g++-10 \ + clang-8 \ + clang-9 \ + clang-10 \ + clang-11 \ + python3.8 \ + python3.8-distutils \ + clang-tidy \ + clang-format + +RUN python3.8 -m easy_install pip + +RUN pip3 install absl-py +RUN pip3 install bidict +RUN pip3 install pytest +RUN pip3 install pytest-xdist +RUN pip3 install sh +RUN pip3 install setuptools +RUN pip3 install networkx +RUN pip3 install wheel + +RUN bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu_arm-16.04 b/extras/dockerfiles/Dockerfile.ubuntu_arm-16.04 deleted file mode 100644 index 35342b9..0000000 --- a/extras/dockerfiles/Dockerfile.ubuntu_arm-16.04 +++ /dev/null @@ -1,9 +0,0 @@ -FROM multiarch/ubuntu-core:arm64-xenial -MAINTAINER Marco Poletti <poletti.marco@gmail.com> - -COPY ubuntu_arm-16.04_custom.list /etc/apt/sources.list.d/ -COPY common_install.sh common_cleanup.sh ubuntu_arm-16.04_install.sh / - -RUN bash -x /common_install.sh && \ - bash -x /ubuntu_arm-16.04_install.sh && \ - bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu_arm-18.04 b/extras/dockerfiles/Dockerfile.ubuntu_arm-18.04 index 852abb5..8ecab4d 100644 --- a/extras/dockerfiles/Dockerfile.ubuntu_arm-18.04 +++ b/extras/dockerfiles/Dockerfile.ubuntu_arm-18.04 @@ -1,9 +1,20 @@ FROM multiarch/ubuntu-core:arm64-bionic MAINTAINER Marco Poletti <poletti.marco@gmail.com> -COPY ubuntu_arm-18.04_custom.list /etc/apt/sources.list.d/ -COPY common_install.sh common_cleanup.sh ubuntu_arm-18.04_install.sh / +COPY common_install.sh common_cleanup.sh / -RUN bash -x /common_install.sh && \ - bash -x /ubuntu_arm-18.04_install.sh && \ - bash -x /common_cleanup.sh +RUN bash -x /common_install.sh +RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ + g++-8 \ + g++-7 \ + g++-5 \ + clang-3.9 \ + clang-4.0 \ + clang-5.0 \ + clang-6.0 \ + python \ + python3-sh \ + python3-typed-ast \ + clang-tidy \ + clang-format +RUN bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/Dockerfile.ubuntu_arm-20.04 b/extras/dockerfiles/Dockerfile.ubuntu_arm-20.04 new file mode 100644 index 0000000..6d84554 --- /dev/null +++ b/extras/dockerfiles/Dockerfile.ubuntu_arm-20.04 @@ -0,0 +1,22 @@ +FROM multiarch/ubuntu-core:arm64-focal +MAINTAINER Marco Poletti <poletti.marco@gmail.com> + +COPY common_install.sh common_cleanup.sh / + +RUN bash -x /common_install.sh +RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ + g++-7 \ + g++-8 \ + g++-9 \ + g++-10 \ + clang-6.0 \ + clang-7 \ + clang-8 \ + clang-9 \ + clang-10 \ + python \ + python3-sh \ + python3-typed-ast \ + clang-tidy \ + clang-format +RUN bash -x /common_cleanup.sh diff --git a/extras/dockerfiles/common_install.sh b/extras/dockerfiles/common_install.sh index ba63b2c..7eff017 100644 --- a/extras/dockerfiles/common_install.sh +++ b/extras/dockerfiles/common_install.sh @@ -3,7 +3,7 @@ set -e apt-get update -qq -apt-get install -y --no-install-recommends wget gnupg +apt-get install -y --no-install-recommends wget gnupg ca-certificates apt-transport-https wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add - @@ -24,15 +24,7 @@ apt-get install -y --allow-unauthenticated --no-install-recommends \ libc++-dev \ libc++abi1 \ libc++abi-dev \ - python3-pip \ - python3-setuptools \ - python3-networkx \ - dirmngr - -pip3 install --upgrade pip -python3 -m pip install absl-py -python3 -m pip install bidict -python3 -m pip install pytest -python3 -m pip install pytest-xdist -python3 -m pip install sh -python3 -m pip install wheel + dirmngr \ + python \ + python3 \ + python3-setuptools diff --git a/extras/dockerfiles/rebuild_all.sh b/extras/dockerfiles/rebuild_all.sh index 545df07..f0e23d2 100755 --- a/extras/dockerfiles/rebuild_all.sh +++ b/extras/dockerfiles/rebuild_all.sh @@ -7,15 +7,15 @@ docker run --rm --privileged multiarch/qemu-user-static:register --reset COMMANDS=() -for V in 16.04 17.04 18.04 18.10 19.04 16.04 +for V in 18.04 19.10 20.04 20.10 do - C="docker build -t polettimarco/fruit-basesystem:ubuntu-$V -f Dockerfile.ubuntu-$V ." + C="docker build --squash -t polettimarco/fruit-basesystem:ubuntu-$V -f Dockerfile.ubuntu-$V ." COMMANDS+=("$C || { echo; echo FAILED: '$C'; echo; exit 1; }") done -for V in 16.04 18.04 +for V in 18.04 20.04 do - C="docker build -t polettimarco/fruit-basesystem:ubuntu_arm-$V -f Dockerfile.ubuntu_arm-$V ." + C="docker build --squash -t polettimarco/fruit-basesystem:ubuntu_arm-$V -f Dockerfile.ubuntu_arm-$V ." COMMANDS+=("$C || { echo; echo FAILED: '$C'; echo; exit 1; }") done @@ -28,10 +28,7 @@ done | xargs -P 0 -L 1 -d '\n' bash -c || { # This way we get better diagnostics. for C in "${COMMANDS[@]}" do - $C || { - echo "Failed: $C" - exit 1 - } + bash -c "$C" || exit 1 done } diff --git a/extras/dockerfiles/ubuntu-16.04_custom.list b/extras/dockerfiles/ubuntu-16.04_custom.list deleted file mode 100644 index 54c95ff..0000000 --- a/extras/dockerfiles/ubuntu-16.04_custom.list +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main -deb-src http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main -deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main -deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main -deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main -deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-4.0 main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-4.0 main -deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8 diff --git a/extras/dockerfiles/ubuntu-16.04_install.sh b/extras/dockerfiles/ubuntu-16.04_install.sh deleted file mode 100644 index 4d47e56..0000000 --- a/extras/dockerfiles/ubuntu-16.04_install.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -set -e - -apt-get install -y --no-install-recommends \ - curl - -# For the Bazel repository -curl https://bazel.build/bazel-release.pub.gpg | apt-key add - - -apt-get install -y --allow-unauthenticated --no-install-recommends \ - clang-3.5 \ - clang-3.6 \ - clang-3.7 \ - clang-3.8 \ - clang-3.9 \ - clang-4.0 \ - g++-5 \ - g++-4.9 \ - g++-6 \ - python \ - bazel \ - git \ - openjdk-8-jdk \ - clang-format - -pip3 install typed_ast diff --git a/extras/dockerfiles/ubuntu-17.04_custom.list b/extras/dockerfiles/ubuntu-17.04_custom.list deleted file mode 100644 index dfafeb4..0000000 --- a/extras/dockerfiles/ubuntu-17.04_custom.list +++ /dev/null @@ -1,8 +0,0 @@ -deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu zesty main -deb-src http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu zesty main -deb http://apt.llvm.org/zesty/ llvm-toolchain-zesty main -deb-src http://apt.llvm.org/zesty/ llvm-toolchain-zesty main -deb http://apt.llvm.org/zesty/ llvm-toolchain-zesty-3.9 main -deb-src http://apt.llvm.org/zesty/ llvm-toolchain-zesty-3.9 main -deb http://apt.llvm.org/zesty/ llvm-toolchain-zesty-4.0 main -deb-src http://apt.llvm.org/zesty/ llvm-toolchain-zesty-4.0 main diff --git a/extras/dockerfiles/ubuntu-17.04_install.sh b/extras/dockerfiles/ubuntu-17.04_install.sh deleted file mode 100644 index 6c774ef..0000000 --- a/extras/dockerfiles/ubuntu-17.04_install.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -e - -apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1E9377A2BA9EF27F - -apt-get install -y --allow-unauthenticated --no-install-recommends \ - clang-3.7 \ - clang-3.8 \ - clang-3.9 \ - clang-4.0 \ - g++-5 \ - g++-4.9 \ - g++-6 \ - python \ - clang-format - -pip3 install typed_ast diff --git a/extras/dockerfiles/ubuntu-18.04_custom.list b/extras/dockerfiles/ubuntu-18.04_custom.list index e69de29..171b878 100644 --- a/extras/dockerfiles/ubuntu-18.04_custom.list +++ b/extras/dockerfiles/ubuntu-18.04_custom.list @@ -0,0 +1,17 @@ +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-5.0 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-5.0 main +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-6.0 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-6.0 main +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main + +deb http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic main +deb-src http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic main diff --git a/extras/dockerfiles/ubuntu-18.04_install.sh b/extras/dockerfiles/ubuntu-18.04_install.sh deleted file mode 100644 index 3d4cde7..0000000 --- a/extras/dockerfiles/ubuntu-18.04_install.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -set -e - -apt-get install -y --no-install-recommends \ - curl - -# For the Bazel repository -curl https://bazel.build/bazel-release.pub.gpg | apt-key add - - -echo 'deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8' >> /etc/apt/sources.list.d/bazel.list - -apt-get update -qq - -apt-get install -y --allow-unauthenticated --no-install-recommends \ - g++-8 \ - g++-7 \ - g++-5 \ - clang-3.9 \ - clang-4.0 \ - clang-5.0 \ - clang-6.0 \ - bazel \ - git \ - python \ - python3-sh \ - python3-typed-ast \ - clang-format diff --git a/extras/dockerfiles/ubuntu-18.10_custom.list b/extras/dockerfiles/ubuntu-18.10_custom.list deleted file mode 100644 index e69de29..0000000 --- a/extras/dockerfiles/ubuntu-18.10_custom.list +++ /dev/null diff --git a/extras/dockerfiles/ubuntu-18.10_install.sh b/extras/dockerfiles/ubuntu-18.10_install.sh deleted file mode 100644 index 1357b11..0000000 --- a/extras/dockerfiles/ubuntu-18.10_install.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -e - -apt-get install -y --allow-unauthenticated --no-install-recommends \ - g++-7 \ - g++-8 \ - g++-5 \ - clang-3.9 \ - clang-4.0 \ - clang-6.0 \ - clang-7 \ - python \ - python3-sh \ - python3-typed-ast \ - clang-format diff --git a/extras/dockerfiles/ubuntu-19.04_custom.list b/extras/dockerfiles/ubuntu-19.04_custom.list deleted file mode 100644 index e69de29..0000000 --- a/extras/dockerfiles/ubuntu-19.04_custom.list +++ /dev/null diff --git a/extras/dockerfiles/ubuntu-19.04_install.sh b/extras/dockerfiles/ubuntu-19.04_install.sh deleted file mode 100644 index 2f78bdd..0000000 --- a/extras/dockerfiles/ubuntu-19.04_install.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -set -e - -apt-get install -y --allow-unauthenticated --no-install-recommends \ - g++-7 \ - g++-8 \ - g++-9 \ - clang-6.0 \ - clang-7 \ - clang-8 \ - python \ - python3-sh \ - python3-typed-ast \ - clang-format diff --git a/extras/dockerfiles/ubuntu-19.10_custom.list b/extras/dockerfiles/ubuntu-19.10_custom.list new file mode 100644 index 0000000..ac1b4bd --- /dev/null +++ b/extras/dockerfiles/ubuntu-19.10_custom.list @@ -0,0 +1,6 @@ +deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan main +deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan main +deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan-9 main +deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan-9 main +deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan-10 main +deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan-10 main diff --git a/extras/dockerfiles/ubuntu-20.04_custom.list b/extras/dockerfiles/ubuntu-20.04_custom.list new file mode 100644 index 0000000..c26e2d9 --- /dev/null +++ b/extras/dockerfiles/ubuntu-20.04_custom.list @@ -0,0 +1,4 @@ +deb http://apt.llvm.org/focal/ llvm-toolchain-focal-9 main +deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-9 main +deb http://apt.llvm.org/focal/ llvm-toolchain-focal-10 main +deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-10 main diff --git a/extras/dockerfiles/ubuntu-20.10_custom.list b/extras/dockerfiles/ubuntu-20.10_custom.list new file mode 100644 index 0000000..c26e2d9 --- /dev/null +++ b/extras/dockerfiles/ubuntu-20.10_custom.list @@ -0,0 +1,4 @@ +deb http://apt.llvm.org/focal/ llvm-toolchain-focal-9 main +deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-9 main +deb http://apt.llvm.org/focal/ llvm-toolchain-focal-10 main +deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-10 main diff --git a/extras/dockerfiles/ubuntu_arm-16.04_install.sh b/extras/dockerfiles/ubuntu_arm-16.04_install.sh deleted file mode 100644 index 504b2c0..0000000 --- a/extras/dockerfiles/ubuntu_arm-16.04_install.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -set -e - -apt-get install -y --allow-unauthenticated --no-install-recommends \ - clang-3.5 \ - clang-3.6 \ - clang-3.7 \ - clang-3.9 \ - clang-4.0 \ - g++-5 \ - g++-4.9 \ - g++-6 \ - python \ - clang-format diff --git a/extras/dockerfiles/ubuntu_arm-18.04_custom.list b/extras/dockerfiles/ubuntu_arm-18.04_custom.list deleted file mode 100644 index e347ae1..0000000 --- a/extras/dockerfiles/ubuntu_arm-18.04_custom.list +++ /dev/null @@ -1,8 +0,0 @@ -#deb [trusted=yes] http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu bionic main -#deb-src [trusted=yes] http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu bionic main -#deb [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic main -#deb-src [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic main -#deb [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic-4.0 main -#deb-src [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic-4.0 main -#deb [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic-5.0 main -#deb-src [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic-5.0 main diff --git a/extras/dockerfiles/ubuntu_arm-18.04_install.sh b/extras/dockerfiles/ubuntu_arm-18.04_install.sh deleted file mode 100644 index 8e21982..0000000 --- a/extras/dockerfiles/ubuntu_arm-18.04_install.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -e - -apt-get install -y --allow-unauthenticated --no-install-recommends \ - g++-8 \ - g++-7 \ - g++-5 \ - clang-3.9 \ - clang-4.0 \ - clang-5.0 \ - clang-6.0 \ - python \ - python3-sh \ - python3-typed-ast \ - clang-format diff --git a/extras/packaging/CMakeLists.txt b/extras/packaging/CMakeLists.txt index 7592bf0..09eb4d0 100644 --- a/extras/packaging/CMakeLists.txt +++ b/extras/packaging/CMakeLists.txt @@ -8,7 +8,7 @@ libfruit.install libfruit.spec ) -# This places configured files (build files with @FRUIT_VERSION@ replaced) in build/extras/packaging/built +# This places configured files (build files with @Fruit_VERSION@ replaced) in build/extras/packaging/built foreach(F ${PACKAGING_FILES}) configure_file(${F} built/${F} @ONLY) @@ -16,9 +16,9 @@ endforeach(F) configure_file(PKGBUILD PKGBUILD-template @ONLY) -add_custom_target(fruit-${FRUIT_VERSION}.tar.gz ALL +add_custom_target(fruit-${Fruit_VERSION}.tar.gz ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/PKGBUILD-template WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../.. - COMMAND git archive -o ${CMAKE_CURRENT_BINARY_DIR}/built/fruit-${FRUIT_VERSION}.tar.gz --prefix=fruit-${FRUIT_VERSION}/ HEAD - COMMAND md5sum ${CMAKE_CURRENT_BINARY_DIR}/built/fruit-${FRUIT_VERSION}.tar.gz | awk '{print $$1}' >${CMAKE_CURRENT_BINARY_DIR}/tarball-md5 + COMMAND git archive -o ${CMAKE_CURRENT_BINARY_DIR}/built/fruit-${Fruit_VERSION}.tar.gz --prefix=fruit-${Fruit_VERSION}/ HEAD + COMMAND md5sum ${CMAKE_CURRENT_BINARY_DIR}/built/fruit-${Fruit_VERSION}.tar.gz | awk '{print $$1}' >${CMAKE_CURRENT_BINARY_DIR}/tarball-md5 COMMAND sed "\"s/.*md5sums.*/md5sums=(`cat" "${CMAKE_CURRENT_BINARY_DIR}/tarball-md5`)/\"" <${CMAKE_CURRENT_BINARY_DIR}/PKGBUILD-template >${CMAKE_CURRENT_BINARY_DIR}/built/PKGBUILD) diff --git a/extras/packaging/PKGBUILD b/extras/packaging/PKGBUILD index b7b06cc..6f68971 100644 --- a/extras/packaging/PKGBUILD +++ b/extras/packaging/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Marco Poletti <poletti.marco@gmail.com> pkgname=libfruit -pkgver=@FRUIT_VERSION@ +pkgver=@Fruit_VERSION@ pkgrel=0 pkgdesc="Fruit is a dependency injection framework for C++." url="https://github.com/google/fruit" diff --git a/extras/packaging/deploy_to_bintray.bat b/extras/packaging/deploy_to_bintray.bat index 2473343..1a28914 100644 --- a/extras/packaging/deploy_to_bintray.bat +++ b/extras/packaging/deploy_to_bintray.bat @@ -1,4 +1,4 @@ -set FRUIT_VERSION=3.4.0 +set FRUIT_VERSION=354.0 for %%G in (Release Debug) DO CMD /C for %%H in (True False) DO CMD /C for %%I in (True False) DO conan create . google/stable -o fruit:shared=%%H -o fruit:use_boost=%%I -s build_type=%%G diff --git a/extras/packaging/deploy_to_bintray.sh b/extras/packaging/deploy_to_bintray.sh index 31a80c7..78d5c51 100755 --- a/extras/packaging/deploy_to_bintray.sh +++ b/extras/packaging/deploy_to_bintray.sh @@ -1,6 +1,6 @@ #!/bin/bash -FRUIT_VERSION=3.4.0 +FRUIT_VERSION=3.6.0 # To authenticate: # conan user -p <BINTRAY_API_KEY_HERE> -r fruit-bintray polettimarco diff --git a/extras/packaging/libfruit.dsc b/extras/packaging/libfruit.dsc index 07bd92e..8b58a26 100644 --- a/extras/packaging/libfruit.dsc +++ b/extras/packaging/libfruit.dsc @@ -1,10 +1,10 @@ Format: 1.0 Source: libfruit -Version: @FRUIT_VERSION@-0 +Version: @Fruit_VERSION@-0 Binary: libfruit Maintainer: Marco Poletti <poletti.marco@gmail.com> Architecture: any Build-Depends: debhelper (>= 4.1.16), cmake, libboost-dev, gcc (>= 4:5.0.0) Files: - d57283ebb8157ae919762c58419353c8 133282 libfruit_@FRUIT_VERSION@.orig.tar.gz - 2fecf324a32123b08cefc0f047bca5ee 63176 libfruit_@FRUIT_VERSION@-0.diff.tar.gz
\ No newline at end of file + d57283ebb8157ae919762c58419353c8 133282 libfruit_@Fruit_VERSION@.orig.tar.gz + 2fecf324a32123b08cefc0f047bca5ee 63176 libfruit_@Fruit_VERSION@-0.diff.tar.gz diff --git a/extras/packaging/libfruit.spec b/extras/packaging/libfruit.spec index 378abe5..dc63192 100644 --- a/extras/packaging/libfruit.spec +++ b/extras/packaging/libfruit.spec @@ -3,7 +3,7 @@ # Name: libfruit -Version: @FRUIT_VERSION@ +Version: @Fruit_VERSION@ Release: 0 Summary: Dependency Injection Framework For C++ License: Apache-2.0 @@ -47,8 +47,8 @@ most injection problems at compile-time. %setup -q -n fruit-%{version} %build -cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} -DINSTALL_LIBRARY_DIR=%{_libdir} -DCMAKE_BUILD_TYPE=RelWithDebInfo - +cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} -DCMAKE_INSTALL_LIBDIR=%{_libdir} -DCMAKE_BUILD_TYPE=RelWithDebInfo + %{__make} %{?jobs:-j%jobs} %install diff --git a/extras/scripts/postsubmit-helper.sh b/extras/scripts/postsubmit-helper.sh index 36169bb..eecd3c0 100755 --- a/extras/scripts/postsubmit-helper.sh +++ b/extras/scripts/postsubmit-helper.sh @@ -37,6 +37,11 @@ gcc-9) export CXX=g++-9 ;; +gcc-10) + export CC=gcc-10 + export CXX=g++-10 + ;; + clang-3.5) export CC=clang-3.5 export CXX=clang++-3.5 @@ -87,6 +92,21 @@ clang-8.0) export CXX=clang++-8 ;; +clang-9.0) + export CC=clang-9 + export CXX=clang++-9 + ;; + +clang-10.0) + export CC=clang-10 + export CXX=clang++-10 + ;; + +clang-11.0) + export CC=clang-11 + export CXX=clang++-11 + ;; + clang-default) export CC=clang export CXX=clang++ @@ -107,28 +127,44 @@ run_make() { if [[ "${COMPILER}" != "bazel" ]] then # This is only needed in OS X but it has no effect on Linux so we can add it unconditionally. - BOOST_INCLUDE_FLAG="-I /usr/local/include/boost" - COMMON_CXX_FLAGS="$STLARG $BOOST_INCLUDE_FLAG -Werror -pedantic" + BOOST_INCLUDE_FLAG="-I /usr/local/include/boost -I /usr/local/include" + # -Wdtor-name (part of -pedantic) is *very* pedantic. Following that results in weird-looking code. + # See https://bugs.llvm.org/show_bug.cgi?id=46979. + COMMON_CXX_FLAGS="$STLARG $BOOST_INCLUDE_FLAG -Werror -pedantic -Wno-unknown-warning-option -Wno-dtor-name -Winvalid-pch" echo CXX version: $($CXX --version) echo C++ Standard library location: $(echo '#include <vector>' | $CXX -x c++ -E - | grep 'vector\"' | awk '{print $3}' | sed 's@/vector@@;s@\"@@g' | head -n 1) echo Normalized C++ Standard library location: $(readlink -f $(echo '#include <vector>' | $CXX -x c++ -E - | grep 'vector\"' | awk '{print $3}' | sed 's@/vector@@;s@\"@@g' | head -n 1)) case "$1" in - DebugPlain) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2") ;; - DebugPlainNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; - DebugAsan) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address") ;; - DebugAsanNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; - DebugAsanUbsan) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address,undefined") ;; - DebugAsanUbsanNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address,undefined" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; - DebugValgrind) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DRUN_TESTS_UNDER_VALGRIND=TRUE) ;; - DebugValgrindNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DRUN_TESTS_UNDER_VALGRIND=TRUE -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; - ReleasePlain) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS") ;; - ReleasePlainNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; - ReleaseValgrind) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DRUN_TESTS_UNDER_VALGRIND=TRUE) ;; - ReleaseValgrindNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DRUN_TESTS_UNDER_VALGRIND=TRUE -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + DebugPlain) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2") ;; + DebugPlainNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2") ;; + DebugPlainNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + DebugPlainNoPchNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + DebugAsan) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address") ;; + DebugAsanNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address") ;; + DebugAsanNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + DebugAsanNoPchNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + DebugAsanUbsan) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address,undefined") ;; + DebugAsanUbsanNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address,undefined") ;; + DebugAsanUbsanNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address,undefined" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + DebugAsanUbsanNoPchNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O0 -fsanitize=address,undefined" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + DebugValgrind) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DRUN_TESTS_UNDER_VALGRIND=TRUE) ;; + DebugValgrindNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DRUN_TESTS_UNDER_VALGRIND=TRUE) ;; + DebugValgrindNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DRUN_TESTS_UNDER_VALGRIND=TRUE -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + DebugValgrindNoPchNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Debug -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS -DFRUIT_DEBUG=1 -DFRUIT_EXTRA_DEBUG=1 -D_GLIBCXX_DEBUG=1 -O2" -DRUN_TESTS_UNDER_VALGRIND=TRUE -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + ReleasePlain) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS") ;; + ReleasePlainNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS") ;; + ReleasePlainNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + ReleasePlainNoPchNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + ReleaseValgrind) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DRUN_TESTS_UNDER_VALGRIND=TRUE) ;; + ReleaseValgrindNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DRUN_TESTS_UNDER_VALGRIND=TRUE) ;; + ReleaseValgrindNoPch) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=TRUE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DRUN_TESTS_UNDER_VALGRIND=TRUE -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; + ReleaseValgrindNoPchNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DRUN_TESTS_UNDER_VALGRIND=TRUE -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;; *) echo "Error: you need to specify one of the supported postsubmit modes (see postsubmit.sh)."; exit 1 ;; esac + # Setting compilers only via env vars doesn't work when using recent versions of XCode. + CMAKE_ARGS+=(-DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX) SOURCES_PATH="$PWD" @@ -165,8 +201,12 @@ then make install else # COMPILER=bazel - - BAZEL_FLAGS=("--python_path=$(which python3)") + + # In recent versions of Bazel (as of May 2020), --python_path is ignored unless + # --noincompatible_use_python_toolchains is also used. + # Ignoring --python_path is ok in Ubuntu 20.04 since 3.8 is the default Python there, but causes problems in docker + # images with older Ubuntu versions that have both 3.8 and another 3.x version installed. + BAZEL_FLAGS=("--python_path=$(which python3.8)" "--noincompatible_use_python_toolchains") case "$1" in DebugPlain) ;; ReleasePlain) BAZEL_FLAGS+=("-c" "opt") ;; diff --git a/extras/scripts/postsubmit.bat b/extras/scripts/postsubmit.bat index 59fbb4c..c23dd79 100644 --- a/extras/scripts/postsubmit.bat +++ b/extras/scripts/postsubmit.bat @@ -42,6 +42,7 @@ IF "%CMAKE_GENERATOR%"=="MinGW Makefiles" ( msbuild ALL_BUILD.vcxproj || exit /b 1 ) +pip3 install absl-py pip3 install pytest pip3 install pytest-xdist diff --git a/extras/scripts/travis_ci_install_osx.sh b/extras/scripts/travis_ci_install_osx.sh index 0bef2b1..d3cc7c8 100755 --- a/extras/scripts/travis_ci_install_osx.sh +++ b/extras/scripts/travis_ci_install_osx.sh @@ -2,8 +2,17 @@ set -e +# These packages depend on the ones that we update but we don't care about these, we don't want to waste time upgrading +# them. +for p in postgis ansible libdap libspatialite gdal mercurial poppler +do + brew pin $p +done + install_brew_package() { - time (brew install "$@" || brew outdated "$1" || brew upgrade "$@") + time (brew install "$@" || brew outdated "$1" || brew upgrade "$@" || true) + # Some formulas are not linked into /usr/local by default, make sure they are. + time (brew link --force --overwrite "$@" || true) } # For md5sum, timeout @@ -24,15 +33,29 @@ gcc-7) install_brew_package gcc@7 ;; gcc-8) install_brew_package gcc@8 ;; gcc-9) install_brew_package gcc@9 ;; clang-default) ;; -clang-3.9) install_brew_package llvm@3.9 ;; -clang-4.0) install_brew_package llvm@4 ;; -clang-5.0) install_brew_package llvm@5 ;; -clang-6.0) install_brew_package llvm@6 ;; -clang-7.0) install_brew_package llvm@7 ;; -clang-8.0) install_brew_package llvm@8 ;; +clang-6.0) + install_brew_package llvm@6 + ln -s /usr/local/opt/llvm@6/bin/clang++ /usr/local/bin/clang++-6.0 + ;; +clang-7.0) + install_brew_package llvm@7 + ln -s /usr/local/opt/llvm@7/bin/clang++ /usr/local/bin/clang++-7 + ;; +clang-8.0) + install_brew_package llvm@8 + ln -s /usr/local/opt/llvm@8/bin/clang++ /usr/local/bin/clang++-8 + ;; +clang-9.0) + install_brew_package llvm@9 + ln -s /usr/local/opt/llvm@9/bin/clang++ /usr/local/bin/clang++-9 + ln -s /usr/local/opt/llvm@9/bin/clang /usr/local/bin/clang-9 + ;; *) echo "Compiler not supported: ${COMPILER}. See travis_ci_install_osx.sh"; exit 1 ;; esac +# So that we can "brew link" python@3 instead. +brew unlink python@2 + install_brew_package boost install_brew_package python time pip3 install absl-py diff --git a/extras/scripts/travis_yml_generator.py b/extras/scripts/travis_yml_generator.py index e2f5581..46c5a92 100755 --- a/extras/scripts/travis_yml_generator.py +++ b/extras/scripts/travis_yml_generator.py @@ -29,7 +29,7 @@ def determine_compiler_kind(compiler): raise Exception('Unexpected compiler: %s' % compiler) -def determine_tests(asan, ubsan, smoke_tests, use_precompiled_headers_in_tests, exclude_tests, +def determine_tests(asan, ubsan, clang_tidy, smoke_tests, use_precompiled_headers_in_tests, exclude_tests, include_only_tests): tests = [] has_debug_build = False @@ -51,7 +51,7 @@ def determine_tests(asan, ubsan, smoke_tests, use_precompiled_headers_in_tests, if excessive_excluded_tests: raise Exception( 'Some tests were excluded but were not going to run anyway: %s. ' - 'Tests to run (ignoring the possible NoPch prefix): %s' + 'Tests to run (ignoring the possible NoPch/NoClangTidy prefixes): %s' % (excessive_excluded_tests, tests)) if include_only_tests is not None: if exclude_tests != []: @@ -61,6 +61,8 @@ def determine_tests(asan, ubsan, smoke_tests, use_precompiled_headers_in_tests, tests = [test for test in tests if test not in exclude_tests] if not use_precompiled_headers_in_tests: tests = [test + 'NoPch' for test in tests] + if not clang_tidy: + tests = [test + 'NoClangTidy' for test in tests] return tests @@ -72,7 +74,7 @@ def generate_env_string_for_env(env): return ' '.join(['%s=%s' % (var_name, value) for (var_name, value) in sorted(env.items())]) -def add_ubuntu_tests(ubuntu_version, compiler, os='linux', stl=None, asan=True, ubsan=True, +def add_ubuntu_tests(ubuntu_version, compiler, os='linux', stl=None, asan=True, ubsan=True, clang_tidy=True, use_precompiled_headers_in_tests=True, smoke_tests=[], exclude_tests=[], include_only_tests=None): env = { 'UBUNTU': ubuntu_version, @@ -84,7 +86,7 @@ def add_ubuntu_tests(ubuntu_version, compiler, os='linux', stl=None, asan=True, export_statements = 'export OS=' + os + '; ' + generate_export_statements_for_env(env=env) test_environment_template = {'os': 'linux', 'compiler': compiler_kind, 'install': '%s extras/scripts/travis_ci_install_linux.sh' % export_statements} - tests = determine_tests(asan, ubsan, smoke_tests, + tests = determine_tests(asan, ubsan, clang_tidy, smoke_tests, use_precompiled_headers_in_tests=use_precompiled_headers_in_tests, exclude_tests=exclude_tests, include_only_tests=include_only_tests) @@ -99,7 +101,7 @@ def add_ubuntu_tests(ubuntu_version, compiler, os='linux', stl=None, asan=True, build_matrix_rows.append(test_environment) -def add_osx_tests(compiler, xcode_version=None, stl=None, asan=True, ubsan=True, +def add_osx_tests(compiler, xcode_version=None, stl=None, asan=True, ubsan=True, clang_tidy=True, use_precompiled_headers_in_tests=True, smoke_tests=[], exclude_tests=[], include_only_tests=None): env = {'COMPILER': compiler} if stl is not None: @@ -107,11 +109,11 @@ def add_osx_tests(compiler, xcode_version=None, stl=None, asan=True, ubsan=True, compiler_kind = determine_compiler_kind(compiler) export_statements = 'export OS=osx; ' + generate_export_statements_for_env(env=env) test_environment_template = {'os': 'osx', 'compiler': compiler_kind, - 'install': '%s extras/scripts/travis_ci_install_osx.sh' % export_statements} + 'install': '%s travis_wait extras/scripts/travis_ci_install_osx.sh' % export_statements} if xcode_version is not None: test_environment_template['osx_image'] = 'xcode%s' % xcode_version - tests = determine_tests(asan, ubsan, smoke_tests, + tests = determine_tests(asan, ubsan, clang_tidy, smoke_tests, use_precompiled_headers_in_tests=use_precompiled_headers_in_tests, exclude_tests=exclude_tests, include_only_tests=include_only_tests) for test in tests: @@ -142,27 +144,26 @@ def add_bazel_tests(ubuntu_version, smoke_tests=[]): else: build_matrix_rows.append(test_environment) - -# TODO: re-enable ASan/UBSan once they work in Travis CI. ATM (as of 18 November 2017) they fail due to https://github.com/google/sanitizers/issues/837 -add_ubuntu_tests(ubuntu_version='19.04', compiler='gcc-9', asan=False, ubsan=False, +add_ubuntu_tests(ubuntu_version='20.10', compiler='gcc-7') +add_ubuntu_tests(ubuntu_version='20.10', compiler='gcc-10', smoke_tests=['DebugPlain', 'ReleasePlain']) -add_ubuntu_tests(ubuntu_version='19.04', compiler='clang-6.0', stl='libstdc++', +add_ubuntu_tests(ubuntu_version='20.10', compiler='clang-8.0', stl='libstdc++', smoke_tests=['DebugPlain', 'DebugAsanUbsan', 'ReleasePlain']) -add_ubuntu_tests(ubuntu_version='19.04', compiler='clang-8.0', stl='libstdc++', - # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625. - use_precompiled_headers_in_tests=False) -add_ubuntu_tests(ubuntu_version='19.04', compiler='clang-8.0', stl='libc++', - # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625. - use_precompiled_headers_in_tests=False) +add_ubuntu_tests(ubuntu_version='20.10', compiler='clang-11.0', stl='libstdc++') +add_ubuntu_tests(ubuntu_version='20.10', compiler='clang-11.0', stl='libc++') -add_ubuntu_tests(ubuntu_version='18.10', compiler='gcc-8', asan=False, ubsan=False) -add_ubuntu_tests(ubuntu_version='18.10', compiler='clang-4.0', stl='libstdc++') -add_ubuntu_tests(ubuntu_version='18.10', compiler='clang-7.0', stl='libstdc++', +add_ubuntu_tests(ubuntu_version='20.04', compiler='gcc-7') +add_ubuntu_tests(ubuntu_version='20.04', compiler='clang-6.0', stl='libstdc++', + smoke_tests=['DebugPlain', 'DebugAsanUbsan', 'ReleasePlain']) + +add_ubuntu_tests(ubuntu_version='18.04', compiler='gcc-5', asan=False, ubsan=False) +add_ubuntu_tests(ubuntu_version='18.04', compiler='gcc-8', asan=False, ubsan=False) +add_ubuntu_tests(ubuntu_version='18.04', compiler='clang-3.9', stl='libstdc++') +add_ubuntu_tests(ubuntu_version='18.04', compiler='clang-7.0', stl='libstdc++', # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625. use_precompiled_headers_in_tests=False) add_bazel_tests(ubuntu_version='18.04', smoke_tests=['DebugPlain']) -add_bazel_tests(ubuntu_version='16.04') # ASan/UBSan are disabled for all these, the analysis on later versions is better anyway. # Also, in some combinations they wouldn't work. @@ -175,19 +176,23 @@ add_ubuntu_tests(ubuntu_version='16.04', compiler='clang-3.9', stl='libstdc++', # overridden at runtime. This was likely caused by different translation units being compiled with different # visibility settings. # and the build eventually fails or times out. -add_osx_tests(compiler='gcc-6', xcode_version='11.4', asan=False, ubsan=False) -add_osx_tests(compiler='gcc-9', xcode_version='11.4', asan=False, ubsan=False, smoke_tests=['DebugPlain']) -add_osx_tests(compiler='clang-4.0', xcode_version='11.4', stl='libc++') +add_osx_tests(compiler='gcc-6', xcode_version='11.4', asan=False, ubsan=False, clang_tidy=False) +add_osx_tests(compiler='gcc-9', xcode_version='11.4', asan=False, ubsan=False, clang_tidy=False, smoke_tests=['DebugPlain'], + # Using PCHs fails with this error: + # error: /Users/travis/build/google/fruit/build/tests/test_common-precompiled.h.gch: had text segment + # at different address + use_precompiled_headers_in_tests=False) +add_osx_tests(compiler='clang-6.0', xcode_version='11.4', stl='libc++', clang_tidy=False) add_osx_tests(compiler='clang-8.0', xcode_version='11.4', stl='libc++', smoke_tests=['DebugPlain'], + clang_tidy=False, # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625. use_precompiled_headers_in_tests=False) -# UBSan is disabled because AppleClang does not support -fsanitize=undefined. -add_osx_tests(compiler='clang-default', xcode_version='8.3', stl='libc++', ubsan=False) - -add_osx_tests(compiler='clang-default', xcode_version='9.4', stl='libc++') -add_osx_tests(compiler='clang-default', xcode_version='10.3', stl='libc++', smoke_tests=['DebugPlain']) -add_osx_tests(compiler='clang-default', xcode_version='11.4', stl='libc++', smoke_tests=['DebugPlain']) +add_osx_tests(compiler='clang-default', xcode_version='9.4', stl='libc++', clang_tidy=False) +add_osx_tests(compiler='clang-default', xcode_version='11.3', stl='libc++', clang_tidy=False, + # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625. + use_precompiled_headers_in_tests=False, + smoke_tests=['DebugPlain']) # ** Disabled combinations ** # @@ -222,7 +227,7 @@ add_osx_tests(compiler='clang-default', xcode_version='11.4', stl='libc++', smok yaml_file = { 'sudo': 'required', - 'dist': 'trusty', + 'dist': 'xenial', 'services': ['docker'], 'language': 'cpp', 'branches': { diff --git a/include/fruit/component.h b/include/fruit/component.h index 98eb727..cd8be1f 100644 --- a/include/fruit/component.h +++ b/include/fruit/component.h @@ -44,7 +44,7 @@ namespace fruit { template <typename... Params> class Component { public: - Component(Component&&) = default; + Component(Component&&) noexcept = default; Component& operator=(Component&&) = delete; Component& operator=(const Component&) = delete; @@ -55,7 +55,7 @@ public: * This is usually called implicitly when returning a component from a function. See PartialComponent for an example. */ template <typename... Bindings> - Component(PartialComponent<Bindings...>&& component); + Component(PartialComponent<Bindings...>&& component) noexcept; // NOLINT(google-explicit-constructor) private: // Do not use. Use fruit::createComponent() instead. @@ -938,7 +938,8 @@ public: Bindings...> with(ReplacedComponent (*)(FormalArgs...), Args&&... args); - PartialComponentWithReplacementInProgress(storage_t storage) : storage(storage) {} + PartialComponentWithReplacementInProgress(storage_t storage) // NOLINT(google-explicit-constructor) + : storage(storage) {} private: storage_t storage; @@ -1048,7 +1049,14 @@ public: fruit::Component<OtherComponentParams...>, FormalArgs...> replace(fruit::Component<OtherComponentParams...> (*)(FormalArgs...), Args&&... args); - ~PartialComponent(); + ~PartialComponent() = default; + + // Do not use. Use fruit::createComponent() instead. + PartialComponent() = delete; + + // Do not use. Only use PartialComponent for temporaries, and then convert it to a Component. + PartialComponent(const PartialComponent&) = delete; + PartialComponent(PartialComponent&&) = delete; private: template <typename... OtherBindings> @@ -1059,14 +1067,7 @@ private: fruit::impl::PartialComponentStorage<Bindings...> storage; - // Do not use. Use fruit::createComponent() instead. - PartialComponent() = delete; - - // Do not use. Only use PartialComponent for temporaries, and then convert it to a Component. - PartialComponent(const PartialComponent&) = delete; - PartialComponent(PartialComponent&&) = delete; - - PartialComponent(fruit::impl::PartialComponentStorage<Bindings...> storage); + PartialComponent(fruit::impl::PartialComponentStorage<Bindings...> storage); // NOLINT(google-explicit-constructor) template <typename NewBinding> using OpFor = typename fruit::impl::meta::OpForComponent<Bindings...>::template AddBinding<NewBinding>; diff --git a/include/fruit/component_function.h b/include/fruit/component_function.h index 56b77a1..70299ed 100644 --- a/include/fruit/component_function.h +++ b/include/fruit/component_function.h @@ -34,7 +34,7 @@ private: /** * This is (intentionally) private, use fruit::componentFunction() to construct ComponentFunction objects. */ - ComponentFunction(ComponentType (*getComponent)(ComponentFunctionArgs...), ComponentFunctionArgs... args); + explicit ComponentFunction(ComponentType (*getComponent)(ComponentFunctionArgs...), ComponentFunctionArgs... args); friend struct fruit::impl::ComponentStorageEntry; @@ -45,10 +45,13 @@ public: ComponentType (*getComponent)(ComponentFunctionArgs...), ActualArgs&&... args); ComponentFunction(const ComponentFunction&) = default; - ComponentFunction(ComponentFunction&&) = default; + ComponentFunction(ComponentFunction&&) noexcept = default; ComponentFunction& operator=(const ComponentFunction&) = default; - ComponentFunction& operator=(ComponentFunction&&) = default; + ComponentFunction& operator=(ComponentFunction&& other) noexcept { + args_tuple = std::move(other.args_tuple); + return *this; + } ComponentType operator()(); }; diff --git a/include/fruit/impl/component.defn.h b/include/fruit/impl/component.defn.h index 382ecac..ddc4810 100644 --- a/include/fruit/impl/component.defn.h +++ b/include/fruit/impl/component.defn.h @@ -48,7 +48,7 @@ struct OpForComponent { template <typename... Params> template <typename... Bindings> -inline Component<Params...>::Component(PartialComponent<Bindings...>&& partial_component) : storage() { +inline Component<Params...>::Component(PartialComponent<Bindings...>&& partial_component) noexcept : storage() { (void)typename fruit::impl::meta::CheckIfError<Comp>::type(); @@ -77,9 +77,6 @@ inline Component<Params...>::Component(PartialComponent<Bindings...>&& partial_c storage = fruit::impl::ComponentStorage(std::move(entries)); } -template <typename... Bindings> -inline PartialComponent<Bindings...>::~PartialComponent() {} - inline PartialComponent<> createComponent() { return {{}}; } diff --git a/include/fruit/impl/component_functors.defn.h b/include/fruit/impl/component_functors.defn.h index e03b0a8..e6778b1 100644 --- a/include/fruit/impl/component_functors.defn.h +++ b/include/fruit/impl/component_functors.defn.h @@ -402,7 +402,7 @@ template <int numAssistedBefore, int numNonAssistedBefore, typename Arg> struct GetAssistedArg<numAssistedBefore, numNonAssistedBefore, Assisted<Arg>> { template <typename InjectedArgsTuple, typename UserProvidedArgsTuple> inline Arg operator()(InjectedArgsTuple&, UserProvidedArgsTuple& user_provided_args) { - return std::get<numAssistedBefore>(user_provided_args); + return std::move(std::get<numAssistedBefore>(user_provided_args)); } }; @@ -437,9 +437,9 @@ struct RegisterFactoryHelper { using Result = Eval<R>; void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { auto function_provider = [](NakedInjectedArgs... args) { - auto injected_args = std::make_tuple(args...); - auto object_provider = [injected_args](NakedUserProvidedArgs... params) mutable { - auto user_provided_args = std::tie(params...); + std::tuple<NakedInjectedArgs...> injected_args{args...}; + auto object_provider = [=](NakedUserProvidedArgs... params) mutable { + std::tuple<NakedUserProvidedArgs...> user_provided_args{std::move(params)...}; // These are unused if they are 0-arg tuples. Silence the unused-variable warnings anyway. (void)injected_args; (void)user_provided_args; @@ -570,8 +570,8 @@ struct PreProcessRegisterConstructor { using CDeps = NormalizeTypeVector(AnnotatedArgs); using CNonConstDeps = NormalizedNonConstTypesIn(AnnotatedArgs); using R = AddProvidedType(Comp, AnnotatedC, Bool<true>, CDeps, CNonConstDeps); - using type = If( - Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature), + using type = If(Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature), + If(Not(IsSame(RemoveAssisted(Args), Args)), ConstructError(AssistedParamInRegisterConstructorSignatureErrorTag, AnnotatedSignature), PropagateError(CheckInjectableType(RemoveAnnotations(C)), PropagateError(CheckInjectableTypeVector(RemoveAnnotationsFromVector(Args)), If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))), @@ -579,7 +579,7 @@ struct PreProcessRegisterConstructor { RemoveAnnotations(SignatureType(AnnotatedSignature))), If(Not(IsConstructibleWithVector(C, Args)), ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, Signature), - PropagateError(R, ComponentFunctorIdentity(R))))))); + PropagateError(R, ComponentFunctorIdentity(R)))))))); }; }; @@ -912,35 +912,45 @@ struct AutoRegisterFactoryHelper { using R = Call(ComposeFunctors(F1, F2, F3), Comp); struct Op { using Result = Eval<GetResult(R)>; + using NakedC = UnwrapType<Eval<C>>; void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { - using NakedC = UnwrapType<Eval<C>>; auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) { - return UnwrapType<Eval<IFunctor>>([=](typename TypeUnwrapper<Args>::type... args) { + return UnwrapType<Eval<IFunctor>>([=](typename Args::type... args) { NakedC* c = fun(args...).release(); NakedI* i = static_cast<NakedI*>(c); return std::unique_ptr<NakedI>(i); }); }; - using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); - using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); - using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); - FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R))); - Eval<RealOp>()(entries); + FruitStaticAssert(IsSame( + GetResult( + Call(ComposeFunctors( + F1, + ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>), + ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)), + Comp)), + GetResult(R))); + Eval<Call(ComposeFunctors( + F1, + ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>), + ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)), + Comp)>()(entries); } std::size_t numEntries() { #if FRUIT_EXTRA_DEBUG - using NakedC = UnwrapType<Eval<C>>; auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) { - return UnwrapType<Eval<IFunctor>>([=](typename TypeUnwrapper<Args>::type... args) { + return UnwrapType<Eval<IFunctor>>([=](typename Args::type... args) { NakedC* c = fun(args...).release(); NakedI* i = static_cast<NakedI*>(c); return std::unique_ptr<NakedI>(i); }); }; - using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); - using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); - using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); - FruitAssert(Eval<R>().numEntries() == Eval<RealOp>().numEntries()); + FruitAssert( + Eval<R>().numEntries() == + Eval<Call(ComposeFunctors( + F1, ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>), + ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)), + Comp)>() + .numEntries()); #endif return Eval<R>().numEntries(); } diff --git a/include/fruit/impl/component_storage/component_storage.defn.h b/include/fruit/impl/component_storage/component_storage.defn.h index c44efb9..0d0d4ce 100644 --- a/include/fruit/impl/component_storage/component_storage.defn.h +++ b/include/fruit/impl/component_storage/component_storage.defn.h @@ -23,14 +23,14 @@ namespace fruit { namespace impl { -inline ComponentStorage::ComponentStorage(FixedSizeVector<ComponentStorageEntry>&& entries) +inline ComponentStorage::ComponentStorage(FixedSizeVector<ComponentStorageEntry>&& entries) noexcept : entries(std::move(entries)) {} inline ComponentStorage::ComponentStorage(const ComponentStorage& other) { *this = other; } -inline ComponentStorage::ComponentStorage(ComponentStorage&& other) { +inline ComponentStorage::ComponentStorage(ComponentStorage&& other) noexcept { *this = std::move(other); } @@ -64,7 +64,7 @@ inline ComponentStorage& ComponentStorage::operator=(const ComponentStorage& oth return *this; } -inline ComponentStorage& ComponentStorage::operator=(ComponentStorage&& other) { +inline ComponentStorage& ComponentStorage::operator=(ComponentStorage&& other) noexcept { entries = std::move(other.entries); // We don't want other to have any entries after this operation because we might otherwise end up destroying those diff --git a/include/fruit/impl/component_storage/component_storage.h b/include/fruit/impl/component_storage/component_storage.h index 45e3f05..c3f96ae 100644 --- a/include/fruit/impl/component_storage/component_storage.h +++ b/include/fruit/impl/component_storage/component_storage.h @@ -43,9 +43,9 @@ private: public: ComponentStorage() = default; - ComponentStorage(FixedSizeVector<ComponentStorageEntry>&& entries); + explicit ComponentStorage(FixedSizeVector<ComponentStorageEntry>&& entries) noexcept; ComponentStorage(const ComponentStorage&); - ComponentStorage(ComponentStorage&&); + ComponentStorage(ComponentStorage&&) noexcept; ~ComponentStorage(); @@ -54,7 +54,7 @@ public: std::size_t numEntries() const; ComponentStorage& operator=(const ComponentStorage&); - ComponentStorage& operator=(ComponentStorage&&); + ComponentStorage& operator=(ComponentStorage&&) noexcept; }; } // namespace impl diff --git a/include/fruit/impl/component_storage/component_storage_entry.h b/include/fruit/impl/component_storage/component_storage_entry.h index 80e1e48..eb64791 100644 --- a/include/fruit/impl/component_storage/component_storage_entry.h +++ b/include/fruit/impl/component_storage/component_storage_entry.h @@ -238,7 +238,7 @@ struct ComponentStorageEntry { using entry_vector_t = std::vector<ComponentStorageEntry, ArenaAllocator<ComponentStorageEntry>>; - ComponentInterface(erased_fun_t erased_fun); + explicit ComponentInterface(erased_fun_t erased_fun); virtual ~ComponentInterface() = default; diff --git a/include/fruit/impl/component_storage/partial_component_storage.defn.h b/include/fruit/impl/component_storage/partial_component_storage.defn.h index 18e65e5..0e4b98c 100644 --- a/include/fruit/impl/component_storage/partial_component_storage.defn.h +++ b/include/fruit/impl/component_storage/partial_component_storage.defn.h @@ -46,7 +46,7 @@ private: PartialComponentStorage<PreviousBindings...>& previous_storage; public: - PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) + PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor) : previous_storage(previous_storage) {} void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const { @@ -64,7 +64,7 @@ private: PartialComponentStorage<PreviousBindings...>& previous_storage; public: - PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) + PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor) : previous_storage(previous_storage) {} void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const { @@ -164,7 +164,7 @@ private: PartialComponentStorage<PreviousBindings...>& previous_storage; public: - PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) + PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor) : previous_storage(previous_storage) {} void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const { @@ -279,7 +279,7 @@ private: PartialComponentStorage<PreviousBindings...>& previous_storage; public: - PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) + PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor) : previous_storage(previous_storage) {} void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const { @@ -297,7 +297,7 @@ private: PartialComponentStorage<PreviousBindings...>& previous_storage; public: - PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) + PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor) : previous_storage(previous_storage) {} void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const { @@ -315,7 +315,7 @@ private: PartialComponentStorage<PreviousBindings...>& previous_storage; public: - PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) + PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor) : previous_storage(previous_storage) {} void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const { diff --git a/include/fruit/impl/data_structures/arena_allocator.h b/include/fruit/impl/data_structures/arena_allocator.h index 3ba0521..207455d 100644 --- a/include/fruit/impl/data_structures/arena_allocator.h +++ b/include/fruit/impl/data_structures/arena_allocator.h @@ -53,10 +53,10 @@ public: * Constructs an arena allocator using the specified memory pool. * The MemoryPool object must outlive all allocators constructed with it and all allocated objects. */ - ArenaAllocator(MemoryPool& memory_pool); + explicit ArenaAllocator(MemoryPool& memory_pool); template <typename U> - ArenaAllocator(const ArenaAllocator<U>&); + ArenaAllocator(const ArenaAllocator<U>&); // NOLINT(google-explicit-constructor) T* allocate(std::size_t n); void deallocate(T* p, std::size_t); diff --git a/include/fruit/impl/data_structures/fixed_size_allocator.defn.h b/include/fruit/impl/data_structures/fixed_size_allocator.defn.h index 7bad811..c5f6faf 100644 --- a/include/fruit/impl/data_structures/fixed_size_allocator.defn.h +++ b/include/fruit/impl/data_structures/fixed_size_allocator.defn.h @@ -98,7 +98,7 @@ inline void FixedSizeAllocator::registerExternallyAllocatedObject(T* p) { on_destruction.push_back(std::pair<destroy_t, void*>{destroyExternalObject<T>, p}); } -inline FixedSizeAllocator::FixedSizeAllocator(FixedSizeAllocatorData allocator_data) +inline FixedSizeAllocator::FixedSizeAllocator(const FixedSizeAllocatorData& allocator_data) : on_destruction(allocator_data.num_types_to_destroy) { // The +1 is because we waste the first byte (storage_last_used points to the beginning of storage). storage_begin = new char[allocator_data.total_size + 1]; @@ -113,7 +113,7 @@ inline FixedSizeAllocator::FixedSizeAllocator(FixedSizeAllocatorData allocator_d #endif } -inline FixedSizeAllocator::FixedSizeAllocator(FixedSizeAllocator&& x) : FixedSizeAllocator() { +inline FixedSizeAllocator::FixedSizeAllocator(FixedSizeAllocator&& x) noexcept : FixedSizeAllocator() { std::swap(storage_begin, x.storage_begin); std::swap(storage_last_used, x.storage_last_used); std::swap(on_destruction, x.on_destruction); @@ -122,7 +122,7 @@ inline FixedSizeAllocator::FixedSizeAllocator(FixedSizeAllocator&& x) : FixedSiz #endif } -inline FixedSizeAllocator& FixedSizeAllocator::operator=(FixedSizeAllocator&& x) { +inline FixedSizeAllocator& FixedSizeAllocator::operator=(FixedSizeAllocator&& x) noexcept { std::swap(storage_begin, x.storage_begin); std::swap(storage_last_used, x.storage_last_used); std::swap(on_destruction, x.on_destruction); diff --git a/include/fruit/impl/data_structures/fixed_size_allocator.h b/include/fruit/impl/data_structures/fixed_size_allocator.h index cbc8ca8..1e057d5 100644 --- a/include/fruit/impl/data_structures/fixed_size_allocator.h +++ b/include/fruit/impl/data_structures/fixed_size_allocator.h @@ -89,10 +89,10 @@ public: FixedSizeAllocator() = default; // Constructs an allocator for the type set in FixedSizeAllocatorData. - FixedSizeAllocator(FixedSizeAllocatorData allocator_data); + explicit FixedSizeAllocator(const FixedSizeAllocatorData& allocator_data); - FixedSizeAllocator(FixedSizeAllocator&&); - FixedSizeAllocator& operator=(FixedSizeAllocator&&); + FixedSizeAllocator(FixedSizeAllocator&&) noexcept; + FixedSizeAllocator& operator=(FixedSizeAllocator&&) noexcept; FixedSizeAllocator(const FixedSizeAllocator&) = delete; FixedSizeAllocator& operator=(const FixedSizeAllocator&) = delete; diff --git a/include/fruit/impl/data_structures/fixed_size_vector.defn.h b/include/fruit/impl/data_structures/fixed_size_vector.defn.h index ed8a533..2467571 100644 --- a/include/fruit/impl/data_structures/fixed_size_vector.defn.h +++ b/include/fruit/impl/data_structures/fixed_size_vector.defn.h @@ -48,12 +48,12 @@ inline FixedSizeVector<T, Allocator>::~FixedSizeVector() { } template <typename T, typename Allocator> -inline FixedSizeVector<T, Allocator>::FixedSizeVector(FixedSizeVector&& other) : FixedSizeVector() { +inline FixedSizeVector<T, Allocator>::FixedSizeVector(FixedSizeVector&& other) noexcept : FixedSizeVector() { swap(other); } template <typename T, typename Allocator> -inline FixedSizeVector<T, Allocator>& FixedSizeVector<T, Allocator>::operator=(FixedSizeVector&& other) { +inline FixedSizeVector<T, Allocator>& FixedSizeVector<T, Allocator>::operator=(FixedSizeVector&& other) noexcept { swap(other); return *this; } diff --git a/include/fruit/impl/data_structures/fixed_size_vector.h b/include/fruit/impl/data_structures/fixed_size_vector.h index 7450bf1..c4fa21b 100644 --- a/include/fruit/impl/data_structures/fixed_size_vector.h +++ b/include/fruit/impl/data_structures/fixed_size_vector.h @@ -44,7 +44,7 @@ public: using iterator = T*; using const_iterator = const T*; - FixedSizeVector(std::size_t capacity = 0, Allocator allocator = Allocator()); + explicit FixedSizeVector(std::size_t capacity = 0, Allocator allocator = Allocator()); // Creates a vector with the specified size (and equal capacity) initialized with the specified value. FixedSizeVector(std::size_t size, const T& value, Allocator allocator = Allocator()); ~FixedSizeVector(); @@ -53,10 +53,10 @@ public: FixedSizeVector(const FixedSizeVector& other) = delete; FixedSizeVector(const FixedSizeVector& other, std::size_t capacity); - FixedSizeVector(FixedSizeVector&& other); + FixedSizeVector(FixedSizeVector&& other) noexcept; FixedSizeVector& operator=(const FixedSizeVector& other) = delete; - FixedSizeVector& operator=(FixedSizeVector&& other); + FixedSizeVector& operator=(FixedSizeVector&& other) noexcept; std::size_t size() const; diff --git a/include/fruit/impl/data_structures/memory_pool.defn.h b/include/fruit/impl/data_structures/memory_pool.defn.h index d4630f9..a104f95 100644 --- a/include/fruit/impl/data_structures/memory_pool.defn.h +++ b/include/fruit/impl/data_structures/memory_pool.defn.h @@ -28,13 +28,13 @@ namespace impl { inline MemoryPool::MemoryPool() : first_free(nullptr), capacity(0) {} -inline MemoryPool::MemoryPool(MemoryPool&& other) +inline MemoryPool::MemoryPool(MemoryPool&& other) noexcept : allocated_chunks(std::move(other.allocated_chunks)), first_free(other.first_free), capacity(other.capacity) { // This is to be sure that we don't double-deallocate. other.allocated_chunks.clear(); } -inline MemoryPool& MemoryPool::operator=(MemoryPool&& other) { +inline MemoryPool& MemoryPool::operator=(MemoryPool&& other) noexcept { destroy(); allocated_chunks = std::move(other.allocated_chunks); diff --git a/include/fruit/impl/data_structures/memory_pool.h b/include/fruit/impl/data_structures/memory_pool.h index 05e4eff..13888dd 100644 --- a/include/fruit/impl/data_structures/memory_pool.h +++ b/include/fruit/impl/data_structures/memory_pool.h @@ -44,9 +44,9 @@ public: MemoryPool(); MemoryPool(const MemoryPool&) = delete; - MemoryPool(MemoryPool&&); + MemoryPool(MemoryPool&&) noexcept; MemoryPool& operator=(const MemoryPool&) = delete; - MemoryPool& operator=(MemoryPool&&); + MemoryPool& operator=(MemoryPool&&) noexcept; ~MemoryPool(); /** diff --git a/include/fruit/impl/data_structures/packed_pointer_and_bool.h b/include/fruit/impl/data_structures/packed_pointer_and_bool.h index 8ac84de..ef65e3c 100644 --- a/include/fruit/impl/data_structures/packed_pointer_and_bool.h +++ b/include/fruit/impl/data_structures/packed_pointer_and_bool.h @@ -41,10 +41,10 @@ public: PackedPointerAndBool() = default; PackedPointerAndBool(const PackedPointerAndBool&) = default; - PackedPointerAndBool(PackedPointerAndBool&&) = default; + PackedPointerAndBool(PackedPointerAndBool&&) noexcept = default; PackedPointerAndBool& operator=(const PackedPointerAndBool&) = default; - PackedPointerAndBool& operator=(PackedPointerAndBool&&) = default; + PackedPointerAndBool& operator=(PackedPointerAndBool&&) noexcept = default; T* getPointer() const; void setPointer(T* p); diff --git a/include/fruit/impl/data_structures/semistatic_graph.h b/include/fruit/impl/data_structures/semistatic_graph.h index 26eaf46..92fd8a2 100644 --- a/include/fruit/impl/data_structures/semistatic_graph.h +++ b/include/fruit/impl/data_structures/semistatic_graph.h @@ -113,7 +113,7 @@ public: friend class SemistaticGraph<NodeId, Node>; - node_iterator(NodeData* itr); + explicit node_iterator(NodeData* itr); public: Node& getNode(); @@ -137,10 +137,10 @@ public: friend class SemistaticGraph<NodeId, Node>; - const_node_iterator(const NodeData* itr); + explicit const_node_iterator(const NodeData* itr); public: - const_node_iterator(node_iterator itr); + explicit const_node_iterator(node_iterator itr); const Node& getNode(); @@ -158,7 +158,7 @@ public: friend class SemistaticGraph<NodeId, Node>; friend class SemistaticGraph<NodeId, Node>::node_iterator; - edge_iterator(InternalNodeId* itr); + explicit edge_iterator(InternalNodeId* itr); public: // getNodeIterator(graph.nodes.begin()) returns the first neighbor. @@ -189,7 +189,7 @@ public: template <typename NodeIter> SemistaticGraph(NodeIter first, NodeIter last, MemoryPool& memory_pool); - SemistaticGraph(SemistaticGraph&&) = default; + SemistaticGraph(SemistaticGraph&&) noexcept = default; SemistaticGraph(const SemistaticGraph&) = delete; /** @@ -208,7 +208,7 @@ public: ~SemistaticGraph(); SemistaticGraph& operator=(const SemistaticGraph&) = delete; - SemistaticGraph& operator=(SemistaticGraph&&) = default; + SemistaticGraph& operator=(SemistaticGraph&&) noexcept = default; // The result is unspecified. The only guarantee is that it's the right value to pass to edge_iterator's // getNodeIterator() methods. diff --git a/include/fruit/impl/data_structures/semistatic_map.h b/include/fruit/impl/data_structures/semistatic_map.h index cd03cc2..1ccb00a 100644 --- a/include/fruit/impl/data_structures/semistatic_map.h +++ b/include/fruit/impl/data_structures/semistatic_map.h @@ -46,8 +46,10 @@ private: static constexpr unsigned char beta = 4; + // The parentheses around std::numeric_limits<NumBits>::max are needed to workaround an issue in Windows where + // max is defined as a macro by a common system header. See https://github.com/google/fruit/issues/127. static_assert( - std::numeric_limits<NumBits>::max() >= sizeof(Unsigned) * CHAR_BIT, + (std::numeric_limits<NumBits>::max)() >= sizeof(Unsigned) * CHAR_BIT, "An unsigned char is not enough to contain the number of bits in your platform. Please report this issue."); struct HashFunction { @@ -102,12 +104,12 @@ public: SemistaticMap(const SemistaticMap<Key, Value>& map, std::vector<value_type, ArenaAllocator<value_type>>&& new_elements); - SemistaticMap(SemistaticMap&&) = default; + SemistaticMap(SemistaticMap&&) noexcept = default; SemistaticMap(const SemistaticMap&) = delete; ~SemistaticMap(); - SemistaticMap& operator=(SemistaticMap&&) = default; + SemistaticMap& operator=(SemistaticMap&&) noexcept = default; SemistaticMap& operator=(const SemistaticMap&) = delete; // Precondition: `key' must exist in the map. diff --git a/include/fruit/impl/injection_errors.h b/include/fruit/impl/injection_errors.h index a0e9def..68247d2 100644 --- a/include/fruit/impl/injection_errors.h +++ b/include/fruit/impl/injection_errors.h @@ -124,6 +124,16 @@ struct NotASignatureError { "the form MyClass(int, float)."); }; +template <typename CandidateSignature> +struct AssistedParamInRegisterConstructorSignatureError { + static_assert(AlwaysFalse<CandidateSignature>::value, + "CandidateSignature was used as signature for a registerConstructor() (explicit or implicit via the " + "INJECT macro / Inject typedef) but it contains an assisted parameter. When using assisted parameters" + "You need to inject a factory like std::function<std::unique_ptr<MyClass>(int, float)> instead of " + "injecting MyClass directly. If you used an explicit registerConstructor(), you also need to switch " + "that to registerFactory()."); +}; + template <typename CandidateLambda> struct NotALambdaError { static_assert(AlwaysFalse<CandidateLambda>::value, @@ -494,6 +504,11 @@ struct NotASignatureErrorTag { using apply = NotASignatureError<CandidateSignature>; }; +struct AssistedParamInRegisterConstructorSignatureErrorTag { + template <typename CandidateSignature> + using apply = AssistedParamInRegisterConstructorSignatureError<CandidateSignature>; +}; + struct NotALambdaErrorTag { template <typename CandidateLambda> using apply = NotALambdaError<CandidateLambda>; diff --git a/include/fruit/impl/injector/injector_storage.defn.h b/include/fruit/impl/injector/injector_storage.defn.h index 2474ada..7494fce 100644 --- a/include/fruit/impl/injector/injector_storage.defn.h +++ b/include/fruit/impl/injector/injector_storage.defn.h @@ -49,7 +49,7 @@ inline bool InjectorStorage::BindingDataNodeIter::operator!=(const BindingDataNo return itr != other.itr; } -inline std::ptrdiff_t InjectorStorage::BindingDataNodeIter::operator-(BindingDataNodeIter other) const { +inline std::ptrdiff_t InjectorStorage::BindingDataNodeIter::operator-(const BindingDataNodeIter& other) const { return itr - other.itr; } diff --git a/include/fruit/impl/injector/injector_storage.h b/include/fruit/impl/injector/injector_storage.h index e9af2da..902b43b 100644 --- a/include/fruit/impl/injector/injector_storage.h +++ b/include/fruit/impl/injector/injector_storage.h @@ -26,6 +26,7 @@ #include <vector> #include <mutex> #include <thread> +#include <fruit/impl/normalized_component_storage/normalized_component_storage_holder.h> namespace fruit { namespace impl { @@ -218,7 +219,7 @@ public: bool operator==(const BindingDataNodeIter& other) const; bool operator!=(const BindingDataNodeIter& other) const; - std::ptrdiff_t operator-(BindingDataNodeIter other) const; + std::ptrdiff_t operator-(const BindingDataNodeIter& other) const; TypeId getId(); NormalizedBinding getValue(); diff --git a/include/fruit/impl/normalized_component_storage/binding_normalization.templates.h b/include/fruit/impl/normalized_component_storage/binding_normalization.templates.h index 1c9b485..19396c8 100644 --- a/include/fruit/impl/normalized_component_storage/binding_normalization.templates.h +++ b/include/fruit/impl/normalized_component_storage/binding_normalization.templates.h @@ -26,8 +26,6 @@ #include <fruit/impl/normalized_component_storage/binding_normalization.h> #include <fruit/impl/util/type_info.h> -using namespace fruit::impl; - namespace fruit { namespace impl { @@ -193,7 +191,7 @@ BindingNormalization::handleBindingForConstructedObject(BindingNormalizationCont } // New binding, add it to the map. - entry_in_map = std::move(entry); + entry_in_map = entry; } template <typename... Params> @@ -227,7 +225,7 @@ FRUIT_ALWAYS_INLINE inline void BindingNormalization::handleBindingForObjectToCo } // New binding, add it to the map. - entry_in_map = std::move(entry); + entry_in_map = entry; } template <typename... Params> @@ -261,7 +259,7 @@ FRUIT_ALWAYS_INLINE inline void BindingNormalization::handleBindingForObjectToCo } // New binding, add it to the map. - entry_in_map = std::move(entry); + entry_in_map = entry; } template <typename... Params> @@ -313,7 +311,7 @@ BindingNormalization::handleComponentWithoutArgsEndMarker(BindingNormalizationCo // components_with_*_with_expansion_in_progress to fully_expanded_components_*. context.components_with_no_args_with_expansion_in_progress.erase(entry.lazy_component_with_no_args); - context.fully_expanded_components_with_no_args.insert(std::move(entry.lazy_component_with_no_args)); + context.fully_expanded_components_with_no_args.insert(entry.lazy_component_with_no_args); } template <typename... Params> @@ -326,14 +324,14 @@ BindingNormalization::handleComponentWithArgsEndMarker(BindingNormalizationConte // components_with_*_with_expansion_in_progress to fully_expanded_components_*. context.components_with_args_with_expansion_in_progress.erase(entry.lazy_component_with_args); - context.fully_expanded_components_with_args.insert(std::move(entry.lazy_component_with_args)); + context.fully_expanded_components_with_args.insert(entry.lazy_component_with_args); } template <typename... Params> void BindingNormalization::handleReplacedLazyComponentWithArgs(BindingNormalizationContext<Params...>& context) { ComponentStorageEntry entry = context.entries_to_process.back(); FruitAssert(entry.kind == ComponentStorageEntry::Kind::REPLACED_LAZY_COMPONENT_WITH_ARGS); - ComponentStorageEntry replaced_component_entry = std::move(entry); + ComponentStorageEntry replaced_component_entry = entry; context.entries_to_process.pop_back(); FruitAssert(!context.entries_to_process.empty()); @@ -343,10 +341,10 @@ void BindingNormalization::handleReplacedLazyComponentWithArgs(BindingNormalizat ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS || replacement_component_entry.kind == ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS); - if (context.components_with_args_with_expansion_in_progress.count(entry.lazy_component_with_args) != 0 || - context.fully_expanded_components_with_args.count(entry.lazy_component_with_args) != 0 || + if (context.components_with_args_with_expansion_in_progress.count(replaced_component_entry.lazy_component_with_args) != 0 || + context.fully_expanded_components_with_args.count(replaced_component_entry.lazy_component_with_args) != 0 || context.functors.is_component_with_args_already_expanded_in_normalized_component( - entry.lazy_component_with_args)) { + replaced_component_entry.lazy_component_with_args)) { printComponentReplacementFailedBecauseTargetAlreadyExpanded(replaced_component_entry, replacement_component_entry); FRUIT_UNREACHABLE; // LCOV_EXCL_LINE } @@ -379,7 +377,7 @@ template <typename... Params> void BindingNormalization::handleReplacedLazyComponentWithNoArgs(BindingNormalizationContext<Params...>& context) { ComponentStorageEntry entry = context.entries_to_process.back(); FruitAssert(entry.kind == ComponentStorageEntry::Kind::REPLACED_LAZY_COMPONENT_WITH_NO_ARGS); - ComponentStorageEntry replaced_component_entry = std::move(entry); + ComponentStorageEntry replaced_component_entry = entry; context.entries_to_process.pop_back(); FruitAssert(!context.entries_to_process.empty()); @@ -389,10 +387,10 @@ void BindingNormalization::handleReplacedLazyComponentWithNoArgs(BindingNormaliz ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS || replacement_component_entry.kind == ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS); - if (context.components_with_no_args_with_expansion_in_progress.count(entry.lazy_component_with_no_args) != 0 || - context.fully_expanded_components_with_no_args.count(entry.lazy_component_with_no_args) != 0 || + if (context.components_with_no_args_with_expansion_in_progress.count(replaced_component_entry.lazy_component_with_no_args) != 0 || + context.fully_expanded_components_with_no_args.count(replaced_component_entry.lazy_component_with_no_args) != 0 || context.functors.is_component_with_no_args_already_expanded_in_normalized_component( - entry.lazy_component_with_no_args)) { + replaced_component_entry.lazy_component_with_no_args)) { printComponentReplacementFailedBecauseTargetAlreadyExpanded(replaced_component_entry, replacement_component_entry); FRUIT_UNREACHABLE; // LCOV_EXCL_LINE } @@ -626,7 +624,7 @@ BindingNormalization::performBindingCompression( auto c_binding_data = binding_data_map.find(c_id); FruitAssert(i_binding_data != binding_data_map.end()); FruitAssert(c_binding_data != binding_data_map.end()); - NormalizedComponentStorage::CompressedBindingUndoInfo undo_info; + NormalizedComponentStorage::CompressedBindingUndoInfo undo_info{}; undo_info.i_type_id = i_id; FruitAssert(i_binding_data->second.kind == ComponentStorageEntry::Kind::BINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_NO_ALLOCATION); diff --git a/include/fruit/impl/normalized_component_storage/normalized_component_storage.h b/include/fruit/impl/normalized_component_storage/normalized_component_storage.h index 22dc8b1..9ec987e 100644 --- a/include/fruit/impl/normalized_component_storage/normalized_component_storage.h +++ b/include/fruit/impl/normalized_component_storage/normalized_component_storage.h @@ -157,7 +157,7 @@ public: // We don't use the default destructor because that will require the inclusion of // the Boost's hashmap header. We define this in the cpp file instead. - ~NormalizedComponentStorage(); + ~NormalizedComponentStorage() noexcept; }; } // namespace impl diff --git a/include/fruit/impl/normalized_component_storage/normalized_component_storage_holder.h b/include/fruit/impl/normalized_component_storage/normalized_component_storage_holder.h index 180f297..6c07680 100644 --- a/include/fruit/impl/normalized_component_storage/normalized_component_storage_holder.h +++ b/include/fruit/impl/normalized_component_storage/normalized_component_storage_holder.h @@ -45,7 +45,8 @@ public: struct WithUndoableCompression {}; struct WithPermanentCompression {}; - NormalizedComponentStorageHolder() = default; + NormalizedComponentStorageHolder() noexcept = default; + /** * The MemoryPool is only used during construction, the constructed object *can* outlive the memory pool. @@ -62,7 +63,7 @@ public: // We don't use the default destructor because that would require the inclusion of // normalized_component_storage.h. We define this in the cpp file instead. - ~NormalizedComponentStorageHolder(); + ~NormalizedComponentStorageHolder() noexcept; }; } // namespace impl diff --git a/include/fruit/impl/util/hash_helpers.defn.h b/include/fruit/impl/util/hash_helpers.defn.h index e75ec4a..2f7544c 100644 --- a/include/fruit/impl/util/hash_helpers.defn.h +++ b/include/fruit/impl/util/hash_helpers.defn.h @@ -68,7 +68,7 @@ inline HashMapWithArenaAllocator<Key, Value, Hasher, EqualityComparator> createHashMapWithArenaAllocatorAndCustomFunctors(size_t capacity, MemoryPool& memory_pool, Hasher hasher, EqualityComparator equality_comparator) { return HashMapWithArenaAllocator<Key, Value, Hasher, EqualityComparator>( - capacity, hasher, equality_comparator, ArenaAllocator<std::pair<const Key, Value>>(memory_pool)); + capacity, hasher, equality_comparator, ArenaAllocator<std::pair<const Key, Value>>{memory_pool}); } } // namespace impl diff --git a/include/fruit/impl/util/lambda_invoker.h b/include/fruit/impl/util/lambda_invoker.h index 2c8d63e..afe0a19 100644 --- a/include/fruit/impl/util/lambda_invoker.h +++ b/include/fruit/impl/util/lambda_invoker.h @@ -31,21 +31,31 @@ namespace fruit { namespace impl { +template <typename T> +struct SafeAlignmentOf { + constexpr static const std::size_t value = alignof(T); +}; + +template <typename T, typename... Args> +struct SafeAlignmentOf<T(Args...)> { + constexpr static const std::size_t value = alignof(int); +}; + class LambdaInvoker { public: template <typename F, typename... Args> - FRUIT_ALWAYS_INLINE static auto invoke(Args&&... args) + FRUIT_ALWAYS_INLINE static auto invoke(Args&&... args) -> decltype(std::declval<const F&>()(std::declval<Args>()...)) { // We reinterpret-cast a char[] to avoid de-referencing nullptr, which would technically be // undefined behavior (even though we would not access any data there anyway). // Sharing this buffer for different types F would also be undefined behavior since we'd break // strict aliasing between those types. - alignas(alignof(F)) static char buf[1]; + alignas(SafeAlignmentOf<F>::value) static char buf[1]; FruitStaticAssert(fruit::impl::meta::IsEmpty(fruit::impl::meta::Type<F>)); FruitStaticAssert(fruit::impl::meta::IsTriviallyCopyable(fruit::impl::meta::Type<F>)); // Since `F' is empty, a valid value of type F is already stored at the beginning of buf. - F* f = reinterpret_cast<F*>(buf); + F* f = reinterpret_cast<F*>((char*)buf); return (*f)(std::forward<Args>(args)...); } }; diff --git a/include/fruit/impl/util/type_info.defn.h b/include/fruit/impl/util/type_info.defn.h index d52fab0..d077b02 100644 --- a/include/fruit/impl/util/type_info.defn.h +++ b/include/fruit/impl/util/type_info.defn.h @@ -147,7 +147,7 @@ struct GetTypeIdsForListHelper; template <typename... Ts> struct GetTypeIdsForListHelper<fruit::impl::meta::Vector<Ts...>> { std::vector<TypeId, ArenaAllocator<TypeId>> operator()(MemoryPool& memory_pool) { - return std::vector<TypeId, ArenaAllocator<TypeId>>(std::initializer_list<TypeId>{getTypeId<Ts>()...}, memory_pool); + return std::vector<TypeId, ArenaAllocator<TypeId>>(std::initializer_list<TypeId>{getTypeId<Ts>()...}, ArenaAllocator<TypeId>{memory_pool}); } }; diff --git a/include/fruit/impl/util/type_info.h b/include/fruit/impl/util/type_info.h index 01fb647..5a9d079 100644 --- a/include/fruit/impl/util/type_info.h +++ b/include/fruit/impl/util/type_info.h @@ -42,7 +42,7 @@ struct alignas(1) alignas(void*) TypeInfo { }; // This should only be used if RTTI is disabled. Use the other constructor if possible. - constexpr TypeInfo(ConcreteTypeInfo concrete_type_info); + explicit constexpr TypeInfo(ConcreteTypeInfo concrete_type_info); constexpr TypeInfo(const std::type_info& info, ConcreteTypeInfo concrete_type_info); @@ -64,7 +64,7 @@ private: struct TypeId { const TypeInfo* type_info; - operator std::string() const; + explicit operator std::string() const; bool operator==(TypeId x) const; bool operator!=(TypeId x) const; diff --git a/include/fruit/injector.h b/include/fruit/injector.h index a62f631..e84112a 100644 --- a/include/fruit/injector.h +++ b/include/fruit/injector.h @@ -48,7 +48,7 @@ template <typename... P> class Injector { public: // Moving injectors is allowed. - Injector(Injector&&) = default; + Injector(Injector&&) noexcept = default; // Copying injectors is forbidden. Injector(const Injector&) = delete; @@ -79,7 +79,7 @@ public: * Foo* foo = injector.get<Foo*>(); */ template <typename... FormalArgs, typename... Args> - Injector(Component<P...> (*)(FormalArgs...), Args&&... args); + explicit Injector(Component<P...> (*)(FormalArgs...), Args&&... args); /** * This creates an injector from a normalized component and a component function. diff --git a/include/fruit/normalized_component.h b/include/fruit/normalized_component.h index 105edf8..e9dca2f 100644 --- a/include/fruit/normalized_component.h +++ b/include/fruit/normalized_component.h @@ -111,9 +111,9 @@ public: * The constraints on the argument types (if there are any) are the same as the ones for PartialComponent::install(). */ template <typename... FormalArgs, typename... Args> - NormalizedComponent(Component<Params...> (*)(FormalArgs...), Args&&... args); + explicit NormalizedComponent(Component<Params...> (*)(FormalArgs...), Args&&... args); - NormalizedComponent(NormalizedComponent&&) = default; + NormalizedComponent(NormalizedComponent&& storage) noexcept : storage(std::move(storage.storage)) {} NormalizedComponent(const NormalizedComponent&) = delete; NormalizedComponent& operator=(NormalizedComponent&&) = delete; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 66bf79f..0e328cf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,5 +22,6 @@ else() endif() install(TARGETS fruit - ARCHIVE DESTINATION "${INSTALL_LIBRARY_DIR}" - LIBRARY DESTINATION "${INSTALL_LIBRARY_DIR}") + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") diff --git a/src/binding_normalization.cpp b/src/binding_normalization.cpp index c353687..db6ee00 100644 --- a/src/binding_normalization.cpp +++ b/src/binding_normalization.cpp @@ -32,8 +32,6 @@ using std::cout; using std::endl; -using namespace fruit::impl; - namespace fruit { namespace impl { @@ -242,7 +240,7 @@ void BindingNormalization::addMultibindings(std::unordered_map<TypeId, Normalize NormalizedMultibinding normalized_multibinding; normalized_multibinding.is_constructed = true; normalized_multibinding.object = i->first.multibinding_for_constructed_object.object_ptr; - b.elems.push_back(std::move(normalized_multibinding)); + b.elems.push_back(normalized_multibinding); } break; case ComponentStorageEntry::Kind::MULTIBINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_NO_ALLOCATION: { @@ -250,7 +248,7 @@ void BindingNormalization::addMultibindings(std::unordered_map<TypeId, Normalize NormalizedMultibinding normalized_multibinding; normalized_multibinding.is_constructed = false; normalized_multibinding.create = i->first.multibinding_for_object_to_construct.create; - b.elems.push_back(std::move(normalized_multibinding)); + b.elems.push_back(normalized_multibinding); } break; case ComponentStorageEntry::Kind::MULTIBINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_ALLOCATION: { @@ -258,7 +256,7 @@ void BindingNormalization::addMultibindings(std::unordered_map<TypeId, Normalize NormalizedMultibinding normalized_multibinding; normalized_multibinding.is_constructed = false; normalized_multibinding.create = i->first.multibinding_for_object_to_construct.create; - b.elems.push_back(std::move(normalized_multibinding)); + b.elems.push_back(normalized_multibinding); } break; default: @@ -292,21 +290,21 @@ void BindingNormalization::normalizeBindingsWithUndoableBindingCompression( [&bindingCompressionInfoMap](TypeId c_type_id, NormalizedComponentStorage::CompressedBindingUndoInfo undo_info) { bindingCompressionInfoMap[c_type_id] = undo_info; }, - [&fully_expanded_components_with_no_args](LazyComponentWithNoArgsSet& fully_expanded_components) { + [&fully_expanded_components_with_no_args, &memory_pool](LazyComponentWithNoArgsSet& fully_expanded_components) { fully_expanded_components_with_no_args = std::move(fully_expanded_components); - fully_expanded_components.clear(); + fully_expanded_components = NormalizedComponentStorage::createLazyComponentWithNoArgsSet(0, memory_pool); }, - [&fully_expanded_components_with_args](LazyComponentWithArgsSet& fully_expanded_components) { + [&fully_expanded_components_with_args, &memory_pool](LazyComponentWithArgsSet& fully_expanded_components) { fully_expanded_components_with_args = std::move(fully_expanded_components); - fully_expanded_components.clear(); + fully_expanded_components = NormalizedComponentStorage::createLazyComponentWithArgsSet(0, memory_pool); }, - [&component_with_no_args_replacements](LazyComponentWithNoArgsReplacementMap& component_replacements) { + [&component_with_no_args_replacements, &memory_pool](LazyComponentWithNoArgsReplacementMap& component_replacements) { component_with_no_args_replacements = std::move(component_replacements); - component_replacements.clear(); + component_replacements = NormalizedComponentStorage::createLazyComponentWithNoArgsReplacementMap(0, memory_pool); }, - [&component_with_args_replacements](LazyComponentWithArgsReplacementMap& component_replacements) { + [&component_with_args_replacements, &memory_pool](LazyComponentWithArgsReplacementMap& component_replacements) { component_with_args_replacements = std::move(component_replacements); - component_replacements.clear(); + component_replacements = NormalizedComponentStorage::createLazyComponentWithArgsReplacementMap(0, memory_pool); }); } @@ -435,9 +433,9 @@ void BindingNormalization::normalizeBindingsAndAddTo( i_binding.kind = ComponentStorageEntry::Kind::BINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_NO_ALLOCATION; i_binding.binding_for_object_to_construct = binding_compression_itr->second.i_binding; - new_bindings_vector.push_back(std::move(c_binding)); + new_bindings_vector.push_back(c_binding); // This TypeId is already in normalized_component.bindings, we overwrite it here. - new_bindings_vector.push_back(std::move(i_binding)); + new_bindings_vector.push_back(i_binding); #if FRUIT_EXTRA_DEBUG std::cout << "InjectorStorage: undoing binding compression for: " << binding_compression_itr->second.i_type_id diff --git a/src/fixed_size_allocator.cpp b/src/fixed_size_allocator.cpp index b490828..2652885 100644 --- a/src/fixed_size_allocator.cpp +++ b/src/fixed_size_allocator.cpp @@ -19,8 +19,6 @@ #include <fruit/impl/data_structures/fixed_size_allocator.h> #include <fruit/impl/data_structures/fixed_size_vector.templates.h> -using namespace fruit::impl; - namespace fruit { namespace impl { diff --git a/src/injector_storage.cpp b/src/injector_storage.cpp index 1e77702..af3a14d 100644 --- a/src/injector_storage.cpp +++ b/src/injector_storage.cpp @@ -32,8 +32,6 @@ using std::cout; using std::endl; -using namespace fruit::impl; - namespace fruit { namespace impl { diff --git a/src/memory_pool.cpp b/src/memory_pool.cpp index 1311b2c..03429c2 100644 --- a/src/memory_pool.cpp +++ b/src/memory_pool.cpp @@ -18,9 +18,7 @@ #include <fruit/impl/data_structures/memory_pool.h> -using namespace fruit::impl; - -void MemoryPool::destroy() { +void fruit::impl::MemoryPool::destroy() { for (void* p : allocated_chunks) { operator delete(p); } diff --git a/src/normalized_component_storage.cpp b/src/normalized_component_storage.cpp index 7449ec5..59d01ca 100644 --- a/src/normalized_component_storage.cpp +++ b/src/normalized_component_storage.cpp @@ -34,9 +34,6 @@ using std::cout; using std::endl; -using namespace fruit; -using namespace fruit::impl; - namespace fruit { namespace impl { @@ -94,7 +91,7 @@ NormalizedComponentStorage::NormalizedComponentStorage(ComponentStorage&& compon memory_pool); } -NormalizedComponentStorage::~NormalizedComponentStorage() { +NormalizedComponentStorage::~NormalizedComponentStorage() noexcept { for (auto& x : fully_expanded_components_with_args) { x.destroy(); } diff --git a/src/normalized_component_storage_holder.cpp b/src/normalized_component_storage_holder.cpp index 0629b99..dfc4fd3 100644 --- a/src/normalized_component_storage_holder.cpp +++ b/src/normalized_component_storage_holder.cpp @@ -19,9 +19,6 @@ #include <fruit/impl/normalized_component_storage/normalized_component_storage.h> #include <fruit/impl/normalized_component_storage/normalized_component_storage_holder.h> -using namespace fruit; -using namespace fruit::impl; - namespace fruit { namespace impl { @@ -31,7 +28,7 @@ NormalizedComponentStorageHolder::NormalizedComponentStorageHolder( : storage(new NormalizedComponentStorage(std::move(component), exposed_types, memory_pool, NormalizedComponentStorage::WithUndoableCompression())) {} -NormalizedComponentStorageHolder::~NormalizedComponentStorageHolder() {} +NormalizedComponentStorageHolder::~NormalizedComponentStorageHolder() noexcept {} } // namespace impl } // namespace fruit diff --git a/src/semistatic_graph.cpp b/src/semistatic_graph.cpp index 1b23d70..71952f5 100644 --- a/src/semistatic_graph.cpp +++ b/src/semistatic_graph.cpp @@ -22,8 +22,6 @@ #include <fruit/impl/normalized_component_storage/normalized_bindings.h> #include <fruit/impl/util/type_info.h> -using namespace fruit::impl; - // Clang requires the following instantiation to be in its namespace. namespace fruit { namespace impl { diff --git a/src/semistatic_map.cpp b/src/semistatic_map.cpp index 281f34a..15778a0 100644 --- a/src/semistatic_map.cpp +++ b/src/semistatic_map.cpp @@ -22,8 +22,6 @@ #include <fruit/impl/util/type_info.h> -using namespace fruit::impl; - // Clang requires the following instantiation to be in its namespace. namespace fruit { namespace impl { diff --git a/tests/BUILD b/tests/BUILD index 4fc016d..e89f144 100644 --- a/tests/BUILD +++ b/tests/BUILD @@ -15,10 +15,14 @@ filegroup( cc_library( name = "test_headers", - srcs = [], + srcs = ["test_common.cpp"], hdrs = TEST_HEADERS, visibility = ["//third_party/fruit/tests:__subpackages__"], includes = ["."], + deps = [ + "//third_party/fruit", + "@boost//:unordered", + ] ) [cc_test( @@ -30,7 +34,7 @@ cc_library( ] ) for filename in glob( ["*.cpp"], - exclude = ["include_test.cpp"])] + exclude = ["include_test.cpp", "test_common.cpp"])] FRUIT_PUBLIC_HEADERS = [ "component", @@ -47,13 +51,15 @@ genrule( srcs = [ "//third_party/fruit", "//third_party/fruit:fruit_headers", + ":test_headers", ":test_headers_filegroup", ], - # Here we copy libfruit.so to work around an issue with py_test where the outputs of a cc_library in the data - # attribute of a py_test are not taken into account. + # Here we copy libfruit.so and test_headers.so to work around an issue with py_test where the outputs of a + # cc_library in the data attribute of a py_test are not taken into account. outs = [ "fruit_test_config.py", - "libfruit.so" + "libfruit.so", + "libtest_headers_copy.so", ], toolchains = [ # For $(CC_FLAGS) @@ -63,10 +69,11 @@ genrule( ], visibility = ["//third_party/fruit/tests:__subpackages__"], cmd = "" - + "FRUIT_HEADERS_LOCATION=`for f in $(locations //third_party/fruit:fruit_headers); do echo \"$$f\"; done | fgrep configuration/bazel/ | head -n 1 | sed 's|configuration/bazel/.*|./|'`;" + "TEST_HEADERS_LOCATION=`for f in $(locations :test_headers_filegroup); do echo \"$$f\"; done | fgrep test_macros.h | sed 's|test_macros.h|./|'`;" + "LIBFRUIT_LOCATION=`for f in $(locations //third_party/fruit); do echo \"$$f\"; done | fgrep libfruit.so | head -n 1 | sed 's|libfruit.so|./|'`;" + + "LIBTEST_HEADERS_LOCATION=`for f in $(locations //third_party/fruit/tests:test_headers); do echo \"$$f\"; done | fgrep libtest_headers.so | head -n 1 | sed 's|libtest_headers.so|./|'`;" + "cp $${LIBFRUIT_LOCATION}/libfruit.so $(@D)/;" + + "cp $${LIBTEST_HEADERS_LOCATION}/libtest_headers.so $(@D)/libtest_headers_copy.so;" + "echo -e \"" + "CXX='$(CC)'\n" + "CXX_COMPILER_NAME='GNU'\n" @@ -76,8 +83,10 @@ genrule( + "CMAKE_BUILD_TYPE=None\n" + "PATH_TO_COMPILED_FRUIT='third_party/fruit/tests'\n" + "PATH_TO_COMPILED_FRUIT_LIB='third_party/fruit/tests'\n" - + "PATH_TO_FRUIT_STATIC_HEADERS='$${FRUIT_HEADERS_LOCATION}/include'\n" - + "PATH_TO_FRUIT_GENERATED_HEADERS='$${FRUIT_HEADERS_LOCATION}/configuration/bazel'\n" + + "PATH_TO_COMPILED_TEST_HEADERS='third_party/fruit/tests/test_headers'\n" + + "PATH_TO_COMPILED_TEST_HEADERS_LIB='third_party/fruit/tests/test_headers'\n" + + "PATH_TO_FRUIT_STATIC_HEADERS='third_party/fruit/include'\n" + + "PATH_TO_FRUIT_GENERATED_HEADERS='third_party/fruit/configuration/bazel'\n" + "PATH_TO_FRUIT_TEST_HEADERS='$${TEST_HEADERS_LOCATION}'\n" + "ADDITIONAL_LINKER_FLAGS='-lstdc++ -lm'\n" + "RUN_TESTS_UNDER_VALGRIND='0'\n" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b5cbfdb..095d3db 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -81,13 +81,19 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(MSVC)$") set(FRUIT_TESTONLY_CXXFLAGS "${FRUIT_TESTONLY_CXXFLAGS} /wd4702 /wd4503") endif() +add_library(test_headers_copy STATIC test_common.cpp) +target_link_libraries(test_headers_copy fruit) + +# Escape the backslash which is a Windows path separator. +string(REPLACE "\\" "\\\\" ADDITIONAL_INCLUDE_DIRS "${Boost_INCLUDE_DIRS}") + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/fruit_test_config.py" CONTENT " CXX='${CMAKE_CXX_COMPILER}' CXX_COMPILER_NAME='${CMAKE_CXX_COMPILER_ID}' CXX_COMPILER_VERSION='${CMAKE_CXX_COMPILER_VERSION}' FRUIT_COMPILE_FLAGS='${FRUIT_COMPILE_FLAGS} ${FRUIT_TESTONLY_CXXFLAGS}' -ADDITIONAL_INCLUDE_DIRS='${BOOST_DIR}' +ADDITIONAL_INCLUDE_DIRS='${ADDITIONAL_INCLUDE_DIRS}' ADDITIONAL_LINKER_FLAGS='${CMAKE_EXE_LINKER_FLAGS}' RUN_TESTS_UNDER_VALGRIND='${RUN_TESTS_UNDER_VALGRIND_FLAG}' VALGRIND_FLAGS='${VALGRIND_FLAGS_STR}' @@ -95,6 +101,8 @@ CMAKE_BUILD_TYPE='${CMAKE_BUILD_TYPE}' PATH_TO_COMPILED_FRUIT='$<TARGET_FILE_DIR:fruit>' PATH_TO_COMPILED_FRUIT_LIB='$<TARGET_FILE:fruit>' +PATH_TO_COMPILED_TEST_HEADERS='$<TARGET_FILE_DIR:test_headers_copy>' +PATH_TO_COMPILED_TEST_HEADERS_LIB='$<TARGET_FILE:test_headers_copy>' PATH_TO_FRUIT_STATIC_HEADERS='${CMAKE_CURRENT_SOURCE_DIR}/../include' PATH_TO_FRUIT_GENERATED_HEADERS='${CMAKE_CURRENT_BINARY_DIR}/../include' PATH_TO_FRUIT_TEST_HEADERS='${CMAKE_CURRENT_SOURCE_DIR}' @@ -106,4 +114,5 @@ file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pytest.ini" [pytest] testpaths = \"${CMAKE_CURRENT_SOURCE_DIR}\" addopts = -r a +timeout = 300 ") diff --git a/tests/build_defs.bzl b/tests/build_defs.bzl index 13d3005..05bd13c 100644 --- a/tests/build_defs.bzl +++ b/tests/build_defs.bzl @@ -12,6 +12,7 @@ def fruit_py_tests(srcs, data=[]): data = data + [ "//third_party/fruit:fruit_headers", "//third_party/fruit/tests:libfruit.so", + "//third_party/fruit/tests:libtest_headers_copy.so", "//third_party/fruit/tests:test_headers_filegroup", ], shard_count = 32, diff --git a/tests/data_structures/test_semistatic_graph.py b/tests/data_structures/test_semistatic_graph.py index e0510da..95629e7 100644 --- a/tests/data_structures/test_semistatic_graph.py +++ b/tests/data_structures/test_semistatic_graph.py @@ -19,30 +19,10 @@ from fruit_test_common import * COMMON_DEFINITIONS = ''' #include "test_common.h" - #define IN_FRUIT_CPP_FILE 1 - #include <fruit/impl/data_structures/semistatic_graph.templates.h> - using namespace std; using namespace fruit::impl; - using Graph = SemistaticGraph<int, const char*>; - using node_iterator = Graph::node_iterator; - using edge_iterator = Graph::edge_iterator; - vector<int> no_neighbors{}; - - struct SimpleNode { - int id; - const char* value; - const vector<int>* neighbors; - bool is_terminal; - - int getId() { return id; } - const char* getValue() { return value; } - bool isTerminal() { return is_terminal; } - vector<int>::const_iterator getEdgesBegin() { return neighbors->begin(); } - vector<int>::const_iterator getEdgesEnd() { return neighbors->end(); } - }; ''' class TestSemistaticGraph(parameterized.TestCase): diff --git a/tests/fruit_test_common.py b/tests/fruit_test_common.py index 28ecc59..36e5b20 100644 --- a/tests/fruit_test_common.py +++ b/tests/fruit_test_common.py @@ -35,7 +35,7 @@ run_under_valgrind = RUN_TESTS_UNDER_VALGRIND.lower() not in ('false', 'off', 'n def pretty_print_command(command, env): return 'cd %s; env -i %s %s' % ( - shlex.quote(env['PWD']), + shlex.quote(os.getcwd()), ' '.join('%s=%s' % (var_name, shlex.quote(value)) for var_name, value in env.items() if var_name != 'PWD'), ' '.join(shlex.quote(x) for x in command)) @@ -166,7 +166,7 @@ class MsvcCompiler: self._compile(include_dirs, args = args) except CommandFailedException as e: # Note that we use stdout here, unlike above. MSVC reports compilation warnings and errors on stdout. - raise CompilationFailedException(e.command, e.stdout) + raise CompilationFailedException(e.command, e.env, e.stdout) def compile_and_link(self, source, include_dirs, output_file_name, args=[]): self._compile( @@ -200,14 +200,21 @@ if CXX_COMPILER_NAME == 'MSVC': path_to_fruit_lib = PATH_TO_COMPILED_FRUIT_LIB[:-4] + '.lib' else: path_to_fruit_lib = PATH_TO_COMPILED_FRUIT_LIB - fruit_tests_linker_flags = [path_to_fruit_lib] + if PATH_TO_COMPILED_TEST_HEADERS_LIB.endswith('.dll'): + path_to_test_headers_lib = PATH_TO_COMPILED_TEST_HEADERS_LIB[:-4] + '.lib' + else: + path_to_test_headers_lib = PATH_TO_COMPILED_TEST_HEADERS_LIB + fruit_tests_linker_flags = [path_to_fruit_lib, path_to_test_headers_lib] fruit_error_message_extraction_regex = 'error C2338: (.*)' else: compiler = PosixCompiler() fruit_tests_linker_flags = [ '-lfruit', + '-ltest_headers_copy', '-L' + PATH_TO_COMPILED_FRUIT, '-Wl,-rpath,' + PATH_TO_COMPILED_FRUIT, + '-L' + PATH_TO_COMPILED_TEST_HEADERS, + '-Wl,-rpath,' + PATH_TO_COMPILED_TEST_HEADERS, ] fruit_error_message_extraction_regex = 'static.assert(.*)' @@ -222,9 +229,12 @@ _assert_helper = unittest.TestCase() def modify_env_for_compiled_executables(env): env = env.copy() path_to_fruit_lib_dir = os.path.dirname(PATH_TO_COMPILED_FRUIT_LIB) + path_to_fruit_test_headers_dir = os.path.dirname(PATH_TO_COMPILED_TEST_HEADERS_LIB) print('PATH_TO_COMPILED_FRUIT_LIB:', PATH_TO_COMPILED_FRUIT_LIB) + print('PATH_TO_COMPILED_TEST_HEADERS_LIB:', PATH_TO_COMPILED_TEST_HEADERS_LIB) print('Adding directory to PATH:', path_to_fruit_lib_dir) - env["PATH"] += os.pathsep + path_to_fruit_lib_dir + print('Adding directory to PATH:', path_to_fruit_test_headers_dir) + env["PATH"] += os.pathsep + path_to_fruit_lib_dir + os.pathsep + path_to_fruit_test_headers_dir return env def _create_temporary_file(file_content, file_name_suffix=''): @@ -298,7 +308,6 @@ def expect_compile_error_helper( error_message = e.error_message error_message_lines = error_message.splitlines() - error_message_lines = error_message.splitlines() error_message_head = _cap_to_lines(error_message, 40) check_error_fun(e, error_message_lines, error_message_head) diff --git a/tests/test_common.cpp b/tests/test_common.cpp new file mode 100644 index 0000000..868827f --- /dev/null +++ b/tests/test_common.cpp @@ -0,0 +1,36 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define IN_FRUIT_CPP_FILE 1 + +#include "test_common.h" + +#include <fruit/impl/data_structures/semistatic_graph.templates.h> + +// Clang requires the following instantiation to be in its namespace. +namespace fruit { +namespace impl { + +template class SemistaticGraph<int, const char*>; +template SemistaticGraph<int, char const*>::SemistaticGraph(std::vector<SimpleNode>::iterator first, std::vector<SimpleNode>::iterator last, MemoryPool& memory_pool); +template SemistaticGraph<int, char const*>::SemistaticGraph(const fruit::impl::SemistaticGraph<int, char const*>& graph, std::vector<SimpleNode>::iterator first, std::vector<SimpleNode>::iterator last, MemoryPool& memory_pool); +template class SemistaticMap<int, SemistaticGraphInternalNodeId>; + +} // namespace impl +} // namespace fruit + + + diff --git a/tests/test_common.h b/tests/test_common.h index d48f110..56e2b13 100644 --- a/tests/test_common.h +++ b/tests/test_common.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef FRUIT_TEST_COMMON_H -#define FRUIT_TEST_COMMON_H +#ifndef FRUIT_COMMON_H +#define FRUIT_COMMON_H // This file includes headers used in various tests. // This allows to improve compilation speed (and therefore test time) by pre-compiling this header. @@ -27,4 +27,23 @@ #include <map> #include <vector> -#endif // FRUIT_TEST_COMMON_H +// These are here because including Boost in test code would require depending on its headers but those files don't have +// public visibility in the bazel repo. +#include <fruit/impl/data_structures/semistatic_graph.h> +using Graph = fruit::impl::SemistaticGraph<int, const char*>; +using node_iterator = Graph::node_iterator; +using edge_iterator = Graph::edge_iterator; +struct SimpleNode { + int id; + const char* value; + const std::vector<int>* neighbors; + bool is_terminal; + + int getId() { return id; } + const char* getValue() { return value; } + bool isTerminal() { return is_terminal; } + std::vector<int>::const_iterator getEdgesBegin() { return neighbors->begin(); } + std::vector<int>::const_iterator getEdgesEnd() { return neighbors->end(); } +}; + +#endif // FRUIT_COMMON_H diff --git a/tests/test_component_functions.py b/tests/test_component_functions.py index ec70bfc..8dc6a76 100755 --- a/tests/test_component_functions.py +++ b/tests/test_component_functions.py @@ -187,7 +187,8 @@ class TestComponentFunctions(parameterized.TestCase): r'error: use of deleted function .Arg::Arg\(Arg&&\).' r'|error: call to deleted constructor of .Arg.' r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.' - r'|error: copying parameter of type .Arg. invokes deleted constructor', + r'|error: copying parameter of type .Arg. invokes deleted constructor' + r'|error C2280: .Arg::Arg\(Arg &&\).: attempting to reference a deleted function', COMMON_DEFINITIONS, source) diff --git a/tests/test_normalized_component.py b/tests/test_normalized_component.py index ba21242..8888019 100755 --- a/tests/test_normalized_component.py +++ b/tests/test_normalized_component.py @@ -175,7 +175,7 @@ class TestNormalizedComponent(parameterized.TestCase): expect_generic_compile_error( r'no matching function for call to .fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent\(fruit::Component<XAnnot> \(&\)\(\)\).' r'|no matching constructor for initialization of .fruit::NormalizedComponent<ConstXAnnot>.' - r'|.fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent.: none of the 2 overloads could convert all the argument types', + r'|.fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent.: none of the .* overloads could convert all the argument types', COMMON_DEFINITIONS, source, locals()) diff --git a/tests/test_register_constructor.py b/tests/test_register_constructor.py index 4e2a4fc..b78191f 100755 --- a/tests/test_register_constructor.py +++ b/tests/test_register_constructor.py @@ -178,6 +178,10 @@ class TestRegisterConstructor(parameterized.TestCase): source) def test_register_constructor_error_abstract_class(self): + if re.search('MSVC', CXX_COMPILER_NAME) is not None: + # MSVC allows to construct the type X(int*) but SignatureType<Type<X(int*)>> doesn't find the + # specialization. + return source = ''' struct X { X(int*) {} @@ -190,7 +194,7 @@ class TestRegisterConstructor(parameterized.TestCase): .registerConstructor<fruit::Annotated<Annotation1, X>(int*)>(); } ''' - if re.search('GNU|MSVC', CXX_COMPILER_NAME) is not None: + if re.search('GNU', CXX_COMPILER_NAME) is not None: expect_generic_compile_error( 'invalid abstract return type' '|.X.: cannot instantiate abstract class', @@ -583,5 +587,46 @@ class TestRegisterConstructor(parameterized.TestCase): source, locals()) + def test_register_constructor_error_assisted_param(self): + source = ''' + struct X { + INJECT(X(ASSISTED(double) factor)) { + (void) factor; + } + }; + + fruit::Component<X> getComponent() { + return fruit::createComponent() + .registerConstructor<X(fruit::Assisted<double>)>(); + } + ''' + expect_compile_error( + 'AssistedParamInRegisterConstructorSignatureError<X\\(fruit::Assisted<double>\\)>', + 'CandidateSignature was used as signature for a registerConstructor.* but it contains an assisted parameter.', + COMMON_DEFINITIONS, + source, + locals()) + + def test_implicit_register_constructor_error_assisted_param(self): + source = ''' + struct X { + INJECT(X(ASSISTED(double) factor)) { + (void) factor; + } + }; + + fruit::Component<X> getComponent() { + return fruit::createComponent(); + } + ''' + expect_compile_error( + 'AssistedParamInRegisterConstructorSignatureError<X\\(fruit::Assisted<double>\\)>', + 'CandidateSignature was used as signature for a registerConstructor.* but it contains an assisted parameter.', + COMMON_DEFINITIONS, + source, + locals()) + + + if __name__ == '__main__': absltest.main() diff --git a/tests/test_register_factory.py b/tests/test_register_factory.py index 202d18b..8f62946 100755 --- a/tests/test_register_factory.py +++ b/tests/test_register_factory.py @@ -2005,6 +2005,79 @@ class TestRegisterFactory(parameterized.TestCase): source, locals()) + @multiple_parameters([ + ('X()', 'X'), + ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'), + ], [ + 'WithNoAnnotation', + 'WithAnnotation1', + ]) + def test_register_factory_with_non_assignable_injected_param_success(self, ConstructX, XPtr, WithAnnot): + source = ''' + struct Y { + Y(const Y&) = delete; + Y& operator=(const Y&) = delete; + + Y() = default; + Y(Y&&) = default; + Y& operator=(Y&&) = default; + }; + struct X {}; + + fruit::Component<WithAnnot<Y>> getYComponent() { + return fruit::createComponent() + .registerConstructor<WithAnnot<Y>()>(); + } + + fruit::Component<std::function<XPtr()>> getComponent() { + return fruit::createComponent() + .install(getYComponent) + .registerFactory<XPtr(WithAnnot<Y&>)>([](Y&){ return ConstructX; }); + } + + int main() { + fruit::Injector<std::function<XPtr()>> injector(getComponent); + XPtr x = injector.get<std::function<XPtr()>>()(); + (void) x; + } + ''' + expect_success( + COMMON_DEFINITIONS, + source, + locals()) + + @multiple_parameters([ + ('X()', 'X'), + ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'), + ]) + def test_register_factory_with_non_assignable_assisted_param_success(self, ConstructX, XPtr): + source = ''' + struct Y { + Y(const Y&) = delete; + Y& operator=(const Y&) = delete; + + Y() = default; + Y(Y&&) = default; + Y& operator=(Y&&) = default; + }; + struct X {}; + + fruit::Component<std::function<XPtr(Y)>> getComponent() { + return fruit::createComponent() + .registerFactory<XPtr(fruit::Assisted<Y>)>([](Y){ return ConstructX; }); + } + + int main() { + fruit::Injector<std::function<XPtr(Y)>> injector(getComponent); + XPtr x = injector.get<std::function<XPtr(Y)>>()(Y()); + (void) x; + } + ''' + expect_success( + COMMON_DEFINITIONS, + source, + locals()) + def test_register_factory_requiring_nonconst_then_requiring_const_ok(self): source = ''' struct X {}; diff --git a/tests/util/test_type_info.py b/tests/util/test_type_info.py index b67f197..d433d60 100644 --- a/tests/util/test_type_info.py +++ b/tests/util/test_type_info.py @@ -51,7 +51,7 @@ class TestTypeInfo(parameterized.TestCase): @parameterized.parameters([ ('MyStruct', '{"MyStruct", "struct MyStruct"}'), - ('std::pair<MyStruct, int>', '{"std::pair<MyStruct, int>", "std::__1::pair<MyStruct, int>"}'), + ('std::pair<MyStruct, int>', '{"std::pair<MyStruct, int>", "std::__1::pair<MyStruct, int>", "struct std::pair<struct MyStruct,int>"}'), ]) def test_name(self, T, Expected): source = ''' |