# CPP project setup ## static analyer 我看到一個 cppcon,我和它只差在 clang-tidy,其他 sanitizer, clang-format... 都是有的。 [Can C++ be 10x Simpler & Safer? - Herb Sutter - CppCon 2022 ](https://www.youtube.com/watch?v=ELeZAKCN4tY) 重點不是用 cppfront,而是講者發現 cpp 有什麼 1.不必要 2.error prone 的東西,透過語法直接**禁止**去使用。我們可以把這些東西加入static analyer 達到一樣的效果。 有兩種大方向的用法 1. integrate with cmake, CI/CD, forbid compile warning code 2. 和 IDE 整合,improve coder develop experience。 ~~我認為先導入 option2 會有幫助一點。一來不會影響 compile time,二來比較像鼓勵,試試水溫。目前 vscode 下,可靠的方法基本只有 clangd。~~ 先用 clang-tidy CI 比較好一點,vscode已經現有 C++ intellisense。clang-tidy CLI 更像是optional,而非強制。 [開發Ray的VSCode Clangd 設置 - You-Cheng Lin](https://owen-lin.medium.com/%E7%B5%A6%E9%96%8B%E7%99%BCray%E7%9A%84-vscode-clangd-%E8%A8%AD%E7%BD%AE-cda47a15a3e5) ## static polymorphism [ Cost of C++ Abstractions in C++ Embedded Systems - Marcell Juhasz - CppCon 2024 ](https://www.youtube.com/watch?v=7gz98K_hCEM) static polymorphism 對 MCU 和 一些 compile time checking 應該有巨大的作用。但是大量使用應該要等 modules 導入。 ## cpp modules enable with conan [A short tour of C++ modules](https://www.kgmw.ch/posts/cpp-modules-intro/#history) contain require tool version [C++ Modules: The Packaging Story](https://blog.conan.io/2023/10/17/modules-the-packaging-story.html) ```bash conan install . --build=missing --profile:host=clang_debug --profile:build=clang_debug source build/Debug/generators/conanbuild.sh cmake -B build/Debug/ -S . -DCMAKE_TOOLCHAIN_FILE=build/Debug/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -G Ninja cmake --build build/Debug/ ``` conan 目前的 recipe 都是沒開 module 的,所以 [C++ Modules: The Packaging Story](https://blog.conan.io/2023/10/17/modules-the-packaging-story.html) 才需要自己寫recipe `tc.cache_variables["FMT_MODULE"] = "ON"` 這表示 modules 可能只能自己用,這樣很難判斷 modules 到底有多少效益,因為 these lib 的 code base 大很多。 [ {fmt} 11.0 released with improved build speed, C++20 module support, faster print and more ](https://www.reddit.com/r/cpp/comments/1dssm2s/fmt_110_released_with_improved_build_speed_c20/), compile time get 4x boost, really huge. #### migrate > gcc 要等到 gcc15 才有完整的 support module 要 改檔名,hpp --> cppm。是 large migration cpp23 才有 stl module。migrate 會順利一點。 ## todo 1. 先用 c++20 without moudle 2. 導入 clang-tidy ~~with clangd~~ CI 3. implement under module ## conan ### profiles #### clang(under linux) ```bash # may need different libstdc++-{}-dev version sudo apt-get install libstdc++-dev # install clang, following is v19 wget -qO- https://apt.llvm.org/llvm.sh | sudo bash -s -- 19 # install clang-tools for e.g. clang-scan-deps sudo apt install clang-tools-19 ``` `clang-scan-deps` is necessary for c++20 moudle. ```ini [settings] arch=x86_64 build_type=Debug compiler=clang compiler.cppstd=20 compiler.libcxx=libstdc++11 compiler.version=19 os=Linux #[options] #*:shared=True [buildenv] CC=/usr/lib/llvm-19/bin/clang CXX=/usr/lib/llvm-19/bin/clang++ # for sys installed lib LIBRARY_PATH=/home/morgana/tx7_out/igh_5.10.21-rt34_build/lib [conf] tools.system.package_manager:sudo=True tools.system.package_manager:mode=install tools.build:cflags+=['-Wall','-fcolor-diagnostics'] tools.build:cxxflags+=['-Wall','-fcolor-diagnostics'] #tools.build:exelinkflags+=['-fuse-ld=mold'] #tools.build:sharedlinkflags+=['-fuse-ld=mold'] # for sys installed lib tools.build:exelinkflags+=["-L/usr/local/lib"] tools.build:compiler_executables={"cpp": "clang++-19", "c": "clang-19", "rc": "clang-19"} *:tools.cmake.cmaketoolchain:generator=Ninja ``` > LIBRARY_PATH=/usr/lib/llvm-19/lib #/usr/local/lib ##### ~~with libc++~~ clang defautl 是配 libc++, gcc 配 libstdc++11。上面配libstdc++11 是因為 default linux 是沒有 libc++ 的。 其實在 linux 下不建議用,很容易找不到 .so, header...。 > **以下尚未成功,勿使用。** ```bash sudo apt install libc++-dev libc++abi-dev ``` ```ini [settings] arch=x86_64 build_type=Debug compiler=clang compiler.cppstd=20 compiler.libcxx=libc++ compiler.version=19 os=Linux #[options] #*:shared=True [buildenv] CC=/usr/lib/llvm-19/bin/clang CXX=/usr/lib/llvm-19/bin/clang++ # CMAKE_PREFIX_PATH=/usr/lib/llvm-19 [conf] tools.system.package_manager:sudo=True tools.system.package_manager:mode=install tools.build:cflags+=['-Wall','-fcolor-diagnostics'] tools.build:cxxflags+=['-Wall','-fcolor-diagnostics'] # '-stdlib=libc++' #tools.build:exelinkflags+=['-fuse-ld=mold'] #tools.build:sharedlinkflags+=['-fuse-ld=mold'] # for sys installed lib tools.build:exelinkflags+=["-L/usr/local/lib"] # "-lc++abi" tools.build:compiler_executables={"cpp": "clang++-19", "c": "clang-19", "rc": "clang-19"} *:tools.cmake.cmaketoolchain:generator=Ninja ``` #### cross compile take arm32 for example, with separate builded lib ```ini [settings] os=Linux arch=armv7hf compiler=gcc compiler.cppstd=20 compiler.libcxx=libstdc++11 compiler.version=12.3 build_type=Release [buildenv] CC=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-gcc CXX=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-g++ LD=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-ld AR=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-ar AS=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-as NM=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-nm GDB=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-gdb STRIP=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-strip RANLIB=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-ranlib OBJCOPY=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-objcopy OBJDUMP=/home/morgana/arm-tx7-linux-gnueabihf/bin/arm-tx7-linux-gnueabihf-objdump LIBTOOL=/home/morgana/arm-tx7-linux-gnueabihf/bin/libtool #CMAKE_PREFIX_PATH=/home/morgana/tx7_out/igh_5.10.21-rt34_build #this only set env variable rather than config cmake variable [conf] tools.build:sysroot=/home/morgana/arm-tx7-linux-gnueabihf/arm-tx7-linux-gnueabihf/sysroot #tools.build:exelinkflags=['-fuse-ld=gold'] #tools.build:sharedlinkflags=['-fuse-ld=gold'] tools.build:exelinkflags+=["-L/home/morgana/tx7_out/igh_5.10.21-rt34_build/lib"] tools.cmake.cmaketoolchain:user_toolchain=["/home/morgana/.conan2/profiles/tx7_external_paths.cmake"] #[replace_requires] #[platform_requires] #[platform_tool_requires] #cmake/3.24.2 *:tools.cmake.cmaketoolchain:generator=Ninja *:tools.build:verbosity=verbose *:tools.compilation:verbosity=verbose [options] #capehand/*:with_igh=True #resymot/*:with_igh=True ``` ```cmake #tx7_external_paths.cmake list(APPEND CMAKE_PREFIX_PATH "/home/morgana/tx7_out/igh_5.10.21-rt34_build") message(STATUS "Conan User Toolchain: Appended /home/morgana/tx7_out/igh_5.10.21-rt34_build to CMAKE_PREFIX_PATH.") ``` ## unittest run for foreign architecture is the most difficult part ### docker as runner newest ubuntu will give you new glibc version ```bash docker run --rm --platform linux/arm/v7 -v $(pwd):/$(pwd) -t ubuntu:24.04 bash -c "cd $(pwd) && apt update && apt install cmake -y && ctest" ``` build your own runner image ```dockerfile # Dockerfile # syntax=docker/dockerfile:1.4 # This line is important for BuildKit features like --platform in FROM # Use a build argument for the target platform. # BUILDPLATFORM is a special BuildKit variable that resolves to the platform # of the builder itself (e.g., linux/amd64 if you're building on an AMD64 machine). # We use it here to ensure the base image is pulled for the correct architecture # that the build process is running on, even if the final target is different. FROM --platform=$BUILDPLATFORM ubuntu:24.04 # Set environment variables for non-interactive apt installations ENV DEBIAN_FRONTEND=noninteractive # Update package lists and install CMake # This also cleans up apt lists to keep the image size down # The 'cmake' package will be installed for the architecture of the base image. RUN apt update && \ apt install -y cmake && \ rm -rf /var/lib/apt/lists/* # Set a default working directory. Your host path will be mounted into this. WORKDIR /usr/src/app # No CMD or ENTRYPOINT specified, making it a general-purpose image. # You will specify the command when you run the container. ``` ```bash docker build --platform linux/arm/v7 -t my-arm32-dev-image:latest . docker run --rm --platform linux/arm/v7 -v $(pwd):$(pwd) -t my-arm32-dev-image:latest bash -c "cd $(pwd) && ctest" ``` encourage compile whole program in static build, or you may have to mount, find and link your shared libs in container ```bash clear && conan build . */*:shared=False -pr armv7x_debug --build=missing ``` other arch ```bash docker buildx build --platform linux/arm64 -t my-dev-image:arm64v8 --load . ```