From 442418b283913d2389d3a7476970c4aeaa2c7ca3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 28 Jul 2014 08:01:54 -0700 Subject: [PATCH] Add a configure script This configure script is similar to rust's in that it doesn't require anything like autotools, it's just a meta-script to "generate" a makefile and perform run-of-the-mill validation/discovery before the Makefile is run. The main purpose of this rewrite is to support multi-target and targeted builds. This will allow us to produce 32-bit snapshots for platforms as well as easily providing `./configure --target $foo` for initialization. cc #274 --- .gitignore | 5 +- Makefile | 106 ----------- Makefile.in | 136 ++++++++++++++ configure | 379 +++++++++++++++++++++++++++++++++++++++ src/bin/cargo-version.rs | 2 +- src/snapshots.txt | 5 + 6 files changed, 525 insertions(+), 108 deletions(-) delete mode 100644 Makefile create mode 100644 Makefile.in create mode 100755 configure diff --git a/.gitignore b/.gitignore index cd8e4b1f6f9..48164142ec2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ -target +/target .cargo +/config.stamp +/Makefile +/config.mk diff --git a/Makefile b/Makefile deleted file mode 100644 index e89e044fabe..00000000000 --- a/Makefile +++ /dev/null @@ -1,106 +0,0 @@ -DESTDIR ?= -PREFIX ?= /usr/local -PKG_NAME ?= cargo-nightly - -ifeq ($(wildcard rustc/bin),) -export RUSTC := rustc -else -export RUSTC := $(CURDIR)/rustc/bin/rustc -export LD_LIBRARY_PATH := $(CURDIR)/rustc/lib:$(LD_LIBRARY_PATH) -export DYLD_LIBRARY_PATH := $(CURDIR)/rustc/lib:$(DYLD_LIBRARY_PATH) -endif - -CFG_RELEASE=0.1.0-pre -CFG_VER_DATE = $(shell git log -1 --pretty=format:'%ai') -CFG_VER_HASH = $(shell git rev-parse --short HEAD) -CFG_VERSION = $(PKG_NAME) $(CFG_RELEASE) ($(CFG_VER_HASH) $(CFG_VER_DATE)) - -export CFG_RELEASE -export CFG_VER_DATE -export CFG_VER_HASH -export CFG_VERSION - -export PATH := $(CURDIR)/rustc/bin:$(PATH) - -ifeq ($(OS),Windows_NT) -X = .exe -endif - -TARGET = target -DISTDIR = $(TARGET)/dist -PKGDIR = $(DISTDIR)/$(PKG_NAME) - -BIN_TARGETS := $(wildcard src/bin/*.rs) -BIN_TARGETS := $(BIN_TARGETS:src/bin/%.rs=%) -BIN_TARGETS := $(filter-out cargo,$(BIN_TARGETS)) -BIN_TARGETS := $(BIN_TARGETS:%=$(TARGET)/%$(X)) - -CARGO := $(TARGET)/snapshot/cargo-nightly/bin/cargo$(X) - -all: $(CARGO) - $(CARGO) build $(ARGS) - -$(CARGO): src/snapshots.txt - python src/etc/dl-snapshot.py - touch $@ - - -# === Tests - -test: test-unit style no-exes - -test-unit: $(CARGO) - $(CARGO) test $(only) - -style: - sh tests/check-style.sh - -no-exes: - find $$(git ls-files) -perm +111 -type f \ - -not -name '*.sh' -not -name '*.rs' | grep '.*' \ - && exit 1 || exit 0 - -# === Misc - -clean-all: clean -clean: - rm -rf $(TARGET) - -dist: $(DISTDIR)/$(PKG_NAME).tar.gz - -distcheck: dist - rm -rf $(TARGET)/distcheck - mkdir -p $(TARGET)/distcheck - (cd $(TARGET)/distcheck && tar xf ../dist/$(PKG_NAME).tar.gz) - $(TARGET)/distcheck/$(PKG_NAME)/install.sh \ - --prefix=$(TARGET)/distcheck/install - $(TARGET)/distcheck/install/bin/cargo -h > /dev/null - $(TARGET)/distcheck/$(PKG_NAME)/install.sh \ - --prefix=$(TARGET)/distcheck/install --uninstall - [ -f $(TARGET)/distcheck/install/bin/cargo ] && exit 1 || exit 0 - -$(DISTDIR)/$(PKG_NAME).tar.gz: $(PKGDIR)/lib/cargo/manifest.in - tar -czvf $@ -C $(DISTDIR) $(PKG_NAME) - -$(PKGDIR)/lib/cargo/manifest.in: all - rm -rf $(PKGDIR) - mkdir -p $(PKGDIR)/bin $(PKGDIR)/lib/cargo - cp $(TARGET)/cargo$(X) $(PKGDIR)/bin - cp $(BIN_TARGETS) $(PKGDIR)/lib/cargo - (cd $(PKGDIR) && find . -type f | sed 's/^\.\///') \ - > $(DISTDIR)/manifest-$(PKG_NAME).in - cp src/etc/install.sh $(PKGDIR) - cp README.md LICENSE-MIT LICENSE-APACHE $(PKGDIR) - cp LICENSE-MIT $(PKGDIR) - mv $(DISTDIR)/manifest-$(PKG_NAME).in $(PKGDIR)/lib/cargo/manifest.in - -install: $(PKGDIR)/lib/cargo/manifest.in - $(PKGDIR)/install.sh --prefix=$(PREFIX) --destdir=$(DESTDIR) - -# Setup phony tasks -.PHONY: all clean test test-unit style - -# Disable unnecessary built-in rules -.SUFFIXES: - - diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000000..dfb599da5b7 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,136 @@ +CFG_RELEASE_NUM=0.0.1 +CFG_RELEASE_LABEL=-pre + +include config.mk + +ifneq ($(CFG_LOCAL_RUST_ROOT),) +export LD_LIBRARY_PATH := $(CFG_LOCAL_RUST_ROOT)/lib:$(LD_LIBRARY_PATH) +export DYLD_LIBRARY_PATH := $(CFG_LOCAL_RUST_ROOT)/lib:$(DYLD_LIBRARY_PATH) +endif + +export PATH := $(dir $(CFG_RUSTC)):$(PATH) + +ifdef CFG_ENABLE_NIGHTLY +CFG_RELEASE=$(CFG_RELEASE_NUM)$(CFG_RELEASE_LABEL)-nightly +CFG_PACKAGE_VERS = nightly +else +CFG_RELEASE=$(CFG_RELEASE_NUM)$(CFG_RELEASE_LABEL) +CFG_PACKAGE_VERS=$(CFG_RELEASE) +endif +CFG_VER_DATE = $(shell git log -1 --pretty=format:'%ai') +CFG_VER_HASH = $(shell git rev-parse --short HEAD) +CFG_VERSION = $(CFG_RELEASE) ($(CFG_VER_HASH) $(CFG_VER_DATE)) +PKG_NAME = cargo-$(CFG_PACKAGE_VERS) + +ifdef CFG_DISABLE_VERIFY_INSTALL +MAYBE_DISABLE_VERIFY=--disable-verify +else +MAYBE_DISABLE_VERIFY= +endif + +export CFG_VERSION + +ifeq ($(OS),Windows_NT) +X = .exe +endif + +TARGET_ROOT = target +BIN_TARGETS := $(wildcard src/bin/*.rs) +BIN_TARGETS := $(BIN_TARGETS:src/bin/%.rs=%) +BIN_TARGETS := $(filter-out cargo,$(BIN_TARGETS)) + +define DIST_TARGET +TARGET_$(1) = $$(TARGET_ROOT)/$(1) +DISTDIR_$(1) = $$(TARGET_$(1))/dist +PKGDIR_$(1) = $$(DISTDIR_$(1))/$$(PKG_NAME)-$(1) +BIN_TARGETS_$(1) := $$(BIN_TARGETS:%=$$(TARGET_$(1))/%$$(X)) +endef +$(foreach target,$(CFG_TARGET),$(eval $(call DIST_TARGET,$(target)))) + +CARGO := $(TARGET_ROOT)/snapshot/cargo-nightly/bin/cargo$(X) + +all: $(foreach target,$(CFG_TARGET),cargo-$(target)) + +define CARGO_TARGET +cargo-$(1): $$(CARGO) + $$(CARGO) build --target $(1) $$(ARGS) +endef +$(foreach target,$(CFG_TARGET),$(eval $(call CARGO_TARGET,$(target)))) + +$(CARGO): src/snapshots.txt + $(CFG_PYTHON) src/etc/dl-snapshot.py + touch $@ + + +# === Tests + +test: test-unit style no-exes + +test-unit: $(CARGO) + $(CARGO) test $(only) + +style: + sh tests/check-style.sh + +no-exes: + find $$(git ls-files) -perm +111 -type f \ + -not -name configure -not -name '*.sh' -not -name '*.rs' | \ + grep '.*' \ + && exit 1 || exit 0 + +# === Misc + +clean-all: clean +clean: + rm -rf $(TARGET_ROOT) + +# === Distribution + +define DO_DIST_TARGET +dist-$(1): $$(DISTDIR_$(1))/$$(PKG_NAME)-$(1).tar.gz + +distcheck-$(1): dist-$(1) + rm -rf $$(TARGET_$(1))/distcheck + mkdir -p $$(TARGET_$(1))/distcheck + (cd $$(TARGET_$(1))/distcheck && tar xf ../dist/$$(PKG_NAME)-$(1).tar.gz) + $$(TARGET_$(1))/distcheck/$$(PKG_NAME)-$(1)/install.sh \ + --prefix=$$(TARGET_$(1))/distcheck/install + $$(TARGET_$(1))/distcheck/install/bin/cargo -V > /dev/null + $$(TARGET_$(1))/distcheck/$$(PKG_NAME)-$(1)/install.sh \ + --prefix=$$(TARGET_$(1))/distcheck/install --uninstall + [ -f $$(TARGET_$(1))/distcheck/install/bin/cargo ] && exit 1 || exit 0 + +$$(DISTDIR_$(1))/$$(PKG_NAME)-$(1).tar.gz: $$(PKGDIR_$(1))/lib/cargo/manifest.in + tar -czvf $$@ -C $$(@D) $$(PKG_NAME)-$(1) + +$$(PKGDIR_$(1))/lib/cargo/manifest.in: all + rm -rf $$(PKGDIR_$(1)) + mkdir -p $$(PKGDIR_$(1))/bin $$(PKGDIR_$(1))/lib/cargo + cp $$(TARGET_$(1))/cargo$$(X) $$(PKGDIR_$(1))/bin + cp $$(BIN_TARGETS_$(1)) $$(PKGDIR_$(1))/lib/cargo + (cd $$(PKGDIR_$(1)) && find . -type f | sed 's/^\.\///') \ + > $$(DISTDIR_$(1))/manifest-$$(PKG_NAME).in + cp src/etc/install.sh $$(PKGDIR_$(1)) + cp README.md LICENSE-MIT LICENSE-APACHE $$(PKGDIR_$(1)) + cp LICENSE-MIT $$(PKGDIR_$(1)) + mv $$(DISTDIR_$(1))/manifest-$$(PKG_NAME).in \ + $$(PKGDIR_$(1))/lib/cargo/manifest.in + +install-$(1): $$(PKGDIR_$(1))/lib/cargo/manifest.in + $$(PKGDIR_$(1))/install.sh \ + --prefix="$$(DESTDIR)$$(CFG_PREFIX)" \ + --destdir="$$(DESTDIR)" $$(MAYBE_DISABLE_VERIFY) +endef +$(foreach target,$(CFG_TARGET),$(eval $(call DO_DIST_TARGET,$(target)))) + +dist: $(CARGO) $(foreach target,$(CFG_TARGET),dist-$(target)) +distcheck: $(CARGO) $(foreach target,$(CFG_TARGET),distcheck-$(target)) +install: $(CARGO) $(foreach target,$(CFG_TARGET),install-$(target)) + +# Setup phony tasks +.PHONY: all clean test test-unit style + +# Disable unnecessary built-in rules +.SUFFIXES: + + diff --git a/configure b/configure new file mode 100755 index 00000000000..c6b9cf5ecd1 --- /dev/null +++ b/configure @@ -0,0 +1,379 @@ +#!/bin/sh + +msg() { + echo "configure: $1" +} + +step_msg() { + msg + msg "$1" + msg +} + +warn() { + echo "configure: WARNING: $1" +} + +err() { + echo "configure: error: $1" + exit 1 +} + +need_ok() { + if [ $? -ne 0 ] + then + err "$1" + fi +} + +need_cmd() { + if command -v $1 >/dev/null 2>&1 + then msg "found $1" + else err "need $1" + fi +} + +make_dir() { + if [ ! -d $1 ] + then + msg "mkdir -p $1" + mkdir -p $1 + fi +} + +copy_if_changed() { + if cmp -s $1 $2 + then + msg "leaving $2 unchanged" + else + msg "cp $1 $2" + cp -f $1 $2 + chmod u-w $2 # make copied artifact read-only + fi +} + +move_if_changed() { + if cmp -s $1 $2 + then + msg "leaving $2 unchanged" + else + msg "mv $1 $2" + mv -f $1 $2 + chmod u-w $2 # make moved artifact read-only + fi +} + +putvar() { + local T + eval T=\$$1 + eval TLEN=\${#$1} + if [ $TLEN -gt 35 ] + then + printf "configure: %-20s := %.35s ...\n" $1 "$T" + else + printf "configure: %-20s := %s %s\n" $1 "$T" "$2" + fi + printf "%-20s := %s\n" $1 "$T" >>config.tmp +} + +probe() { + local V=$1 + shift + local P + local T + for P + do + T=$(command -v $P 2>&1) + if [ $? -eq 0 ] + then + VER0=$($P --version 2>/dev/null | head -1 \ + | sed -e 's/[^0-9]*\([vV]\?[0-9.]\+[^ ]*\).*/\1/' ) + if [ $? -eq 0 -a "x${VER0}" != "x" ] + then + VER="($VER0)" + else + VER="" + fi + break + else + VER="" + T="" + fi + done + eval $V=\$T + putvar $V "$VER" +} + +probe_need() { + local V=$1 + probe $* + eval VV=\$$V + if [ -z "$VV" ] + then + err "needed, but unable to find any of: $*" + fi +} + +validate_opt () { + for arg in $CFG_CONFIGURE_ARGS + do + isArgValid=0 + for option in $BOOL_OPTIONS + do + if test --disable-$option = $arg + then + isArgValid=1 + fi + if test --enable-$option = $arg + then + isArgValid=1 + fi + done + for option in $VAL_OPTIONS + do + if echo "$arg" | grep -q -- "--$option=" + then + isArgValid=1 + fi + done + if [ "$arg" = "--help" ] + then + echo + echo "No more help available for Configure options," + echo "check the Wiki or join our IRC channel" + break + else + if test $isArgValid -eq 0 + then + err "Option '$arg' is not recognized" + fi + fi + done +} + +valopt() { + VAL_OPTIONS="$VAL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + if [ $HELP -eq 0 ] + then + local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') + local V="CFG_${UOP}" + eval $V="$DEFAULT" + for arg in $CFG_CONFIGURE_ARGS + do + if echo "$arg" | grep -q -- "--$OP=" + then + val=$(echo "$arg" | cut -f2 -d=) + eval $V=$val + fi + done + putvar $V + else + if [ -z "$DEFAULT" ] + then + DEFAULT="" + fi + OP="${OP}=[${DEFAULT}]" + printf " --%-30s %s\n" "$OP" "$DOC" + fi +} + +opt() { + BOOL_OPTIONS="$BOOL_OPTIONS $1" + + local OP=$1 + local DEFAULT=$2 + shift + shift + local DOC="$*" + local FLAG="" + + if [ $DEFAULT -eq 0 ] + then + FLAG="enable" + else + FLAG="disable" + DOC="don't $DOC" + fi + + if [ $HELP -eq 0 ] + then + for arg in $CFG_CONFIGURE_ARGS + do + if [ "$arg" = "--${FLAG}-${OP}" ] + then + OP=$(echo $OP | tr 'a-z-' 'A-Z_') + FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') + local V="CFG_${FLAG}_${OP}" + eval $V=1 + putvar $V + fi + done + else + if [ ! -z "$META" ] + then + OP="$OP=<$META>" + fi + printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" + fi +} + +envopt() { + local NAME=$1 + local V="CFG_${NAME}" + eval VV=\$$V + + # If configure didn't set a value already, then check environment. + # + # (It is recommended that the configure script always check the + # environment before setting any values to envopt variables; see + # e.g. how CFG_CC is handled, where it first checks `-z "$CC"`, + # and issues msg if it ends up employing that provided value.) + if [ -z "$VV" ] + then + eval $V=\$$NAME + eval VV=\$$V + fi + + # If script or environment provided a value, save it. + if [ ! -z "$VV" ] + then + putvar $V + fi +} + +msg "looking for configure programs" +need_cmd cmp +need_cmd mkdir +need_cmd printf +need_cmd cut +need_cmd head +need_cmd grep +need_cmd xargs +need_cmd cp +need_cmd find +need_cmd uname +need_cmd date +need_cmd tr +need_cmd sed +need_cmd file + +CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/" +CFG_BUILD_DIR="$(pwd)/" +CFG_SELF="$0" +CFG_CONFIGURE_ARGS="$@" + +OPTIONS="" +HELP=0 +if [ "$1" = "--help" ] +then + HELP=1 + shift + echo + echo "Usage: $CFG_SELF [options]" + echo + echo "Options:" + echo +else + msg "recreating config.tmp" + echo '' >config.tmp + + step_msg "processing $CFG_SELF args" +fi + +BOOL_OPTIONS="" +VAL_OPTIONS="" + +opt debug 1 "build with extra debug fun" +opt nightly 0 "build nightly packages" +opt verify-install 1 "verify installed binaries work" +valopt prefix "/usr/local" "set installation prefix" +valopt local-rust-root "" "set prefix for local rust binary" + +if [ $HELP -eq 0 ]; then + if [ ! -z "${CFG_LOCAL_RUST_ROOT}" ]; then + export LD_LIBRARY_PATH="${CFG_LOCAL_RUST_ROOT}/lib:$LD_LIBRARY_PATH" + export DYLD_LIBRARY_PATH="${CFG_LOCAL_RUST_ROOT}/lib:$DYLD_LIBRARY_PATH" + LRV=`${CFG_LOCAL_RUST_ROOT}/bin/rustc --version` + if [ $? -eq 0 ]; then + step_msg "using rustc at: ${CFG_LOCAL_RUST_ROOT} with version: $LRV" + else + err "failed to run rustc at: ${CFG_LOCAL_RUST_ROOT}" + fi + CFG_RUSTC="${CFG_LOCAL_RUST_ROOT}/bin/rustc" + else + probe_need CFG_RUSTC rustc + fi + DEFAULT_BUILD=$(${CFG_RUSTC} --version verbose | grep 'host: ' | sed 's/host: //') +fi + +valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple" +valopt host "${CFG_BUILD}" "GNUs ./configure syntax LLVM host triples" +valopt target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples" + +valopt localstatedir "/var/lib" "local state directory" +valopt sysconfdir "/etc" "install system configuration files" +valopt datadir "${CFG_PREFIX}/share" "install data" +valopt infodir "${CFG_PREFIX}/share/info" "install additional info" +valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH" +valopt libdir "${CFG_PREFIX}/lib" "install libraries" + +if [ $HELP -eq 1 ] +then + echo + exit 0 +fi + +# Validate Options +step_msg "validating $CFG_SELF args" +validate_opt + +step_msg "looking for build programs" + +probe_need CFG_CURLORWGET curl wget +probe_need CFG_PYTHON python + +# a little post-processing of various config values +CFG_PREFIX=${CFG_PREFIX%/} +CFG_MANDIR=${CFG_MANDIR%/} +CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')" +CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')" + +# copy host-triples to target-triples so that hosts are a subset of targets +V_TEMP="" +for i in $CFG_HOST $CFG_TARGET; +do + echo "$V_TEMP" | grep -qF $i || V_TEMP="$V_TEMP${V_TEMP:+ }$i" +done +CFG_TARGET=$V_TEMP + +if [ "$CFG_SRC_DIR" != "$CFG_BUILD_DIR" ]; then + err "cargo does not currently support an out-of-tree build dir" +fi + +step_msg "writing configuration" + +putvar CFG_SRC_DIR +putvar CFG_BUILD_DIR +putvar CFG_CONFIGURE_ARGS +putvar CFG_PREFIX +putvar CFG_BUILD +putvar CFG_HOST +putvar CFG_TARGET +putvar CFG_LIBDIR +putvar CFG_MANDIR +putvar CFG_RUSTC + +msg +copy_if_changed ${CFG_SRC_DIR}Makefile.in ./Makefile +move_if_changed config.tmp config.mk +rm -f config.tmp +touch config.stamp + +step_msg "complete" +msg diff --git a/src/bin/cargo-version.rs b/src/bin/cargo-version.rs index 3f0b2e0de07..4c5b1e0d22e 100644 --- a/src/bin/cargo-version.rs +++ b/src/bin/cargo-version.rs @@ -27,7 +27,7 @@ fn main() { fn execute(_: Options, _: &mut MultiShell) -> CliResult> { debug!("executing; cmd=cargo-version; args={}", os::args()); - println!("{}", env!("CFG_VERSION")); + println!("cargo {}", env!("CFG_VERSION")); Ok(None) } diff --git a/src/snapshots.txt b/src/snapshots.txt index 3b0618d14e6..7869ab79149 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,8 @@ +2014-07-29 + mac 53f8bc39132e987d25e022698c3234fee0916ecf + linux b7dbdc89126577fda2eef7d63c5f7fc1d8d28f99 + win 9551454e2ce649d146ad8d856cee3672ab0def02 + 2014-07-26 mac 9a78815c7fcdb1cdabc93eb120f80444f209d968 linux b38e7c45292d2cc6a1932fa9a1f349f9b92c0c1d