From b74af2d9eea3e3b54302f3044feea8334b90ed60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Wed, 19 Sep 2018 23:12:53 +0200 Subject: [PATCH] Configure Crystal compiler version in Makefile Some complicated logic was used to detect the current compiler version from git tags. This method is unreliable and could produce invalid results. This is completely removed from Crystal source code and the version is set as env var `CRYSTAL_CONFIG_VERSION` in the `Makefile`. The value is determined from the most recent release listed in `CHANGELOG.md`. This is a reliable method even if the code is not checked out in a git repository. By default, `-dev` suffix is appended to the version. For creating a release build with a non-dev version, `CRYSTAL_CONFIG_VERSION` needs to be explicitly specified. --- Makefile | 11 +++++++- src/compiler/crystal/config.cr | 50 ++++++++++----------------------- src/compiler/crystal/program.cr | 6 ++-- 3 files changed, 27 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 2f224f3af38d..df9a28656214 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,9 @@ SOURCES := $(shell find src -name '*.cr') SPEC_SOURCES := $(shell find spec -name '*.cr') override FLAGS += $(if $(release),--release )$(if $(stats),--stats )$(if $(progress),--progress )$(if $(threads),--threads $(threads) )$(if $(debug),-d )$(if $(static),--static )$(if $(LDFLAGS),--link-flags="$(LDFLAGS)" ) SPEC_FLAGS := $(if $(verbose),-v )$(if $(junit_output),--junit_output $(junit_output) ) -EXPORTS := $(if $(release),,CRYSTAL_CONFIG_PATH="$(PWD)/src") +CRYSTAL_CONFIG_VERSION ?= $(shell grep -oEi '(^|\n)\#\s+([0-9]+\.[0-9]+\.[0-9]\w*)' --max-count=1 CHANGELOG.md | awk '{print $$2}')-dev +CRYSTAL_CONFIG_COMMIT ?= $(shell git rev-parse --short HEAD 2> /dev/null) +EXPORTS := $(if $(release),,CRYSTAL_CONFIG_PATH="$(PWD)/src") CRYSTAL_CONFIG_VERSION=$(CRYSTAL_CONFIG_VERSION) CRYSTAL_CONFIG_COMMIT=$(CRYSTAL_CONFIG_COMMIT) SHELL = sh LLVM_CONFIG_FINDER := \ [ -n "$(LLVM_CONFIG)" ] && command -v "$(LLVM_CONFIG)" || \ @@ -60,6 +62,13 @@ else $(shell echo $(shell printf '\033[33m')Using $(LLVM_CONFIG) [version=$(shell $(LLVM_CONFIG) --version)]$(shell printf '\033[0m') >&2) endif +ifeq (${CRYSTAL_CONFIG_VERSION},) + $(error Missing version information, could not read from CHANGELOG.md. Please provide a valid CRYSTAL_CONFIG_VERSION setting) +endif +ifeq (${CRYSTAL_CONFIG_VERSION},-dev) + $(error Missing version information, could not read from CHANGELOG.md. Please provide a valid CRYSTAL_CONFIG_VERSION setting) +endif + .PHONY: all all: crystal ## Build all files (currently crystal only) [default] diff --git a/src/compiler/crystal/config.cr b/src/compiler/crystal/config.cr index 7b230ac05c3f..75f6a3c4efd2 100644 --- a/src/compiler/crystal/config.cr +++ b/src/compiler/crystal/config.cr @@ -1,11 +1,21 @@ module Crystal module Config - def self.path - {{env("CRYSTAL_CONFIG_PATH") || ""}} + def self.path : String + {{ env("CRYSTAL_CONFIG_PATH") || "" }} end - def self.version - version_and_sha.first + def self.version : String + {% begin %} + {% version = env("CRYSTAL_CONFIG_VERSION") || raise "Missing required environment variable CRYSTAL_CONFIG_VERSION" %} + {% compare_versions(version, "0.0.0") %} + {{ version }} + {% end %} + end + + def self.build_commit : String? + commit = {{ env("CRYSTAL_CONFIG_COMMIT") }} + return if commit.try &.empty? + commit end def self.llvm_version @@ -13,7 +23,7 @@ module Crystal end def self.description - version, sha = version_and_sha + sha = build_commit formatted_sha = "[#{sha}] " if sha <<-DOC Crystal #{version} #{formatted_sha}(#{date}) @@ -23,36 +33,6 @@ module Crystal DOC end - @@version_and_sha : {String, String?}? - - def self.version_and_sha - @@version_and_sha ||= compute_version_and_sha - end - - private def self.compute_version_and_sha - # Set explicitly: 0.0.0, ci, HEAD, whatever - config_version = {{env("CRYSTAL_CONFIG_VERSION")}} - return {config_version, nil} if config_version - - git_version = {{`(git describe --tags --long --always 2>/dev/null) || true`.stringify.chomp}} - - # Failed git and no explicit version set: "" - # We inherit the version of the compiler building us for now. - return { {{Crystal::VERSION}}, nil } if git_version.empty? - - # Shallow clone with no tag in reach: abcd123 - # We assume being compiled with the latest released compiler - return {"#{{{Crystal::VERSION}}}+?", git_version} unless git_version.includes? '-' - - # On release: 0.0.0-0-gabcd123 - # Ahead of last release: 0.0.0-42-gabcd123 - tag, commits, sha = git_version.split('-') - sha = sha[1..-1] # Strip g - tag = "#{tag}+#{commits}" unless commits == "0" # Reappend commits since release unless we hit it exactly - - {tag, sha} - end - def self.date {{ `date "+%Y-%m-%d"`.stringify.chomp }} end diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr index 41e92c3a6126..8323f730cb70 100644 --- a/src/compiler/crystal/program.cr +++ b/src/compiler/crystal/program.cr @@ -243,9 +243,7 @@ module Crystal # Defines a predefined constant in the Crystal module, such as BUILD_DATE and VERSION. private def define_crystal_constants - version, sha = Crystal::Config.version_and_sha - - if sha + if sha = Crystal::Config.build_commit define_crystal_string_constant "BUILD_COMMIT", sha else define_crystal_nil_constant "BUILD_COMMIT" @@ -256,7 +254,7 @@ module Crystal define_crystal_string_constant "DEFAULT_PATH", Crystal::Config.path define_crystal_string_constant "DESCRIPTION", Crystal::Config.description define_crystal_string_constant "PATH", Crystal::CrystalPath.default_path - define_crystal_string_constant "VERSION", version + define_crystal_string_constant "VERSION", Crystal::Config.version define_crystal_string_constant "LLVM_VERSION", Crystal::Config.llvm_version end