diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..2d34b20 --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +--- +Language: Cpp +BasedOnStyle: Google +IndentWidth: 4 +TabWidth: 4 +AccessModifierOffset: -4 diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..836223e --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,225 @@ +--- +Checks: + 'clang-diagnostic-*, + clang-analyzer-*, + cppcoreguidelines-*, + performance-*, + readibility-*, + modernize-*, + misc-*, + google-*, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-owning-memory, + -google-build-using-namespace, + -google-runtime-references, + -modernize-use-trailing-return-type' +WarningsAsErrors: + 'clang-diagnostic-*, + clang-analyzer-*, + cppcoreguidelines-*, + performance-*, + readibility-*, + modernize-*, + misc-*, + google-*, + -clang-diagnostic-sign-conversion, + -cppcoreguidelines-narrowing-conversions, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-avoid-goto, + -google-build-using-namespace, + -google-runtime-references, + -modernize-use-equals-default, + -modernize-use-trailing-return-type, + -performance-move-const-arg' +HeaderFilterRegex: "*.cuh" +FormatStyle: none +CheckOptions: + - key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' + - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: '0' + - key: cppcoreguidelines-avoid-magic-numbers.IgnoredFloatingPointValues + value: '1.0;100.0;' + - key: cppcoreguidelines-avoid-magic-numbers.IgnoredIntegerValues + value: '1;2;3;4;' + - key: cppcoreguidelines-explicit-virtual-functions.AllowOverrideAndFinal + value: '0' + - key: cppcoreguidelines-explicit-virtual-functions.FinalSpelling + value: final + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: '1' + - key: cppcoreguidelines-explicit-virtual-functions.OverrideSpelling + value: override + - key: cppcoreguidelines-macro-usage.AllowedRegexp + value: '^DEBUG_*' + - key: cppcoreguidelines-macro-usage.CheckCapsOnly + value: '0' + - key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros + value: '1' + - key: cppcoreguidelines-no-malloc.Allocations + value: '::malloc;::calloc' + - key: cppcoreguidelines-no-malloc.Deallocations + value: '::free' + - key: cppcoreguidelines-no-malloc.Reallocations + value: '::realloc' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: '1' + - key: cppcoreguidelines-owning-memory.LegacyResourceConsumers + value: '::free;::realloc;::freopen;::fclose' + - key: cppcoreguidelines-owning-memory.LegacyResourceProducers + value: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile' + - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader + value: '' + - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle + value: llvm + - key: cppcoreguidelines-pro-type-member-init.IgnoreArrays + value: '0' + - key: cppcoreguidelines-pro-type-member-init.UseAssignment + value: '0' + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions + value: '0' + - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor + value: '1' + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted + value: '1' + - key: google-build-namespaces.HeaderFileExtensions + value: ',h,hh,hpp,hxx' + - key: google-global-names-in-headers.HeaderFileExtensions + value: ',h,hh,hpp,hxx' + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: google-readability-function-size.BranchThreshold + value: '4294967295' + - key: google-readability-function-size.LineThreshold + value: '4294967295' + - key: google-readability-function-size.NestingThreshold + value: '4294967295' + - key: google-readability-function-size.ParameterThreshold + value: '4294967295' + - key: google-readability-function-size.StatementThreshold + value: '800' + - key: google-readability-function-size.VariableThreshold + value: '4294967295' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: google-runtime-int.SignedTypePrefix + value: int + - key: google-runtime-int.TypeSuffix + value: '' + - key: google-runtime-int.UnsignedTypePrefix + value: uint + - key: google-runtime-references.WhiteListTypes + value: '' + - key: misc-definitions-in-headers.HeaderFileExtensions + value: ',h,hh,hpp,hxx' + - key: misc-definitions-in-headers.UseHeaderFileExtension + value: '1' + - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: '1' + - key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries + value: '1' + - key: misc-unused-parameters.StrictMode + value: '0' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-make-shared.IgnoreMacros + value: '1' + - key: modernize-make-shared.IncludeStyle + value: llvm + - key: modernize-make-shared.MakeSmartPtrFunction + value: 'std::make_shared' + - key: modernize-make-shared.MakeSmartPtrFunctionHeader + value: memory + - key: modernize-make-unique.IgnoreMacros + value: '1' + - key: modernize-make-unique.IncludeStyle + value: llvm + - key: modernize-make-unique.MakeSmartPtrFunction + value: 'std::make_unique' + - key: modernize-make-unique.MakeSmartPtrFunctionHeader + value: memory + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-pass-by-value.ValuesOnly + value: '0' + - key: modernize-raw-string-literal.ReplaceShorterLiterals + value: '0' + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-replace-random-shuffle.IncludeStyle + value: llvm + - key: modernize-use-auto.MinTypeNameLength + value: '5' + - key: modernize-use-auto.RemoveStars + value: '0' + - key: modernize-use-default-member-init.IgnoreMacros + value: '1' + - key: modernize-use-default-member-init.UseAssignment + value: '0' + - key: modernize-use-emplace.ContainersWithPushBack + value: '::std::vector;::std::list;::std::deque' + - key: modernize-use-emplace.SmartPointers + value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' + - key: modernize-use-emplace.TupleMakeFunctions + value: '::std::make_pair;::std::make_tuple' + - key: modernize-use-emplace.TupleTypes + value: '::std::pair;::std::tuple' + - key: modernize-use-equals-default.IgnoreMacros + value: '1' + - key: modernize-use-equals-delete.IgnoreMacros + value: '1' + - key: modernize-use-nodiscard.ReplacementString + value: '[[nodiscard]]' + - key: modernize-use-noexcept.ReplacementString + value: '' + - key: modernize-use-noexcept.UseNoexceptFalse + value: '1' + - key: modernize-use-nullptr.NullMacros + value: 'NULL' + - key: modernize-use-override.AllowOverrideAndFinal + value: '0' + - key: modernize-use-override.FinalSpelling + value: final + - key: modernize-use-override.IgnoreDestructors + value: '0' + - key: modernize-use-override.OverrideSpelling + value: override + - key: modernize-use-transparent-functors.SafeMode + value: '0' + - key: modernize-use-using.IgnoreMacros + value: '1' + - key: performance-faster-string-find.StringLikeClasses + value: 'std::basic_string' + - key: performance-for-range-copy.AllowedTypes + value: '' + - key: performance-for-range-copy.WarnOnAllAutoCopies + value: '0' + - key: performance-inefficient-string-concatenation.StrictMode + value: '0' + - key: performance-inefficient-vector-operation.EnableProto + value: '0' + - key: performance-inefficient-vector-operation.VectorLikeClasses + value: '::std::vector' + - key: performance-move-const-arg.CheckTriviallyCopyableMove + value: '1' + - key: performance-move-constructor-init.IncludeStyle + value: llvm + - key: performance-no-automatic-move.AllowedTypes + value: '' + - key: performance-type-promotion-in-math-fn.IncludeStyle + value: llvm + - key: performance-unnecessary-copy-initialization.AllowedTypes + value: '' + - key: performance-unnecessary-value-param.AllowedTypes + value: '' + - key: performance-unnecessary-value-param.IncludeStyle + value: llvm diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..fba6ac2 --- /dev/null +++ b/.clangd @@ -0,0 +1,7 @@ +CompileFlags: + CompilationDatabase: build/clang + Add: [ + -std=c++23, + -fmodules, + -fcxx-modules + ] \ No newline at end of file diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml new file mode 100644 index 0000000..e546a6a --- /dev/null +++ b/.github/workflows/cmake-multi-platform.yml @@ -0,0 +1,113 @@ +# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. +# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml +name: CMake on multiple platforms + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ${{ matrix.runner }} + strategy: + # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. + fail-fast: false + + # Set up a matrix to run the following 3 configurations: + # 1. + # 2. + # 3. + # + # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. + matrix: + os: [ubuntu-26.04, windows-2025-vs2026] + build_type: [Release] + c_compiler: [gcc, clang, cl] + include: + - runner: windows-2025-vs2026 + os: Windows + c_compiler: cl + cpp_compiler: cl + - runner: ubuntu-26.04 + os: Linux + c_compiler: gcc + cpp_compiler: g++ + - runner: ubuntu-26.04 + os: Linux + c_compiler: clang + cpp_compiler: clang++ + exclude: + - os: Windows + c_compiler: gcc + - os: Windows + c_compiler: clang + - runner: Linux + c_compiler: cl + + steps: + - uses: actions/checkout@v4 + + - name: Set reusable strings + # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + - name: Create Conan Dependencies Profile + run: | + if [[ "${{ matrix.c_compiler }}" == "clang" ]]; then + libcxx="compiler.libcxx=libc++11" + else + libcxx="compiler.libcxx=libstdc++11" + fi + + cat << EOF > profile.txt + [settings] + arch=x86_64 + os=${{ matrix.os }} + compiler=${{ matrix.c_compiler }} + compiler.version=$(${{ matrix.c_compiler }} -dumpversion | cut -d. -f1) + compiler.cppstd=23 + $([[ "${{ matrix.c_compiler }}" == "clang" ]] && echo "compiler.libcxx=libstdc++11") + + [buildenv] + CC=${{ matrix.c_compiler }} + CXX=${{ matrix.cpp_compiler }} + + [conf] + tools.cmake.cmaketoolchain:generator=Ninja Multi-Config + tools.cmake.cmake_layout:build_folder_vars=['settings.compiler', 'settings.arch'] + EOF + + - name: Configure Conan Dependencies + run: > + conan install + -of ${{ steps.strings.outputs.build-output-dir }} + -s build_type=${{ matrix.build_type }} + -b=missing + -pr=profile.txt + ${{ github.workspace }} + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + --preset=conan-${{ matrix.c_compiler }}-x86_64 + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -S ${{ github.workspace }} + + - name: Build + # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + + - name: Test + working-directory: ${{ steps.strings.outputs.build-output-dir }} + # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest --preset=conan-${{ matrix.c_compiler }}-x86_64-release diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b68eec5 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,29 @@ +repos: + - repo: https://github.com/pocc/pre-commit-hooks + rev: v1.3.5 + hooks: + - id: clang-format + args: [-i] + # - id: clang-tidy + # - id: oclint + # - id: uncrustify + # - id: cppcheck + # - id: cpplint + # - id: include-what-you-use + - repo: https://github.com/thibthibaut/clangd-format-pre-commit + rev: v1.0.0 + hooks: + - id: clangd-tidy + args: [ + -p=build/clang, + --clangd-executable=/usr/bin/clangd, + "--allow-extensions=c,h,cpp,cc,cxx,cppm,hpp,hh,hxx,cu,cuh", + # "--tqdm" + ] + types: ["file"] + files: '\.(c|h|cpp|cc|cxx|cppm|hpp|hh|hxx|cu|cuh)$' + + # - repo: https://github.com/cpp-linter/cpp-linter-hooks + # rev: v1.6.0 + # hooks: + # - id: clang-format diff --git a/CMakeLists.txt b/CMakeLists.txt index e0b2f3b..4afe8fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,10 @@ if (CMAKE_VERSION VERSION_LESS "4.0.3") set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "a9e1cf81-9932-4810-974b-6eccaf14e457") elseif (CMAKE_VERSION VERSION_LESS "4.3.0") set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") -else() +elseif (CMAKE_VERSION VERSION_LESS "4.4.0") set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "451f2fe2-a8a2-47c3-bc32-94786d8fc91b") +else() + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "f35a9ac6-8463-4d38-8eec-5d6008153e7d") endif() # Project + Language @@ -26,6 +28,10 @@ else() set(CMAKE_CXX_MODULE_STD ON) endif() +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + + + # Options option(ENABLE_EIGEN "Add Eigen support?" ON) option(ENABLE_CUDA "Add Cuda support?" OFF) diff --git a/Changelog.md b/Changelog.md new file mode 100644 index 0000000..4dc68c6 --- /dev/null +++ b/Changelog.md @@ -0,0 +1,2 @@ +# Changelog + diff --git a/README.md b/README.md index 53a0d9d..ec85836 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ cmake -B build/clang --preset=conan-clang-x86_64 # build cmake --build build/clang --config Release -j8 # test -ctest -C Release --test-dir build/clang --no-compress-output --verbose +ctest -preset=${CONAN_PROFILE} --no-compress-output --verbose ``` ### GNU @@ -115,7 +115,7 @@ cmake -B build/gcc --preset=conan-gcc-x86_64 # build cmake --build build/gcc --config Release -j8 # test -ctest -C Release --test-dir build/gcc --no-compress-output --verbose +ctest -preset=${CONAN_PROFILE} --no-compress-output --verbose ``` ## Dockerfile diff --git a/targets/examples/helloworld/src/main.cxx b/targets/examples/helloworld/src/main.cxx index 49bdf55..4c40fa2 100644 --- a/targets/examples/helloworld/src/main.cxx +++ b/targets/examples/helloworld/src/main.cxx @@ -6,21 +6,20 @@ import range_v3; #if ENABLE_EIGEN import eigen.dense; -#endif // ENABLE_EIGEN +#endif // ENABLE_EIGEN -int main(int argc, char** argv) -{ +int main([[maybe_unused]] int argc, [[maybe_unused]] char** argv) { auto s = std::make_unique(2); - std::printf("Hello World!\n"); + std::println("Hello World! {}", *s); #if ENABLE_EIGEN auto m = Eigen::Vector2f(1.2, 2.3); - std::print("{} {}!\n", m.x(), m.y()); -#endif // ENABLE_EIGEN + std::println("{} {}!", m.x(), m.y()); +#endif // ENABLE_EIGEN cmake_cpp_modules_template::foobar::foo f; - std::print("foo: {}\n", f.fibonacci_str(10)); + std::println("foo: {}", f.fibonacci_str(10)); bar b; - fmt::print("bar: {}\n", b.get()); + fmt::println("bar: {}", b.get()); return 0; } diff --git a/targets/foobar/src/cycle.B.cppm b/targets/foobar/src/cycle.B.cppm index c72d7d6..effc695 100644 --- a/targets/foobar/src/cycle.B.cppm +++ b/targets/foobar/src/cycle.B.cppm @@ -5,6 +5,6 @@ import :fwd; export class cycleB { public: - std::string name() const { return "cycleB"; } + [[nodiscard]] std::string name() const { return "cycleB"; } std::string concat_names(cycleA& a); }; diff --git a/targets/foobar/src/cycle.cppm b/targets/foobar/src/cycle.cppm index ebaf194..8bdddb9 100644 --- a/targets/foobar/src/cycle.cppm +++ b/targets/foobar/src/cycle.cppm @@ -6,12 +6,6 @@ export import :fwd; export import :A; export import :B; -std::string cycleA::concat_names(cycleB& b) -{ - return name() + b.name(); -} +std::string cycleA::concat_names(cycleB& b) { return name() + b.name(); } -std::string cycleB::concat_names(cycleA& a) -{ - return name() + a.name(); -} +std::string cycleB::concat_names(cycleA& a) { return name() + a.name(); } diff --git a/targets/foobar/src/cycle.fwd.cppm b/targets/foobar/src/cycle.fwd.cppm index ec08479..ac9164d 100644 --- a/targets/foobar/src/cycle.fwd.cppm +++ b/targets/foobar/src/cycle.fwd.cppm @@ -1,4 +1,4 @@ export module cmake_cpp_modules_template.foobar.cycle:fwd; export class cycleA; -export class cycleB; \ No newline at end of file +export class cycleB; diff --git a/targets/foobar/src/fibonacci.cppm b/targets/foobar/src/fibonacci.cppm index 5434835..2ce6bc9 100644 --- a/targets/foobar/src/fibonacci.cppm +++ b/targets/foobar/src/fibonacci.cppm @@ -3,26 +3,23 @@ export module cmake_cpp_modules_template.foobar.fibonacci; import range_v3; import std; - -export template -ranges::experimental::generator fibonacci() -{ +export template +ranges::experimental::generator fibonacci() { // Largest index of a fibonacci number not greater than F is: // n(F) := floor(log(sqrt(5)(F + 0.5)) / log(phi)) // = floor((log(F+0.5) + log(sqrt(5)) / log(phi)) /*constexpr*/ int n_max = - (std::log2(std::numeric_limits::max()) + std::log2(std::sqrt(5.0))) - / std::log2(std::numbers::phi_v) - 1; + (std::log2(std::numeric_limits::max()) + std::log2(std::sqrt(5.0))) / + std::log2(std::numbers::phi_v) - + 1; - T a=0, b=1; + T a = 0, b = 1; co_yield a; co_yield b; - for (auto n : ranges::views::iota(0, n_max)) - { + for (auto n : ranges::views::iota(0, n_max)) { T s = a + b; co_yield s; a = b; b = s; } } -