crystalline
crystalline copied to clipboard
Should have an M1 compatible build or a Universal Binary
It would be great to have an M1 compatible build or a Universal Binary.
Hey @uchuugaka,
Yes that would be great. Unfortunately I don't have an M1 mac, so I won't be able to implement this (I could - but I'm not that comfortable shipping something without testing it).
So I'll need to rely on external contributions.
Sadly, there is no M1 runners available for GitHub Actions: https://github.com/actions/virtual-environments/issues/2187. If there is a way to get "free for open source" M1 instance somewhere, then it can be built with self-hosted runners.
It may be done with cross-compilation, but I had hard time trying to link object file on foreign architecture.
Just in case, here is m1 build from current HEAD: crystalline-v0.5-arm64-apple-darwin.zip
Just in case, here is m1 build from current HEAD: crystalline-v0.5-arm64-apple-darwin.zip
Works great for me. Thank you!
Here is m1 build from HEAD crystalline-v0.6-arm64-apple-darwin.gz
@elbywan I have an M1 Mac and can help test.
Here is m1 build from HEAD crystalline-v0.6-arm64-apple-darwin.gz
I can't get it work with vscode:
dyld[20271]: Symbol not found: __ZN4llvm9DIBuilder14createFunctionEPNS_7DIScopeENS_9StringRefES3_PNS_6DIFileEjPNS_16DISubroutineTypeEjNS_6DINode7DIFlagsENS_12DISubprogram9DISPFlagsENS_24MDTupleTypedArrayWrapperINS_19DITemplateParameterEEEPSA_NSC_INS_6DITypeEEE
Referenced from: /Users/iambudi/Development/Library/crystalline/crystalline
Expected in: /opt/homebrew/Cellar/llvm/14.0.6/lib/libLLVM.dylib
[Info - 12:41:47 PM] Connection to server got closed. Server will restart.
...
The Crystal Language server crashed 5 times in the last 3 minutes. The server will not be restarted.
That either indicates the dylib referenced wasn’t not found at the expected path nor in the searched paths OR the one found does not contain the symbol.
I saw a lot of this with having the dependency dylibs at different paths and shimmed them in with symlinks.
Not sure if it is a project config issue or an issue with where a given brew install is installing the dependencies
Here is a build made with crystal v1.5.0 on llvm v14.0.6 on current HEAD (a7c9aba74c43efce53941f940da0e1485e95bc7f), that fixes issue with missing symbols.
Here is a build made with crystal v1.5.0 on llvm v14.0.6 on current HEAD (a7c9aba), that fixes issue with missing symbols.
Thank you it works nicely :)
@y8 how long does it takes to compile crystalline on M1 machine?
@y8 how long does it takes to compile crystalline on M1 machine?
Insanely fast 🤯
About 3 minutes on my low-end MacBook Air with 16 gigs of ram for full build without cache. Crystal itself builds in about 5 minutes.
I’ve just got an idea: we can publish crystalline formula in homebrew. They have m1 build infrastructure to provide precompiled “bottles”.
I can make a formula if @elbywan is okay with that
I can make a formula if @elbywan is okay with that
@y8 Go for it! Thanks! 🙏
@y8 Go for it! Thanks! 🙏
I've made a draft formula. It builds and passes all the formula check on macOS. Most likely it will work on linux as well, but I haven't tested that yet.
Few questions:
-
Homebrew consider a good practice to add meaningful test after formula is installed. I'm not familiar with LSP architecture. It would be awesome, if you can share "one-liner" that can verify that
crystalline
in fact runs correctly. If possible, something that will keep working between releases, so there is no need to change formula to update tests for each release. -
As far I understand, static builds are not possible on macOS. What is relation between llvm version and crystalline executable? Maybe you or fellow readers know how to deal with it. I haven't had time to check homebrew for existent formulas that are built from crystal sources, so if anyone have a link, it will help!
Formula for reference:
class Crystalline < Formula
desc "Language Server Protocol implementation for Crystal"
homepage "https://github.com/elbywan/crystalline"
url "https://github.com/elbywan/crystalline/archive/refs/tags/v0.6.0.tar.gz"
sha256 "0d15cc0208edcbfe11bb280c2dd535091003ff89016f990a123a49325f8a8f9a"
license "MIT"
livecheck do
url :homepage
end
depends_on "crystal" => :build
depends_on "llvm" => :build
def install
system "shards", "install"
system "crystal", "build", "./src/crystalline.cr",
"--release", "--no-debug",
"-Dpreview_mt",
"--progress", "--stats",
"--time", "-o", "crystalline"
bin.install "crystalline"
end
test do
system "false"
end
end
Thanks!
@y8 Thanks a bunch for the forumula (and sorry for not replying sooner)!
It would be awesome, if you can share "one-liner" that can verify that crystalline in fact runs correctly. If possible, something that will keep working between releases, so there is no need to change formula to update tests for each release.
Sure thing, I am lacking free time currently but I will share something as soon as I can.
What is relation between llvm version and crystalline executable?
I don't think that the installed LLVM version matters, AFAIK LLM is only used to build crystalline from source.
The Homebrew formula above looks like a good idea to me!
Separately, if you want to have Apple Silicon artifacts attached to future releases, I tested the following using https://cirrus-ci.org/. It works and is free.
The steps from here would be:
- Decide where you want the bash script to live. I just created a
mac_arm64.sh
file in the crystalline root dir. - Link your GitHub repo to Cirrus.
- Enter a GitHub token into the Cirrus "Secured Variables" field for the repo to generated an encrypted value that can be used in
.cirrus.yml
.
.cirrus.yml
:
macos_instance:
image: ghcr.io/cirruslabs/macos-ventura-base:latest
env:
GITHUB_TOKEN: ENCRYPTED[abc123]
task:
script: ./mac_arm64.sh
mac_arm64.sh
:
#!/bin/bash
if [[ "$CIRRUS_RELEASE" == "" ]]; then
echo "Not a release. No need to deploy!"
exit 0
fi
if [[ "$GITHUB_TOKEN" == "" ]]; then
echo "Please provide GitHub access token via GITHUB_TOKEN environment variable!"
exit 1
fi
brew update
brew install openssl crystal
export LLVM_CONFIG="/opt/homebrew/opt/llvm@14/bin/llvm-config"
shards build crystalline --release --no-debug -Dpreview_mt --stats --progress --ignore-crystal-version
gzip -c bin/crystalline > crystalline_arm_64-apple-darwin.gz
echo "Uploading file..."
url_to_upload="https://uploads.github.com/repos/$CIRRUS_REPO_FULL_NAME/releases/$CIRRUS_RELEASE/assets?name=crystalline_arm_64-apple-darwin.gz"
curl -X POST \
--data-binary @crystalline_arm_64-apple-darwin.gz \
--header "Authorization: token $GITHUB_TOKEN" \
--header "Content-Type: application/octet-stream" \
"$url_to_upload"
I'm also using Crystalline on an M1 and built from source. Here's a 0.8 build made with Crystal 1.8.0. Hope this helps!
@dorkrawk How were you able to build Crystalline on an M1? I get these errors when I try:
Undefined symbols for architecture arm64:
"llvm::DISubprogram::toSPFlags(bool, bool, bool, unsigned int, bool)", referenced from:
_LLVMExtDIBuilderCreateFunction in llvm_ext.o
"llvm::DIBuilder::createFunction(llvm::DIScope*, llvm::StringRef, llvm::StringRef, llvm::DIFile*, unsigned int, llvm::DISubroutineType*, unsigned int, llvm::DINode::DIFlags, llvm::DISubprogram::DISPFlags, llvm::MDTupleTypedArrayWrapper<llvm::DITemplateParameter>, llvm::DISubprogram*, llvm::MDTupleTypedArrayWrapper<llvm::DIType>, llvm::MDTupleTypedArrayWrapper<llvm::DINode>, llvm::StringRef)", referenced from:
_LLVMExtDIBuilderCreateFunction in llvm_ext.o
"llvm::DIBuilder::createMemberType(llvm::DIScope*, llvm::StringRef, llvm::DIFile*, unsigned int, unsigned long long, unsigned int, unsigned long long, llvm::DINode::DIFlags, llvm::DIType*, llvm::MDTupleTypedArrayWrapper<llvm::DINode>)", referenced from:
_LLVMExtDIBuilderCreateMemberType in llvm_ext.o
"llvm::DIBuilder::createPointerType(llvm::DIType*, unsigned long long, unsigned int, llvm::Optional<unsigned int>, llvm::StringRef, llvm::MDTupleTypedArrayWrapper<llvm::DINode>)", referenced from:
_LLVMExtDIBuilderCreatePointerType in llvm_ext.o
"llvm::DIBuilder::createParameterVariable(llvm::DIScope*, llvm::StringRef, unsigned int, llvm::DIFile*, unsigned int, llvm::DIType*, bool, llvm::DINode::DIFlags, llvm::MDTupleTypedArrayWrapper<llvm::DINode>)", referenced from:
_LLVMExtDIBuilderCreateParameterVariable in llvm_ext.o
"llvm::DIBuilder::createReplaceableCompositeType(unsigned int, llvm::StringRef, llvm::DIScope*, llvm::DIFile*, unsigned int, unsigned int, unsigned long long, unsigned int, llvm::DINode::DIFlags, llvm::StringRef, llvm::MDTupleTypedArrayWrapper<llvm::DINode>)", referenced from:
_LLVMExtDIBuilderCreateReplaceableCompositeType in llvm_ext.o
"llvm::AttributeList::addAttributeAtIndex(llvm::LLVMContext&, unsigned int, llvm::Attribute::AttrKind) const", referenced from:
llvm::IRBuilderBase::CreateCall(llvm::FunctionType*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::ArrayRef<llvm::OperandBundleDefT<llvm::Value*>>, llvm::Twine const&, llvm::MDNode*) in llvm_ext.o
llvm::IRBuilderBase::CreateInvoke(llvm::FunctionType*, llvm::Value*, llvm::BasicBlock*, llvm::BasicBlock*, llvm::ArrayRef<llvm::Value*>, llvm::ArrayRef<llvm::OperandBundleDefT<llvm::Value*>>, llvm::Twine const&) in llvm_ext.o
"llvm::AttributeList::addAttributeAtIndex(llvm::LLVMContext&, unsigned int, llvm::StringRef, llvm::StringRef) const", referenced from:
_LLVMExtCreateMCJITCompilerForModule in llvm_ext.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: execution of command failed with exit status 1: cc "${@}" -o /Users/avrameisner/Dev/crystal-code/crystalline/bin/crystalline -rdynamic -L/opt/homebrew/Cellar/crystal/1.8.2/libexec/../../../../lib -L/opt/homebrew/Cellar/libyaml/0.2.5/lib -lyaml /opt/homebrew/Cellar/crystal/1.8.2/share/crystal/src/llvm/ext/llvm_ext.o `"/opt/homebrew/opt/llvm@13/bin/llvm-config" --libs --system-libs --ldflags 2> /dev/null` -lstdc++ -lpcre2-8 -lgc -L/opt/homebrew/Cellar/libevent/2.1.12/lib -levent_pthreads -levent -L/opt/homebrew/Cellar/libevent/2.1.12/lib -levent -liconv
@y8 did you try submitting the homebrew formula above to homebrew-core (I can't find it).
It would be awesome, if you can share "one-liner" that can verify that crystalline in fact runs correctly. If possible, something that will keep working between releases, so there is no need to change formula to update tests for each release.
I suspect (based on previous experience) that something as simple as showing help text would be accepted as a test that compilation worked.
@y8 did you try submitting the homebrew formula above to homebrew-core (I can't find it).
I've found a way to do some simple check that lsp works, so here is homebrew's PR: https://github.com/Homebrew/homebrew-core/pull/136517