From 16c7eb41354c3c1ca5fca08bd0501568fa2b5212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Fri, 3 Jan 2014 21:25:18 +0100 Subject: [PATCH 01/11] Speed up `realpath()` with dynamically loaded C extension On systems that support both C compiling and dynamic loading, we can speed up `realpath()` (where most time in rbenv is spent) by replacing it with a dynamically loaded bash builtin. When `make -C src` is called in the project's root, `libexec/rbenv-realpath.dylib` will be created. If it exists, rbenv will attempt to load it as a builtin command. If it fails, execution will fall back to the old `realpath()` shell function. --- .gitignore | 2 ++ libexec/rbenv-hooks | 4 +++- src/Makefile | 10 ++++++++++ src/bash.h | 31 +++++++++++++++++++++++++++++++ src/realpath.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/Makefile create mode 100644 src/bash.h create mode 100644 src/realpath.c diff --git a/.gitignore b/.gitignore index cfcaaa17..e64b0156 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ /versions /sources /cache +/libexec/*.dylib +/src/*.o diff --git a/libexec/rbenv-hooks b/libexec/rbenv-hooks index 86386719..939891d1 100755 --- a/libexec/rbenv-hooks +++ b/libexec/rbenv-hooks @@ -19,6 +19,7 @@ if [ -z "$RBENV_COMMAND" ]; then exit 1 fi +if ! enable -f "${BASH_SOURCE%/*}"/rbenv-realpath.dylib realpath 2>/dev/null; then READLINK=$(type -p greadlink readlink | head -1) if [ -z "$READLINK" ]; then echo "rbenv: cannot find readlink - are you missing GNU coreutils?" >&2 @@ -42,13 +43,14 @@ realpath() { echo "$(pwd)/$name" cd "$cwd" } +fi IFS=: hook_paths=($RBENV_HOOK_PATH) shopt -s nullglob for path in "${hook_paths[@]}"; do for script in "$path/$RBENV_COMMAND"/*.bash; do - echo $(realpath $script) + realpath "$script" done done shopt -u nullglob diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 00000000..3d359c0d --- /dev/null +++ b/src/Makefile @@ -0,0 +1,10 @@ +SHOBJ_LDFLAGS = -dynamiclib -current_version 1.0 + +.c.o: + $(CC) $(CFLAGS) -c -o $@ $< + +../libexec/rbenv-realpath.dylib: realpath.o + $(CC) $(CFLAGS) $(SHOBJ_LDFLAGS) -o $@ realpath.o + +clean: + rm -f *.o ../libexec/*.dylib diff --git a/src/bash.h b/src/bash.h new file mode 100644 index 00000000..1b29fd05 --- /dev/null +++ b/src/bash.h @@ -0,0 +1,31 @@ +#ifndef __BASH_H__ +#define __BASH_H__ + +#define EXECUTION_SUCCESS 0 +#define EXECUTION_FAILURE 1 +#define EX_USAGE 258 + +#define BUILTIN_ENABLED 1 + +typedef struct word_desc { + char *word; + int flags; +} WORD_DESC; + +typedef struct word_list { + struct word_list *next; + WORD_DESC *word; +} WORD_LIST; + +typedef int sh_builtin_func_t(WORD_LIST *); + +struct builtin { + char *name; + sh_builtin_func_t *function; + int flags; + char * const *long_doc; + const char *short_doc; + char *unused; +}; + +#endif diff --git a/src/realpath.c b/src/realpath.c new file mode 100644 index 00000000..6c0c9f3c --- /dev/null +++ b/src/realpath.c @@ -0,0 +1,43 @@ +#include "bash.h" +#include +#include + +int realpath_builtin(list) +WORD_LIST *list; +{ + int es; + char *realbuf, *p; + + if (list == 0) { + // builtin_usage(); + return (EX_USAGE); + } + + for (es = EXECUTION_SUCCESS; list; list = list->next) { + p = list->word->word; + realbuf = realpath(p, NULL); + if (realbuf == NULL) { + es = EXECUTION_FAILURE; + // builtin_error("%s: cannot resolve: %s", p, strerror(errno)); + } else { + printf("%s\n", realbuf); + free(realbuf); + } + } + return es; +} + +char *realpath_doc[] = { + "Display each PATHNAME argument, resolving symbolic links. The exit status", + "is 0 if each PATHNAME was resolved; non-zero otherwise.", + (char *)NULL +}; + +struct builtin realpath_struct = { + "realpath", + realpath_builtin, + BUILTIN_ENABLED, + realpath_doc, + "realpath pathname [pathname...]", + 0 +}; From 284588f9b4769297c8affa5419ec2e6f59047c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 4 Jan 2014 16:32:54 +0100 Subject: [PATCH 02/11] Fix hooks tests on OS X by expanding BATS_TMPDIR With `realpath` extension, hooks tests on OS X will output `/private/tmp` instead of `/tmp` because the latter is an actual symlink to the former. Avoid this mistmach in output assertions by expanding BATS_TMPDIR if `realpath` extension is compiled. --- test/test_helper.bash | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/test_helper.bash b/test/test_helper.bash index 53ae8e64..1f772bea 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -1,7 +1,11 @@ unset RBENV_VERSION unset RBENV_DIR -RBENV_TEST_DIR="${BATS_TMPDIR}/rbenv" +if enable -f "${BATS_TEST_DIRNAME}"/../libexec/rbenv-realpath.dylib realpath 2>/dev/null; then + RBENV_TEST_DIR="$(realpath "$BATS_TMPDIR")/rbenv" +else + RBENV_TEST_DIR="${BATS_TMPDIR}/rbenv" +fi # guard against executing this block twice due to bats internals if [ "$RBENV_ROOT" != "${RBENV_TEST_DIR}/root" ]; then From 5287e2ebf46b8636af653c1c61d4dc0dffd65796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 4 Jan 2014 16:36:02 +0100 Subject: [PATCH 03/11] Avoid slow `abs_dirname()` by loading `realpath` extension This speeds up every `rbenv` invocation significantly. --- libexec/rbenv | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libexec/rbenv b/libexec/rbenv index 2d475857..a458c473 100755 --- a/libexec/rbenv +++ b/libexec/rbenv @@ -12,6 +12,12 @@ if [ -n "$RBENV_DEBUG" ]; then set -x fi +if enable -f "${0%/*}"/../libexec/rbenv-realpath.dylib realpath 2>/dev/null; then + abs_dirname() { + local path="$(realpath "$1")" + echo "${path%/*}" + } +else READLINK=$(type -p greadlink readlink | head -1) if [ -z "$READLINK" ]; then echo "rbenv: cannot find readlink - are you missing GNU coreutils?" >&2 @@ -35,6 +41,7 @@ abs_dirname() { pwd cd "$cwd" } +fi if [ -z "${RBENV_ROOT}" ]; then RBENV_ROOT="${HOME}/.rbenv" From 8bac95899491cc043a40b274be224236a8224483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 4 Jan 2014 16:37:20 +0100 Subject: [PATCH 04/11] Stop using `abs_dirname()` in rbenv-init It's slow and not necessary since we expect `$0` to already be expanded. In tests this change forces us to deal with some relative paths, but it's not a big deal. The `rbenv init -` output in the most common case will be the same as before: source '/home/myuser/.rbenv/libexec/../completions/rbenv.bash' --- libexec/rbenv-init | 26 +------------------------- test/init.bats | 4 ++-- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/libexec/rbenv-init b/libexec/rbenv-init index 5f9079a7..8718c116 100755 --- a/libexec/rbenv-init +++ b/libexec/rbenv-init @@ -28,31 +28,7 @@ if [ -z "$shell" ]; then shell="$(basename "${shell:-$SHELL}")" fi -READLINK=$(type -p greadlink readlink | head -1) -if [ -z "$READLINK" ]; then - echo "rbenv: cannot find readlink - are you missing GNU coreutils?" >&2 - exit 1 -fi - -resolve_link() { - $READLINK "$1" -} - -abs_dirname() { - local cwd="$(pwd)" - local path="$1" - - while [ -n "$path" ]; do - cd "${path%/*}" - local name="${path##*/}" - path="$(resolve_link "$name" || true)" - done - - pwd - cd "$cwd" -} - -root="$(abs_dirname "$0")/.." +root="${0%/*}/.." if [ -z "$print" ]; then case "$shell" in diff --git a/test/init.bats b/test/init.bats index aa50f091..2587a014 100644 --- a/test/init.bats +++ b/test/init.bats @@ -21,7 +21,7 @@ load test_helper root="$(cd $BATS_TEST_DIRNAME/.. && pwd)" run rbenv-init - bash assert_success - assert_line "source '${root}/libexec/../completions/rbenv.bash'" + assert_line "source '${root}/test/../libexec/../completions/rbenv.bash'" } @test "detect parent shell" { @@ -35,7 +35,7 @@ load test_helper root="$(cd $BATS_TEST_DIRNAME/.. && pwd)" run rbenv-init - fish assert_success - assert_line ". '${root}/libexec/../completions/rbenv.fish'" + assert_line ". '${root}/test/../libexec/../completions/rbenv.fish'" } @test "fish instructions" { From 68b92a7f5d408b57dbba195ddd3920d533f1f429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 4 Jan 2014 21:58:12 +0100 Subject: [PATCH 05/11] Test compiled native extensions on Travis CI --- .travis.yml | 6 ++++-- test/run | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100755 test/run diff --git a/.travis.yml b/.travis.yml index ca1abab7..95b46cc2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ install: git clone https://github.com/sstephenson/bats.git -script: bats/bin/bats --tap test -# skips unnecessary Ruby-specific setup +script: PATH="./bats/bin:$PATH" test/run language: c +env: + - RBENV_NATIVE_EXT= + - RBENV_NATIVE_EXT=1 diff --git a/test/run b/test/run new file mode 100755 index 00000000..44f41288 --- /dev/null +++ b/test/run @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e + +if [ -n "$RBENV_NATIVE_EXT" ]; then + make -C src +fi + +exec bats ${CI:+--tap} test From 3f74da0e73a088f1273554f8d520e893a0697d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 4 Jan 2014 21:59:27 +0100 Subject: [PATCH 06/11] Fail hard if RBENV_NATIVE_EXT is set but extensions failed to load --- libexec/rbenv | 4 ++++ libexec/rbenv-hooks | 4 ++++ test/test_helper.bash | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/libexec/rbenv b/libexec/rbenv index a458c473..4041df82 100755 --- a/libexec/rbenv +++ b/libexec/rbenv @@ -18,6 +18,10 @@ if enable -f "${0%/*}"/../libexec/rbenv-realpath.dylib realpath 2>/dev/null; the echo "${path%/*}" } else + if [ -n "$RBENV_NATIVE_EXT" ]; then + echo "rbenv: failed to load \`realpath' builtin" >&2 + exit 1 + fi READLINK=$(type -p greadlink readlink | head -1) if [ -z "$READLINK" ]; then echo "rbenv: cannot find readlink - are you missing GNU coreutils?" >&2 diff --git a/libexec/rbenv-hooks b/libexec/rbenv-hooks index 939891d1..201c91da 100755 --- a/libexec/rbenv-hooks +++ b/libexec/rbenv-hooks @@ -20,6 +20,10 @@ if [ -z "$RBENV_COMMAND" ]; then fi if ! enable -f "${BASH_SOURCE%/*}"/rbenv-realpath.dylib realpath 2>/dev/null; then + if [ -n "$RBENV_NATIVE_EXT" ]; then + echo "rbenv: failed to load \`realpath' builtin" >&2 + exit 1 + fi READLINK=$(type -p greadlink readlink | head -1) if [ -z "$READLINK" ]; then echo "rbenv: cannot find readlink - are you missing GNU coreutils?" >&2 diff --git a/test/test_helper.bash b/test/test_helper.bash index 1f772bea..461bb085 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -4,6 +4,10 @@ unset RBENV_DIR if enable -f "${BATS_TEST_DIRNAME}"/../libexec/rbenv-realpath.dylib realpath 2>/dev/null; then RBENV_TEST_DIR="$(realpath "$BATS_TMPDIR")/rbenv" else + if [ -n "$RBENV_NATIVE_EXT" ]; then + echo "rbenv: failed to load \`realpath' builtin" >&2 + exit 1 + fi RBENV_TEST_DIR="${BATS_TMPDIR}/rbenv" fi From b5622bee3ab562dd867a1189df8551f44d36443e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 4 Jan 2014 22:04:59 +0100 Subject: [PATCH 07/11] Try without `-current_version` Seems to only work on OS X; fails on Travis https://travis-ci.org/sstephenson/rbenv/jobs/16384866 --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 3d359c0d..6b31fd06 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ -SHOBJ_LDFLAGS = -dynamiclib -current_version 1.0 +SHOBJ_LDFLAGS = -dynamiclib .c.o: $(CC) $(CFLAGS) -c -o $@ $< From 8facb3b3a790fd275a4e8d5f4de474bbd837c040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sun, 5 Jan 2014 17:58:07 +0100 Subject: [PATCH 08/11] Import `shobj-conf` script from bash Given the `-o ` parameter, the script generates environment variables with information how to compile dynamically loadable libraries for that system. Imported from bash-3.2.48 --- src/shobj-conf | 547 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 547 insertions(+) create mode 100755 src/shobj-conf diff --git a/src/shobj-conf b/src/shobj-conf new file mode 100755 index 00000000..ef7863a3 --- /dev/null +++ b/src/shobj-conf @@ -0,0 +1,547 @@ +#! /bin/sh +# +# shobj-conf -- output a series of variable assignments to be substituted +# into a Makefile by configure which specify system-dependent +# information for creating shared objects that may be loaded +# into bash with `enable -f' +# +# usage: shobj-conf [-C compiler] -c host_cpu -o host_os -v host_vendor +# +# Chet Ramey +# chet@po.cwru.edu + +# Copyright (C) 1996-2002 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +# +# defaults +# +SHOBJ_STATUS=supported +SHLIB_STATUS=supported + +SHOBJ_CC=cc +SHOBJ_CFLAGS= +SHOBJ_LD= +SHOBJ_LDFLAGS= +SHOBJ_XLDFLAGS= +SHOBJ_LIBS= + +SHLIB_XLDFLAGS= +SHLIB_LIBS= + +SHLIB_DOT='.' +SHLIB_LIBPREF='lib' +SHLIB_LIBSUFF='so' + +SHLIB_LIBVERSION='$(SHLIB_LIBSUFF)' +SHLIB_DLLVERSION='$(SHLIB_MAJOR)' + +PROGNAME=`basename $0` +USAGE="$PROGNAME [-C compiler] -c host_cpu -o host_os -v host_vendor" + +while [ $# -gt 0 ]; do + case "$1" in + -C) shift; SHOBJ_CC="$1"; shift ;; + -c) shift; host_cpu="$1"; shift ;; + -o) shift; host_os="$1"; shift ;; + -v) shift; host_vendor="$1"; shift ;; + *) echo "$USAGE" >&2 ; exit 2;; + esac +done + +case "${host_os}-${SHOBJ_CC}" in +sunos4*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD=/usr/bin/ld + SHOBJ_LDFLAGS='-assert pure-text' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +sunos4*) + SHOBJ_CFLAGS=-pic + SHOBJ_LD=/usr/bin/ld + SHOBJ_LDFLAGS='-assert pure-text' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +sunos5*-*gcc*|solaris2*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + ld_used=`gcc -print-prog-name=ld` + if ${ld_used} -V 2>&1 | grep GNU >/dev/null 2>&1; then + # This line works for the GNU ld + SHOBJ_LDFLAGS='-shared -Wl,-h,$@' + else + # This line works for the Solaris linker in /usr/ccs/bin/ld + SHOBJ_LDFLAGS='-shared -Wl,-i -Wl,-h,$@' + fi + +# SHLIB_XLDFLAGS='-R $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sunos5*|solaris2*) + SHOBJ_CFLAGS='-K pic' + SHOBJ_LD=/usr/ccs/bin/ld + SHOBJ_LDFLAGS='-G -dy -z text -i -h $@' + +# SHLIB_XLDFLAGS='-R $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +# All versions of Linux or the semi-mythical GNU Hurd. +linux*-*|gnu*-*|k*bsd*-gnu-*) + SHOBJ_CFLAGS=-fPIC + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-Wl,-rpath,$(libdir) -Wl,-soname,`basename $@ $(SHLIB_MINOR)`' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +freebsd2* | netbsd*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-x -Bshareable' + + SHLIB_XLDFLAGS='-R$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +# FreeBSD-3.x ELF +freebsd[3-9]*|freebsdelf[3-9]*|freebsdaout[3-9]*|dragonfly*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + + if [ -x /usr/bin/objformat ] && [ "`/usr/bin/objformat`" = "elf" ]; then + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-Wl,-rpath,$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + else + SHOBJ_LDFLAGS='-shared' + + SHLIB_XLDFLAGS='-R$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + fi + ;; + +# Darwin/MacOS X +darwin8*) + SHOBJ_STATUS=supported + SHLIB_STATUS=supported + + SHOBJ_CFLAGS='-fno-common' + + SHOBJ_LD='MACOSX_DEPLOYMENT_TARGET=10.3 ${CC}' + + SHLIB_LIBVERSION='$(SHLIB_MAJOR)$(SHLIB_MINOR).$(SHLIB_LIBSUFF)' + SHLIB_LIBSUFF='dylib' + + SHOBJ_LDFLAGS='-undefined dynamic_lookup' + SHLIB_XLDFLAGS='-dynamiclib -arch_only `/usr/bin/arch` -install_name $(libdir)/$@ -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR) -v' + + SHLIB_LIBS='-lncurses' # see if -lcurses works on MacOS X 10.1 + ;; + +darwin*|macosx*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=supported + + SHOBJ_CFLAGS='-fno-common' + + SHOBJ_LD='${CC}' + + SHLIB_LIBVERSION='$(SHLIB_MAJOR)$(SHLIB_MINOR).$(SHLIB_LIBSUFF)' + SHLIB_LIBSUFF='dylib' + + case "${host_os}" in + darwin[78]*) SHOBJ_LDFLAGS='' + SHLIB_XLDFLAGS='-dynamiclib -arch_only `/usr/bin/arch` -install_name $(libdir)/$@ -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR) -v' + ;; + *) SHOBJ_LDFLAGS='-dynamic' + SHLIB_XLDFLAGS='-arch_only `/usr/bin/arch` -install_name $(libdir)/$@ -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR) -v' + ;; + esac + + SHLIB_LIBS='-lncurses' # see if -lcurses works on MacOS X 10.1 + ;; + +openbsd*) + SHOBJ_CFLAGS=-fPIC + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_XLDFLAGS='-R$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +bsdi2*) + SHOBJ_CC=shlicc2 + SHOBJ_CFLAGS= + SHOBJ_LD=ld + SHOBJ_LDFLAGS=-r + SHOBJ_LIBS=-lc_s.2.1.0 + + # BSD/OS 2.x and 3.x `shared libraries' are too much of a pain in + # the ass -- they require changing {/usr/lib,etc}/shlib.map on + # each system, and the library creation process is byzantine + SHLIB_STATUS=unsupported + ;; + +bsdi3*) + SHOBJ_CC=shlicc2 + SHOBJ_CFLAGS= + SHOBJ_LD=ld + SHOBJ_LDFLAGS=-r + SHOBJ_LIBS=-lc_s.3.0.0 + + # BSD/OS 2.x and 3.x `shared libraries' are too much of a pain in + # the ass -- they require changing {/usr/lib,etc}/shlib.map on + # each system, and the library creation process is byzantine + SHLIB_STATUS=unsupported + ;; + +bsdi4*) + # BSD/OS 4.x now supports ELF and SunOS-style dynamically-linked + # shared libraries. gcc 2.x is the standard compiler, and the + # `normal' gcc options should work as they do in Linux. + + SHOBJ_CFLAGS=-fPIC + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-Wl,-soname,`basename $@ $(SHLIB_MINOR)`' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +osf*-*gcc*) + # Fix to use gcc linker driver from bfischer@TechFak.Uni-Bielefeld.DE + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-rpath $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +osf*) + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-shared -soname $@ -expect_unresolved "*"' + + SHLIB_XLDFLAGS='-rpath $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +aix4.[2-9]*-*gcc*) # lightly tested by jik@cisco.com + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='ld' + SHOBJ_LDFLAGS='-bdynamic -bnoentry -bexpall' + SHOBJ_XLDFLAGS='-G' + + SHLIB_XLDFLAGS='-bM:SRE' + SHLIB_LIBS='-lcurses -lc' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +aix4.[2-9]*) + SHOBJ_CFLAGS=-K + SHOBJ_LD='ld' + SHOBJ_LDFLAGS='-bdynamic -bnoentry -bexpall' + SHOBJ_XLDFLAGS='-G' + + SHLIB_XLDFLAGS='-bM:SRE' + SHLIB_LIBS='-lcurses -lc' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +# +# THE FOLLOWING ARE UNTESTED -- and some may not support the dlopen interface +# +irix[56]*-*gcc*) + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-Wl,-rpath,$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +irix[56]*) + SHOBJ_CFLAGS='-K PIC' + SHOBJ_LD=ld +# SHOBJ_LDFLAGS='-call_shared -hidden_symbol -no_unresolved -soname $@' +# Change from David Kaelbling . If you have problems, +# remove the `-no_unresolved' + SHOBJ_LDFLAGS='-shared -no_unresolved -soname $@' + + SHLIB_XLDFLAGS='-rpath $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +hpux9*-*gcc*) + # must use gcc; the bundled cc cannot compile PIC code + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-b -Wl,+s' + + SHLIB_XLDFLAGS='-Wl,+b,$(libdir)' + SHLIB_LIBSUFF='sl' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +hpux9*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + + # If you are using the HP ANSI C compiler, you can uncomment and use + # this code (I have not tested it) +# SHOBJ_STATUS=supported +# SHLIB_STATUS=supported +# +# SHOBJ_CFLAGS='+z' +# SHOBJ_LD='ld' +# SHOBJ_LDFLAGS='-b +s' +# +# SHLIB_XLDFLAGS='+b $(libdir)' +# SHLIB_LIBSUFF='sl' +# SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + + ;; + +hpux10*-*gcc*) + # must use gcc; the bundled cc cannot compile PIC code + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' + # if you have problems linking here, moving the `-Wl,+h,$@' from + # SHLIB_XLDFLAGS to SHOBJ_LDFLAGS has been reported to work + SHOBJ_LDFLAGS='-shared -Wl,-b -Wl,+s' + + SHLIB_XLDFLAGS='-Wl,+h,$@ -Wl,+b,$(libdir)' + SHLIB_LIBSUFF='sl' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +hpux10*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + + # If you are using the HP ANSI C compiler, you can uncomment and use + # this code (I have not tested it) +# SHOBJ_STATUS=supported +# SHLIB_STATUS=supported +# +# SHOBJ_CFLAGS='+z' +# SHOBJ_LD='ld' +# SHOBJ_LDFLAGS='-b +s +h $@' +# +# SHLIB_XLDFLAGS='+b $(libdir)' +# SHLIB_LIBSUFF='sl' +# SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + + ;; + +hpux11*-*gcc*) + # must use gcc; the bundled cc cannot compile PIC code + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' +# SHOBJ_LDFLAGS='-shared -Wl,-b -Wl,-B,symbolic -Wl,+s -Wl,+std -Wl,+h,$@' + SHOBJ_LDFLAGS='-shared -fpic -Wl,-b -Wl,+s -Wl,+h,$@' + + SHLIB_XLDFLAGS='-Wl,+b,$(libdir)' + SHLIB_LIBSUFF='sl' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +hpux11*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + + # If you are using the HP ANSI C compiler, you can uncomment and use + # this code (I have not tested it) +# SHOBJ_STATUS=supported +# SHLIB_STATUS=supported +# +# SHOBJ_CFLAGS='+z' +# SHOBJ_LD='ld' +# SHOBJ_LDFLAGS='-b +s +h $@' +# +# SHLIB_XLDFLAGS='+b $(libdir)' +# SHLIB_LIBSUFF='sl' +# SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + + ;; + +sysv4*-*gcc*) + SHOBJ_CFLAGS=-shared + SHOBJ_LDFLAGS='-shared -h $@' + SHOBJ_LD='${CC}' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv4*) + SHOBJ_CFLAGS='-K PIC' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-dy -z text -G -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sco3.2v5*-*gcc*) + SHOBJ_CFLAGS='-fpic' # DEFAULTS TO ELF + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sco3.2v5*) + SHOBJ_CFLAGS='-K pic -b elf' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-G -b elf -dy -z text -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv5uw7*-*gcc*) + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv5uw7*) + SHOBJ_CFLAGS='-K PIC' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-G -dy -z text -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv5UnixWare*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv5UnixWare*) + SHOBJ_CFLAGS='-K PIC' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-G -dy -z text -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv5OpenUNIX*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv5OpenUNIX*) + SHOBJ_CFLAGS='-K PIC' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-G -dy -z text -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +dgux*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +dgux*) + SHOBJ_CFLAGS='-K pic' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-G -dy -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +msdos*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + ;; + +cygwin*) + SHOBJ_LD='$(CC)' + SHOBJ_LDFLAGS='-shared -Wl,--enable-auto-import -Wl,--enable-auto-image-base -Wl,--export-all -Wl,--out-implib=$(@).a' + SHLIB_LIBPREF='cyg' + SHLIB_LIBSUFF='dll' + SHLIB_LIBVERSION='$(SHLIB_DLLVERSION).$(SHLIB_LIBSUFF)' + SHLIB_LIBS='$(TERMCAP_LIB)' + + SHLIB_DOT= + # For official cygwin releases, DLLVERSION will be defined in the + # environment of configure, and will be incremented any time the API + # changes in a non-backwards compatible manner. Otherwise, it is just + # SHLIB_MAJOR. + if [ -n "$DLLVERSION" ] ; then + SHLIB_DLLVERSION="$DLLVERSION" + fi + ;; + +# +# Rely on correct gcc configuration for everything else +# +*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + ;; + +esac + +echo SHOBJ_CC=\'"$SHOBJ_CC"\' +echo SHOBJ_CFLAGS=\'"$SHOBJ_CFLAGS"\' +echo SHOBJ_LD=\'"$SHOBJ_LD"\' +echo SHOBJ_LDFLAGS=\'"$SHOBJ_LDFLAGS"\' +echo SHOBJ_XLDFLAGS=\'"$SHOBJ_XLDFLAGS"\' +echo SHOBJ_LIBS=\'"$SHOBJ_LIBS"\' + +echo SHLIB_XLDFLAGS=\'"$SHLIB_XLDFLAGS"\' +echo SHLIB_LIBS=\'"$SHLIB_LIBS"\' + +echo SHLIB_DOT=\'"$SHLIB_DOT"\' + +echo SHLIB_LIBPREF=\'"$SHLIB_LIBPREF"\' +echo SHLIB_LIBSUFF=\'"$SHLIB_LIBSUFF"\' + +echo SHLIB_LIBVERSION=\'"$SHLIB_LIBVERSION"\' +echo SHLIB_DLLVERSION=\'"$SHLIB_DLLVERSION"\' + +echo SHOBJ_STATUS=\'"$SHOBJ_STATUS"\' +echo SHLIB_STATUS=\'"$SHLIB_STATUS"\' + +exit 0 From 302b317b895777cbf8a322b3362a17005131ae48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sun, 5 Jan 2014 18:00:31 +0100 Subject: [PATCH 09/11] Fix `shobj-conf` on Darwin The `shobj-conf` script imported from bash seems to not support the latest OS X. This makes sure that `SHOBJ_LDFLAG=-dynamiclib` is output for Darwin10+ (latest version is Darwin 13.0). --- src/shobj-conf | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/shobj-conf b/src/shobj-conf index ef7863a3..593867ee 100755 --- a/src/shobj-conf +++ b/src/shobj-conf @@ -142,6 +142,17 @@ freebsd[3-9]*|freebsdelf[3-9]*|freebsdaout[3-9]*|dragonfly*) ;; # Darwin/MacOS X +darwin1*) + SHOBJ_STATUS=supported + SHLIB_STATUS=supported + + SHOBJ_CFLAGS='' + SHLIB_LIBSUFF='dylib' + + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-dynamiclib' + ;; + darwin8*) SHOBJ_STATUS=supported SHLIB_STATUS=supported From a6e0785b84993fa3a5192a66ee816ed7c0e0a43e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sun, 5 Jan 2014 17:55:43 +0100 Subject: [PATCH 10/11] Create `configure` script to generate a cross-platform Makefile The previous Makefile only worked on OS X. The dynamically generated Makefile (from `Makefile.in`) should now work on multiple platforms (tested on OS X and Ubuntu). --- .gitignore | 1 + src/Makefile | 10 ---------- src/Makefile.in | 25 +++++++++++++++++++++++++ src/configure | 39 +++++++++++++++++++++++++++++++++++++++ test/run | 1 + 5 files changed, 66 insertions(+), 10 deletions(-) delete mode 100644 src/Makefile create mode 100644 src/Makefile.in create mode 100755 src/configure diff --git a/.gitignore b/.gitignore index e64b0156..84639e79 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ /sources /cache /libexec/*.dylib +/src/Makefile /src/*.o diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 6b31fd06..00000000 --- a/src/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -SHOBJ_LDFLAGS = -dynamiclib - -.c.o: - $(CC) $(CFLAGS) -c -o $@ $< - -../libexec/rbenv-realpath.dylib: realpath.o - $(CC) $(CFLAGS) $(SHOBJ_LDFLAGS) -o $@ realpath.o - -clean: - rm -f *.o ../libexec/*.dylib diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 00000000..b4b1825b --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,25 @@ +CC = @CC@ + +CFLAGS = @CFLAGS@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ +DEFS = @DEFS@ +LOCAL_DEFS = @LOCAL_DEFS@ + +CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS) + +SHOBJ_CC = @SHOBJ_CC@ +SHOBJ_CFLAGS = @SHOBJ_CFLAGS@ +SHOBJ_LD = @SHOBJ_LD@ +SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@ +SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@ +SHOBJ_LIBS = @SHOBJ_LIBS@ +SHOBJ_STATUS = @SHOBJ_STATUS@ + +.c.o: + $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) -c -o $@ $< + +../libexec/rbenv-realpath.dylib: realpath.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS) + +clean: + rm -f *.o ../libexec/*.dylib diff --git a/src/configure b/src/configure new file mode 100755 index 00000000..f54f09d2 --- /dev/null +++ b/src/configure @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -e + +src_dir="${0%/*}" + +CC="${CC:-gcc}" + +if ! which "$CC" &>/dev/null; then + echo "no compiler found: $CC" >&2 + exit 1 +fi + +case "$(uname -s)" in +Darwin* ) + host_os="darwin$(uname -r)" + ;; +OpenBSD* ) + host_os="openbsd$(uname -r)" + ;; +* ) + host_os="linux-gnu" +esac + +eval "$("$src_dir"/shobj-conf -C "$CC" -o "$host_os")" + +sed " + s,@CC@,${CC}, + s,@CFLAGS@,${CFLAGS}, + s,@LOCAL_CFLAGS@,${LOCAL_CFLAGS}, + s,@DEFS@,${DEFS}, + s,@LOCAL_DEFS@,${LOCAL_DEFS}, + s,@SHOBJ_CC@,${SHOBJ_CC}, + s,@SHOBJ_CFLAGS@,${SHOBJ_CFLAGS}, + s,@SHOBJ_LD@,${SHOBJ_LD}, + s,@SHOBJ_LDFLAGS@,${SHOBJ_LDFLAGS//,/\,}, + s,@SHOBJ_XLDFLAGS@,${SHOBJ_XLDFLAGS//,/\,}, + s,@SHOBJ_LIBS@,${SHOBJ_LIBS}, + s,@SHOBJ_STATUS@,${SHOBJ_STATUS}, +" "$src_dir"/Makefile.in > "$src_dir"/Makefile diff --git a/test/run b/test/run index 44f41288..9d3b9e52 100755 --- a/test/run +++ b/test/run @@ -2,6 +2,7 @@ set -e if [ -n "$RBENV_NATIVE_EXT" ]; then + src/configure make -C src fi From 294cff3fd4a2d6bfbabf91591383f99715144d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sun, 5 Jan 2014 18:27:35 +0100 Subject: [PATCH 11/11] Fall back to `cc` as default compiler when `gcc` is not available --- src/configure | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/configure b/src/configure index f54f09d2..dc29eb79 100755 --- a/src/configure +++ b/src/configure @@ -3,10 +3,17 @@ set -e src_dir="${0%/*}" -CC="${CC:-gcc}" +if [ -z "$CC" ]; then + if type -p gcc >/dev/null; then + CC=gcc + else + echo "warning: gcc not found; using CC=cc" >&2 + CC=cc + fi +fi -if ! which "$CC" &>/dev/null; then - echo "no compiler found: $CC" >&2 +if ! type -p "$CC" >/dev/null; then + echo "aborted: compiler not found: $CC" >&2 exit 1 fi