diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-01 04:30:34 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-01 04:30:34 +0800 |
| commit | 81cf8b68eca2636574f3d0a9fa1cf0b428c163e9 (patch) | |
| tree | f3a83496e71358123cc5f838269dc134d02b63f6 | |
| parent | 72af0dedf9e18911da65b9a5c4906689e868d9fc (diff) | |
| download | rcc-project-81cf8b68eca2636574f3d0a9fa1cf0b428c163e9.tar.gz rcc-project-81cf8b68eca2636574f3d0a9fa1cf0b428c163e9.tar.xz | |
[Backend] Establish standalone build infrastructure
Add the thin monorepo CMake entry point and an independently configurable backend project. Enforce the Clang/C++23 toolchain, expose Make/Ninja-neutral tests and developer checks, export an installable RCCBackend package, and introduce the first Support error abstraction.
| -rw-r--r-- | .clang-format | 20 | ||||
| -rw-r--r-- | .clang-format-ignore | 9 | ||||
| -rw-r--r-- | .clang-tidy | 39 | ||||
| -rw-r--r-- | CMakeLists.txt | 34 | ||||
| -rw-r--r-- | README.md | 46 | ||||
| -rw-r--r-- | backend/.clang-format | 20 | ||||
| -rw-r--r-- | backend/.clang-tidy | 49 | ||||
| -rw-r--r-- | backend/CMakeLists.txt | 85 | ||||
| -rw-r--r-- | backend/cmake/RCCBackendConfig.cmake.in | 7 | ||||
| -rw-r--r-- | backend/cmake/modules/RCCBackendBuild.cmake | 93 | ||||
| -rw-r--r-- | backend/cmake/modules/RCCBackendDeveloperTools.cmake | 50 | ||||
| -rw-r--r-- | backend/include/rcc/Support/Error.h | 49 | ||||
| -rw-r--r-- | backend/lib/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | backend/lib/Support/CMakeLists.txt | 40 | ||||
| -rw-r--r-- | backend/lib/Support/Error.cpp | 28 | ||||
| -rw-r--r-- | backend/unittests/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | backend/unittests/Support/CMakeLists.txt | 16 | ||||
| -rw-r--r-- | backend/unittests/Support/ErrorTest.cpp | 33 | ||||
| -rw-r--r-- | cmake/modules/RCCPreventInSourceBuild.cmake | 8 | ||||
| -rw-r--r-- | cmake/modules/RCCProjects.cmake | 40 |
20 files changed, 650 insertions, 22 deletions
diff --git a/.clang-format b/.clang-format index 5d323cc..fc4f3fc 100644 --- a/.clang-format +++ b/.clang-format @@ -1,2 +1,20 @@ -BasedOnStyle: Google +BasedOnStyle: LLVM +Language: Cpp +Standard: Latest +ColumnLimit: 100 +IndentWidth: 2 +ContinuationIndentWidth: 4 +UseTab: Never +BreakBeforeBraces: Attach +PointerAlignment: Right +ReferenceAlignment: Pointer +DerivePointerAlignment: false +NamespaceIndentation: None +FixNamespaceComments: true +SortIncludes: CaseSensitive +IncludeBlocks: Regroup +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false LineEnding: LF diff --git a/.clang-format-ignore b/.clang-format-ignore index d495386..3d19633 100644 --- a/.clang-format-ignore +++ b/.clang-format-ignore @@ -1,4 +1,11 @@ # Do not attempt to format .td files; we have too many formatting needs across # the various files to allow automatic formatting. **/*.td -rcc-legacy/
\ No newline at end of file + +# MIR and structured test inputs are compatibility fixtures, not C++ sources. +**/*.mir +**/test/Inputs/** + +# Generated files are formatted by their generator, if applicable. +**/generated/** +rcc-legacy/ diff --git a/.clang-tidy b/.clang-tidy index 856ac61..dcad2ae 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,16 +1,29 @@ HeaderFilterRegex: '' +WarningsAsErrors: '' +FormatStyle: file Checks: > -*, clang-diagnostic-*, - llvm-*, - misc-*, - -misc-const-correctness, - -misc-include-cleaner, - -misc-no-recursion, - -misc-non-private-member-variables-in-classes, - -misc-unused-parameters, - -misc-use-anonymous-namespace, - readability-identifier-naming + bugprone-*, + -bugprone-easily-swappable-parameters, + performance-*, + portability-*, + llvm-header-guard, + llvm-namespace-comment, + llvm-qualified-auto, + misc-definitions-in-headers, + misc-misplaced-const, + misc-new-delete-overloads, + misc-non-copyable-objects, + modernize-use-default-member-init, + modernize-use-equals-default, + modernize-use-equals-delete, + modernize-use-nullptr, + modernize-use-override, + readability-container-size-empty, + readability-identifier-naming, + readability-redundant-*, + readability-simplify-boolean-expr CheckOptions: # Type @@ -26,11 +39,9 @@ CheckOptions: - { key: readability-identifier-naming.FunctionCase, value: camelBack } - { key: readability-identifier-naming.MethodCase, value: camelBack } # Variable - - { key: readability-identifier-naming.VariableCase, value: lower_case } - - { key: readability-identifier-naming.ParameterCase, value: lower_case } - - { key: readability-identifier-naming.MemberCase, value: lower_case } - - { key: readability-identifier-naming.PrivateMemberSuffix, value: _ } - - { key: readability-identifier-naming.ProtectedMemberSuffix, value: _ } + - { key: readability-identifier-naming.VariableCase, value: CamelCase } + - { key: readability-identifier-naming.ParameterCase, value: CamelCase } + - { key: readability-identifier-naming.MemberCase, value: CamelCase } # Constant - { key: readability-identifier-naming.GlobalConstantCase, value: CamelCase } - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..597963a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +cmake_minimum_required(VERSION 3.25) + +project( + RCC + VERSION 0.1.0 + DESCRIPTION "RCC compiler collection" + LANGUAGES CXX +) + +list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + +include(RCCPreventInSourceBuild) +include(RCCProjects) +include(CTest) + +rcc_add_enabled_projects("${CMAKE_CURRENT_SOURCE_DIR}") + +if(TARGET rcc-backend-format) + add_custom_target(format DEPENDS rcc-backend-format) +endif() + +if(TARGET rcc-backend-format-check) + add_custom_target(format-check DEPENDS rcc-backend-format-check) +endif() + +if(TARGET rcc-backend-tidy) + add_custom_target(tidy DEPENDS rcc-backend-tidy) +endif() + +if(TARGET rcc-backend-analyze) + add_custom_target(analyze DEPENDS rcc-backend-analyze) +endif() @@ -1,12 +1,46 @@ # RCC Project -Welcome to the RCC Project! +RCC is a compiler collection under active development. The current implementation +focuses on a standalone machine-code backend. -The RCC Project is free software. See the file LICENSE -for copying permission. +## Repository layout -This project aims to build a highly optimized compiler collection. -Obviously, its name comes from GNU Compiler Collection (GCC). +```text +backend/ Standalone backend project +cmake/ Monorepo orchestration support +docs/ Architecture and implementation records +``` -The development of RCC is ongoing. Your contribution is welcome. +Future frontend, middle-end, and driver projects will be sibling components. +## Build the enabled projects + +RCC requires Clang and C++23. Both Ninja and Unix Makefiles are supported. + +```bash +cmake -S . -B build -G Ninja \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DRCC_ENABLE_PROJECTS=backend +cmake --build build +ctest --test-dir build --output-on-failure +``` + +## Build the backend independently + +```bash +cmake -S backend -B build-backend -G Ninja \ + -DCMAKE_CXX_COMPILER=clang++ +cmake --build build-backend +ctest --test-dir build-backend --output-on-failure +``` + +Replace `Ninja` with `Unix Makefiles` to build with Make. + +Developer checks are exposed as `rcc-backend-format-check`, +`rcc-backend-tidy`, and `rcc-backend-analyze` in a standalone backend build. +The monorepo exposes the aggregate `format-check`, `tidy`, and `analyze` +targets. + +## License + +RCC is free software distributed under GPL-3.0-or-later. See `LICENSE`. diff --git a/backend/.clang-format b/backend/.clang-format new file mode 100644 index 0000000..fc4f3fc --- /dev/null +++ b/backend/.clang-format @@ -0,0 +1,20 @@ +BasedOnStyle: LLVM +Language: Cpp +Standard: Latest +ColumnLimit: 100 +IndentWidth: 2 +ContinuationIndentWidth: 4 +UseTab: Never +BreakBeforeBraces: Attach +PointerAlignment: Right +ReferenceAlignment: Pointer +DerivePointerAlignment: false +NamespaceIndentation: None +FixNamespaceComments: true +SortIncludes: CaseSensitive +IncludeBlocks: Regroup +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +LineEnding: LF diff --git a/backend/.clang-tidy b/backend/.clang-tidy new file mode 100644 index 0000000..a0e18ce --- /dev/null +++ b/backend/.clang-tidy @@ -0,0 +1,49 @@ +HeaderFilterRegex: '(^|/)(include|lib|tools|utils|unittests)/' +WarningsAsErrors: '' +FormatStyle: file +Checks: > + -*, + clang-diagnostic-*, + bugprone-*, + -bugprone-easily-swappable-parameters, + performance-*, + portability-*, + llvm-header-guard, + llvm-namespace-comment, + llvm-qualified-auto, + misc-definitions-in-headers, + misc-misplaced-const, + misc-new-delete-overloads, + misc-non-copyable-objects, + modernize-use-default-member-init, + modernize-use-equals-default, + modernize-use-equals-delete, + modernize-use-nullptr, + modernize-use-override, + readability-container-size-empty, + readability-identifier-naming, + readability-redundant-*, + readability-simplify-boolean-expr + +CheckOptions: + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } + - { key: readability-identifier-naming.ClassCase, value: CamelCase } + - { key: readability-identifier-naming.StructCase, value: CamelCase } + - { key: readability-identifier-naming.UnionCase, value: CamelCase } + - { key: readability-identifier-naming.EnumCase, value: CamelCase } + - { key: readability-identifier-naming.TypeAliasCase, value: CamelCase } + - { key: readability-identifier-naming.TypedefCase, value: CamelCase } + - { key: readability-identifier-naming.TypeTemplateParameterCase, value: CamelCase } + - { key: readability-identifier-naming.FunctionCase, value: camelBack } + - { key: readability-identifier-naming.MethodCase, value: camelBack } + - { key: readability-identifier-naming.VariableCase, value: CamelCase } + - { key: readability-identifier-naming.ParameterCase, value: CamelCase } + - { key: readability-identifier-naming.MemberCase, value: CamelCase } + - { key: readability-identifier-naming.GlobalConstantCase, value: CamelCase } + - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } + - { key: readability-identifier-naming.ClassConstantCase, value: CamelCase } + - { key: readability-identifier-naming.EnumConstantCase, value: CamelCase } + - { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE } + - { key: readability-identifier-naming.IgnoreMainLikeFunctions, value: 1 } + - { key: readability-redundant-member-init.IgnoreBaseInCopyConstructors, value: 1 } + - { key: modernize-use-default-member-init.UseAssignment, value: 1 } diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt new file mode 100644 index 0000000..2d5cc82 --- /dev/null +++ b/backend/CMakeLists.txt @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +cmake_minimum_required(VERSION 3.25) + +set(RCC_BACKEND_VERSION 0.1.0) +set(RCC_BACKEND_IS_STANDALONE OFF) +set(RCC_BACKEND_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +set(RCC_BACKEND_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + project( + RCCBackend + VERSION ${RCC_BACKEND_VERSION} + DESCRIPTION "Independent RCC machine-code backend" + LANGUAGES CXX + ) + set(RCC_BACKEND_IS_STANDALONE ON) + include(CTest) +endif() + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") + message( + FATAL_ERROR + "RCC Backend must be compiled with Clang; found '${CMAKE_CXX_COMPILER_ID}'" + ) +endif() + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message( + FATAL_ERROR + "RCC Backend does not support in-source builds. Configure a separate build directory." + ) +endif() + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) +include(RCCBackendBuild) +include(RCCBackendDeveloperTools) + +option(RCC_BACKEND_BUILD_TESTS "Build RCC Backend tests" "${BUILD_TESTING}") +option(RCC_BACKEND_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF) +option(RCC_BACKEND_ENABLE_CLANG_TIDY "Run clang-tidy during each compilation" OFF) + +rcc_backend_initialize_toolchain() + +add_subdirectory(lib) + +if(RCC_BACKEND_BUILD_TESTS) + enable_testing() + add_subdirectory(unittests) +endif() + +rcc_backend_add_developer_targets() + +install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + +configure_package_config_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/RCCBackendConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/RCCBackendConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/RCCBackend" +) + +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/RCCBackendConfigVersion.cmake" + VERSION "${RCC_BACKEND_VERSION}" + COMPATIBILITY SameMajorVersion +) + +install( + EXPORT RCCBackendTargets + FILE RCCBackendTargets.cmake + NAMESPACE RCCBackend:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/RCCBackend" +) + +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/RCCBackendConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/RCCBackendConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/RCCBackend" +) diff --git a/backend/cmake/RCCBackendConfig.cmake.in b/backend/cmake/RCCBackendConfig.cmake.in new file mode 100644 index 0000000..910572b --- /dev/null +++ b/backend/cmake/RCCBackendConfig.cmake.in @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/RCCBackendTargets.cmake") + +check_required_components(RCCBackend) diff --git a/backend/cmake/modules/RCCBackendBuild.cmake b/backend/cmake/modules/RCCBackendBuild.cmake new file mode 100644 index 0000000..79e7bb1 --- /dev/null +++ b/backend/cmake/modules/RCCBackendBuild.cmake @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +function(rcc_backend_initialize_toolchain) + string(REGEX MATCH "^[0-9]+" RCCBackendClangMajor "${CMAKE_CXX_COMPILER_VERSION}") + + find_program( + RCC_BACKEND_CLANG_FORMAT + NAMES "clang-format-${RCCBackendClangMajor}" clang-format + REQUIRED + ) + find_program( + RCC_BACKEND_CLANG_TIDY + NAMES "clang-tidy-${RCCBackendClangMajor}" clang-tidy + REQUIRED + ) + + foreach(Tool IN ITEMS RCC_BACKEND_CLANG_FORMAT RCC_BACKEND_CLANG_TIDY) + execute_process( + COMMAND "${${Tool}}" --version + OUTPUT_VARIABLE ToolVersionOutput + ERROR_VARIABLE ToolVersionError + RESULT_VARIABLE ToolVersionResult + ) + if(NOT ToolVersionResult EQUAL 0) + message( + FATAL_ERROR + "Unable to query ${Tool}: ${ToolVersionOutput}${ToolVersionError}" + ) + endif() + + string(REGEX MATCH "version[ \t]+([0-9]+)" ToolVersionMatch "${ToolVersionOutput}") + if(NOT CMAKE_MATCH_1 STREQUAL RCCBackendClangMajor) + message( + FATAL_ERROR + "${Tool} must have Clang major version ${RCCBackendClangMajor}: " + "${ToolVersionOutput}" + ) + endif() + endforeach() + + set(RCC_BACKEND_CLANG_FORMAT "${RCC_BACKEND_CLANG_FORMAT}" PARENT_SCOPE) + set(RCC_BACKEND_CLANG_TIDY "${RCC_BACKEND_CLANG_TIDY}" PARENT_SCOPE) +endfunction() + +function(rcc_backend_configure_target Target) + target_compile_features("${Target}" PUBLIC cxx_std_23) + set_target_properties( + "${Target}" + PROPERTIES + CXX_EXTENSIONS OFF + CXX_STANDARD 23 + CXX_STANDARD_REQUIRED ON + ) + + target_compile_options( + "${Target}" + PRIVATE + -Wall + -Wextra + -Wpedantic + -Wconversion + -Wsign-conversion + -Wshadow + -Wnon-virtual-dtor + -Wold-style-cast + -Wcast-align + -Woverloaded-virtual + -Wnull-dereference + -Wdouble-promotion + -Wformat=2 + ) + + if(RCC_BACKEND_WARNINGS_AS_ERRORS) + target_compile_options("${Target}" PRIVATE -Werror) + endif() + + if(RCC_BACKEND_ENABLE_CLANG_TIDY) + set_target_properties( + "${Target}" + PROPERTIES + CXX_CLANG_TIDY + "${RCC_BACKEND_CLANG_TIDY};--warnings-as-errors=*" + ) + endif() +endfunction() + +function(rcc_backend_register_format_files) + set_property(GLOBAL APPEND PROPERTY RCC_BACKEND_FORMAT_FILES ${ARGN}) +endfunction() + +function(rcc_backend_register_tidy_files) + set_property(GLOBAL APPEND PROPERTY RCC_BACKEND_TIDY_FILES ${ARGN}) +endfunction() diff --git a/backend/cmake/modules/RCCBackendDeveloperTools.cmake b/backend/cmake/modules/RCCBackendDeveloperTools.cmake new file mode 100644 index 0000000..d3693cd --- /dev/null +++ b/backend/cmake/modules/RCCBackendDeveloperTools.cmake @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +function(rcc_backend_add_developer_targets) + get_property(FormatFiles GLOBAL PROPERTY RCC_BACKEND_FORMAT_FILES) + get_property(TidyFiles GLOBAL PROPERTY RCC_BACKEND_TIDY_FILES) + + if(FormatFiles) + list(REMOVE_DUPLICATES FormatFiles) + + add_custom_target( + rcc-backend-format + COMMAND "${RCC_BACKEND_CLANG_FORMAT}" -i ${FormatFiles} + COMMAND_EXPAND_LISTS + COMMENT "Formatting RCC Backend C++ sources" + VERBATIM + ) + + add_custom_target( + rcc-backend-format-check + COMMAND "${RCC_BACKEND_CLANG_FORMAT}" --dry-run --Werror ${FormatFiles} + COMMAND_EXPAND_LISTS + COMMENT "Checking RCC Backend C++ formatting" + VERBATIM + ) + endif() + + if(TidyFiles) + list(REMOVE_DUPLICATES TidyFiles) + + add_custom_target( + rcc-backend-tidy + COMMAND + "${RCC_BACKEND_CLANG_TIDY}" --warnings-as-errors=* + "-p=${CMAKE_BINARY_DIR}" ${TidyFiles} + COMMAND_EXPAND_LISTS + COMMENT "Running clang-tidy on RCC Backend" + VERBATIM + ) + + add_custom_target( + rcc-backend-analyze + COMMAND + "${RCC_BACKEND_CLANG_TIDY}" "--checks=-*,clang-analyzer-*" + --warnings-as-errors=* "-p=${CMAKE_BINARY_DIR}" ${TidyFiles} + COMMAND_EXPAND_LISTS + COMMENT "Running Clang Static Analyzer checks on RCC Backend" + VERBATIM + ) + endif() +endfunction() diff --git a/backend/include/rcc/Support/Error.h b/backend/include/rcc/Support/Error.h new file mode 100644 index 0000000..3d50b46 --- /dev/null +++ b/backend/include/rcc/Support/Error.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_SUPPORT_ERROR_H +#define RCC_SUPPORT_ERROR_H + +#include <cstdint> +#include <expected> +#include <string> +#include <string_view> +#include <utility> + +namespace rcc { + +enum class ErrorCode : std::uint8_t { + InvalidArgument, + ParseError, + VerificationError, + Unsupported, + IoError, + InternalError, +}; + +[[nodiscard]] std::string_view getErrorCodeName(ErrorCode Code) noexcept; + +class Error final { +public: + Error(ErrorCode Code, std::string Message); + + [[nodiscard]] ErrorCode code() const noexcept { + return Code; + } + [[nodiscard]] std::string_view message() const noexcept { + return Message; + } + +private: + ErrorCode Code; + std::string Message; +}; + +template <typename ValueT> using Expected = std::expected<ValueT, Error>; + +[[nodiscard]] inline std::unexpected<Error> makeUnexpected(ErrorCode Code, std::string Message) { + return std::unexpected<Error>(Error(Code, std::move(Message))); +} + +} // namespace rcc + +#endif // RCC_SUPPORT_ERROR_H diff --git a/backend/lib/CMakeLists.txt b/backend/lib/CMakeLists.txt new file mode 100644 index 0000000..13f7c7b --- /dev/null +++ b/backend/lib/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +add_subdirectory(Support) diff --git a/backend/lib/Support/CMakeLists.txt b/backend/lib/Support/CMakeLists.txt new file mode 100644 index 0000000..88c959d --- /dev/null +++ b/backend/lib/Support/CMakeLists.txt @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +set(RCCBackendSupportSources Error.cpp) +set( + RCCBackendSupportHeaders + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Support/Error.h" +) + +add_library(RCCBackendSupport ${RCCBackendSupportSources}) +add_library(RCCBackend::Support ALIAS RCCBackendSupport) + +rcc_backend_configure_target(RCCBackendSupport) + +target_include_directories( + RCCBackendSupport + PUBLIC + "$<BUILD_INTERFACE:${RCC_BACKEND_SOURCE_DIR}/include>" + "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" +) + +set_target_properties( + RCCBackendSupport + PROPERTIES + EXPORT_NAME Support + OUTPUT_NAME RCCBackendSupport +) + +install( + TARGETS RCCBackendSupport + EXPORT RCCBackendTargets + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) + +rcc_backend_register_format_files( + "${CMAKE_CURRENT_SOURCE_DIR}/Error.cpp" + ${RCCBackendSupportHeaders} +) +rcc_backend_register_tidy_files("${CMAKE_CURRENT_SOURCE_DIR}/Error.cpp") diff --git a/backend/lib/Support/Error.cpp b/backend/lib/Support/Error.cpp new file mode 100644 index 0000000..dc7d590 --- /dev/null +++ b/backend/lib/Support/Error.cpp @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/Support/Error.h" + +namespace rcc { + +std::string_view getErrorCodeName(ErrorCode Code) noexcept { + switch (Code) { + case ErrorCode::InvalidArgument: + return "invalid argument"; + case ErrorCode::ParseError: + return "parse error"; + case ErrorCode::VerificationError: + return "verification error"; + case ErrorCode::Unsupported: + return "unsupported"; + case ErrorCode::IoError: + return "I/O error"; + case ErrorCode::InternalError: + return "internal error"; + } + + return "unknown error"; +} + +Error::Error(ErrorCode Code, std::string Message) : Code(Code), Message(std::move(Message)) {} + +} // namespace rcc diff --git a/backend/unittests/CMakeLists.txt b/backend/unittests/CMakeLists.txt new file mode 100644 index 0000000..13f7c7b --- /dev/null +++ b/backend/unittests/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +add_subdirectory(Support) diff --git a/backend/unittests/Support/CMakeLists.txt b/backend/unittests/Support/CMakeLists.txt new file mode 100644 index 0000000..0c0aabc --- /dev/null +++ b/backend/unittests/Support/CMakeLists.txt @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +set(RCCBackendSupportTestSources ErrorTest.cpp) + +add_executable(RCCBackendSupportTests ${RCCBackendSupportTestSources}) +rcc_backend_configure_target(RCCBackendSupportTests) +target_link_libraries(RCCBackendSupportTests PRIVATE RCCBackend::Support) + +add_test(NAME RCCBackend.Support.Error COMMAND RCCBackendSupportTests) + +rcc_backend_register_format_files( + "${CMAKE_CURRENT_SOURCE_DIR}/ErrorTest.cpp" +) +rcc_backend_register_tidy_files( + "${CMAKE_CURRENT_SOURCE_DIR}/ErrorTest.cpp" +) diff --git a/backend/unittests/Support/ErrorTest.cpp b/backend/unittests/Support/ErrorTest.cpp new file mode 100644 index 0000000..23140e3 --- /dev/null +++ b/backend/unittests/Support/ErrorTest.cpp @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/Support/Error.h" + +#include <iostream> +#include <string> + +namespace { + +int fail(const char *Message) { + std::cerr << Message << '\n'; + return 1; +} + +} // namespace + +int main() { + rcc::Expected<int> Value = 42; + if (!Value || *Value != 42) + return fail("Expected must preserve a successful value"); + + rcc::Expected<int> Failure = rcc::makeUnexpected(rcc::ErrorCode::ParseError, "bad MIR"); + if (Failure) + return fail("Expected must preserve an error"); + if (Failure.error().code() != rcc::ErrorCode::ParseError) + return fail("Error must preserve its code"); + if (Failure.error().message() != "bad MIR") + return fail("Error must preserve its message"); + if (rcc::getErrorCodeName(Failure.error().code()) != "parse error") + return fail("Error code must have a stable name"); + + return 0; +} diff --git a/cmake/modules/RCCPreventInSourceBuild.cmake b/cmake/modules/RCCPreventInSourceBuild.cmake new file mode 100644 index 0000000..97b3392 --- /dev/null +++ b/cmake/modules/RCCPreventInSourceBuild.cmake @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message( + FATAL_ERROR + "RCC does not support in-source builds. Configure a separate build directory." + ) +endif() diff --git a/cmake/modules/RCCProjects.cmake b/cmake/modules/RCCProjects.cmake new file mode 100644 index 0000000..59c4fc5 --- /dev/null +++ b/cmake/modules/RCCProjects.cmake @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +set(RCC_KNOWN_PROJECTS backend) +set(RCC_DEFAULT_PROJECTS backend) + +set( + RCC_ENABLE_PROJECTS + "${RCC_DEFAULT_PROJECTS}" + CACHE STRING + "Semicolon-separated RCC projects to build, or 'all'" +) + +function(rcc_add_enabled_projects RCCSourceRoot) + if(RCC_ENABLE_PROJECTS STREQUAL "all") + set(EnabledProjects ${RCC_KNOWN_PROJECTS}) + else() + set(EnabledProjects ${RCC_ENABLE_PROJECTS}) + endif() + + if(NOT EnabledProjects) + message(FATAL_ERROR "RCC_ENABLE_PROJECTS must name at least one project") + endif() + + list(REMOVE_DUPLICATES EnabledProjects) + + foreach(Project IN LISTS EnabledProjects) + if(NOT Project IN_LIST RCC_KNOWN_PROJECTS) + message( + FATAL_ERROR + "Unknown RCC project '${Project}'. Known projects: ${RCC_KNOWN_PROJECTS}" + ) + endif() + endforeach() + + # Component order is controlled here rather than by the user-provided list. + # Future inter-project dependency closure will also be resolved here. + if("backend" IN_LIST EnabledProjects) + add_subdirectory("${RCCSourceRoot}/backend" "${CMAKE_BINARY_DIR}/backend") + endif() +endfunction() |
