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 make install #10878

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ all_spec
/src/llvm/ext/llvm_ext.o
/src/llvm/ext/llvm_ext.obj
/src/llvm/ext/llvm_ext.dwo
/man/*.gz
49 changes: 49 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ DEPS = $(LLVM_EXT_OBJ)
CXXFLAGS += $(if $(debug),-g -O0)
CRYSTAL_VERSION ?= $(shell cat src/VERSION)

DESTDIR ?=
PREFIX ?= /usr/local
Copy link
Member

Choose a reason for hiding this comment

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

What's the rationale for having DESTDIR in addition to PREFIX?

Copy link
Member Author

Choose a reason for hiding this comment

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

We're already using the same setup in shards. And it seems to be commonly used (https://stackoverflow.com/questions/11307465/destdir-and-prefix-of-make).
The original purpose is probably that the path PREFIX could be baked into the binary, so it's set at ./configure. And DESTDIR is only used for the install recipe directly. We wouldn't really need that with #10877 and can get the same functionality with PREFIX only (which can include the path to DESTDIR). But I think it still makes sense to have both.

BINDIR ?= $(DESTDIR)$(PREFIX)/bin
MANDIR ?= $(DESTDIR)$(PREFIX)/share/man
LIBDIR ?= $(DESTDIR)$(PREFIX)/lib
DATADIR ?= $(DESTDIR)$(PREFIX)/share/crystal
INSTALL ?= /usr/bin/install

ifeq ($(shell command -v ld.lld >/dev/null && uname -s),Linux)
EXPORT_CC ?= CC="cc -fuse-ld=lld"
endif
Expand Down Expand Up @@ -105,6 +113,44 @@ crystal: $(O)/crystal ## Build the compiler
deps: $(DEPS) ## Build dependencies
llvm_ext: $(LLVM_EXT_OBJ)

.PHONY: install
install: $(O)/crystal man/crystal.1.gz ## Install the compiler at DESTDIR
$(INSTALL) -D -m 0755 "$(O)/crystal" "$(BINDIR)/crystal"

$(INSTALL) -d -m 0755 $(DATADIR)
cp -av src "$(DATADIR)/src"
Copy link
Member

@jhass jhass Jul 5, 2021

Choose a reason for hiding this comment

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

At least Ruby and Python put their standard library into /usr/lib. Why is /usr/share better? What's the advantage of including a src subdirectory?

Copy link
Member Author

Choose a reason for hiding this comment

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

Again, this structure is directly copied from the tarball generation in distribution-scripts.

I don't know the specific reasons for lib vs. share. But in the Filesystem Hierarchy Standard, ˋ/usr/libˋ is for (binary) libraries and ˋ/usr/shareˋ for architecture-independent data. Ths stdlib source code is architecture-independent, so I suppose it makes sense to place it there. Not sure why Ruby and Python put it in ˋlibˋ.

The reason for the ˋsrcˋ folder is because there's other data that is to be placed beside it, for example ˋdocsˋ and ˋsamplesˋ.

Copy link
Member

@jhass jhass Jul 5, 2021

Choose a reason for hiding this comment

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

/usr/lib includes object files and libraries. On some systems, it may also include internal binaries that are not intended to be executed directly by users or shell scripts.

Applications may use a single subdirectory under /usr/lib. If an application uses a subdirectory, all architecture-dependent data exclusively used by the application must be placed within that subdirectory.

https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s06.html

Where does this say only architecture dependent or binary?

Just looking randomly through my /usr/lib I find "text" files by:

  • Go

  • NodeJS

  • Ruby

  • Python

  • TCL

  • udev

  • systemd

  • resolveconf

Furthermore precompiled libraries by

  • Erlang
  • OCaml

/usr/share seems preferred by Perl and Vala only from a quick look.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree, the exact semantics of the specification may be subject to interpretation. They're not completely clear.

But I don't think this really matters much. /usr/share/crystal is not wrong, so there's no reason against it. We're using this path in all distribution packages (at least for linux, not sure about mac). I don't see much reason to change it.

Copy link
Member

@jhass jhass Jul 5, 2021

Choose a reason for hiding this comment

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

There would be no need for that weird src subdirectory? :P

Copy link
Member Author

Choose a reason for hiding this comment

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

Why not? And why is it weird?

At /usr/lib/crystal there's already a subfolder lib which contains the bundled libraries (currently only libgc.a). If we would put the source files there too, they should obviously go into another subdirectory.

rm -rf "$(DATADIR)/$(LLVM_EXT_OBJ)" # Don't install llvm_ext.o

$(INSTALL) -D -m 644 man/crystal.1.gz "$(MANDIR)/man1/crystal.1.gz"
$(INSTALL) -D -m 644 LICENSE "$(DESTDIR)$(PREFIX)/share/licenses/crystal/LICENSE"

$(INSTALL) -D -m 644 etc/completion.bash "$(DESTDIR)$(PREFIX)/share/bash-completion/completions/crystal"
$(INSTALL) -D -m 644 etc/completion.zsh "$(DESTDIR)$(PREFIX)/share/zsh/site-functions/_crystal"

.PHONY: uninstall
uninstall: ## Uninstall the compiler from DESTDIR
rm -f "$(BINDIR)/crystal"

rm -rf "$(DATADIR)/src"

rm -f "$(MANDIR)/man1/crystal.1.gz"
rm -f "$(DESTDIR)$(PREFIX)/share/licenses/crystal/LICENSE"

rm -f "$(DESTDIR)$(PREFIX)/share/bash-completion/completions/crystal"
rm -f "$(DESTDIR)$(PREFIX)/share/zsh/site-functions/_crystal"

.PHONY: install_docs
install_docs: docs ## Install docs at DESTDIR
$(INSTALL) -d -m 0755 $(DATADIR)

cp -av docs "$(DATADIR)/docs"
cp -av samples "$(DATADIR)/examples"

.PHONY: uninstall_docs
uninstall_docs: ## Uninstall docs from DESTDIR
rm -rf "$(DATADIR)/docs"
rm -rf "$(DATADIR)/examples"

$(O)/all_spec: $(DEPS) $(SOURCES) $(SPEC_SOURCES)
@mkdir -p $(O)
$(EXPORT_CC) $(EXPORTS) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/all_spec.cr
Expand All @@ -124,6 +170,9 @@ $(O)/crystal: $(DEPS) $(SOURCES)
$(LLVM_EXT_OBJ): $(LLVM_EXT_DIR)/llvm_ext.cc
$(CXX) -c $(CXXFLAGS) -o $@ $< $(shell $(LLVM_CONFIG) --cxxflags)

man/%.gz: man/%
gzip -c -9 $< > $@

.PHONY: clean
clean: clean_crystal ## Clean up built directories and files
rm -rf $(LLVM_EXT_OBJ)
Expand Down