diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 12e2e5fe66..cfcf6791c0 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -30,7 +30,6 @@ jobs: name: clang-format runs-on: ubuntu-latest steps: - - run: sudo rm /usr/bin/clang-format - name: Checkout uses: actions/checkout@v4 with: @@ -49,20 +48,12 @@ jobs: - name: Install LLVM run: | curl -fsSL https://apt.llvm.org/llvm.sh | sudo bash -s -- ${{ env.LLVM_VERSION_MAJOR }} all - - run: ls -l /usr/lib/llvm-${LLVM_VERSION_MAJOR}/bin/ - - run: echo "/usr/lib/llvm-${LLVM_VERSION_MAJOR}/bin/" >> $GITHUB_PATH - - name: Clang Format Version - env: - ENABLE_CCACHE: OFF - LLVM_VERSION: ${{ env.LLVM_VERSION }} - run: | - bun run clang-format:version - name: Clang Format env: ENABLE_CCACHE: OFF LLVM_VERSION: ${{ env.LLVM_VERSION }} run: | - bun run clang-format + bun run clang-format:diff - name: Commit uses: stefanzweifel/git-auto-commit-action@v5 with: diff --git a/CMakeLists.txt b/CMakeLists.txt index c3daa3702a..37dc684b91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,10 +43,11 @@ include(BuildBun) # --- Analysis --- -include(RunClangFormat) -include(RunClangTidy) -include(RunZigFormat) +optionx(ENABLE_ANALYSIS BOOL "If analysis targets should be enabled" DEFAULT OFF) -if (ENABLE_PRETTIER) +if(ENABLE_ANALYSIS) + include(RunClangFormat) + include(RunClangTidy) + include(RunZigFormat) include(RunPrettier) endif() diff --git a/bench/snippets/color.mjs b/bench/snippets/color.mjs index 7d13177b2b..14b12356b9 100644 --- a/bench/snippets/color.mjs +++ b/bench/snippets/color.mjs @@ -1,6 +1,6 @@ import Color from "color"; import tinycolor from "tinycolor2"; -import { bench, run, group } from "./runner.mjs"; +import { bench, group, run } from "./runner.mjs"; const inputs = ["#f00", "rgb(255, 0, 0)", "rgba(255, 0, 0, 1)", "hsl(0, 100%, 50%)"]; diff --git a/cmake/Globals.cmake b/cmake/Globals.cmake index 303e49802a..978800a941 100644 --- a/cmake/Globals.cmake +++ b/cmake/Globals.cmake @@ -30,6 +30,10 @@ macro(optionx variable type description) set(multiValueArgs) cmake_parse_arguments(${variable} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(DEFINED ${variable}) + set(${variable}_VALUE ${${variable}}) + endif() + if(NOT ${type} MATCHES "^(BOOL|STRING|FILEPATH|PATH|INTERNAL)$") set(${variable}_REGEX ${type}) set(${variable}_TYPE STRING) @@ -65,7 +69,9 @@ macro(optionx variable type description) message(FATAL_ERROR "Invalid ${${variable}_SOURCE}: ${${variable}_PREVIEW}=\"${${variable}}\", please use ${${variable}_PREVIEW}=<${${variable}_REGEX}>") endif() - message(STATUS "Set ${variable}: ${${variable}}") + if(NOT ${variable}_VALUE STREQUAL ${variable}) + message(STATUS "Set ${variable}: ${${variable}}") + endif() endmacro() # unsupported() @@ -194,102 +200,153 @@ function(setenv variable value) message(STATUS "Set ENV ${variable}: ${value}") endfunction() -# check_command() +# satisfies_range() # Description: -# Checks if a command is available, used by `find_command()` as a validator. +# Check if a version satisfies a version range # Arguments: -# FOUND bool - The variable to set to true if the version is found -# CMD string - The executable to check the version of -function(check_command FOUND CMD) - set(${FOUND} OFF PARENT_SCOPE) - - if(${CMD} MATCHES "zig") - set(CHECK_COMMAND ${CMD} version) - else() - set(CHECK_COMMAND ${CMD} --version) - endif() - - execute_process( - COMMAND ${CHECK_COMMAND} - RESULT_VARIABLE RESULT - OUTPUT_VARIABLE OUTPUT - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - if(NOT RESULT EQUAL 0 OR NOT OUTPUT) - message(DEBUG "${CHECK_COMMAND}, exited with code ${RESULT}") +# version string - The version to check (e.g. "1.2.3") +# range string - The range to check against (e.g. ">=1.2.3") +# variable string - The variable to store the result in +function(satisfies_range version range variable) + if(range STREQUAL "ignore") + set(${variable} ON PARENT_SCOPE) return() endif() - parse_semver(${OUTPUT} CMD) - parse_semver(${CHECK_COMMAND_VERSION} CHECK) + set(${variable} OFF PARENT_SCOPE) - if(CHECK_COMMAND_VERSION MATCHES ">=") - if(NOT CMD_VERSION VERSION_GREATER_EQUAL ${CHECK_VERSION}) - message(DEBUG "${CHECK_COMMAND}, actual: ${CMD_VERSION}, expected: ${CHECK_COMMAND_VERSION}") - return() - endif() - elseif(CHECK_COMMAND_VERSION MATCHES ">") - if(NOT CMD_VERSION VERSION_GREATER ${CHECK_VERSION}) - message(DEBUG "${CHECK_COMMAND}, actual: ${CMD_VERSION}, expected: ${CHECK_COMMAND_VERSION}") - return() - endif() + string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" match "${version}") + if(NOT match) + return() + endif() + set(version ${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}) + + string(REGEX MATCH "(>=|<=|>|<)?([0-9]+)\\.([0-9]+)\\.([0-9]+)" match "${range}") + if(NOT match) + return() + endif() + set(comparator ${CMAKE_MATCH_1}) + set(range ${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${CMAKE_MATCH_4}) + + if(comparator STREQUAL ">=") + set(comparator VERSION_GREATER_EQUAL) + elseif(comparator STREQUAL ">") + set(comparator VERSION_GREATER) + elseif(comparator STREQUAL "<=") + set(comparator VERSION_LESS_EQUAL) + elseif(comparator STREQUAL "<") + set(comparator VERSION_LESS) else() - if(NOT CMD_VERSION VERSION_EQUAL ${CHECK_VERSION}) - message(DEBUG "${CHECK_COMMAND}, actual: ${CMD_VERSION}, expected: =${CHECK_COMMAND_VERSION}") - return() - endif() + set(comparator VERSION_EQUAL) endif() - set(${FOUND} TRUE PARENT_SCOPE) + if(version ${comparator} ${range}) + set(${variable} ON PARENT_SCOPE) + endif() endfunction() # find_command() # Description: # Finds a command, similar to `find_program()`, but allows for version checking. # Arguments: -# VARIABLE string - The variable to set -# COMMAND string[] - The names of the command to find -# PATHS string[] - The paths to search for the command -# REQUIRED bool - If false, the command is optional -# VERSION string - The version of the command to find (e.g. "1.2.3" or ">1.2.3") +# VARIABLE string - The variable to set +# VERSION_VARIABLE string - The variable to check for the version +# COMMAND string[] - The names of the command to find +# PATHS string[] - The paths to search for the command +# REQUIRED bool - If false, the command is optional +# VERSION string - The version of the command to find (e.g. "1.2.3" or ">1.2.3") function(find_command) - set(options) - set(args VARIABLE VERSION MIN_VERSION REQUIRED) + set(args VARIABLE VERSION_VARIABLE REQUIRED VERSION) set(multiArgs COMMAND PATHS) - cmake_parse_arguments(CMD "${options}" "${args}" "${multiArgs}" ${ARGN}) + cmake_parse_arguments(FIND "" "${args}" "${multiArgs}" ${ARGN}) - if(NOT CMD_VARIABLE) - message(FATAL_ERROR "find_command: VARIABLE is required") + if(NOT FIND_VARIABLE OR NOT FIND_COMMAND) + message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: VARIABLE and COMMAND are required") endif() - if(NOT CMD_COMMAND) - message(FATAL_ERROR "find_command: COMMAND is required") + if(NOT FIND_VERSION_VARIABLE) + set(FIND_VERSION_VARIABLE ${FIND_VARIABLE}_VERSION) endif() - if(CMD_VERSION) - set(CHECK_COMMAND_VERSION ${CMD_VERSION}) # special global variable - set(CMD_VALIDATOR VALIDATOR check_command) + list(GET FIND_COMMAND 0 FIND_NAME) + optionx(${FIND_VERSION_VARIABLE} STRING "The version of ${FIND_NAME} to find" DEFAULT "${FIND_VERSION}") + + if(${FIND_VERSION_VARIABLE}) + function(find_command_version variable exe) + set(${variable} OFF PARENT_SCOPE) + + if(${exe} MATCHES "(go|zig)(\.exe)?$") + set(command ${exe} version) + else() + set(command ${exe} --version) + endif() + + execute_process( + COMMAND ${command} + RESULT_VARIABLE result + OUTPUT_VARIABLE output + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NOT result EQUAL 0) + set(reason "exited with ${result}") + elseif(NOT output) + set(reason "no output") + else() + string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" match "${output}") + if(match) + set(version ${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}) + set(reason "\"${version}\"") + else() + set(reason "no version") + endif() + endif() + + set_property(GLOBAL PROPERTY ${FIND_NAME} "${exe}: ${reason}" APPEND) + + if(version) + satisfies_range(${version} ${${FIND_VERSION_VARIABLE}} ${variable}) + set(${variable} ${${variable}} PARENT_SCOPE) + endif() + endfunction() + + set(FIND_VALIDATOR VALIDATOR find_command_version) endif() find_program( - ${CMD_VARIABLE} - NAMES ${CMD_COMMAND} - PATHS ${CMD_PATHS} - ${CMD_VALIDATOR} + ${FIND_VARIABLE} + NAMES ${FIND_COMMAND} + PATHS ${FIND_PATHS} + ${FIND_VALIDATOR} ) - if(NOT CMD_REQUIRED STREQUAL "OFF" AND ${CMD_VARIABLE} MATCHES "NOTFOUND") - if(CMD_VERSION) - message(FATAL_ERROR "Command not found: \"${CMD_COMMAND}\" that matches version \"${CHECK_COMMAND_VERSION}\"") + if(NOT FIND_REQUIRED STREQUAL "OFF" AND ${FIND_VARIABLE} MATCHES "NOTFOUND") + set(error "Command not found: \"${FIND_NAME}\"") + + if(FIND_VERSION) + set(error "${error} that satisfies version \"${${FIND_VERSION_VARIABLE}}\"") endif() - message(FATAL_ERROR "Command not found: \"${CMD_COMMAND}\"") + + get_property(FIND_RESULTS GLOBAL PROPERTY ${FIND_NAME}) + if(NOT FIND_RESULTS MATCHES "NOTFOUND") + set(error "${error}\nThe following commands did not satisfy the requirement:") + foreach(result ${FIND_RESULTS}) + set(error "${error}\n ${result}") + endforeach() + endif() + + set(error "${error}\nTo fix this, either: + 1. Install ${FIND_NAME} ${${FIND_VERSION_VARIABLE}} + 2. Set -D${FIND_VERSION_VARIABLE}= to require a different version + 3. Set -D${FIND_VERSION_VARIABLE}=ignore to allow any version +") + message(FATAL_ERROR ${error}) endif() - if(${CMD_VARIABLE} MATCHES "NOTFOUND") - unset(${CMD_VARIABLE} PARENT_SCOPE) + if(${FIND_VARIABLE} MATCHES "NOTFOUND") + unset(${FIND_VARIABLE} PARENT_SCOPE) else() - setx(${CMD_VARIABLE} ${${CMD_VARIABLE}} PARENT_SCOPE) + setx(${FIND_VARIABLE} ${${FIND_VARIABLE}} PARENT_SCOPE) endif() endfunction() diff --git a/cmake/analysis/RunClangFormat.cmake b/cmake/analysis/RunClangFormat.cmake index 31e9140205..b89af01b78 100644 --- a/cmake/analysis/RunClangFormat.cmake +++ b/cmake/analysis/RunClangFormat.cmake @@ -3,6 +3,8 @@ find_command( VARIABLE CLANG_FORMAT_PROGRAM + VERSION_VARIABLE + LLVM_VERSION COMMAND clang-format REQUIRED @@ -11,17 +13,6 @@ find_command( set(CLANG_FORMAT_SOURCES ${BUN_C_SOURCES} ${BUN_CXX_SOURCES}) -register_command( - TARGET - clang-format-version - COMMENT - "Print clang-format version" - COMMAND - ${CLANG_FORMAT_PROGRAM} - --version - ALWAYS_RUN -) - register_command( TARGET clang-format-check diff --git a/cmake/analysis/RunClangTidy.cmake b/cmake/analysis/RunClangTidy.cmake index 36f60306b9..6f49aca0b6 100644 --- a/cmake/analysis/RunClangTidy.cmake +++ b/cmake/analysis/RunClangTidy.cmake @@ -3,10 +3,10 @@ find_command( VARIABLE CLANG_TIDY_PROGRAM + VERSION_VARIABLE + LLVM_VERSION COMMAND clang-tidy - VERSION - ${LLVM_VERSION} REQUIRED OFF ) diff --git a/cmake/tools/SetupLLVM.cmake b/cmake/tools/SetupLLVM.cmake index c01aaab822..35fe5162e2 100644 --- a/cmake/tools/SetupLLVM.cmake +++ b/cmake/tools/SetupLLVM.cmake @@ -35,6 +35,7 @@ set(LLVM_PATH ${LLVM_PREFIX}/bin) macro(find_llvm_command VARIABLE COMMAND) find_command( VARIABLE ${VARIABLE} + VERSION_VARIABLE LLVM_VERSION COMMAND ${COMMAND} ${COMMAND}-${LLVM_VERSION_MAJOR} PATHS ${LLVM_PATH} VERSION ${LLVM_VERSION} @@ -45,6 +46,7 @@ endmacro() macro(find_llvm_command_no_version VARIABLE COMMAND) find_command( VARIABLE ${VARIABLE} + VERSION_VARIABLE LLVM_VERSION COMMAND ${COMMAND} ${COMMAND}-${LLVM_VERSION_MAJOR} PATHS ${LLVM_PATH} REQUIRED ON diff --git a/package.json b/package.json index f302e0f074..8dca018f4e 100644 --- a/package.json +++ b/package.json @@ -58,9 +58,8 @@ "zig:check": "bun run zig build check --summary new", "zig:check-all": "bun run zig build check-all --summary new", "zig:check-windows": "bun run zig build check-windows --summary new", - "cmake": "bun ./scripts/build.mjs -DCMAKE_BUILD_TYPE=Debug -B build/debug", + "cmake": "bun ./scripts/build.mjs -DCMAKE_BUILD_TYPE=Debug -DENABLE_ANALYSIS=ON -B build/debug", "clang-format": "bun run cmake --target clang-format", - "clang-format:version": "bun run cmake --target clang-format-version", "clang-format:check": "bun run cmake --target clang-format-check", "clang-format:diff": "bun run cmake --target clang-format-diff", "clang-tidy": "bun run cmake --target clang-tidy", @@ -69,9 +68,9 @@ "zig-format": "bun run cmake --target zig-format", "zig-format:check": "bun run cmake --target zig-format-check", "zig-format:diff": "bun run cmake --target zig-format-diff", - "prettier": "bun run cmake -DENABLE_PRETTIER=ON --target prettier", - "prettier:check": "bun run cmake -DENABLE_PRETTIER=ON --target prettier-check", - "prettier:extra": "bun run cmake -DENABLE_PRETTIER=ON --target prettier-extra", - "prettier:diff": "bun run cmake -DENABLE_PRETTIER=ON --target prettier-diff" + "prettier": "bun run cmake --target prettier", + "prettier:check": "bun run cmake --target prettier-check", + "prettier:extra": "bun run cmake --target prettier-extra", + "prettier:diff": "bun run cmake --target prettier-diff" } }