Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Apple Silicon (M1/M2) support #128

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

FtZPetruska
Copy link

@FtZPetruska FtZPetruska commented Jun 19, 2023

Compiling natively on my M1 machine failed with the following issues:

  • CONFIGURE_COMMAND using ${compiler_flags} ${command_wrapper} fail due to _CFLAGS being treated as a command rather than an environment variable.
  • Dependencies built with autotools not knowing about the arm64/aarch64-apple-darwin triple.
  • Project-specific issues.

Moreover, the latest macOS x64 release no longer works on Apple Silicon due to missing shared libraries.

For the CONFIGURE_COMMAND issue, the fix consists in invoking the command_wrapper using cmake -E env. This achieves the expected behaviour where the compiler_flags variables are treated as environment variables, and passed to the command_wrapper script.

A similar issue happened for vita-headers with the call to python, starting macOS 12.3 there is no longer a python binary in PATH. To fix this, I used CMake to find the Python executable and used it instead.

For the dependencies, they typically needed to be updated to their latest version so the platform could be correctly detected.

Two notable exceptions were gmp and libelf:

  • For gmp, the patch used by Homebrew is used. Since GMP 6.3.0, running autoreconf has the same effect as the patch.
  • For libelf, the config.guess and config.sub files are updated using the ones from automake 1.16.

Lastly, there were some project-specific issues:

  • zlib shared libraries would not be deleted
  • I had difficulties downloading libyaml from the pyyaml website, so I switched the download source to github. It is functionally identical.
  • gdb did not declare its dependencies on the other projects, and would also fail to find said dependencies.

With these changes, I was able to build the toolchain natively on my M1 mac, compile the SDL2 port and link it against executables.

A few additional notes:

  • Use the correct triple for arm64 #126 is not strictly required for this PR, most config.sub scripts are able to canonicalise arm64-apple-darwin into aarch64-apple-darwin.
  • mpfr provides a cumulative patch for version 4.2.0 that addresses a handful of bugs. This patch is included in this PR. The patch is no longer needed for 4.2.1.
  • CI should be able to build an Apple Silicon version, but it would require additional changes (namely, making sure to pass the correct -target CFLAGS to every configure script). Let me know if this should be part of this PR or a subsequent one.

This PR closes #101, closes #107, and closes #122.

@FtZPetruska FtZPetruska marked this pull request as draft July 20, 2023 17:06
@FtZPetruska
Copy link
Author

FtZPetruska commented Jul 29, 2023

Alright, rebased on master to get the latest changes, fixed the conflicts and updated this PR a bit.

To sum up the changes:

  • binutils and gcc were (re?)updated to 2.40 2.41 and 13.1.0 13.2.0 respectively, the current versions did not support Apple Silicon.
  • Build zstd. Recent versions of GCC, Binutils, and GDB received support for zstd-compressed debug section. Building it ourselves avoids picking up a system installation (most notably in CI), and also users can enjoy up-to-date feature! It does require CMake 3.7, due to the necessary use of SOURCE_SUBDIR in ExternalProject.
  • Update the mpfr cumulative patch from p9 to p12.

Here's a sample CI run if you wish to test the binaries.

@FtZPetruska FtZPetruska marked this pull request as ready for review July 29, 2023 03:12
This allows detecting newer platforms like Apple Silicon.

Also update the commands to use `cmake -E env`.
- Download from github rather than pyyaml.
- Update to the latest version (0.2.5).
- Use `cmake -E env` to invoke the wrapper command.
- Run autoreconf to fix flat namespace issues on macOS 11+.
- Don't use the command wrapper to build, this breaks on arm64 linux.
@zetanumbers
Copy link
Contributor

Using vita-toolchain built with this PR (after rebasing it onto master). Haven't had any issues yet.

This adds support for Apple Silicon.
This adds Apple Silicon support.
This is needed by the latest gcc, binutils, and gdb, and will avoid
using the host's version.
- The version update provides support for Apple Silicon.
- The patch offsets were also updated.
- The configure command had to be updated to find GMP/MPFR/MPC. The GDB
configure script called during build uses different flags to set lib
paths.
This adds support for Apple Silicon and zstd.
- This adds support for Apple Silicon hosts.
- The patch was renamed (and updated) to reflect the change.
- Add zstd support.
- zstd external project requires CMake 3.7, so GIT_SHALLOW can be used
unconditionally.
- Use `option` to declare OFFLINE.
- Expand `OFFLINE` in the ExternalProject calls instead of using an
intermediate variable.
- Set CMP0135 to NEW.
Binutils 2.41 requires a version newer than what is provided by macOS.
Also run autoreconf to fix a sporadic issue with automake.
Use the github URL as it will not change when the next version releases.
@FtZPetruska
Copy link
Author

FtZPetruska commented Sep 18, 2023

Thank you for your feedback!

I just rebased on master. While doing so, I noticed several more issues when running CI on my fork, namely:

  • Using the command wrapper to build GMP would break during linking due to a race condition. Its use should not be necessary since the flags were already passed during configure.
  • expat would sporadically break in the Windows and Linux builds due to an automake version mismatch. Running autoreconf fixes the issue.
  • mpfr had the same issue, running autoreconf also handled it.

For zlib, I also switched the URL to the github release, so it does not break when the next release comes out.


Here's the latest CI run on my fork if you want to test the builds.

@zetanumbers
Copy link
Contributor

zetanumbers commented Sep 28, 2023

Here's the latest CI run on my fork if you want to test the builds.

It says it's Mach-O 64-bit executable x86_64

UPDATE: i have built vitasdk from deps-upgrade. Using it for now.

@Midar
Copy link

Midar commented Dec 29, 2024

This PR doesn't seem to work with current Xcode anymore:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__locale:496:3: error: '__abi_tag__' attribute only applies to structs, variables, functions, and namespaces
  496 |   _LIBCPP_HIDE_FROM_ABI char_type toupper(char_type __c) const { return do_toupper(__c); }
      |   ^

@saghul
Copy link

saghul commented Jan 20, 2025

I solved compiling with Xcode 16 with the following patch on top of this PR:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index db290bd..1dd322f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,8 +12,8 @@ if(POLICY CMP0135)
 endif()
 
 # Use the following gcc version
-set(GCC_VERSION 13.2.0)
-set(GCC_HASH SHA256=e275e76442a6067341a27f04c5c6b83d8613144004c0413528863dc6b5c743da)
+set(GCC_VERSION 13.3.0)
+set(GCC_HASH SHA256=0845e9621c9543a13f484e94584a49ffc0129970e9914624235fc1d061a0c083)
 
 set(ZLIB_VERSION 1.3)
 set(ZLIB_HASH SHA256=8a9ba2898e1d0d774eca6ba5b4627a11e5588ba85c8851336eb38de4683050a7)
@@ -468,7 +468,7 @@ list(APPEND pthread_tools
 
 if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
     # GCC on OSX (Clang in diguise) needs more bracket nesting depth to compile gcc
-    set(GCC_CFLAGS "${GCC_CFLAGS} -fbracket-depth=512")
+    set(GCC_CFLAGS "${GCC_CFLAGS} -fbracket-depth=512 -Wno-mismatched-tags -Wno-deprecated-declarations")
 endif()
 
 # Common gcc configure options
@@ -572,7 +572,6 @@ ExternalProject_Add(newlib
     DEPENDS binutils_${target_suffix} gcc-base vita-headers
     GIT_REPOSITORY https://github.com/vitasdk/newlib
     GIT_TAG ${NEWLIB_TAG}
-    GIT_SHALLOW 1
     # Pass the compiler_target_tools here so newlib picks up the fresh gcc-base compiler
     CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${compiler_flag} ${toolchain_tools} ${compiler_target_tools}
     ${wrapper_command} <SOURCE_DIR>/configure "CFLAGS_FOR_TARGET=-g -O2 -ffunction-sections -fdata-sections"
diff --git a/patches/gdb.patch b/patches/gdb.patch
index 31331e8..b030d5a 100644
--- a/patches/gdb.patch
+++ b/patches/gdb.patch
@@ -1,5 +1,5 @@
 diff --git a/gdb/Makefile.in b/gdb/Makefile.in
-index fa7c81a..258cc35 100644
+index fa7c81a0fab..258cc35ac88 100644
 --- a/gdb/Makefile.in
 +++ b/gdb/Makefile.in
 @@ -771,6 +771,7 @@ ALL_TARGET_OBS = \
@@ -12,7 +12,7 @@ index fa7c81a..258cc35 100644
  	bfin-linux-tdep.o \
 diff --git a/gdb/arm-vita-tdep.c b/gdb/arm-vita-tdep.c
 new file mode 100644
-index 0000000..5fdcea0
+index 00000000000..5fdcea08b5d
 --- /dev/null
 +++ b/gdb/arm-vita-tdep.c
 @@ -0,0 +1,53 @@
@@ -70,7 +70,7 @@ index 0000000..5fdcea0
 +                            arm_vita_init_abi);
 +}
 diff --git a/gdb/configure.tgt b/gdb/configure.tgt
-index e84e222..61202f9 100644
+index e84e222ba0d..61202f9e3ae 100644
 --- a/gdb/configure.tgt
 +++ b/gdb/configure.tgt
 @@ -198,6 +198,10 @@ arm*-*-openbsd*)
@@ -85,7 +85,7 @@ index e84e222..61202f9 100644
  	# Target: ARM embedded system
  	gdb_target_obs="arm-pikeos-tdep.o"
 diff --git a/gdb/osabi.c b/gdb/osabi.c
-index d18802a..8bc8f8b 100644
+index d18802ac3a4..8bc8f8bbbb4 100644
 --- a/gdb/osabi.c
 +++ b/gdb/osabi.c
 @@ -82,6 +82,7 @@ static const struct osabi_names gdb_osabi_names[] =
@@ -97,7 +97,7 @@ index d18802a..8bc8f8b 100644
    { "<invalid>", NULL }
  };
 diff --git a/gdb/osabi.h b/gdb/osabi.h
-index 35f14ec..14504ce 100644
+index 35f14ec433c..14504ce650f 100644
 --- a/gdb/osabi.h
 +++ b/gdb/osabi.h
 @@ -46,6 +46,7 @@ enum gdb_osabi
@@ -108,3 +108,95 @@ index 35f14ec..14504ce 100644
  
    GDB_OSABI_INVALID		/* keep this last */
  };
+diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c
+index ea0f78c9ad8..4aa270b41ac 100644
+--- a/gdb/python/py-gdb-readline.c
++++ b/gdb/python/py-gdb-readline.c
+@@ -52,13 +52,11 @@ gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout,
+       if (except.reason == RETURN_QUIT)
+ 	return NULL;
+ 
+-      /* The thread state is nulled during gdbpy_readline_wrapper,
+-	 with the original value saved in the following undocumented
+-	 variable (see Python's Parser/myreadline.c and
+-	 Modules/readline.c).  */
+-      PyEval_RestoreThread (_PyOS_ReadlineTState);
++
++      /* This readline callback is called without the GIL held.  */
++      gdbpy_gil gil;
++
+       gdbpy_convert_exception (except);
+-      PyEval_SaveThread ();
+       return NULL;
+     }
+ 
+diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
+index c41a43bac96..96c0008ae25 100644
+--- a/gdb/python/python-internal.h
++++ b/gdb/python/python-internal.h
+@@ -706,6 +706,30 @@ class gdbpy_allow_threads
+   PyThreadState *m_save;
+ };
+ 
++/* A helper class to save and restore the GIL, but without touching
++   the other globals that are handled by gdbpy_enter.  */
++
++class gdbpy_gil
++{
++public:
++
++  gdbpy_gil ()
++    : m_state (PyGILState_Ensure ())
++  {
++  }
++
++  ~gdbpy_gil ()
++  {
++    PyGILState_Release (m_state);
++  }
++
++  DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
++
++private:
++
++  PyGILState_STATE m_state;
++};
++
+ /* Use this after a TRY_EXCEPT to throw the appropriate Python
+    exception.  */
+ #define GDB_PY_HANDLE_EXCEPTION(Exception)	\
+diff --git a/gdb/python/python.c b/gdb/python/python.c
+index 9d558119e09..4e0692abed8 100644
+--- a/gdb/python/python.c
++++ b/gdb/python/python.c
+@@ -255,30 +255,6 @@ gdbpy_enter::finalize ()
+   python_gdbarch = target_gdbarch ();
+ }
+ 
+-/* A helper class to save and restore the GIL, but without touching
+-   the other globals that are handled by gdbpy_enter.  */
+-
+-class gdbpy_gil
+-{
+-public:
+-
+-  gdbpy_gil ()
+-    : m_state (PyGILState_Ensure ())
+-  {
+-  }
+-
+-  ~gdbpy_gil ()
+-  {
+-    PyGILState_Release (m_state);
+-  }
+-
+-  DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
+-
+-private:
+-
+-  PyGILState_STATE m_state;
+-};
+-
+ /* Set the quit flag.  */
+ 
+ static void

The bump to GCC 13.3 was necessary for it to compile with Xcode 16.

The extra GDB patch is necessary for compiling with a host Python 3.13 version.

Finally, the latest newlib didn't compile for me (see vitasdk/newlib#105 (comment)), so I built the previous one like so:

cmake -B build -DNEWLIB_TAG=b89e5bc183b516945f9ee07eef483ecb916e45ff

That's why my patch removes GIT_SHALLOW since it doesn't work for commits.

I haven't tried to compile any actual code with the toolchain yet, will do and report back!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants