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

opam does not compile packages to ARM arch on macOS #5450

Closed
tiuno opened this issue Feb 22, 2023 · 13 comments · Fixed by #5451
Closed

opam does not compile packages to ARM arch on macOS #5450

tiuno opened this issue Feb 22, 2023 · 13 comments · Fixed by #5451

Comments

@tiuno
Copy link

tiuno commented Feb 22, 2023

# opam config report
# opam-version         2.1.4 
# self-upgrade         no
# system               arch=x86_64 os=macos os-distribution=homebrew os-version=12.5
# solver               builtin-mccs+glpk
# install-criteria     -removed,-count[avoid-version,changed],-count[version-lag,request],-count[version-lag,changed],-count[missing-depexts,changed],-changed
# upgrade-criteria     -removed,-count[avoid-version,changed],-count[version-lag,solution],-count[missing-depexts,changed],-new
# jobs                 7
# repositories         1 (http), 1 (version-controlled) (default repo at 15da45a2)
# pinned               0
# current-switch       default
# ocaml:native         true
# ocaml:native-tools   true
# ocaml:native-dynlink true
# ocaml:stubsdir       /Users/colin/.opam/default/lib/ocaml/stublibs:/Users/colin/.opam/default/lib/ocaml
# ocaml:preinstalled   false
# ocaml:compiler       4.14.1

On macOS Monterey with a M1 arm64 machine, opam does not detect the host architecture properly.

Even if set manually, opam will not compile packages for the correct architecture.

To recreate this behaviour, install opam following the site instructions, configure opam architecture manually to arm64, create a switch and install a package.
The problem is then observed by checking the kind of file produced using macOS file.

arch -arm64 /usr/bin/bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"

opam init --bare
opam var --global arch=arm64
opam switch create arm 4.14.0
opam switch set arm
eval $(opam env)
opam install dune
file $(command -v ocamlc) $(command -v dune)

The last two commands will should produce similar outputs like the following : .opam/arm/bin/ocamlc: Mach-O 64-bit executable x86_64 instead of the expected Mach-O 64-bit executable arm64.

Is this the expected behaviour? This yields incompatibility issues with third party libraries.

@tiuno tiuno changed the title MacOs opam does not compile package to ARM arch macOS opam does not compile package to ARM arch Feb 22, 2023
@tiuno tiuno changed the title macOS opam does not compile package to ARM arch opam does not compile packags to ARM arch on macOS Feb 22, 2023
@tiuno tiuno changed the title opam does not compile packags to ARM arch on macOS opam does not compile packages to ARM arch on macOS Feb 22, 2023
@kit-ty-kate
Copy link
Member

Your default terminal seems to be running in x86_64 mode, so any programs run by opam (even if opam if an arm64 executable) will be run in x86_64 mode.
If you really want to keep the x86_64 mode by default in your terminal you will need to run every opam call through arch -arm64

@tiuno
Copy link
Author

tiuno commented Feb 22, 2023

Your default terminal seems to be running in x86_64 mode, so any programs run by opam (even if opam if an arm64 executable) will be run in x86_64 mode. If you really want to keep the x86_64 mode by default in your terminal you will need to run every opam call through arch -arm64

Well, running uname -m prints arm64, I should expect it to be equivalent to running every opam call with arch -arm64.

@kit-ty-kate
Copy link
Member

Well, running uname -m prints arm64

In that case it is indeed not expected. I'm unable to reproduce this on my machine.
What does file opam give you? If it gives you the expected arm64 output, maybe try to remove the $HOME/.opam directory, make sure uname -m returns arm64 then rerun opam init --bare. If opam var arch returns something other than arm64 I have no idea what could be going wrong.

@tiuno
Copy link
Author

tiuno commented Feb 22, 2023

This is what I got

$ file $(command -v opam)
/usr/local/bin/opam: Mach-O 64-bit executable arm64
$ opam init --bare
...
$ opam var arch
arm64
# proceed to create a switch
$ file $(command -v ocamlc) $(command -v dune)
~/.opam/arm/bin/ocamlc: Mach-O 64-bit executable x86_64
~/.opam/arm/bin/dune: Mach-O 64-bit executable x86_64

@kit-ty-kate
Copy link
Member

ah so it's something in your build toolchain that's compiled in x86_64 mode. Could you give us the output of:

file $(command -v make)
file $(command -v cc)
file $(command -v ranlib)
file $(command -v ld)
file $(command -v sh)

There are other commands used but that's a start

@tiuno
Copy link
Author

tiuno commented Feb 22, 2023

Here's the output, they are all universal builds. You should note that ranlib and ld are scripts that call xcrun,
but I tested the output of xcrun too.

file $(command -v make) $(command -v cc) $(command -v ranlib) $(command -v ld) $(command -v sh)
/usr/bin/make:         Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64
- Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e
- Mach-O 64-bit executable arm64e]
/usr/bin/make (for architecture x86_64):	Mach-O 64-bit executable x86_64
/usr/bin/make (for architecture arm64e):	Mach-O 64-bit executable arm64e
/usr/bin/cc:           Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64
- Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e
- Mach-O 64-bit executable arm64e]
/usr/bin/cc (for architecture x86_64):	Mach-O 64-bit executable x86_64
/usr/bin/cc (for architecture arm64e):	Mach-O 64-bit executable arm64e
/opt/local/bin/ranlib: Bourne-Again shell script text executable, ASCII text
/opt/local/bin/ld:     Bourne-Again shell script text executable, ASCII text
/bin/sh:               Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64
- Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e
- Mach-O 64-bit executable arm64e]
/bin/sh (for architecture x86_64):	Mach-O 64-bit executable x86_64
/bin/sh (for architecture arm64e):	Mach-O 64-bit executable arm64e
$ cat /opt/local/bin/ld                                                                     
#!/bin/bash
if [[ -x /usr/bin/xcrun ]] ; then
  exec /usr/bin/xcrun ld "${@}"
elif [[ -x /usr/bin/ld ]] ; then
  exec /usr/bin/ld "${@}"
else
  exec ld "${@}"
fi
$ cat /opt/local/bin/ranlib                                                                      
#!/bin/bash
if [[ -x /usr/bin/xcrun ]] ; then
  exec /usr/bin/xcrun ranlib "${@}"
elif [[ -x /usr/bin/ranlib ]] ; then
  exec /usr/bin/ranlib "${@}"
else
  exec ranlib "${@}"
fi
$ file $(/usr/bin/xcrun -f ld)                                                                 
/Library/Developer/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64
- Mach-O 64-bit executable x86_64] [arm64]
/Library/Developer/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld (for architecture x86_64):	Mach-O 64-bit executable x86_64
/Library/Developer/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld (for architecture arm64):	Mach-O 64-bit executable arm64
$ file $(/usr/bin/xcrun -f ranlib)                                                               
/Library/Developer/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64
- Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64
- Mach-O 64-bit executable arm64]
/Library/Developer/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib (for architecture x86_64):	Mach-O 64-bit executable x86_64
/Library/Developer/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib (for architecture arm64):	Mach-O 64-bit executable arm64
$file /bin/bash 
/bin/bash: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64
- Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e
- Mach-O 64-bit executable arm64e]
/bin/bash (for architecture x86_64):	Mach-O 64-bit executable x86_64
/bin/bash (for architecture arm64e):	Mach-O 64-bit executable arm64e

@kit-ty-kate
Copy link
Member

mmmh, maybe try to run what opam is running by hand and see what happens:

curl -LO https://github.com/ocaml/ocaml/archive/4.14.0.tar.gz
tar xvf 4.14.0.tar.gz
cd ocaml-4.14.0
./configure --prefix ~/.opam/arm --docdir ~/.opam/arm/doc/ocaml -C CC=cc "ASPP=cc -c"
make -j8

and see the result of file ./ocamlc.opt

@tiuno
Copy link
Author

tiuno commented Feb 22, 2023

$ curl -LO https://github.com/ocaml/ocaml/archive/4.14.0.tar.gz
tar xvf 4.14.0.tar.gz
cd ocaml-4.14.0
./configure --prefix ~/.opam/arm --docdir ~/.opam/arm/doc/ocaml -C CC=cc "ASPP=cc -c"
make -j8
...
$ file ocamlc.opt
ocamlc.opt: Mach-O 64-bit executable arm64

@dbuenzli
Copy link
Contributor

These bash wrappers are suspicious. What happens if you remove them from your PATH ?

@tiuno
Copy link
Author

tiuno commented Feb 22, 2023

These bash wrappers are suspicious. What happens if you remove them from your PATH ?

This yields the same result.

@kit-ty-kate
Copy link
Member

kit-ty-kate commented Feb 22, 2023

What does ~/.opam/opam-init/hooks/sandbox.sh build uname -m return for you?

@tiuno
Copy link
Author

tiuno commented Feb 22, 2023

I get

$ ~/.opam/opam-init/hooks/sandbox.sh build uname -m
x86_64

I think I found the culprit, it seems to use a distribution of bash that is not arm64, I'll try to fix it and report later.

EDIT: it was that indeed feel free to close the issue and many thanks for the help debugging

@kit-ty-kate
Copy link
Member

To avoid this very specific issue in the future in opam I've opened #5451. However you would've certainly gotten similar issues elsewhere at a later time so it only tries to make the user's experience more consistent.

@rjbou rjbou added this to the 2.2.0~alpha milestone Mar 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants