crystal-lang / shards

Dependency manager for the Crystal language
Other
758 stars 99 forks source link

Support for cross compilation #627

Open noraj opened 2 months ago

noraj commented 2 months ago

shards build is more convenient than crystal build for building multiple binaries. However, shards build doesn't support --cross-compile and --target flags than are a must for static compilation since only Alpine is supported and so most people need to compile inside a docker.

straight-shoota commented 2 months ago

This is already supported. shards build delegates all options following the build target name to crystal build. So indeed shards build --cross-compile invokes crystal build ... --cross-compile.

luislavena commented 1 month ago

Hello folks,

There might be other problem with build command, as it doesn't pass things transparently to crystal build.

Take the example attempting to cross-compile drift target:

name: drift
version: 0.3.2
license: Apache-2.0
crystal: ">= 1.4.0, < 2.0.0"
authors:
  - Luis Lavena <luislavena@gmail.com>
targets:
  drift:
    main: src/cli.cr
dependencies:
  db:
    github: crystal-lang/crystal-db
    version: ~> 0.13.1
  sqlite3:
    github: crystal-lang/crystal-sqlite3
    version: ~> 0.21.0
$ uname -s -m
Linux aarch64

# native build
$ shards build drift

$ file bin/drift
bin/drift: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-aarch64.so.1, BuildID[sha1]=14dbaf89b60cfdbf55b27f830753b856beb8ac8b, with debug_info, not stripped

Attempting to use --cross-compile, --target fails:

$ shards build drift --cross-compile --target x86_64-linux-musl
Dependencies are satisfied
Building: drift
Error target drift failed to compile:
Error: Missing option: --target

When run with --verbose, we can see that platform arguments are not passed to build:

$ shards build drift --verbose --cross-compile --target x86_64-linux-musl
db: checking...
sqlite3: checking...
db: checking...
Dependencies are satisfied
Building: drift
crystal build -o /app/bin/drift src/cli.cr --verbose --cross-compile --target
Error target drift failed to compile:
Error: Missing option: --target

Forcing you to use --target=x86_64-linux-musl, at which points it works:

$ shards build drift --cross-compile --target=x86_64-linux-musl
Dependencies are satisfied
Building: drift
cc /app/bin/drift.o -o /app/bin/drift  -rdynamic -L/usr/local/bin/../lib/crystal -lsqlite3 -lpcre2-8 -lgc -lpthread -ldl -levent

$ x86_64-linux-musl-cc bin/drift.o -o /app/bin/drift -lsqlite3 -lpcre2-8 -lgc -lpthread -ldl -levent -lunwind

$ file bin/drift
bin/drift: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped

Cheers.

straight-shoota commented 1 month ago

shards build forwards all options it does not recognize. But x86_64-linux-musl is recognized as a target name. I think it's generally a good idea to write a single option with key and value joined by =. Alternatively, you can also use double dash to tell shards build that the following options are to be forwarded: shards build drift --verbose -- --cross-compile --target x86_64-linux-musl.

straight-shoota commented 1 month ago

It might be a good idea to change the forwarding behaviour so that any unrecognized option has the same effect as -- and all following options won't be parsed as options of shards build. This forces a certain order of options: all target names and options for shards build itself need to go before any forwarded options. This is probably what most users do and expect to happen.

HertzDevil commented 1 month ago

Related: crystal-lang/crystal#5845

luislavena commented 1 month ago

Alternatively, you can also use double dash to tell shards build that the following options are to be forwarded: shards build drift --verbose -- --cross-compile --target x86_64-linux-musl.

Sadly, that is not how build has been coded, so that doesn't work:

$ shards build drift --verbose -- --cross-compile --target x86_64-linux-musl
db: checking...
sqlite3: checking...
db: checking...
Dependencies are satisfied
Building: drift
crystal build -o /app/bin/drift src/cli.cr --verbose

None of the options after -- are passed to crystal build.

Only shards run forwards options after --: https://github.com/crystal-lang/shards/blob/master/src/cli.cr#L66-L69

straight-shoota commented 1 month ago

Indeed. I had incorrectly inferred that to work. I'm pretty sure it should work, though.

ysbaddaden commented 1 month ago

I'm pretty sure it should work, though.

Yes, it definitely should.