From c43038c8ec4ef38739ea817026f84077bb3952ec Mon Sep 17 00:00:00 2001 From: Edward Nolan Date: Thu, 30 Apr 2026 23:48:31 -0400 Subject: [PATCH] Apply exemplar To implement this commit, I stamped out a new cookiecutter template from the latest beman.exemplar and copied over the relevant code from span. This adds CI support and brings the repository into alignment with the other Beman repositories. Closes #11 --- .clang-format | 242 ++++++++++++++ .exemplar_version | 1 + .gitattributes | 5 + .github/CODEOWNERS | 3 + .../implementation-deficiency.md | 35 ++ .../ISSUE_TEMPLATE/infrastructure-issues.md | 29 ++ .github/ISSUE_TEMPLATE/paper-discussion.md | 33 ++ .github/pull_request_template.md | 5 + .github/workflows/ci_tests.yml | 155 +++++++++ .github/workflows/pre-commit-check.yml | 19 ++ .github/workflows/pre-commit-update.yml | 15 + .github/workflows/vcpkg-release.yml | 13 + .gitignore | 24 +- .markdownlint.yaml | 10 + .pre-commit-config.yaml | 48 +++ CMakeLists.txt | 9 +- CMakePresets.json | 305 ++++++++++++++++-- CONTRIBUTING.md | 129 ++++++-- README.md | 161 ++++++--- examples/CMakeLists.txt | 1 - examples/todo.cpp | 7 + infra/.beman_submodule | 3 + infra/.github/CODEOWNERS | 1 + infra/.github/workflows/pre-commit.yml | 78 +++++ ...reusable-beman-create-issue-when-fault.yml | 28 ++ infra/.gitignore | 59 ++++ infra/.pre-commit-config.yaml | 21 ++ infra/LICENSE | 219 +++++++++++++ infra/README.md | 88 +++++ infra/cmake/BuildTelemetry.cmake | 4 + infra/cmake/BuildTelemetryConfig.cmake | 58 ++++ infra/cmake/Config.cmake.in | 6 +- infra/cmake/appleclang-toolchain.cmake | 44 +++ infra/cmake/beman-install-library.cmake | 38 +-- infra/cmake/gnu-toolchain.cmake | 41 +++ infra/cmake/llvm-libc++-toolchain.cmake | 20 ++ infra/cmake/llvm-toolchain.cmake | 41 +++ infra/cmake/msvc-toolchain.cmake | 41 +++ infra/cmake/telemetry.sh | 118 +++++++ infra/cmake/use-fetch-content.cmake | 219 +++++++------ lockfile.json | 13 + port/portfile.cmake.in | 28 ++ port/vcpkg.json.in | 17 + tests/beman/span/CMakeLists.txt | 2 +- vcpkg-configuration.json | 15 + vcpkg.json | 10 + 46 files changed, 2214 insertions(+), 247 deletions(-) create mode 100644 .clang-format create mode 100644 .exemplar_version create mode 100644 .gitattributes create mode 100644 .github/CODEOWNERS create mode 100644 .github/ISSUE_TEMPLATE/implementation-deficiency.md create mode 100644 .github/ISSUE_TEMPLATE/infrastructure-issues.md create mode 100644 .github/ISSUE_TEMPLATE/paper-discussion.md create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/ci_tests.yml create mode 100644 .github/workflows/pre-commit-check.yml create mode 100644 .github/workflows/pre-commit-update.yml create mode 100644 .github/workflows/vcpkg-release.yml create mode 100644 .markdownlint.yaml create mode 100644 .pre-commit-config.yaml create mode 100644 examples/todo.cpp create mode 100644 infra/.beman_submodule create mode 100644 infra/.github/CODEOWNERS create mode 100644 infra/.github/workflows/pre-commit.yml create mode 100644 infra/.github/workflows/reusable-beman-create-issue-when-fault.yml create mode 100644 infra/.gitignore create mode 100644 infra/.pre-commit-config.yaml create mode 100644 infra/LICENSE create mode 100644 infra/README.md create mode 100755 infra/cmake/BuildTelemetry.cmake create mode 100755 infra/cmake/BuildTelemetryConfig.cmake create mode 100644 infra/cmake/appleclang-toolchain.cmake create mode 100644 infra/cmake/gnu-toolchain.cmake create mode 100644 infra/cmake/llvm-libc++-toolchain.cmake create mode 100644 infra/cmake/llvm-toolchain.cmake create mode 100644 infra/cmake/msvc-toolchain.cmake create mode 100755 infra/cmake/telemetry.sh create mode 100644 lockfile.json create mode 100644 port/portfile.cmake.in create mode 100644 port/vcpkg.json.in create mode 100644 vcpkg-configuration.json create mode 100644 vcpkg.json diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..74f95dc --- /dev/null +++ b/.clang-format @@ -0,0 +1,242 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: false +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Custom +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +# Please update .markdownlint.yaml if this line is to be updated +ColumnLimit: 119 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: BeforeHash +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +KeepEmptyLinesAtEOF: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: NextLine +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +PPIndentWidth: -1 +QualifierAlignment: Custom +QualifierOrder: + - inline + - static + - constexpr + - const + - volatile + - type +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: Never +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... diff --git a/.exemplar_version b/.exemplar_version new file mode 100644 index 0000000..8f59e27 --- /dev/null +++ b/.exemplar_version @@ -0,0 +1 @@ +0131279454a8b54a6038203a7b714e2e0a835039 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..793dce7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +infra/** linguist-vendored +cookiecutter/** linguist-vendored +*.bib -linguist-detectable +*.tex -linguist-detectable +papers/* linguist-documentation diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..75a3a31 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +* @SamareshSingh diff --git a/.github/ISSUE_TEMPLATE/implementation-deficiency.md b/.github/ISSUE_TEMPLATE/implementation-deficiency.md new file mode 100644 index 0000000..4a0ee77 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/implementation-deficiency.md @@ -0,0 +1,35 @@ +--- +name: Implementation Deficiency +about: Report a bug or performance issue of our implementation +title: '' +labels: bug +assignees: '' + +--- + + + +## Describe the deficiency + +A clear and concise description of what the deficiency is. +Link all relevant issues. +This could be a bug, or a performance problem. + +## To Reproduce + +```c++ +// Use case +``` + +## Expected Behavior + +A clear and concise description of what you expected to happen. + +## Additional Discussions + +Add any other context about the problem here. +If you believe your issue is platform dependent, +please post your compiler versions here. diff --git a/.github/ISSUE_TEMPLATE/infrastructure-issues.md b/.github/ISSUE_TEMPLATE/infrastructure-issues.md new file mode 100644 index 0000000..11fbd13 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/infrastructure-issues.md @@ -0,0 +1,29 @@ +--- +name: Infrastructure Issues +about: Report a bug or feature request with our Infrastructure +title: '' +labels: infra +assignees: '' + +--- + + + +## I am attempting to + +Describe what you were attempting to do. + +## Expected Behavior + +A clear and concise description of what you expected to happen. + +## Current Behavior + +A clear and concise description of what actually happened. + +## Additional Discussions + +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/paper-discussion.md b/.github/ISSUE_TEMPLATE/paper-discussion.md new file mode 100644 index 0000000..14c9e4f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/paper-discussion.md @@ -0,0 +1,33 @@ +--- +name: Paper Discussion +about: Provide feedback to current API +title: '' +labels: '' +assignees: '' + +--- + + + +## Use case + +Describe your concerns about adding this change to the C++ Standard Library. + +```c++ +// example snippet +``` + +## What I like + +Let us know what you find positive about current approach / design. + +## What I dislike + +Let us know what you find negative about current approach / design. + +## Discussion + +Let us know if you have any more remarks. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..071cb28 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,5 @@ + diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml new file mode 100644 index 0000000..bbff1b2 --- /dev/null +++ b/.github/workflows/ci_tests.yml @@ -0,0 +1,155 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: Continuous Integration Tests + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + schedule: + - cron: '39 16 * * 0' + +jobs: + beman-submodule-check: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-submodule-check.yml@1.6.0 + + preset-test: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-preset-test.yml@1.6.0 + with: + matrix_config: > + [ + {"preset": "gcc-debug", "image": "ghcr.io/bemanproject/infra-containers-gcc:latest"}, + {"preset": "gcc-release", "image": "ghcr.io/bemanproject/infra-containers-gcc:latest"}, + {"preset": "llvm-debug", "image": "ghcr.io/bemanproject/infra-containers-clang:latest"}, + {"preset": "llvm-release", "image": "ghcr.io/bemanproject/infra-containers-clang:latest"}, + {"preset": "appleclang-debug", "runner": "macos-latest"}, + {"preset": "appleclang-release", "runner": "macos-latest"}, + {"preset": "msvc-debug", "runner": "windows-latest"}, + {"preset": "msvc-release", "runner": "windows-latest"} + ] + + build-and-test: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-build-and-test.yml@1.6.0 + with: + matrix_config: > + { + "gcc": [ + { "versions": ["15"], + "tests": [ + { "cxxversions": ["c++26"], + "tests": [ + { "stdlibs": ["libstdc++"], + "tests": [ + "Debug.Default", "Release.Default", "Release.TSan", + "Release.MaxSan", "Debug.Werror", + "Debug.Coverage" + ] + } + ] + }, + { "cxxversions": ["c++23", "c++20"], + "tests": [{ "stdlibs": ["libstdc++"], "tests": ["Release.Default"]}] + } + ] + }, + { "versions": ["14", "13"], + "tests": [ + { "cxxversions": ["c++26", "c++23", "c++20"], + "tests": [{ "stdlibs": ["libstdc++"], "tests": ["Release.Default"]}] + } + ] + }, + { + "versions": ["12", "11"], + "tests": [ + { "cxxversions": ["c++23", "c++20"], + "tests": [{ "stdlibs": ["libstdc++"], "tests": ["Release.Default"]}] + } + ] + } + ], + "clang": [ + { "versions": ["22"], + "tests": [ + {"cxxversions": ["c++26"], + "tests": [ + { "stdlibs": ["libstdc++", "libc++"], + "tests": [ + "Debug.Default", "Release.Default", "Release.TSan", + "Release.MaxSan", "Debug.Werror" + ] + } + ] + }, + { "cxxversions": ["c++23", "c++20"], + "tests": [ + {"stdlibs": ["libstdc++", "libc++"], "tests": ["Release.Default"]} + ] + } + ] + }, + { "versions": ["21", "20", "19"], + "tests": [ + { "cxxversions": ["c++26", "c++23", "c++20"], + "tests": [ + {"stdlibs": ["libstdc++", "libc++"], "tests": ["Release.Default"]} + ] + } + ] + }, + { "versions": ["18"], + "tests": [ + { "cxxversions": ["c++26", "c++23", "c++20"], + "tests": [{"stdlibs": ["libc++"], "tests": ["Release.Default"]}] + }, + { "cxxversions": ["c++23", "c++20"], + "tests": [{"stdlibs": ["libstdc++"], "tests": ["Release.Default"]}] + } + ] + }, + { "versions": ["17"], + "tests": [ + { "cxxversions": ["c++26", "c++23", "c++20"], + "tests": [{"stdlibs": ["libc++"], "tests": ["Release.Default"]}] + }, + { "cxxversions": ["c++20"], + "tests": [{"stdlibs": ["libstdc++"], "tests": ["Release.Default"]}] + } + ] + } + ], + "appleclang": [ + { "versions": ["latest"], + "tests": [ + { "cxxversions": ["c++26", "c++23", "c++20"], + "tests": [{ "stdlibs": ["libc++"], "tests": ["Release.Default"]}] + } + ] + } + ], + "msvc": [ + { "versions": ["latest"], + "tests": [ + { "cxxversions": ["c++23"], + "tests": [ + { "stdlibs": ["stl"], + "tests": ["Debug.Default", "Release.Default", "Release.MaxSan"] + } + ] + } + ] + } + ] + } + + vcpkg-ci: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-vcpkg-ci.yml@1.6.0 + with: + port_name: beman-span + + create-issue-when-fault: + needs: [preset-test, build-and-test] + if: failure() && github.event_name == 'schedule' + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-create-issue-when-fault.yml@1.6.0 diff --git a/.github/workflows/pre-commit-check.yml b/.github/workflows/pre-commit-check.yml new file mode 100644 index 0000000..15c5280 --- /dev/null +++ b/.github/workflows/pre-commit-check.yml @@ -0,0 +1,19 @@ +name: Lint Check (pre-commit) + +on: + # We have to use pull_request_target here as pull_request does not grant + # enough permission for reviewdog + pull_request_target: + push: + branches: + - main + +permissions: + contents: read + checks: write + issues: write + pull-requests: write + +jobs: + pre-commit: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-pre-commit.yml@1.6.0 diff --git a/.github/workflows/pre-commit-update.yml b/.github/workflows/pre-commit-update.yml new file mode 100644 index 0000000..e42d7d5 --- /dev/null +++ b/.github/workflows/pre-commit-update.yml @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: Weekly pre-commit autoupdate + +on: + workflow_dispatch: + schedule: + - cron: "17 14 * * 3" + +jobs: + auto-update-pre-commit: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-update-pre-commit.yml@1.6.0 + secrets: + APP_ID: ${{ secrets.AUTO_PR_BOT_APP_ID }} + PRIVATE_KEY: ${{ secrets.AUTO_PR_BOT_PRIVATE_KEY }} diff --git a/.github/workflows/vcpkg-release.yml b/.github/workflows/vcpkg-release.yml new file mode 100644 index 0000000..372fc19 --- /dev/null +++ b/.github/workflows/vcpkg-release.yml @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: vcpkg registry release +on: + release: + types: [published] +jobs: + vcpkg-release: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-vcpkg-release.yml@1.6.0 + with: + port_name: beman-span + secrets: + VCPKG_REGISTRY_TOKEN: ${{ secrets.VCPKG_REGISTRY_TOKEN }} diff --git a/.gitignore b/.gitignore index 6a794e9..d62996c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,18 @@ -build/ -.cache/ -CMakeUserPresets.json -*.swp -*.orig -.DS_Store +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +/.cache +/compile_commands.json +/build + +# ignore emacs temp files +*~ +\#*\# + +# ignore vscode settings +.vscode + +# ignore vim swap files +.swp + +# ignore merge/patch backup files +.orig diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..21c2849 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,10 @@ +# MD033/no-inline-html : Inline HTML : https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/md033.md +# Disable inline html linter is needed for
+MD033: false + +# MD013/line-length : Line length : https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/md013.md +# Conforms to .clang-format ColumnLimit +# Update the comment in .clang-format if we no-longer tie these two column limits. +MD013: + line_length: 119 + code_blocks: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b4dce7a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,48 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + + # Clang-format for C++ + # This brings in a portable version of clang-format. + # See also: https://github.com/ssciwr/clang-format-wheel + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v22.1.4 + hooks: + - id: clang-format + types_or: [c++, c] + + # CMake linting and formatting + - repo: https://github.com/BlankSpruce/gersemi-pre-commit + rev: 0.27.2 + hooks: + - id: gersemi + name: CMake linting + exclude: ^.*/tests/.*/data/ # Exclude test data directories + + # Markdown linting + # Config file: .markdownlint.yaml + # Commented out to disable this by default. Uncomment to enable markdown linting. + # - repo: https://github.com/igorshubovych/markdownlint-cli + # rev: v0.42.0 + # hooks: + # - id: markdownlint + + - repo: https://github.com/codespell-project/codespell + rev: v2.4.2 + hooks: + - id: codespell + + # Beman Standard checking via beman-tidy + - repo: https://github.com/bemanproject/beman-tidy + rev: v0.3.1 + hooks: + - id: beman-tidy + +exclude: 'cookiecutter/|infra/|port/' diff --git a/CMakeLists.txt b/CMakeLists.txt index ca2dee8..c032302 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.25...4.3) +cmake_minimum_required(VERSION 3.30...4.3) project( beman.span - DESCRIPTION "A Beman implementation of std::span (C++20)" + DESCRIPTION "A Beman implementation of std::span" LANGUAGES CXX VERSION 0.1.0 ) @@ -23,13 +23,13 @@ option( ${PROJECT_IS_TOP_LEVEL} ) +# for find of beman_install_library and configure_build_telemetry include(infra/cmake/beman-install-library.cmake) +include(infra/cmake/BuildTelemetryConfig.cmake) add_library(beman.span INTERFACE) add_library(beman::span ALIAS beman.span) -target_compile_features(beman.span INTERFACE cxx_std_20) - target_sources( beman.span PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" @@ -43,6 +43,7 @@ set_target_properties( add_subdirectory(include/beman/span) beman_install_library(beman.span TARGETS beman.span) +configure_build_telemetry() if(BEMAN_SPAN_BUILD_TESTS) enable_testing() diff --git a/CMakePresets.json b/CMakePresets.json index a53ef97..483e1a3 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -30,7 +30,10 @@ { "name": "gcc-debug", "displayName": "GCC Debug Build", - "inherits": ["_root-config", "_debug-base"], + "inherits": [ + "_root-config", + "_debug-base" + ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/gnu-toolchain.cmake" } @@ -38,7 +41,10 @@ { "name": "gcc-release", "displayName": "GCC Release Build", - "inherits": ["_root-config", "_release-base"], + "inherits": [ + "_root-config", + "_release-base" + ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/gnu-toolchain.cmake" } @@ -46,7 +52,10 @@ { "name": "llvm-debug", "displayName": "Clang Debug Build", - "inherits": ["_root-config", "_debug-base"], + "inherits": [ + "_root-config", + "_debug-base" + ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-toolchain.cmake" } @@ -54,10 +63,57 @@ { "name": "llvm-release", "displayName": "Clang Release Build", - "inherits": ["_root-config", "_release-base"], + "inherits": [ + "_root-config", + "_release-base" + ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-toolchain.cmake" } + }, + { + "name": "appleclang-debug", + "displayName": "Appleclang Debug Build", + "inherits": [ + "_root-config", + "_debug-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" + } + }, + { + "name": "appleclang-release", + "displayName": "Appleclang Release Build", + "inherits": [ + "_root-config", + "_release-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" + } + }, + { + "name": "msvc-debug", + "displayName": "MSVC Debug Build", + "inherits": [ + "_root-config", + "_debug-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "infra/cmake/msvc-toolchain.cmake" + } + }, + { + "name": "msvc-release", + "displayName": "MSVC Release Build", + "inherits": [ + "_root-config", + "_release-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "infra/cmake/msvc-toolchain.cmake" + } } ], "buildPresets": [ @@ -66,54 +122,251 @@ "hidden": true, "jobs": 0 }, - {"name": "gcc-debug", "configurePreset": "gcc-debug", "inherits": ["_root-build"]}, - {"name": "gcc-release", "configurePreset": "gcc-release", "inherits": ["_root-build"]}, - {"name": "llvm-debug", "configurePreset": "llvm-debug", "inherits": ["_root-build"]}, - {"name": "llvm-release", "configurePreset": "llvm-release", "inherits": ["_root-build"]} + { + "name": "gcc-debug", + "configurePreset": "gcc-debug", + "inherits": [ + "_root-build" + ] + }, + { + "name": "gcc-release", + "configurePreset": "gcc-release", + "inherits": [ + "_root-build" + ] + }, + { + "name": "llvm-debug", + "configurePreset": "llvm-debug", + "inherits": [ + "_root-build" + ] + }, + { + "name": "llvm-release", + "configurePreset": "llvm-release", + "inherits": [ + "_root-build" + ] + }, + { + "name": "appleclang-debug", + "configurePreset": "appleclang-debug", + "inherits": [ + "_root-build" + ] + }, + { + "name": "appleclang-release", + "configurePreset": "appleclang-release", + "inherits": [ + "_root-build" + ] + }, + { + "name": "msvc-debug", + "configurePreset": "msvc-debug", + "inherits": [ + "_root-build" + ] + }, + { + "name": "msvc-release", + "configurePreset": "msvc-release", + "inherits": [ + "_root-build" + ] + } ], "testPresets": [ { "name": "_test_base", "hidden": true, - "output": {"outputOnFailure": true}, - "execution": {"noTestsAction": "error", "stopOnFailure": true} + "output": { + "outputOnFailure": true + }, + "execution": { + "noTestsAction": "error", + "stopOnFailure": true + } + }, + { + "name": "gcc-debug", + "inherits": "_test_base", + "configurePreset": "gcc-debug" + }, + { + "name": "gcc-release", + "inherits": "_test_base", + "configurePreset": "gcc-release" + }, + { + "name": "llvm-debug", + "inherits": "_test_base", + "configurePreset": "llvm-debug" + }, + { + "name": "llvm-release", + "inherits": "_test_base", + "configurePreset": "llvm-release" + }, + { + "name": "appleclang-debug", + "inherits": "_test_base", + "configurePreset": "appleclang-debug" + }, + { + "name": "appleclang-release", + "inherits": "_test_base", + "configurePreset": "appleclang-release" }, - {"name": "gcc-debug", "inherits": "_test_base", "configurePreset": "gcc-debug"}, - {"name": "gcc-release", "inherits": "_test_base", "configurePreset": "gcc-release"}, - {"name": "llvm-debug", "inherits": "_test_base", "configurePreset": "llvm-debug"}, - {"name": "llvm-release", "inherits": "_test_base", "configurePreset": "llvm-release"} + { + "name": "msvc-debug", + "inherits": "_test_base", + "configurePreset": "msvc-debug" + }, + { + "name": "msvc-release", + "inherits": "_test_base", + "configurePreset": "msvc-release" + } ], "workflowPresets": [ { "name": "gcc-debug", "steps": [ - {"type": "configure", "name": "gcc-debug"}, - {"type": "build", "name": "gcc-debug"}, - {"type": "test", "name": "gcc-debug"} + { + "type": "configure", + "name": "gcc-debug" + }, + { + "type": "build", + "name": "gcc-debug" + }, + { + "type": "test", + "name": "gcc-debug" + } ] }, { "name": "gcc-release", "steps": [ - {"type": "configure", "name": "gcc-release"}, - {"type": "build", "name": "gcc-release"}, - {"type": "test", "name": "gcc-release"} + { + "type": "configure", + "name": "gcc-release" + }, + { + "type": "build", + "name": "gcc-release" + }, + { + "type": "test", + "name": "gcc-release" + } ] }, { "name": "llvm-debug", "steps": [ - {"type": "configure", "name": "llvm-debug"}, - {"type": "build", "name": "llvm-debug"}, - {"type": "test", "name": "llvm-debug"} + { + "type": "configure", + "name": "llvm-debug" + }, + { + "type": "build", + "name": "llvm-debug" + }, + { + "type": "test", + "name": "llvm-debug" + } ] }, { "name": "llvm-release", "steps": [ - {"type": "configure", "name": "llvm-release"}, - {"type": "build", "name": "llvm-release"}, - {"type": "test", "name": "llvm-release"} + { + "type": "configure", + "name": "llvm-release" + }, + { + "type": "build", + "name": "llvm-release" + }, + { + "type": "test", + "name": "llvm-release" + } + ] + }, + { + "name": "appleclang-debug", + "steps": [ + { + "type": "configure", + "name": "appleclang-debug" + }, + { + "type": "build", + "name": "appleclang-debug" + }, + { + "type": "test", + "name": "appleclang-debug" + } + ] + }, + { + "name": "appleclang-release", + "steps": [ + { + "type": "configure", + "name": "appleclang-release" + }, + { + "type": "build", + "name": "appleclang-release" + }, + { + "type": "test", + "name": "appleclang-release" + } + ] + }, + { + "name": "msvc-debug", + "steps": [ + { + "type": "configure", + "name": "msvc-debug" + }, + { + "type": "build", + "name": "msvc-debug" + }, + { + "type": "test", + "name": "msvc-debug" + } + ] + }, + { + "name": "msvc-release", + "steps": [ + { + "type": "configure", + "name": "msvc-release" + }, + { + "type": "build", + "name": "msvc-release" + }, + { + "type": "test", + "name": "msvc-release" + } ] } ] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 231c95b..e6c5280 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,58 +7,129 @@ Presets](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html). Appro presets for major compilers have been included by default. You can use `cmake --list-presets=workflow` to see all available presets. -Example using the `gcc-debug` preset: +Here is an example of invoking the `gcc-debug` preset: ```shell cmake --workflow --preset gcc-debug ``` -Generally, there are two kinds of presets — `debug` and `release`. +Generally, there are two kinds of presets, `debug` and `release`. -- **debug**: debuginfo and sanitizers enabled, suitable for development. -- **release**: highest optimisation (`-O3`), suitable for benchmarking. +The `debug` presets are designed to aid development, so they have debuginfo and sanitizers +enabled. + +> [!NOTE] +> +> The sanitizers that are enabled vary from compiler to compiler. See the toolchain files +> under ([`infra/cmake`](infra/cmake/)) to determine the exact configuration used for each +> preset. + +The `release` presets are designed for production use, and +consequently have the highest optimization turned on (e.g. `O3`). ## Configure and Build Manually -If presets are not suitable, you can invoke CMake directly. Note that GoogleTest -must be installed (`libgtest-dev` on Debian/Ubuntu, `gtest` via vcpkg, etc.). +If the presets are not suitable for your use case, a traditional CMake invocation will +provide more configurability. + +To configure, build and test the project manually, you can run this set of commands. Note +that this requires GoogleTest to be installed. ```bash -cmake -B build -S . -DCMAKE_CXX_STANDARD=20 +cmake \ + -B build \ + -S . \ + -DCMAKE_CXX_STANDARD=20 \ + # Your extra arguments here. cmake --build build ctest --test-dir build ``` -> **Important:** `beman.span` is a [passive project]( -> https://github.com/bemanproject/beman/blob/main/docs/beman_standard.md#cmakepassive_projects). -> Always pass `-DCMAKE_CXX_STANDARD=20` when configuring manually. +> [!IMPORTANT] +> +> Beman projects are [passive projects]( +> https://github.com/bemanproject/beman/blob/main/docs/beman_standard.md#cmakepassive_projects), +> so you need to specify the C++ version via `CMAKE_CXX_STANDARD` when manually +> configuring the project. ## Dependency Management -### FetchContent (automatic) +### vcpkg -Configure the project with `-DFETCHCONTENT_PROVIDER=fetchcontent` (or set it -in a CMake preset) and CMake will automatically download GoogleTest. +The best way to install the project's dependencies is to use the vcpkg workflow. -### Package manager +To do so, make sure vcpkg is installed and `VCPKG_ROOT` is defined in your environment, +then specify +`-DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"`. Vcpkg will handle +the project's dependencies, including GoogleTest. -Install GoogleTest through your system package manager or vcpkg: +Example commands: -```bash -# Debian / Ubuntu -sudo apt install libgtest-dev +``` +cmake \ + -B build \ + -S . \ + -DCMAKE_CXX_STANDARD=17 \ + -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" +cmake --build build +ctest --test-dir build +``` + +The file `./vcpkg.json` configures the list of dependencies that will be configured by +vcpkg. + +### FetchContent + +Instead of installing the project's dependencies via a package manager, you can optionally +configure beman.span to fetch them automatically via CMake FetchContent. + +To do so, specify +`-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./infra/cmake/use-fetch-content.cmake`. This will +bring in GoogleTest automatically along with any other dependency the project may require. + +Example commands: + +```shell +cmake \ + -B build \ + -S . \ + -DCMAKE_CXX_STANDARD=20 \ + -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./infra/cmake/use-fetch-content.cmake +cmake --build build +ctest --test-dir build +``` + +The file `./lockfile.json` configures the list of dependencies and versions that will be +acquired by FetchContent. -# vcpkg -vcpkg install gtest +## Project-specific configure arguments + +Project-specific options are prefixed with `BEMAN_SPAN`. +You can see the list of available options with: + +```bash +cmake -LH -S . -B build | grep "BEMAN_SPAN" -C 2 ``` -## Code Style +
+ +Some project-specific configure arguments + +### `BEMAN_SPAN_BUILD_TESTS` + +Enable building tests and test infrastructure. Default: `ON`. +Values: `{ ON, OFF }`. + +### `BEMAN_SPAN_BUILD_EXAMPLES` + +Enable building examples. Default: `ON`. Values: `{ ON, OFF }`. + +### `BEMAN_SPAN_INSTALL_CONFIG_FILE_PACKAGE` + +Enable installing the CMake config file package. Default: `ON`. +Values: `{ ON, OFF }`. + +This is required so that users of `beman.span` can use +`find_package(beman.span)` to locate the library. -- Follow the [Beman Standard](https://github.com/bemanproject/beman/blob/main/docs/beman_standard.md). -- All source files must start with the SPDX identifier: - ```cpp - // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - ``` -- Header guards: `#ifndef BEMAN_SPAN__HPP` -- Test files use the `*.test.cpp` naming convention. -- Run `clang-format` (`.clang-format` config in the repo root) before submitting. +
diff --git a/README.md b/README.md index d22dd91..30315c8 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,23 @@ -# beman.span: A Beman implementation of `std::span` +# beman.span: A Beman implementation of std::span -[![Apache-2.0 License](https://img.shields.io/badge/license-Apache--2.0%20WITH%20LLVM--exception-blue.svg)](LICENSE) -[![C++20](https://img.shields.io/badge/C%2B%2B-20-blue.svg)](https://en.cppreference.com/w/cpp/20) + +![Library Status](https://raw.githubusercontent.com/bemanproject/beman/refs/heads/main/images/badges/beman_badge-beman_library_under_development.svg) ![Continuous Integration Tests](https://github.com/bemanproject/span/actions/workflows/ci_tests.yml/badge.svg) ![Lint Check (pre-commit)](https://github.com/bemanproject/span/actions/workflows/pre-commit-check.yml/badge.svg) [![Coverage](https://coveralls.io/repos/github/bemanproject/span/badge.svg?branch=main)](https://coveralls.io/github/bemanproject/span?branch=main) ![Standard Target](https://github.com/bemanproject/beman/blob/main/images/badges/cpp29.svg) + +`beman.span` is an implementation of various proposed updates to `std::span`. **Implements:** `std::span` a non-owning view over a contiguous sequence of objects. See [cppreference — std::span](https://en.cppreference.com/w/cpp/container/span) and [eel.is/c++draft/views.span](https://eel.is/c++draft/views.span). -**Status:** Under development and not yet ready for production use. -See the [Beman Library Maturity Model](https://github.com/bemanproject/beman/blob/main/docs/beman_library_maturity_model.md). +**Status**: [Under development and not yet ready for production use.](https://github.com/bemanproject/beman/blob/main/docs/beman_library_maturity_model.md#under-development-and-not-yet-ready-for-production-use) ---- +## License + +`beman.span` is licensed under the Apache License v2.0 with LLVM Exceptions. ## Features @@ -27,8 +30,6 @@ See the [Beman Library Maturity Model](https://github.com/bemanproject/beman/blo - `constexpr` throughout - Compared with `std::span` in tests when available (`__cpp_lib_span`) ---- - ## Usage ```cpp @@ -63,73 +64,131 @@ int main() { } ``` ---- +Full runnable examples can be found in [`examples/`](examples/). + +## Dependencies + +### Build Environment + +This project requires at least the following to build: + +* A C++ compiler that conforms to the C++20 standard or greater +* CMake 3.30 or later +* (Test Only) GoogleTest -## Building +You can disable building tests by setting CMake option `BEMAN_SPAN_BUILD_TESTS` to +`OFF` when configuring the project. -### Requirements +### Supported Platforms -| Dependency | Version | -|------------|---------| -| CMake | ≥ 3.30 | -| C++ compiler | C++20 (GCC 11+, Clang 13+, MSVC 19.29+) | -| GTest | any recent version (for tests) | +| Compiler | Version | C++ Standards | Standard Library | +|------------|---------|---------------|-------------------| +| GCC | 15-13 | C++26-C++20 | libstdc++ | +| GCC | 12-11 | C++23, C++20 | libstdc++ | +| Clang | 22-19 | C++26-C++20 | libstdc++, libc++ | +| Clang | 18 | C++26-C++20 | libc++ | +| Clang | 18 | C++23, C++20 | libstdc++ | +| Clang | 17 | C++26-C++20 | libc++ | +| Clang | 17 | C++20 | libstdc++ | +| AppleClang | latest | C++26-C++20 | libc++ | +| MSVC | latest | C++23 | MSVC STL | -### Build with presets +## Development + +See the [Contributing Guidelines](CONTRIBUTING.md). + +## Integrate beman.span into your project + +### Build + +You can build span using a CMake workflow preset: ```bash -cmake --preset gcc-release # configure -cmake --build build/gcc-release -ctest --test-dir build/gcc-release +cmake --workflow --preset gcc-release ``` -### Manual build +To list available workflow presets, you can invoke: ```bash -cmake -B build -S . -DCMAKE_CXX_STANDARD=20 -cmake --build build -ctest --test-dir build +cmake --list-presets=workflow ``` -### Options +For details on building beman.span without using a CMake preset, refer to the +[Contributing Guidelines](CONTRIBUTING.md). -| Option | Default | Description | -|--------|---------|-------------| -| `BEMAN_SPAN_BUILD_TESTS` | `ON` (top-level) | Build and run unit tests | -| `BEMAN_SPAN_BUILD_EXAMPLES` | `ON` (top-level) | Build example programs | +### Installation ---- +#### Vcpkg -## Consuming as a dependency +The preferred way to install span is via vcpkg. To do so, after installing vcpkg +itself, you need to add support for the Beman project's [vcpkg +registry](https://github.com/bemanproject/vcpkg-registry) by configuring a +`vcpkg-configuration.json` file (which span [provides](vcpkg-configuration.json)). -```cmake -find_package(beman.span REQUIRED) -target_link_libraries(my_target PRIVATE beman::span) +Then, simply run `vcpkg install beman-span`. + +#### Manual + +To install beman.span globally after building with the `gcc-release` preset, you can +run: + +```bash +sudo cmake --install build/gcc-release ``` -Or via FetchContent: +Alternatively, to install to a prefix, for example `/opt/beman`, you can run: + +```bash +sudo cmake --install build/gcc-release --prefix /opt/beman +``` + +This will generate the following directory structure: + +```txt +/opt/beman +├── include +│ └── beman +│ └── span +│ ├── span.hpp +│ └── ... +└── lib + └── cmake + └── beman.span + ├── beman.span-config-version.cmake + ├── beman.span-config.cmake + └── beman.span-targets.cmake +``` + +### CMake Configuration + +If you installed beman.span to a prefix, you can specify that prefix to your CMake +project using `CMAKE_PREFIX_PATH`; for example, `-DCMAKE_PREFIX_PATH=/opt/beman`. + +You need to bring in the `beman.span` package to define the `beman::span` CMake +target: ```cmake -include(FetchContent) -FetchContent_Declare( - beman.span - GIT_REPOSITORY https://github.com/SamareshSingh/span.git - GIT_TAG main -) -FetchContent_MakeAvailable(beman.span) -target_link_libraries(my_target PRIVATE beman::span) +find_package(beman.span REQUIRED) ``` ---- +You will then need to add `beman::span` to the link libraries of any libraries or +executables that include `beman.span` headers. -## License +```cmake +target_link_libraries(yourlib PUBLIC beman::span) +``` -`beman.span` is licensed under the Apache License v2.0 with LLVM Exceptions. -See [LICENSE](LICENSE) for details. +### Using beman.span ---- +To use `beman.span` in your C++ project, +include an appropriate `beman.span` header from your source code. -## Contributing +```c++ +#include +``` -See [CONTRIBUTING.md](CONTRIBUTING.md) and the -[Beman Standard](https://github.com/bemanproject/beman/blob/main/docs/beman_standard.md). +> [!NOTE] +> +> `beman.span` headers are to be included with the `beman/span/` prefix. +> Altering include search paths to spell the include target another way (e.g. +> `#include `) is unsupported. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 2de438d..7ace533 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception set(ALL_EXAMPLES span_basic_usage span_subviews span_bytes) - message("Examples to be built: ${ALL_EXAMPLES}") foreach(example ${ALL_EXAMPLES}) diff --git a/examples/todo.cpp b/examples/todo.cpp new file mode 100644 index 0000000..c567f1c --- /dev/null +++ b/examples/todo.cpp @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +int main() { + // TODO +} diff --git a/infra/.beman_submodule b/infra/.beman_submodule new file mode 100644 index 0000000..a2ad45f --- /dev/null +++ b/infra/.beman_submodule @@ -0,0 +1,3 @@ +[beman_submodule] +remote=https://github.com/bemanproject/infra.git +commit_hash=1b14bad2cd2cf0e44d1aeb608557e0e35ce27eaa diff --git a/infra/.github/CODEOWNERS b/infra/.github/CODEOWNERS new file mode 100644 index 0000000..4ff90a4 --- /dev/null +++ b/infra/.github/CODEOWNERS @@ -0,0 +1 @@ +* @ednolan @neatudarius @rishyak @wusatosi @JeffGarland diff --git a/infra/.github/workflows/pre-commit.yml b/infra/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..9646831 --- /dev/null +++ b/infra/.github/workflows/pre-commit.yml @@ -0,0 +1,78 @@ +name: Lint Check (pre-commit) + +on: + # We have to use pull_request_target here as pull_request does not grant + # enough permission for reviewdog + pull_request_target: + push: + branches: + - main + +jobs: + pre-commit-push: + name: Pre-Commit check on Push + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.13 + + # We wish to run pre-commit on all files instead of the changes + # only made in the push commit. + # + # So linting error persists when there's formatting problem. + - uses: pre-commit/action@v3.0.1 + + pre-commit-pr: + name: Pre-Commit check on PR + runs-on: ubuntu-latest + if: ${{ github.event_name == 'pull_request_target' }} + + permissions: + contents: read + checks: write + issues: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # pull_request_target checkout the base of the repo + # We need to checkout the actual pr to lint the changes. + - name: Checkout pr + run: gh pr checkout ${{ github.event.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.13 + + # we only lint on the changed file in PR. + - name: Get Changed Files + id: changed-files + uses: tj-actions/changed-files@v45 + + # See: + # https://github.com/tj-actions/changed-files?tab=readme-ov-file#using-local-git-directory- + - uses: pre-commit/action@v3.0.1 + id: run-pre-commit + with: + extra_args: --files ${{ steps.changed-files.outputs.all_changed_files }} + + # Review dog posts the suggested change from pre-commit to the pr. + - name: suggester / pre-commit + uses: reviewdog/action-suggester@v1 + if: ${{ failure() && steps.run-pre-commit.conclusion == 'failure' }} + with: + tool_name: pre-commit + level: warning + reviewdog_flags: "-fail-level=error" diff --git a/infra/.github/workflows/reusable-beman-create-issue-when-fault.yml b/infra/.github/workflows/reusable-beman-create-issue-when-fault.yml new file mode 100644 index 0000000..024a51f --- /dev/null +++ b/infra/.github/workflows/reusable-beman-create-issue-when-fault.yml @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: 'Beman issue creation workflow' +on: + workflow_call: + workflow_dispatch: +jobs: + create-issue: + runs-on: ubuntu-latest + steps: + # See https://github.com/cli/cli/issues/5075 + - uses: actions/checkout@v4 + - name: Create issue + run: | + issue_num=$(gh issue list -s open -S "[SCHEDULED-BUILD] infra repo CI job failure" -L 1 --json number | jq 'if length == 0 then -1 else .[0].number end') + body="**CI job failure Report** + - **Time of Failure**: $(date -u '+%B %d, %Y, %H:%M %Z') + - **Commit**: [${{ github.sha }}](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}) + - **Action Run**: [View logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) + The scheduled job triggered by cron has failed. + Please investigate the logs and recent changes associated with this commit or rerun the workflow if you believe this is an error." + if [[ $issue_num -eq -1 ]]; then + gh issue create --repo ${{ github.repository }} --title "[SCHEDULED-BUILD] infra repo CI job failure" --body "$body" --assignee ${{ github.actor }} + else + gh issue comment --repo ${{ github.repository }} $issue_num --body "$body" + fi + env: + GH_TOKEN: ${{ github.token }} diff --git a/infra/.gitignore b/infra/.gitignore new file mode 100644 index 0000000..b7cdbb5 --- /dev/null +++ b/infra/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Python +__pycache__/ +.pytest_cache/ +*.pyc +*.pyo +*.pyd +*.pyw +*.pyz +*.pywz +*.pyzw +*.pyzwz +*.delete_me + +# MAC OS +*.DS_Store + +# Editor files +.vscode/ +.idea/ + +# Build directories +infra.egg-info/ +beman_tidy.egg-info/ +*.egg-info/ +build/ +dist/ diff --git a/infra/.pre-commit-config.yaml b/infra/.pre-commit-config.yaml new file mode 100644 index 0000000..8052e18 --- /dev/null +++ b/infra/.pre-commit-config.yaml @@ -0,0 +1,21 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + + - repo: https://github.com/codespell-project/codespell + rev: v2.4.2 + hooks: + - id: codespell + + # CMake linting and formatting + - repo: https://github.com/BlankSpruce/gersemi-pre-commit + rev: 0.27.2 + hooks: + - id: gersemi + name: CMake linting + exclude: ^.*/tests/.*/data/ # Exclude test data directories diff --git a/infra/LICENSE b/infra/LICENSE new file mode 100644 index 0000000..f6db814 --- /dev/null +++ b/infra/LICENSE @@ -0,0 +1,219 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. diff --git a/infra/README.md b/infra/README.md new file mode 100644 index 0000000..6cb8dd6 --- /dev/null +++ b/infra/README.md @@ -0,0 +1,88 @@ +# Beman Project Infrastructure Repository + + + +This repository contains the infrastructure for The Beman Project. This is NOT a library repository, +so it does not respect the usual structure of a Beman library repository nor The Beman Standard! + +## Description + +* `cmake/`: CMake modules and toolchain files used by Beman libraries. +* `containers/`: Containers used for CI builds and tests in the Beman org. + +## Usage + +This repository is intended to be used as a beman-submodule in other Beman repositories. See +[the beman-submodule documentation](https://github.com/bemanproject/beman-submodule) for details. + + +### CMake Modules + + +#### `beman_install_library` + +The CMake modules in this repository are intended to be used by Beman libraries. Use the +`beman_install_library()` function to install your library, along with header +files, any metadata files, and a CMake config file for `find_package()` support. + +```cmake +add_library(beman.something) +add_library(beman::something ALIAS beman.something) + +# ... configure your target as needed ... + +include(infra/cmake/beman-install-library.cmake) +beman_install_library(beman.something) +``` + +Note that the target must be created before calling `beman_install_library()`. The module +also assumes that the target is named using the `beman.something` convention, and it +uses that assumption to derive the names to match other Beman standards and conventions. +If your target does not follow that convention, raise an issue or pull request to add +more configurability to the module. + +The module will configure the target to install: + +* The library target itself +* Any public headers associated with the target +* CMake files for `find_package(beman.something)` support + +Some options for the project and target will also be supported: + +* `BEMAN_INSTALL_CONFIG_FILE_PACKAGES` - a list of package names (e.g., `beman.something`) for which to install the config file + (default: all packages) +* `_INSTALL_CONFIG_FILE_PACKAGE` - a per-project option to enable/disable config file installation (default: `ON` if the project is top-level, `OFF` otherwise). For instance for `beman.something`, the option would be `BEMAN_SOMETHING_INSTALL_CONFIG_FILE_PACKAGE`. + +# BuildTelemetry + +The cmake modules in this library provide access to CMake instrumentation data in Google Trace format which is visualizable with chrome://tracing and https://ui.perfetto.dev. + +Telemetry may be enabled in several ways: + +## `include` + +```cmake +include (infra/cmake/BuildTelemetry.cmake) +configure_build_telemetry() +``` + +## `find_package` + +```cmake +find_package(BuildTelemetry) +configure_build_telemetry() +``` + +as long as [BuildTelemetryConfig.cmake](./cmake/BuildTelemetryConfig.cmake) is in your module path. + +## `CMAKE_PROJECT_TOP_LEVEL_INCLUDES` +A non-invasive way to inject this telemetry into a CMake build you do not want to modify. +Add: +```sh +-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=infra/cmake/BuildTelemetry.cmake +``` +To the cmake invocation. + +In any form, CMake will call `telemetry.sh` which will copy the trace data in json format into a `.trace` subdirectory within the build directory. + +Multiple calls to `configure_build_telemetry` will only configure the callback hooks once, so it is safe to enable multiple times, including by TOP_LEVEL_INCLUDE. diff --git a/infra/cmake/BuildTelemetry.cmake b/infra/cmake/BuildTelemetry.cmake new file mode 100755 index 0000000..c2ff343 --- /dev/null +++ b/infra/cmake/BuildTelemetry.cmake @@ -0,0 +1,4 @@ +include_guard(GLOBAL) + +include(${CMAKE_CURRENT_LIST_DIR}/BuildTelemetryConfig.cmake) +configure_build_telemetry() diff --git a/infra/cmake/BuildTelemetryConfig.cmake b/infra/cmake/BuildTelemetryConfig.cmake new file mode 100755 index 0000000..15aae48 --- /dev/null +++ b/infra/cmake/BuildTelemetryConfig.cmake @@ -0,0 +1,58 @@ +include_guard(GLOBAL) + +set(BUILD_TELEMETRY_DIR ${CMAKE_CURRENT_LIST_DIR}) + +function(configure_build_telemetry) + if(NOT BUILD_TELEMETRY_CONFIGURATION) + # Check if the CMake version is at least 4.3 + if(CMAKE_VERSION VERSION_LESS "4.3") + message( + STATUS + "CMake version is less than 4.3, configuring cmake_instrumentation is unavailable." + ) + return() + else() + message(STATUS "Configuring Build Telemetry") + endif() + + # Find bash and jq for the telemetry callback script. + # On Windows, Git for Windows provides bash if available. + find_program(BEMAN_BASH bash) + find_program(BEMAN_JQ jq) + if(NOT BEMAN_BASH OR NOT BEMAN_JQ) + message( + STATUS + "bash or jq not found, build telemetry disabled on this platform." + ) + return() + endif() + + # Telemetry query + cmake_instrumentation( + API_VERSION 1 + DATA_VERSION 1 + OPTIONS staticSystemInformation dynamicSystemInformation trace + HOOKS + postGenerate + preBuild + postBuild + preCMakeBuild + postCMakeBuild + postCMakeInstall + postCTest + CALLBACK ${BEMAN_BASH} + ${BUILD_TELEMETRY_DIR}/telemetry.sh + ) + message( + DEBUG + "using callback script ${BUILD_TELEMETRY_DIR}/telemetry.sh via ${BEMAN_BASH}" + ) + + # Mark configuration as done in cache + set(BUILD_TELEMETRY_CONFIGURATION + TRUE + CACHE INTERNAL + "Flag to ensure Build Telemetry configured only once" + ) + endif() +endfunction(configure_build_telemetry) diff --git a/infra/cmake/Config.cmake.in b/infra/cmake/Config.cmake.in index 81adf80..3f1341c 100644 --- a/infra/cmake/Config.cmake.in +++ b/infra/cmake/Config.cmake.in @@ -3,10 +3,10 @@ include(CMakeFindDependencyMacro) -@BEMAN_FIND_DEPENDENCIES@ +@BEMAN_INSTALL_FIND_DEPENDENCIES@ @PACKAGE_INIT@ -include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/@BEMAN_INSTALL_BASE_PKG_NAME@-targets.cmake) -check_required_components(@PROJECT_NAME@) +check_required_components(@BEMAN_INSTALL_BASE_PKG_NAME@) diff --git a/infra/cmake/appleclang-toolchain.cmake b/infra/cmake/appleclang-toolchain.cmake new file mode 100644 index 0000000..70ef548 --- /dev/null +++ b/infra/cmake/appleclang-toolchain.cmake @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for apple clang family of compiler. +# Note this is different from LLVM toolchain. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures clang and clang++ to use all available non-conflicting +# sanitizers. Note that apple clang does not support leak sanitizer. +# - TSan: configures clang and clang++ to enable the use of thread sanitizer. + +include_guard(GLOBAL) + +# Prevent PATH collision with an LLVM clang installation by using the system +# compiler shims +set(CMAKE_C_COMPILER cc) +set(CMAKE_CXX_COMPILER c++) + +if(BEMAN_BUILDSYS_SANITIZER STREQUAL "MaxSan") + set(SANITIZER_FLAGS + "-fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined" + ) +elseif(BEMAN_BUILDSYS_SANITIZER STREQUAL "TSan") + set(SANITIZER_FLAGS "-fsanitize=thread") +endif() + +set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") +set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") + +set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") + +set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") + +# Add this dir to the module path so that `find_package(beman-install-library)` works +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") diff --git a/infra/cmake/beman-install-library.cmake b/infra/cmake/beman-install-library.cmake index a77ee1a..dc5a4d1 100644 --- a/infra/cmake/beman-install-library.cmake +++ b/infra/cmake/beman-install-library.cmake @@ -86,14 +86,14 @@ function(beman_install_library name) set(multiValueArgs TARGETS DEPENDENCIES) cmake_parse_arguments( - BEMAN + BEMAN_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - if(NOT BEMAN_TARGETS) + if(NOT BEMAN_INSTALL_TARGETS) message( FATAL_ERROR "beman_install_library(${name}): TARGETS must be specified" @@ -103,7 +103,7 @@ function(beman_install_library name) if(CMAKE_SKIP_INSTALL_RULES) message( WARNING - "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" + "beman_install_library(${name}): not installing targets '${BEMAN_INSTALL_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" ) return() endif() @@ -113,16 +113,16 @@ function(beman_install_library name) # ---------------------------- # Defaults # ---------------------------- - if(NOT BEMAN_NAMESPACE) - set(BEMAN_NAMESPACE "beman::") + if(NOT BEMAN_INSTALL_NAMESPACE) + set(BEMAN_INSTALL_NAMESPACE "beman::") endif() - if(NOT BEMAN_EXPORT_NAME) - set(BEMAN_EXPORT_NAME "${name}-targets") + if(NOT BEMAN_INSTALL_EXPORT_NAME) + set(BEMAN_INSTALL_EXPORT_NAME "${name}-targets") endif() - if(NOT BEMAN_DESTINATION) - set(BEMAN_DESTINATION "${_config_install_dir}/modules") + if(NOT BEMAN_INSTALL_DESTINATION) + set(BEMAN_INSTALL_DESTINATION "${_config_install_dir}/modules") endif() string(REPLACE "beman." "" install_component_name "${name}") @@ -134,7 +134,7 @@ function(beman_install_library name) # -------------------------------------------------- # Install each target with all of its file sets # -------------------------------------------------- - foreach(_tgt IN LISTS BEMAN_TARGETS) + foreach(_tgt IN LISTS BEMAN_INSTALL_TARGETS) if(NOT TARGET "${_tgt}") message( WARNING @@ -177,8 +177,7 @@ function(beman_install_library name) ) foreach(_install_header_set IN LISTS _available_header_sets) list( - APPEND - _install_header_set_args + APPEND _install_header_set_args FILE_SET "${_install_header_set}" COMPONENT @@ -198,7 +197,7 @@ function(beman_install_library name) ) install( TARGETS "${_tgt}" - EXPORT ${BEMAN_EXPORT_NAME} + EXPORT ${BEMAN_INSTALL_EXPORT_NAME} ARCHIVE COMPONENT "${install_component_name}_Development" LIBRARY COMPONENT "${install_component_name}_Runtime" @@ -206,7 +205,7 @@ function(beman_install_library name) RUNTIME COMPONENT "${install_component_name}_Runtime" ${_install_header_set_args} FILE_SET ${_module_sets} - DESTINATION "${BEMAN_DESTINATION}" + DESTINATION "${BEMAN_INSTALL_DESTINATION}" COMPONENT "${install_component_name}_Development" # NOTE: There's currently no convention for this location! CK CXX_MODULES_BMI @@ -217,7 +216,7 @@ function(beman_install_library name) else() install( TARGETS "${_tgt}" - EXPORT ${BEMAN_EXPORT_NAME} + EXPORT ${BEMAN_INSTALL_EXPORT_NAME} ARCHIVE COMPONENT "${install_component_name}_Development" LIBRARY COMPONENT "${install_component_name}_Runtime" @@ -233,8 +232,8 @@ function(beman_install_library name) # -------------------------------------------------- # gersemi: off install( - EXPORT ${BEMAN_EXPORT_NAME} - NAMESPACE ${BEMAN_NAMESPACE} + EXPORT ${BEMAN_INSTALL_EXPORT_NAME} + NAMESPACE ${BEMAN_INSTALL_NAMESPACE} CXX_MODULES_DIRECTORY cxx-modules DESTINATION ${_config_install_dir} COMPONENT "${install_component_name}_Development" @@ -279,19 +278,20 @@ function(beman_install_library name) # expand dependencies # ---------------------------------------- set(_beman_find_deps "") - foreach(dep IN LISTS BEMAN_DEPENDENCIES) + foreach(dep IN LISTS BEMAN_INSTALL_DEPENDENCIES) message( VERBOSE "beman-install-library(${name}): Add find_dependency(${dep})" ) string(APPEND _beman_find_deps "find_dependency(${dep})\n") endforeach() - set(BEMAN_FIND_DEPENDENCIES "${_beman_find_deps}") + set(BEMAN_INSTALL_FIND_DEPENDENCIES "${_beman_find_deps}") # ---------------------------------------- # Generate + install config files # ---------------------------------------- if(_install_config) + set(BEMAN_INSTALL_BASE_PKG_NAME ${name}) configure_package_config_file( "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" diff --git a/infra/cmake/gnu-toolchain.cmake b/infra/cmake/gnu-toolchain.cmake new file mode 100644 index 0000000..d3b9f92 --- /dev/null +++ b/infra/cmake/gnu-toolchain.cmake @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for GNU family of compiler. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures gcc and g++ to use all available non-conflicting +# sanitizers. +# - TSan: configures gcc and g++ to enable the use of thread sanitizer + +include_guard(GLOBAL) + +set(CMAKE_C_COMPILER gcc) +set(CMAKE_CXX_COMPILER g++) + +if(BEMAN_BUILDSYS_SANITIZER STREQUAL "MaxSan") + set(SANITIZER_FLAGS + "-fsanitize=address -fsanitize=leak -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined -fsanitize-undefined-trap-on-error" + ) +elseif(BEMAN_BUILDSYS_SANITIZER STREQUAL "TSan") + set(SANITIZER_FLAGS "-fsanitize=thread") +endif() + +set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") +set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") + +set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") + +set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") + +# Add this dir to the module path so that `find_package(beman-install-library)` works +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") diff --git a/infra/cmake/llvm-libc++-toolchain.cmake b/infra/cmake/llvm-libc++-toolchain.cmake new file mode 100644 index 0000000..eabf363 --- /dev/null +++ b/infra/cmake/llvm-libc++-toolchain.cmake @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for LLVM family of compiler. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures clang and clang++ to use all available non-conflicting +# sanitizers. +# - TSan: configures clang and clang++ to enable the use of thread sanitizer. + +include(${CMAKE_CURRENT_LIST_DIR}/llvm-toolchain.cmake) + +if(NOT CMAKE_CXX_FLAGS MATCHES "-stdlib=libc\\+\\+") + string(APPEND CMAKE_CXX_FLAGS " -stdlib=libc++") +endif() diff --git a/infra/cmake/llvm-toolchain.cmake b/infra/cmake/llvm-toolchain.cmake new file mode 100644 index 0000000..f1623b7 --- /dev/null +++ b/infra/cmake/llvm-toolchain.cmake @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for LLVM family of compiler. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures clang and clang++ to use all available non-conflicting +# sanitizers. +# - TSan: configures clang and clang++ to enable the use of thread sanitizer. + +include_guard(GLOBAL) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) + +if(BEMAN_BUILDSYS_SANITIZER STREQUAL "MaxSan") + set(SANITIZER_FLAGS + "-fsanitize=address -fsanitize=leak -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined -fsanitize-undefined-trap-on-error" + ) +elseif(BEMAN_BUILDSYS_SANITIZER STREQUAL "TSan") + set(SANITIZER_FLAGS "-fsanitize=thread") +endif() + +set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") +set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") + +set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") + +set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") + +# Add this dir to the module path so that `find_package(beman-install-library)` works +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") diff --git a/infra/cmake/msvc-toolchain.cmake b/infra/cmake/msvc-toolchain.cmake new file mode 100644 index 0000000..bdc24de --- /dev/null +++ b/infra/cmake/msvc-toolchain.cmake @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for MSVC family of compiler. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures cl to use all available non-conflicting sanitizers. +# +# Note that in other toolchain files, TSan is also a possible value for +# BEMAN_BUILDSYS_SANITIZER, however, MSVC does not support thread sanitizer, +# thus this value is omitted. + +include_guard(GLOBAL) + +set(CMAKE_C_COMPILER cl) +set(CMAKE_CXX_COMPILER cl) + +if(BEMAN_BUILDSYS_SANITIZER STREQUAL "MaxSan") + # /Zi flag (add debug symbol) is needed when using address sanitizer + # See C5072: https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-c5072 + set(SANITIZER_FLAGS "/fsanitize=address /Zi") +endif() + +set(CMAKE_CXX_FLAGS_DEBUG_INIT "/EHsc /permissive- ${SANITIZER_FLAGS}") +set(CMAKE_C_FLAGS_DEBUG_INIT "/EHsc /permissive- ${SANITIZER_FLAGS}") + +set(RELEASE_FLAGS "/EHsc /permissive- /O2 ${SANITIZER_FLAGS}") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") + +set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") + +# Add this dir to the module path so that `find_package(beman-install-library)` works +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") diff --git a/infra/cmake/telemetry.sh b/infra/cmake/telemetry.sh new file mode 100755 index 0000000..323982e --- /dev/null +++ b/infra/cmake/telemetry.sh @@ -0,0 +1,118 @@ +#!/usr/bin/env bash + +set -o nounset +set -o errexit +trap 'echo "Aborting due to errexit on line $LINENO. Exit code: $?" >&2' ERR +set -o errtrace +set -o pipefail +IFS=$'\n\t' + +############################################################################### +# Environment +############################################################################### + +# $_ME +# +# This program's basename. +_ME="$(basename "${0}")" + +############################################################################### +# Help +############################################################################### + +# _print_help() +# +# Usage: +# _print_help +# +# Print the program help information. +_print_help() { + cat <] + ${_ME} -h | --help + +Options: + -h --help Show this screen. + +Environment: + Setting DEBUG_TELEMETRY in the environment will enable DEBUG logging +HEREDOC +} + +############################################################################### +# Program Functions +############################################################################### +_debug_print() { + if [[ -n "${DEBUG_TELEMETRY:-}" ]]; then + printf "[DEBUG] $(date +'%H:%M:%S'): %s \n" "$1" >&2 + fi +} + +_check_file_exists() { + local file="$1" + if [[ ! -f "${file}" ]]; then + echo "Error: File not found: ${file}" >&2 + exit 1 # Exit the entire script with a non-zero status + fi +} + +_process_index() { + indexFile=${1:-} + _check_file_exists "${indexFile}" + _debug_print "$(cat "${indexFile}")" + + local buildDir + buildDir=$(jq -r '.buildDir' "${1:-}") + _debug_print "$(printf "buildDir is |%q|" "${buildDir}")" + + local dataDir + dataDir=$(jq -r '.dataDir' "${1:-}") + _debug_print "$(printf "dataDir is |%q|" "${dataDir}")" + + local hook + hook=$(jq -r '.hook' "${1:-}") + _debug_print "$(printf "hook is |%q|" "${hook}")" + + local trace + trace=$(jq -r '.trace' "${1:-}") + _debug_print "$(printf "trace is |%q|" "${trace}")" + + local outputDir + outputDir="${buildDir}/.trace" + _debug_print "$(printf "Copy trace to |%q|" "${outputDir}")" + mkdir -p "${outputDir}" + + local traceDestFile + traceDestFile="${outputDir}/${hook}-$(basename "${trace}")" + _debug_print "$(printf "traceDestFile: |%q|" "${traceDestFile}")" + cp "${dataDir}/${trace}" "${outputDir}/${hook}-$(basename "${trace}")" +} + +############################################################################### +# Main +############################################################################### + +# _main() +# +# Usage: +# _main [] [] +# +# Description: +# Entry point for the program, handling basic option parsing and dispatching. +_main() { + # Avoid complex option parsing when only one program option is expected. + if [[ "${1:-}" =~ ^-h|--help$ ]] + then + _print_help + else + _process_index "$@" + fi +} + +# Call `_main` after everything has been defined. +_main "$@" diff --git a/infra/cmake/use-fetch-content.cmake b/infra/cmake/use-fetch-content.cmake index eb22be4..73594be 100644 --- a/infra/cmake/use-fetch-content.cmake +++ b/infra/cmake/use-fetch-content.cmake @@ -2,196 +2,201 @@ cmake_minimum_required(VERSION 3.24) include(FetchContent) -if(NOT BEMAN_EXEMPLAR_LOCKFILE) - set(BEMAN_EXEMPLAR_LOCKFILE +if(NOT BEMAN_LOCKFILE) + set(BEMAN_LOCKFILE "lockfile.json" CACHE FILEPATH - "Path to the dependency lockfile for the Beman Exemplar." + "Path to the dependency lockfile for the Beman project." ) endif() -set(BemanExemplar_projectDir "${CMAKE_CURRENT_LIST_DIR}/../..") -message(TRACE "BemanExemplar_projectDir=\"${BemanExemplar_projectDir}\"") +set(Beman_projectDir "${CMAKE_CURRENT_LIST_DIR}/../..") +message(TRACE "Beman_projectDir=\"${Beman_projectDir}\"") -message(TRACE "BEMAN_EXEMPLAR_LOCKFILE=\"${BEMAN_EXEMPLAR_LOCKFILE}\"") +message(TRACE "BEMAN_LOCKFILE=\"${BEMAN_LOCKFILE}\"") file( - REAL_PATH - "${BEMAN_EXEMPLAR_LOCKFILE}" - BemanExemplar_lockfile - BASE_DIRECTORY "${BemanExemplar_projectDir}" + REAL_PATH "${BEMAN_LOCKFILE}" + Beman_lockfile + BASE_DIRECTORY "${Beman_projectDir}" EXPAND_TILDE ) -message(DEBUG "Using lockfile: \"${BemanExemplar_lockfile}\"") +message(DEBUG "Using lockfile: \"${Beman_lockfile}\"") # Force CMake to reconfigure the project if the lockfile changes set_property( - DIRECTORY "${BemanExemplar_projectDir}" + DIRECTORY "${Beman_projectDir}" APPEND - PROPERTY CMAKE_CONFIGURE_DEPENDS "${BemanExemplar_lockfile}" + PROPERTY CMAKE_CONFIGURE_DEPENDS "${Beman_lockfile}" ) # For more on the protocol for this function, see: # https://cmake.org/cmake/help/latest/command/cmake_language.html#provider-commands -function(BemanExemplar_provideDependency method package_name) +function(Beman_provideDependency method package_name) # Read the lockfile - file(READ "${BemanExemplar_lockfile}" BemanExemplar_rootObj) + file(READ "${Beman_lockfile}" Beman_rootObj) - # Get the "dependencies" field and store it in BemanExemplar_dependenciesObj + # Get the "dependencies" field and store it in Beman_dependenciesObj string( - JSON - BemanExemplar_dependenciesObj - ERROR_VARIABLE BemanExemplar_error - GET "${BemanExemplar_rootObj}" + JSON Beman_dependenciesObj + ERROR_VARIABLE Beman_error + GET "${Beman_rootObj}" "dependencies" ) - if(BemanExemplar_error) - message(FATAL_ERROR "${BemanExemplar_lockfile}: ${BemanExemplar_error}") + if(Beman_error) + message(FATAL_ERROR "${Beman_lockfile}: ${Beman_error}") endif() - # Get the length of the libraries array and store it in BemanExemplar_dependenciesObj + # Get the length of the libraries array and store it in Beman_dependenciesObj string( - JSON - BemanExemplar_numDependencies - ERROR_VARIABLE BemanExemplar_error - LENGTH "${BemanExemplar_dependenciesObj}" + JSON Beman_numDependencies + ERROR_VARIABLE Beman_error + LENGTH "${Beman_dependenciesObj}" ) - if(BemanExemplar_error) - message(FATAL_ERROR "${BemanExemplar_lockfile}: ${BemanExemplar_error}") + if(Beman_error) + message(FATAL_ERROR "${Beman_lockfile}: ${Beman_error}") endif() - if(BemanExemplar_numDependencies EQUAL 0) + if(Beman_numDependencies EQUAL 0) return() endif() # Loop over each dependency object - math(EXPR BemanExemplar_maxIndex "${BemanExemplar_numDependencies} - 1") - foreach(BemanExemplar_index RANGE "${BemanExemplar_maxIndex}") - set(BemanExemplar_errorPrefix - "${BemanExemplar_lockfile}, dependency ${BemanExemplar_index}" - ) + math(EXPR Beman_maxIndex "${Beman_numDependencies} - 1") + foreach(Beman_index RANGE "${Beman_maxIndex}") + set(Beman_errorPrefix "${Beman_lockfile}, dependency ${Beman_index}") - # Get the dependency object at BemanExemplar_index - # and store it in BemanExemplar_depObj + # Get the dependency object at Beman_index + # and store it in Beman_depObj string( - JSON - BemanExemplar_depObj - ERROR_VARIABLE BemanExemplar_error - GET "${BemanExemplar_dependenciesObj}" - "${BemanExemplar_index}" + JSON Beman_depObj + ERROR_VARIABLE Beman_error + GET "${Beman_dependenciesObj}" + "${Beman_index}" ) - if(BemanExemplar_error) - message( - FATAL_ERROR - "${BemanExemplar_errorPrefix}: ${BemanExemplar_error}" - ) + if(Beman_error) + message(FATAL_ERROR "${Beman_errorPrefix}: ${Beman_error}") endif() - # Get the "name" field and store it in BemanExemplar_name + # Get the "name" field and store it in Beman_name string( - JSON - BemanExemplar_name - ERROR_VARIABLE BemanExemplar_error - GET "${BemanExemplar_depObj}" + JSON Beman_name + ERROR_VARIABLE Beman_error + GET "${Beman_depObj}" "name" ) - if(BemanExemplar_error) - message( - FATAL_ERROR - "${BemanExemplar_errorPrefix}: ${BemanExemplar_error}" - ) + if(Beman_error) + message(FATAL_ERROR "${Beman_errorPrefix}: ${Beman_error}") endif() - # Get the "package_name" field and store it in BemanExemplar_pkgName + # Get the "package_name" field and store it in Beman_pkgName string( - JSON - BemanExemplar_pkgName - ERROR_VARIABLE BemanExemplar_error - GET "${BemanExemplar_depObj}" + JSON Beman_pkgName + ERROR_VARIABLE Beman_error + GET "${Beman_depObj}" "package_name" ) - if(BemanExemplar_error) - message( - FATAL_ERROR - "${BemanExemplar_errorPrefix}: ${BemanExemplar_error}" - ) + if(Beman_error) + message(FATAL_ERROR "${Beman_errorPrefix}: ${Beman_error}") endif() - # Get the "git_repository" field and store it in BemanExemplar_repo + # Get the "git_repository" field and store it in Beman_repo string( - JSON - BemanExemplar_repo - ERROR_VARIABLE BemanExemplar_error - GET "${BemanExemplar_depObj}" + JSON Beman_repo + ERROR_VARIABLE Beman_error + GET "${Beman_depObj}" "git_repository" ) - if(BemanExemplar_error) - message( - FATAL_ERROR - "${BemanExemplar_errorPrefix}: ${BemanExemplar_error}" - ) + if(Beman_error) + message(FATAL_ERROR "${Beman_errorPrefix}: ${Beman_error}") endif() - # Get the "git_tag" field and store it in BemanExemplar_tag + # Get the "git_tag" field and store it in Beman_tag string( - JSON - BemanExemplar_tag - ERROR_VARIABLE BemanExemplar_error - GET "${BemanExemplar_depObj}" + JSON Beman_tag + ERROR_VARIABLE Beman_error + GET "${Beman_depObj}" "git_tag" ) - if(BemanExemplar_error) - message( - FATAL_ERROR - "${BemanExemplar_errorPrefix}: ${BemanExemplar_error}" - ) + if(Beman_error) + message(FATAL_ERROR "${Beman_errorPrefix}: ${Beman_error}") endif() if(method STREQUAL "FIND_PACKAGE") - if(package_name STREQUAL BemanExemplar_pkgName) + if(package_name STREQUAL Beman_pkgName) string( - APPEND - BemanExemplar_debug - "Redirecting find_package calls for ${BemanExemplar_pkgName} " + APPEND Beman_debug + "Redirecting find_package calls for ${Beman_pkgName} " "to FetchContent logic.\n" ) string( - APPEND - BemanExemplar_debug - "Fetching ${BemanExemplar_repo} at " - "${BemanExemplar_tag} according to ${BemanExemplar_lockfile}." + APPEND Beman_debug + "Fetching ${Beman_repo} at " + "${Beman_tag} according to ${Beman_lockfile}." ) - message(DEBUG "${BemanExemplar_debug}") + message(DEBUG "${Beman_debug}") FetchContent_Declare( - "${BemanExemplar_name}" - GIT_REPOSITORY "${BemanExemplar_repo}" - GIT_TAG "${BemanExemplar_tag}" + "${Beman_name}" + GIT_REPOSITORY "${Beman_repo}" + GIT_TAG "${Beman_tag}" EXCLUDE_FROM_ALL ) - set(INSTALL_GTEST OFF) # Disable GoogleTest installation - FetchContent_MakeAvailable("${BemanExemplar_name}") + + # Apply per-dependency cmake_args from the lockfile + string( + JSON Beman_cmakeArgs + ERROR_VARIABLE Beman_cmakeArgsError + GET "${Beman_depObj}" + "cmake_args" + ) + if(NOT Beman_cmakeArgsError) + string(JSON Beman_numCmakeArgs LENGTH "${Beman_cmakeArgs}") + if(Beman_numCmakeArgs GREATER 0) + math(EXPR Beman_maxArgIndex "${Beman_numCmakeArgs} - 1") + foreach(Beman_argIndex RANGE "${Beman_maxArgIndex}") + string( + JSON Beman_argKey + MEMBER "${Beman_cmakeArgs}" + "${Beman_argIndex}" + ) + string( + JSON Beman_argValue + GET "${Beman_cmakeArgs}" + "${Beman_argKey}" + ) + message( + DEBUG + "Setting ${Beman_argKey}=${Beman_argValue} for ${Beman_name}" + ) + set("${Beman_argKey}" "${Beman_argValue}") + endforeach() + endif() + endif() + + FetchContent_MakeAvailable("${Beman_name}") # Catch2's CTest integration module isn't on CMAKE_MODULE_PATH # when brought in via FetchContent. Add it so that # `include(Catch)` works. - if(BemanExemplar_pkgName STREQUAL "Catch2") + if(Beman_pkgName STREQUAL "Catch2") list( - APPEND - CMAKE_MODULE_PATH - "${${BemanExemplar_name}_SOURCE_DIR}/extras" + APPEND CMAKE_MODULE_PATH + "${${Beman_name}_SOURCE_DIR}/extras" ) set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE) endif() # Important! _FOUND tells CMake that `find_package` is # not needed for this package anymore - set("${BemanExemplar_pkgName}_FOUND" TRUE PARENT_SCOPE) + set("${Beman_pkgName}_FOUND" TRUE PARENT_SCOPE) endif() endif() endforeach() endfunction() +set(BEMAN_USE_FETCH_CONTENT_ENABLED ON) + cmake_language( - SET_DEPENDENCY_PROVIDER BemanExemplar_provideDependency + SET_DEPENDENCY_PROVIDER Beman_provideDependency SUPPORTED_METHODS FIND_PACKAGE ) diff --git a/lockfile.json b/lockfile.json new file mode 100644 index 0000000..787b905 --- /dev/null +++ b/lockfile.json @@ -0,0 +1,13 @@ +{ + "dependencies": [ + { + "name": "googletest", + "package_name": "GTest", + "git_repository": "https://github.com/google/googletest.git", + "git_tag": "6910c9d9165801d8827d628cb72eb7ea9dd538c5", + "cmake_args": { + "INSTALL_GTEST": "OFF" + } + } + ] +} diff --git a/port/portfile.cmake.in b/port/portfile.cmake.in new file mode 100644 index 0000000..1b9c649 --- /dev/null +++ b/port/portfile.cmake.in @@ -0,0 +1,28 @@ +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO bemanproject/span + REF "v@VERSION@" + SHA512 @SHA512@ + HEAD_REF main +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -DBEMAN_SPAN_BUILD_TESTS=OFF + -DBEMAN_SPAN_BUILD_EXAMPLES=OFF +) + +vcpkg_cmake_install() + +vcpkg_cmake_config_fixup( + PACKAGE_NAME beman.span + CONFIG_PATH lib/cmake/beman.span +) + +file(REMOVE_RECURSE + "${CURRENT_PACKAGES_DIR}/debug" + "${CURRENT_PACKAGES_DIR}/lib" +) + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") diff --git a/port/vcpkg.json.in b/port/vcpkg.json.in new file mode 100644 index 0000000..8ea66bd --- /dev/null +++ b/port/vcpkg.json.in @@ -0,0 +1,17 @@ +{ + "name": "beman-span", + "version-semver": "@VERSION@", + "description": "A Beman implementation of std::span", + "homepage": "https://github.com/bemanproject/span", + "license": "Apache-2.0 WITH LLVM-exception", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} diff --git a/tests/beman/span/CMakeLists.txt b/tests/beman/span/CMakeLists.txt index 7f4db42..abeaaac 100644 --- a/tests/beman/span/CMakeLists.txt +++ b/tests/beman/span/CMakeLists.txt @@ -10,4 +10,4 @@ target_link_libraries( ) include(GoogleTest) -gtest_discover_tests(beman.span.tests.span) +gtest_discover_tests(beman.span.tests.span DISCOVERY_TIMEOUT 60) diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 0000000..25169b2 --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,15 @@ +{ + "default-registry": { + "kind": "git", + "repository": "https://github.com/microsoft/vcpkg.git", + "baseline": "80f9bcfa455e875d9c1bf7a7c6692d7e1e481061" + }, + "registries": [ + { + "kind": "git", + "repository": "https://github.com/bemanproject/vcpkg-registry.git", + "baseline": "5195f94f2b550163917c1152180fc59bbd760556", + "packages": ["beman-*"] + } + ] +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..853fb70 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,10 @@ +{ + "name": "beman-span", + "version-semver": "0.1.0", + "dependencies": [ + { + "name": "gtest", + "host": true + } + ] +}