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

New Shipping Apps section #377

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ftarulla
Copy link
Contributor

with using docker and using snapcraft subsections

Copy link
Member

@straight-shoota straight-shoota left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that this only shows publishing options using container tools. It suggests you need docker or snapcraft to run Crystal applications. That's far from the truth and somewhat deviates from the goal to compile to efficient native code when you need third party tools to execute that native code.

The very first step should be to demonstrate publishing a plain executable. For some applications, this is already fine and it doesn't need anything else. Docker or snapcraft would just be unnecessary overhead.

Only after discussing the problems that come with publishing a single executable, these tools should be mentioned as possible alternatives. But they're just two of many options and selecting which one to use depends on many factors which are far to complex for covering all of that. I'm pretty sure I most likely wouldn't chose either of the two demonstrated methods for publishing Crystal apps.

This seems far to narrow fetched to be an effective guide on shipping Crystal applications. It doesn't provide a comprehensive overview, but only two arbitrary and opinionated examples.
The guides for shipping with docker and shipping with snapcraft might be good by themselves, but not for filling a guides section in the language reference. I'd rather suggest to publish them as individual posts on the blog. And later they can be referenced from the language reference (or even integrated in a larger section).


## Compiling our application

Let’s go over Crystal’s [introduction](https://crystal-lang.org/reference/). One of the main goals of the language is to _Compile to efficient native code_. That means that each time that we compile our code then an executable is built, but with an important property: it has a target platform (architecture and operating system), which is where the application will run. Crystal knows the target platform because is the same as the one being used to compile.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Let’s go over Crystal’s [introduction](https://crystal-lang.org/reference/). One of the main goals of the language is to _Compile to efficient native code_. That means that each time that we compile our code then an executable is built, but with an important property: it has a target platform (architecture and operating system), which is where the application will run. Crystal knows the target platform because is the same as the one being used to compile.
Let’s go over Crystal’s [introduction](https://crystal-lang.org/reference/). One of the main goals of the language is to _Compile to efficient native code_. That means that each time that we compile our code then an executable is built, but with an important property: it has a target platform (architecture and operating system), which is where the application will run. Crystal chooses the target platform by default as the same as the one being used to compile.

## Compiling our application

Let’s go over Crystal’s [introduction](https://crystal-lang.org/reference/). One of the main goals of the language is to _Compile to efficient native code_. That means that each time that we compile our code then an executable is built, but with an important property: it has a target platform (architecture and operating system), which is where the application will run. Crystal knows the target platform because is the same as the one being used to compile.
For example, if we use a Linux OS based computer for compiling, then the executable will be meant to run on a Linux OS (and in some cases we will need to use the same Linux distribution).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(and in some cases we will need to use the same Linux distribution) - I'm not aware of any distribution-specific limitations. Do you have an example for that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that without further setting up the environment the binary can't be dropped on any linux distro. We played safe maybe. But on different distros paths of libraries might change and would require the user to set LD_LIBRARY_PATH before running the executable. I am not sure if on a plain Alpine any binary linked with glibc can run (Ref).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but that's not restricted by the distro, but the specific environment setup. You should be able to run a Linux executable on any Linux system (i.e. not needing to use the same distro), assuming the environment is configured appropriately.

Let’s go over Crystal’s [introduction](https://crystal-lang.org/reference/). One of the main goals of the language is to _Compile to efficient native code_. That means that each time that we compile our code then an executable is built, but with an important property: it has a target platform (architecture and operating system), which is where the application will run. Crystal knows the target platform because is the same as the one being used to compile.
For example, if we use a Linux OS based computer for compiling, then the executable will be meant to run on a Linux OS (and in some cases we will need to use the same Linux distribution).

Can we set the target when calling the compiler? Oh, that’s a great idea, but for now it’s not an option (there are a lot of great buccanears [working on a solution](https://forum.crystal-lang.org/t/cross-compiling-automatically-to-osx/1330/12) and remember that Crystal is open source: so you are welcome aboard!)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section suggest you can't cross compile Crystal. That is very much possible, though.

Only linking the final executable is not covered for a cross-compile target.

I'd either rephrase this paragraph or maybe even remove it entirely?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree to rephrase it. Cross compiling can be mention as something possible as long as you are aware of the difference between compiling, linking. But I would not aim for an explanation. At most that currently you would need a target environment to perform the linking.

Let’s compile our application:

```shell-session
$ shards build --production
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not about shards, so it rather only use crystal build.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that shards create a nicer directory structure.

But either we show the shards.yml and the structure of the whole folder.
Or we use crystal build (and update the samples below removing the bin).

But since we are simulating a whole app, using shards makes sense to me. Otherwise, it feels we are not using our own tools.

Copy link
Member

@bcardiff bcardiff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@straight-shoota The top-level guide aims for an intro and to explain the underlying challenges of distributing a native binary. The audience is people with no background in compiling and linking. Someone with advanced knowledge can scan that and double-check his assumptions.

Maybe we could add a paragraph so the reader can seek for resources for building packages (deb/rpm/apk) that will solve the dependencies requirement.

But Docker and Snapcraft although more have than a plain binary have enough momentum to be included. If you build micro-services or web apps having a guide for Docker is good. Snapcraft is easier to pick up and deal for distributing applications. oq for example was the first to choose to deliver a snap instead of a native package since it gives a lot of benefits with little burden.

There will always be a chance for things to improve and get better, but we want to offer at least one entry guide for how to complete the whole development cycle and don't send the users in the wild for the seek of answers.

Does this help to frame better the intention of this guide?

Audience: Crystal users with possible no compile/linking experience.
Goals: Intro to the challenges of distributing native apps. Offer a couple of simple solutions and suggest how to look for deeper/more advance information.
Non-Goals: Explain how linking works.

## Compiling our application

Let’s go over Crystal’s [introduction](https://crystal-lang.org/reference/). One of the main goals of the language is to _Compile to efficient native code_. That means that each time that we compile our code then an executable is built, but with an important property: it has a target platform (architecture and operating system), which is where the application will run. Crystal knows the target platform because is the same as the one being used to compile.
For example, if we use a Linux OS based computer for compiling, then the executable will be meant to run on a Linux OS (and in some cases we will need to use the same Linux distribution).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that without further setting up the environment the binary can't be dropped on any linux distro. We played safe maybe. But on different distros paths of libraries might change and would require the user to set LD_LIBRARY_PATH before running the executable. I am not sure if on a plain Alpine any binary linked with glibc can run (Ref).

Let’s go over Crystal’s [introduction](https://crystal-lang.org/reference/). One of the main goals of the language is to _Compile to efficient native code_. That means that each time that we compile our code then an executable is built, but with an important property: it has a target platform (architecture and operating system), which is where the application will run. Crystal knows the target platform because is the same as the one being used to compile.
For example, if we use a Linux OS based computer for compiling, then the executable will be meant to run on a Linux OS (and in some cases we will need to use the same Linux distribution).

Can we set the target when calling the compiler? Oh, that’s a great idea, but for now it’s not an option (there are a lot of great buccanears [working on a solution](https://forum.crystal-lang.org/t/cross-compiling-automatically-to-osx/1330/12) and remember that Crystal is open source: so you are welcome aboard!)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree to rephrase it. Cross compiling can be mention as something possible as long as you are aware of the difference between compiling, linking. But I would not aim for an explanation. At most that currently you would need a target environment to perform the linking.

Let’s compile our application:

```shell-session
$ shards build --production
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that shards create a nicer directory structure.

But either we show the shards.yml and the structure of the whole folder.
Or we use crystal build (and update the samples below removing the bin).

But since we are simulating a whole app, using shards makes sense to me. Otherwise, it feels we are not using our own tools.

@straight-shoota
Copy link
Member

Does this help to frame better the intention of this guide?

I think I already understood the intention before, but I still think we should not have a shipping guide that's only about two arbitrary shipping methods.

But Docker and Snapcraft although more have than a plain binary have enough momentum to be included.

I'm not doubting that they can't be included, I'm just saying they shouldn't be the first and only options to be mentioned. They're still useful guides, that's why I suggested to publish them on the blog for now.

There will always be a chance for things to improve and get better, but we want to offer at least one entry guide for how to complete the whole development cycle and don't send the users in the wild for the seek of answers.

That's good. But when we start a section about shipping apps, it should not consist of only two arbitrary options for a similar mechanism.

@bcardiff
Copy link
Member

The description in the top-level aims to describe the needs. Even if we add some other distribution method it will still be arbitrary N methods to me, and there needs to be a start.

But when we start a section about shipping apps, it should not consist of only two arbitrary options for a similar mechanism.

What other content you think is a minimum requirement to add a shipping section?

@straight-shoota
Copy link
Member

The main issue I have is that these particular examples suggest that Crystal applications can only be shipped containerized. And that's far from the truth.
Additionally, it would be great to have at least one example for shipping for macOS.

So the minimum required alternatives are basic, non-containerized shipping methods like shipping a single binary, covering both dynamically linked and statically linked examples. For many applications, including the example static file server, shipping a statically linked binary should work pretty well without much hassle. You don't need to reach for complex containerization tools for that.

@bcardiff
Copy link
Member

I am happy to include a couple of paragraphs in the main file to mitigate the confusion you suggest and explain there are lots of other possibilities.

My main experience is using the approaches included in this PR: Docker & snapcraft.

But further complete guides can be written added once these are in place.

Talking about specific additional guides:

  • For osx we could add a guide to make a brew tap formula. But it seems that it can be added later.
    Having other alternative to build .pkg would be great, but the only alternative I am aware of is using omnibus and is too convoluted for a guide. (Or maybe is my lack of deep understanding)

  • For static building using Alpine or other Linux, I would feel comfortable with others making the first attempt. Since it is not something I regularly use. There were some ideas to have some base Dockerfile/template that will facilitate this but is something that has not happened yet, at least within the organization.

The efforts are to help the user discover the current possibilities. Not to develop something and write a short guide about it.

@RX14
Copy link
Contributor

RX14 commented Dec 21, 2019

How about showing how to produce a basic binary, then talk about static vs dynamic linking and the problems you have with shipping the binary, mention musl and alpine as an ideal option but it's not ready yet, then go into snap/docker.

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

Successfully merging this pull request may close these issues.

None yet

5 participants