From 591aeb8b30415c91da2638832edd4174415e8954 Mon Sep 17 00:00:00 2001 From: David Candler Date: Thu, 28 Nov 2024 16:03:12 +0000 Subject: [PATCH 1/3] Use the same patching script and command for all repos To simplify patching, the script used for the LLVM repo can be expanded for use on all repos. This also updates the newlib patch to use the same format as llvm-project and picolibc; using git's patch format means the .patch file is compatible with both git am and git apply, whereas a simple diff only works with git apply. This also adds an option to control the patch method used by the script, since using git am may be preferable to the default git apply. The script already supports the option, so all that is needed to pass down the selection from the CMake cache if present. Running git --check together with --apply --3way does not generatean error return code when the patches are valid but contain conflicts, so this particular combination is now marked as incompatible with the --restore_on_fail option, since this relies on --check generating an error. --- cmake/fetch_llvm.cmake | 11 +++-- cmake/fetch_newlib.cmake | 11 ++++- cmake/fetch_picolibc.cmake | 15 ++++--- cmake/{patch_llvm.py => patch_repo.py} | 45 ++++++++++++------- .../0001-Enable-newlib-build.patch} | 34 +++++++++++++- 5 files changed, 89 insertions(+), 27 deletions(-) rename cmake/{patch_llvm.py => patch_repo.py} (77%) rename patches/{newlib.patch => newlib/0001-Enable-newlib-build.patch} (94%) diff --git a/cmake/fetch_llvm.cmake b/cmake/fetch_llvm.cmake index 574c45a..deb8258 100644 --- a/cmake/fetch_llvm.cmake +++ b/cmake/fetch_llvm.cmake @@ -11,11 +11,16 @@ if(NOT VERSIONS_JSON) endif() read_repo_version(llvmproject llvm-project) -set(llvm_patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_llvm.py) +set(patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_repo.py) +if(GIT_PATCH_METHOD STREQUAL "am") + set(patch_script_args --method am) +elseif(GIT_PATCH_METHOD STREQUAL "apply") + set(patch_script_args --method apply) +endif() set(patch_dir ${CMAKE_CURRENT_LIST_DIR}/../patches) -set(LLVM_PATCH_COMMAND ${Python3_EXECUTABLE} ${llvm_patch_script} ${patch_dir}/llvm-project) +set(LLVM_PATCH_COMMAND ${Python3_EXECUTABLE} ${patch_script} ${patch_script_args} ${patch_dir}/llvm-project) if(APPLY_LLVM_PERFORMANCE_PATCHES) - set(LLVM_PATCH_COMMAND ${LLVM_PATCH_COMMAND} && ${Python3_EXECUTABLE} ${llvm_patch_script} ${patch_dir}/llvm-project-perf) + set(LLVM_PATCH_COMMAND ${LLVM_PATCH_COMMAND} && ${Python3_EXECUTABLE} ${patch_script} ${patch_script_args} ${patch_dir}/llvm-project-perf) endif() FetchContent_Declare(llvmproject diff --git a/cmake/fetch_newlib.cmake b/cmake/fetch_newlib.cmake index 4d7b372..b3b621e 100644 --- a/cmake/fetch_newlib.cmake +++ b/cmake/fetch_newlib.cmake @@ -11,14 +11,21 @@ if(NOT VERSIONS_JSON) endif() read_repo_version(newlib newlib) -set(newlib_patch ${CMAKE_CURRENT_LIST_DIR}/../patches/newlib.patch) +set(patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_repo.py) +if(GIT_PATCH_METHOD STREQUAL "am") + set(patch_script_args --method am) +elseif(GIT_PATCH_METHOD STREQUAL "apply") + set(patch_script_args --method apply) +endif() +set(patch_dir ${CMAKE_CURRENT_LIST_DIR}/../patches) +set(NEWLIB_PATCH_COMMAND ${Python3_EXECUTABLE} ${patch_script} ${patch_script_args} ${patch_dir}/newlib) FetchContent_Declare(newlib GIT_REPOSITORY https://sourceware.org/git/newlib-cygwin.git GIT_TAG "${newlib_TAG}" GIT_SHALLOW "${newlib_SHALLOW}" GIT_PROGRESS TRUE - PATCH_COMMAND git reset --quiet --hard && git clean --quiet --force -dx && git apply ${newlib_patch} + PATCH_COMMAND ${NEWLIB_PATCH_COMMAND} # Similarly to picolibc, we don't do the configuration here. SOURCE_SUBDIR do_not_add_newlib_subdir ) diff --git a/cmake/fetch_picolibc.cmake b/cmake/fetch_picolibc.cmake index 67a3f3c..f0ad368 100644 --- a/cmake/fetch_picolibc.cmake +++ b/cmake/fetch_picolibc.cmake @@ -11,18 +11,21 @@ if(NOT VERSIONS_JSON) endif() read_repo_version(picolibc picolibc) -set( - picolibc_patches - ${CMAKE_CURRENT_LIST_DIR}/../patches/picolibc/0001-Enable-libcxx-builds.patch - ${CMAKE_CURRENT_LIST_DIR}/../patches/picolibc/0002-Add-bootcode-for-AArch64-FVPs.patch -) +set(patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_repo.py) +if(GIT_PATCH_METHOD STREQUAL "am") + set(patch_script_args --method am) +elseif(GIT_PATCH_METHOD STREQUAL "apply") + set(patch_script_args --method apply) +endif() +set(patch_dir ${CMAKE_CURRENT_LIST_DIR}/../patches) +set(PICOLIBC_PATCH_COMMAND ${Python3_EXECUTABLE} ${patch_script} ${patch_script_args} ${patch_dir}/picolibc) FetchContent_Declare(picolibc GIT_REPOSITORY https://github.com/picolibc/picolibc.git GIT_TAG "${picolibc_TAG}" GIT_SHALLOW "${picolibc_SHALLOW}" GIT_PROGRESS TRUE - PATCH_COMMAND git reset --quiet --hard && git clean --quiet --force -dx && git apply ${picolibc_patches} + PATCH_COMMAND ${PICOLIBC_PATCH_COMMAND} # We only want to download the content, not configure it at this # stage. picolibc will be built in many configurations using # ExternalProject_Add using the sources that are checked out here. diff --git a/cmake/patch_llvm.py b/cmake/patch_repo.py similarity index 77% rename from cmake/patch_llvm.py rename to cmake/patch_repo.py index 85bf535..962e111 100644 --- a/cmake/patch_llvm.py +++ b/cmake/patch_repo.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ -Script to apply a set of patches to llvm-project sources. +Script to apply a set of patches to a git repository. """ import argparse @@ -18,8 +18,8 @@ def main(): help="Set of patches to apply. This should be a directory containing one or more ordered *.patch files.", ) parser.add_argument( - "--llvm_dir", - help="Directory of the llvm-project git checkout, if not the current directory.", + "--repo_dir", + help="Directory of the git checkout, if not the current directory.", ) parser.add_argument( "--method", @@ -36,10 +36,20 @@ def main(): action="store_true", help="If a patch in a series cannot be applied, restore the original state instead of leaving patches missing. Return code will be 2 instead of 1.", ) + parser.add_argument( + "--3way", + action="store_true", + dest="three_way", + help="If the patch does not apply cleanly, fall back on 3-way merge.", + ) args = parser.parse_args() - if args.llvm_dir: - git_cmd = ["git", "-C", args.llvm_dir] + if args.method == "apply" and args.restore_on_fail and args.three_way: + print("--restore_on_fail is incompatible with --3way using apply") + exit(1) + + if args.repo_dir: + git_cmd = ["git", "-C", args.repo_dir] else: git_cmd = ["git"] @@ -57,7 +67,9 @@ def main(): print("\n".join(p.name for p in patch_list)) if args.method == "am": - merge_args = git_cmd + ["am", "-k", "--ignore-whitespace", "--3way"] + merge_args = git_cmd + ["am", "-k", "--ignore-whitespace"] + if args.three_way: + merge_args.append("--3way") for patch in patch_list: merge_args.append(str(patch)) p = subprocess.run(merge_args, capture_output=True, text=True) @@ -72,8 +84,8 @@ def main(): # git am doesn't give any specific return codes, # so check for unresolved working files. rebase_apply_path = os.path.join(".git", "rebase-apply") - if args.llvm_dir: - rebase_apply_path = os.path.join(args.llvm_dir, rebase_apply_path) + if args.repo_dir: + rebase_apply_path = os.path.join(args.repo_dir, rebase_apply_path) if os.path.isdir(rebase_apply_path): print("Aborting git am...") subprocess.run(git_cmd + ["am", "--abort"], check=True) @@ -90,10 +102,11 @@ def main(): apply_check_args = git_cmd + [ "apply", "--ignore-whitespace", - "--3way", "--check", - str(current_patch), ] + if args.three_way: + apply_check_args.append("--3way") + apply_check_args.append(str(current_patch)) p_check = subprocess.run(apply_check_args) if p_check.returncode == 0: @@ -102,10 +115,11 @@ def main(): apply_args = git_cmd + [ "apply", "--ignore-whitespace", - "--3way", - str(current_patch), ] - apply_args = subprocess.run(apply_args, check=True) + if args.three_way: + apply_args.append("--3way") + apply_args.append(str(current_patch)) + p = subprocess.run(apply_args, check=True) applied_patches.append(current_patch) else: # Patch won't apply. @@ -118,10 +132,11 @@ def main(): reverse_args = git_cmd + [ "apply", "--ignore-whitespace", - "--3way", "--reverse", - str(previous_patch), ] + if args.three_way: + reverse_args.append("--3way") + reverse_args.append(str(previous_patch)) p_check = subprocess.run(reverse_args, check=True) print( f"Rollback successful, failure occured on {current_patch.name}" diff --git a/patches/newlib.patch b/patches/newlib/0001-Enable-newlib-build.patch similarity index 94% rename from patches/newlib.patch rename to patches/newlib/0001-Enable-newlib-build.patch index f520a7f..e70a97a 100644 --- a/patches/newlib.patch +++ b/patches/newlib/0001-Enable-newlib-build.patch @@ -1,3 +1,32 @@ +From 0e1475e5112b986ef5d9caee23dac554c749c54b Mon Sep 17 00:00:00 2001 +From: David Candler +Date: Thu, 28 Nov 2024 15:31:35 +0000 +Subject: [PATCH] Enable newlib build + +--- + libgloss/aarch64/syscalls.c | 6 ++ + libgloss/arm/cpu-init/rdimon-aem.S | 107 ++++++++++++------------ + libgloss/arm/crt0.S | 2 +- + libgloss/arm/linux-crt0.c | 2 +- + libgloss/arm/syscalls.c | 6 +- + libgloss/arm/trap.S | 2 +- + libgloss/libnosys/configure | 2 +- + newlib/libc/include/sys/features.h | 2 + + newlib/libc/machine/aarch64/memchr.S | 6 +- + newlib/libc/machine/aarch64/strchr.S | 6 +- + newlib/libc/machine/aarch64/strchrnul.S | 6 +- + newlib/libc/machine/aarch64/strrchr.S | 10 +-- + newlib/libc/stdlib/aligned_alloc.c | 1 + + newlib/libc/sys/arm/crt0.S | 2 +- + newlib/libc/sys/arm/trap.S | 2 +- + newlib/libm/machine/arm/sf_ceil.c | 2 +- + newlib/libm/machine/arm/sf_floor.c | 2 +- + newlib/libm/machine/arm/sf_nearbyint.c | 2 +- + newlib/libm/machine/arm/sf_rint.c | 2 +- + newlib/libm/machine/arm/sf_round.c | 2 +- + newlib/libm/machine/arm/sf_trunc.c | 2 +- + 21 files changed, 92 insertions(+), 82 deletions(-) + diff --git a/libgloss/aarch64/syscalls.c b/libgloss/aarch64/syscalls.c index 7343cc61f..2c4b63c17 100644 --- a/libgloss/aarch64/syscalls.c @@ -5,7 +34,7 @@ index 7343cc61f..2c4b63c17 100644 @@ -172,6 +172,12 @@ newslot (void) return i; } - + +int __aarch64_sme_accessible() { + int result = 0; + asm volatile ( "mrs %x[result], id_aa64pfr1_el1" : [result]"=r"(result) : : ); @@ -635,3 +664,6 @@ index 64e4aeb9a..c08fa6fed 100644 #include float +-- +2.43.0 + From 88c5d02d2913880e10834c6a2e2d769295868fe0 Mon Sep 17 00:00:00 2001 From: David Candler Date: Fri, 29 Nov 2024 13:49:45 +0000 Subject: [PATCH 2/3] fixup! Use the same patching script and command for all repos --- cmake/fetch_llvm.cmake | 16 +++++----------- cmake/fetch_newlib.cmake | 13 +++---------- cmake/fetch_picolibc.cmake | 13 +++---------- cmake/patch_repo.cmake | 16 ++++++++++++++++ 4 files changed, 27 insertions(+), 31 deletions(-) create mode 100644 cmake/patch_repo.cmake diff --git a/cmake/fetch_llvm.cmake b/cmake/fetch_llvm.cmake index deb8258..c94c669 100644 --- a/cmake/fetch_llvm.cmake +++ b/cmake/fetch_llvm.cmake @@ -5,22 +5,16 @@ # top level to any library builds to prevent repeated checkouts. include(FetchContent) +include(${CMAKE_CURRENT_LIST_DIR}/patch_repo.cmake) if(NOT VERSIONS_JSON) include(${CMAKE_CURRENT_LIST_DIR}/read_versions.cmake) endif() read_repo_version(llvmproject llvm-project) - -set(patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_repo.py) -if(GIT_PATCH_METHOD STREQUAL "am") - set(patch_script_args --method am) -elseif(GIT_PATCH_METHOD STREQUAL "apply") - set(patch_script_args --method apply) -endif() -set(patch_dir ${CMAKE_CURRENT_LIST_DIR}/../patches) -set(LLVM_PATCH_COMMAND ${Python3_EXECUTABLE} ${patch_script} ${patch_script_args} ${patch_dir}/llvm-project) +get_patch_command(llvm-project llvm_patch_command) if(APPLY_LLVM_PERFORMANCE_PATCHES) - set(LLVM_PATCH_COMMAND ${LLVM_PATCH_COMMAND} && ${Python3_EXECUTABLE} ${patch_script} ${patch_script_args} ${patch_dir}/llvm-project-perf) + get_patch_command(llvm-project-perf llvm_perf_patch_command) + set(llvm_patch_command ${llvm_patch_command} && ${llvm_perf_patch_command} ) endif() FetchContent_Declare(llvmproject @@ -28,7 +22,7 @@ FetchContent_Declare(llvmproject GIT_TAG "${llvmproject_TAG}" GIT_SHALLOW "${llvmproject_SHALLOW}" GIT_PROGRESS TRUE - PATCH_COMMAND ${LLVM_PATCH_COMMAND} + PATCH_COMMAND ${llvm_patch_command} # Add the llvm subdirectory later to ensure that # LLVMEmbeddedToolchainForArm is the first project declared. # Otherwise CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT diff --git a/cmake/fetch_newlib.cmake b/cmake/fetch_newlib.cmake index b3b621e..e0f20de 100644 --- a/cmake/fetch_newlib.cmake +++ b/cmake/fetch_newlib.cmake @@ -5,27 +5,20 @@ # top level to any library builss to prevent repeated checkouts. include(FetchContent) +include(${CMAKE_CURRENT_LIST_DIR}/patch_repo.cmake) if(NOT VERSIONS_JSON) include(${CMAKE_CURRENT_LIST_DIR}/read_versions.cmake) endif() read_repo_version(newlib newlib) - -set(patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_repo.py) -if(GIT_PATCH_METHOD STREQUAL "am") - set(patch_script_args --method am) -elseif(GIT_PATCH_METHOD STREQUAL "apply") - set(patch_script_args --method apply) -endif() -set(patch_dir ${CMAKE_CURRENT_LIST_DIR}/../patches) -set(NEWLIB_PATCH_COMMAND ${Python3_EXECUTABLE} ${patch_script} ${patch_script_args} ${patch_dir}/newlib) +get_patch_command(newlib newlib_patch_command) FetchContent_Declare(newlib GIT_REPOSITORY https://sourceware.org/git/newlib-cygwin.git GIT_TAG "${newlib_TAG}" GIT_SHALLOW "${newlib_SHALLOW}" GIT_PROGRESS TRUE - PATCH_COMMAND ${NEWLIB_PATCH_COMMAND} + PATCH_COMMAND ${newlib_patch_command} # Similarly to picolibc, we don't do the configuration here. SOURCE_SUBDIR do_not_add_newlib_subdir ) diff --git a/cmake/fetch_picolibc.cmake b/cmake/fetch_picolibc.cmake index f0ad368..4dabc45 100644 --- a/cmake/fetch_picolibc.cmake +++ b/cmake/fetch_picolibc.cmake @@ -5,27 +5,20 @@ # top level to any library builss to prevent repeated checkouts. include(FetchContent) +include(${CMAKE_CURRENT_LIST_DIR}/patch_repo.cmake) if(NOT VERSIONS_JSON) include(${CMAKE_CURRENT_LIST_DIR}/read_versions.cmake) endif() read_repo_version(picolibc picolibc) - -set(patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_repo.py) -if(GIT_PATCH_METHOD STREQUAL "am") - set(patch_script_args --method am) -elseif(GIT_PATCH_METHOD STREQUAL "apply") - set(patch_script_args --method apply) -endif() -set(patch_dir ${CMAKE_CURRENT_LIST_DIR}/../patches) -set(PICOLIBC_PATCH_COMMAND ${Python3_EXECUTABLE} ${patch_script} ${patch_script_args} ${patch_dir}/picolibc) +get_patch_command(picolibc picolibc_patch_command) FetchContent_Declare(picolibc GIT_REPOSITORY https://github.com/picolibc/picolibc.git GIT_TAG "${picolibc_TAG}" GIT_SHALLOW "${picolibc_SHALLOW}" GIT_PROGRESS TRUE - PATCH_COMMAND ${PICOLIBC_PATCH_COMMAND} + PATCH_COMMAND ${picolibc_patch_command} # We only want to download the content, not configure it at this # stage. picolibc will be built in many configurations using # ExternalProject_Add using the sources that are checked out here. diff --git a/cmake/patch_repo.cmake b/cmake/patch_repo.cmake new file mode 100644 index 0000000..c0677f7 --- /dev/null +++ b/cmake/patch_repo.cmake @@ -0,0 +1,16 @@ + +# Function to generate a PATCH_COMMAND, calling the +# patch_repo.py script using a target set of patches. + +function(get_patch_command patch_dir patch_command_out) + set(patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_repo.py) + list(APPEND patch_script_args ${Python3_EXECUTABLE} ${patch_script}) + if(GIT_PATCH_METHOD STREQUAL "am") + list(APPEND patch_script_args "--method" "am") + elseif(GIT_PATCH_METHOD STREQUAL "apply") + list(APPEND patch_script_args "--method" "apply") + endif() + list(APPEND patch_script_args ${CMAKE_CURRENT_LIST_DIR}/../patches/${patch_dir}) + + set(${patch_command_out} ${patch_script_args} PARENT_SCOPE) +endfunction() From 6cb16d3e0dd71f9ffddcbb25856944f72f307921 Mon Sep 17 00:00:00 2001 From: David Candler Date: Fri, 29 Nov 2024 15:49:02 +0000 Subject: [PATCH 3/3] fixup! Use the same patching script and command for all repos --- cmake/fetch_llvm.cmake | 4 ++-- cmake/fetch_newlib.cmake | 2 +- cmake/fetch_picolibc.cmake | 2 +- cmake/patch_repo.cmake | 6 +++--- cmake/patch_repo.py | 4 ++++ 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cmake/fetch_llvm.cmake b/cmake/fetch_llvm.cmake index c94c669..1838148 100644 --- a/cmake/fetch_llvm.cmake +++ b/cmake/fetch_llvm.cmake @@ -11,9 +11,9 @@ if(NOT VERSIONS_JSON) include(${CMAKE_CURRENT_LIST_DIR}/read_versions.cmake) endif() read_repo_version(llvmproject llvm-project) -get_patch_command(llvm-project llvm_patch_command) +get_patch_command(${CMAKE_CURRENT_LIST_DIR}/.. llvm-project llvm_patch_command) if(APPLY_LLVM_PERFORMANCE_PATCHES) - get_patch_command(llvm-project-perf llvm_perf_patch_command) + get_patch_command(${CMAKE_CURRENT_LIST_DIR}/.. llvm-project-perf llvm_perf_patch_command) set(llvm_patch_command ${llvm_patch_command} && ${llvm_perf_patch_command} ) endif() diff --git a/cmake/fetch_newlib.cmake b/cmake/fetch_newlib.cmake index e0f20de..6962b5b 100644 --- a/cmake/fetch_newlib.cmake +++ b/cmake/fetch_newlib.cmake @@ -11,7 +11,7 @@ if(NOT VERSIONS_JSON) include(${CMAKE_CURRENT_LIST_DIR}/read_versions.cmake) endif() read_repo_version(newlib newlib) -get_patch_command(newlib newlib_patch_command) +get_patch_command(${CMAKE_CURRENT_LIST_DIR}/.. newlib newlib_patch_command) FetchContent_Declare(newlib GIT_REPOSITORY https://sourceware.org/git/newlib-cygwin.git diff --git a/cmake/fetch_picolibc.cmake b/cmake/fetch_picolibc.cmake index 4dabc45..050b136 100644 --- a/cmake/fetch_picolibc.cmake +++ b/cmake/fetch_picolibc.cmake @@ -11,7 +11,7 @@ if(NOT VERSIONS_JSON) include(${CMAKE_CURRENT_LIST_DIR}/read_versions.cmake) endif() read_repo_version(picolibc picolibc) -get_patch_command(picolibc picolibc_patch_command) +get_patch_command(${CMAKE_CURRENT_LIST_DIR}/.. picolibc picolibc_patch_command) FetchContent_Declare(picolibc GIT_REPOSITORY https://github.com/picolibc/picolibc.git diff --git a/cmake/patch_repo.cmake b/cmake/patch_repo.cmake index c0677f7..c81a76b 100644 --- a/cmake/patch_repo.cmake +++ b/cmake/patch_repo.cmake @@ -2,15 +2,15 @@ # Function to generate a PATCH_COMMAND, calling the # patch_repo.py script using a target set of patches. -function(get_patch_command patch_dir patch_command_out) - set(patch_script ${CMAKE_CURRENT_LIST_DIR}/patch_repo.py) +function(get_patch_command toolchain_root patch_dir patch_command_out) + set(patch_script ${toolchain_root}/cmake/patch_repo.py) list(APPEND patch_script_args ${Python3_EXECUTABLE} ${patch_script}) if(GIT_PATCH_METHOD STREQUAL "am") list(APPEND patch_script_args "--method" "am") elseif(GIT_PATCH_METHOD STREQUAL "apply") list(APPEND patch_script_args "--method" "apply") endif() - list(APPEND patch_script_args ${CMAKE_CURRENT_LIST_DIR}/../patches/${patch_dir}) + list(APPEND patch_script_args ${toolchain_root}/patches/${patch_dir}) set(${patch_command_out} ${patch_script_args} PARENT_SCOPE) endfunction() diff --git a/cmake/patch_repo.py b/cmake/patch_repo.py index 962e111..59294b1 100644 --- a/cmake/patch_repo.py +++ b/cmake/patch_repo.py @@ -44,6 +44,10 @@ def main(): ) args = parser.parse_args() + # If the patch is valid but contain conflicts, using --3way --apply can apply + # the patch but leave conflict markers in the source for the user to resolve. + # This doesn't return an error code, making it compatible with this script's + # --restore_on_fail option, which relies on the error code from running --check. if args.method == "apply" and args.restore_on_fail and args.three_way: print("--restore_on_fail is incompatible with --3way using apply") exit(1)