From 34f6c34dfb6d8f1bfc53ef232ef34531e45803e9 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Sat, 30 Dec 2017 15:04:22 +0200 Subject: [PATCH 01/10] Correct jbuild-ignore Since beta15, jbuilder no longer permits subdirectories in jbuild-ignore files so the sub-directory ones are split off to separate files. Signed-off-by: David Allsopp --- .gitignore | 1 + jbuild-ignore | 2 -- src_ext/Makefile | 9 +++++++-- tests/jbuild-ignore | 1 + 4 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 tests/jbuild-ignore diff --git a/.gitignore b/.gitignore index 885ea173088..c00344afd54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ src_ext/*.tbz src_ext/*.tar.gz src_ext/archives/* src_ext/*.download +src_ext/jbuild-ignore *.tar.bz2 *.annot *.tar.gz diff --git a/jbuild-ignore b/jbuild-ignore index b793755791a..b7c200acbff 100644 --- a/jbuild-ignore +++ b/jbuild-ignore @@ -1,3 +1 @@ bootstrap -src_ext/jbuilder -tests/packages diff --git a/src_ext/Makefile b/src_ext/Makefile index f616e444832..edc1479cc8a 100644 --- a/src_ext/Makefile +++ b/src_ext/Makefile @@ -77,7 +77,12 @@ endif jbuilder/_build/install/default/bin/jbuilder$(EXE): $(JBUILDER_CLONE) cd jbuilder && ocaml bootstrap.ml && ./boot.exe -clone: $(JBUILDER_CLONE) $(SRC_EXTS:=.stamp) +.PHONY: ext-ignore +ext-ignore: + @echo "This file is automatically generated" > jbuild-ignore + @echo jbuilder >> jbuild-ignore + +clone: $(JBUILDER_CLONE) $(SRC_EXTS:=.stamp) | ext-ignore @ .PHONY: archives @@ -132,5 +137,5 @@ clean: distclean: clean rm -rf jbuilder $(SRC_EXTS) mccs - rm -f *.tar.gz *.tbz *.stamp *.download + rm -f *.tar.gz *.tbz *.stamp *.download jbuild-ignore [ -d archives ] && ([ "$$(find archives -maxdepth 0 -type d -empty)" != "" ] && rmdir archives || echo "WARNING! $$(pwd)/archives/ not empty so left") || true diff --git a/tests/jbuild-ignore b/tests/jbuild-ignore new file mode 100644 index 00000000000..f9ced93c2fe --- /dev/null +++ b/tests/jbuild-ignore @@ -0,0 +1 @@ +packages From f278ebf4c5e31adcc1237ccde219fadd8ed0e402 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Sat, 2 Sep 2017 12:31:56 +0100 Subject: [PATCH 02/10] Flip MCCS_DISABLED to MCCS_ENABLED Signed-off-by: David Allsopp --- Makefile.config.in | 2 +- configure | 8 ++++---- configure.ac | 4 ++-- src_ext/Makefile | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.config.in b/Makefile.config.in index 37a30a912cf..43b6e0a9fa2 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -8,7 +8,7 @@ PACKS = $(filter-out no,@OCAML_PKG_unix@ @OCAML_PKG_bigarray@ @OCAML_PKG_extlib@ CONF_OCAMLFLAGS = @CONF_OCAMLFLAGS@ -MCCS_DISABLED = @MCCS_DISABLED@ +MCCS_ENABLED = @MCCS_ENABLED@ OCAMLFIND = @OCAMLFIND@ OCAML = @OCAML@ diff --git a/configure b/configure index 66218b4cbac..124ed8288e9 100755 --- a/configure +++ b/configure @@ -609,7 +609,7 @@ PATH_PREPEND EXE WIN32 CONF_OCAMLFLAGS -MCCS_DISABLED +MCCS_ENABLED DEVELOPER OBJEXT EXEEXT @@ -3782,10 +3782,10 @@ else fi if test "x${with_mccs}" = "xno"; then : - MCCS_DISABLED=true + MCCS_ENABLED=false else - MCCS_DISABLED=false + MCCS_ENABLED=true fi @@ -5715,7 +5715,7 @@ bindir="`eval echo ${bindir}`" mandir="`eval echo ${mandir}`" mandir="`eval echo ${mandir}`" -if { test "x$MCCS_DISABLED" = "xtrue" && test "x${hasalldeps}" = "x"; } || +if { test "x$MCCS_ENABLED" = "xfalse" && test "x${hasalldeps}" = "x"; } || { test "x$OCAML_PKG_mccs" = "xno" && test "x${hasalldeps}" = "xtrue"; }; then : echo "Opam will be built WITHOUT a built-in solver" else diff --git a/configure.ac b/configure.ac index 6dfc59fc1af..5ad713fe9ac 100644 --- a/configure.ac +++ b/configure.ac @@ -56,7 +56,7 @@ AC_PROG_CC([$($OCAMLBESTCC -config | sed -n -e "s/native_c_compiler: \(.*\) .*/\ AS_IF([test "x${enable_developer_mode}" = "xyes"], [AC_SUBST(DEVELOPER,true)], [AC_SUBST(DEVELOPER,false)]) -AS_IF([test "x${with_mccs}" = "xno"], [AC_SUBST(MCCS_DISABLED,true)], [AC_SUBST(MCCS_DISABLED,false)]) +AS_IF([test "x${with_mccs}" = "xno"], [AC_SUBST(MCCS_ENABLED,false)], [AC_SUBST(MCCS_ENABLED,true)]) AS_IF([test "x${CI}" != "x" -o "x${enable_developer_mode}" = "xyes"], [ CONF_OCAMLFLAGS="-warn-error A" @@ -189,7 +189,7 @@ bindir="`eval echo ${bindir}`" mandir="`eval echo ${mandir}`" mandir="`eval echo ${mandir}`" -AS_IF([{ test "x$MCCS_DISABLED" = "xtrue" && test "x${hasalldeps}" = "x"; } || +AS_IF([{ test "x$MCCS_ENABLED" = "xfalse" && test "x${hasalldeps}" = "x"; } || { test "x$OCAML_PKG_mccs" = "xno" && test "x${hasalldeps}" = "xtrue"; }], [echo "Opam will be built WITHOUT a built-in solver"], [echo "Opam will be built WITH a built-in solver"]) diff --git a/src_ext/Makefile b/src_ext/Makefile index edc1479cc8a..c41422059b5 100644 --- a/src_ext/Makefile +++ b/src_ext/Makefile @@ -3,7 +3,7 @@ ifneq ($(filter-out archives cache-archives,$(MAKECMDGOALS)),) endif SRC_EXTS = cppo extlib re cmdliner ocamlgraph cudf dose3 opam-file-format result -ifneq ($(MCCS_DISABLED),true) +ifeq ($(MCCS_ENABLED),true) SRC_EXTS := $(SRC_EXTS) mccs endif From 556c88e0d4d98dad5da802a2e54079da1d8cb504 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Wed, 3 Jan 2018 10:08:14 +0000 Subject: [PATCH 03/10] Suppress stderr in shell/check_linker Causing innocuous error message on AppVeyor (conflict with Git's link command) --- shell/check_linker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/check_linker b/shell/check_linker index 173899080a5..8f475d0dd6f 100644 --- a/shell/check_linker +++ b/shell/check_linker @@ -5,7 +5,7 @@ FIRST=1 FAULT=0 PREPEND= while IFS= read -r line; do - OUTPUT=$("$line" --version | head -1 | fgrep "Microsoft (R) Incremental Linker") + OUTPUT=$("$line" --version 2>/dev/null | head -1 | fgrep "Microsoft (R) Incremental Linker") if [ "x$OUTPUT" = "x" -a $FIRST -eq 1 ] ; then FAULT=1 elif [ $FAULT -eq 1 ] ; then From c85ca739fcf5aa4ed9122c664c317244db510151 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Wed, 22 Jul 2015 10:36:00 +0100 Subject: [PATCH 04/10] Detect Microsoft C Compiler from installation Allow configure to detect cl from a Windows SDK or Visual Studio installation, even if cl.exe isn't in the PATH. Simplifies the launching of bash for multiple compiler architectures as PATH doesn't require manual editing. --- .gitattributes | 1 + Makefile.config.in | 4 +- configure | 80 +++- configure.ac | 45 +- shell/msvs-detect | 1085 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1209 insertions(+), 6 deletions(-) create mode 100644 shell/msvs-detect diff --git a/.gitattributes b/.gitattributes index 1ab590f4048..9d3747cd63a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,6 +6,7 @@ *.zsh text eol=lf configure text eol=lf configure.ac text eol=lf +msvs-detect text eol=lf check_linker text eol=lf *.m4 text eol=lf diff --git a/Makefile.config.in b/Makefile.config.in index 43b6e0a9fa2..30070d93d36 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -21,9 +21,11 @@ EXE = @EXE@ WIN32 = @WIN32@ PATH:=@PATH_PREPEND@$(PATH) +INCLUDE:=@INC_PREPEND@$(INCLUDE) +LIB:=@LIB_PREPEND@$(LIB) LIB_PREFIX = @LIB_PREFIX@ CPATH = @CPATH@ LIBRARY_PATH = @LIBRARY_PATH@ -export OCAMLVERSION OCAMLFIND OCAML OCAMLC OCAMLOPT EXE PATH CPATH LIBRARY_PATH +export OCAMLVERSION OCAMLFIND OCAML OCAMLC OCAMLOPT EXE PATH INCLUDE LIB CPATH LIBRARY_PATH diff --git a/configure b/configure index 124ed8288e9..e69c58293d7 100755 --- a/configure +++ b/configure @@ -605,6 +605,8 @@ JBUILDER FETCH OCAMLFIND OCAMLOBJINFO +INC_PREPEND +LIB_PREPEND PATH_PREPEND EXE WIN32 @@ -3169,11 +3171,77 @@ x$ax_compare_version_B" | sed 's/^ *//' | sort -r | sed "s/x${ax_compare_version fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler type" >&5 +$as_echo_n "checking for compiler type... " >&6; } +CCOMP_TYPE=`$OCAML shell/print_config.ml ccomp_type 2>/dev/null | fgrep -v "Cannot find" || $OCAMLC -config | tr -d '\r' | sed -n -e "s/ccomp_type: //p"` +if test "$?" -eq 0 ; then : + +else + as_fn_error $? "failed" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CCOMP_TYPE" >&5 +$as_echo "$CCOMP_TYPE" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler architecture" >&5 +$as_echo_n "checking for compiler architecture... " >&6; } +ARCH=`$OCAML shell/print_config.ml arch 2>/dev/null | fgrep -v "Cannot find" || $OCAMLC -config | tr -d '\r' | sed -n -e "s/architecture: //p"` +if test "$?" -eq 0 ; then : + +else + as_fn_error $? "failed" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ARCH" >&5 +$as_echo "$ARCH" >&6; } + +LIB_PREPEND= +INC_PREPEND= # Need the C compiler used for OCaml (important on Windows, as both x86 and x64 are used) if test "$OCAMLBEST" = "opt"; then : OCAMLBESTCC=$OCAMLOPT else OCAMLBESTCC=$OCAMLC +fi +OCAML_CC="$($OCAMLBESTCC -config | sed -n -e "s/native_c_compiler: \(.*\) .*/\1/p")" +set dummy ${OCAML_CC}; OCAML_TEST_CC=$2 +if test ! -x ${OCAML_TEST_CC}; then : + + if test "x${CCOMP_TYPE}" = "xmsvc"; then : + + if test "${ARCH}" = "i386"; then : + SDK_ARCH=x86 +else + SDK_ARCH=x64 +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an installed Microsoft C Compiler for ${SDK_ARCH}" >&5 +$as_echo_n "checking for an installed Microsoft C Compiler for ${SDK_ARCH}... " >&6; } + eval `./shell/msvs-detect --arch=$SDK_ARCH; echo RESULT=$?` + if test "x$MSVS_NAME" = "x" ; then : + + if test ${RESULT} -eq 0 ; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: from PATH" >&5 +$as_echo "from PATH" >&6; } + +else + + as_fn_error $? "no" "$LINENO" 5 + +fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: from $MSVS_NAME" >&5 +$as_echo "from $MSVS_NAME" >&6; } + export PATH_PREPEND="${MSVS_PATH}:${PATH_PREPEND}" + export PATH="${PATH_PREPEND}$PATH" + LIB_PREPEND="${MSVS_LIB};" + INC_PREPEND="${MSVS_INC};" + export Lib="${MSVS_LIB};$LIB" + export Include="${MSVS_INC};$INCLUDE" + +fi + +fi + fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -3181,7 +3249,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then - for ac_prog in $($OCAMLBESTCC -config | sed -n -e "s/native_c_compiler: \(.*\) .*/\1/p") gcc cl cc + for ac_prog in "${OCAML_CC}" gcc cc do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -3225,7 +3293,7 @@ fi fi if test -z "$CC"; then ac_ct_CC=$CC - for ac_prog in $($OCAMLBESTCC -config | sed -n -e "s/native_c_compiler: \(.*\) .*/\1/p") gcc cl cc + for ac_prog in "${OCAML_CC}" gcc cc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -3819,12 +3887,18 @@ if test ${WIN32} -eq 1 -a "$GCC" != "yes" ; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Microsoft Linker needs a PATH shim" >&5 $as_echo_n "checking whether Microsoft Linker needs a PATH shim... " >&6; } + PREV_PREPEND="$PATH_PREPEND" PATH_PREPEND=$(bash ./shell/check_linker) - if test "x${PATH_PREPEND}" = "x" ; then : + if test "x${PATH_PREPEND}" = "x${PREV_PREPEND}" ; then : PATH_PREPEND_RESULT=no else PATH_PREPEND_RESULT=yes fi + PATH_PREPEND=`echo "${PATH_PREPEND}" | sed -e 's/#/\\\\#/g' -e 's/\\$/$$/g'` + LIB_PREPEND=`echo ${LIB_PREPEND} | sed -e 's/#/\\\\#/g' -e 's/\\$/$$/g'` + INC_PREPEND=`echo ${INC_PREPEND} | sed -e 's/#/\\\\#/g' -e 's/\\$/$$/g'` + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_PREPEND_RESULT" >&5 $as_echo "$PATH_PREPEND_RESULT" >&6; } diff --git a/configure.ac b/configure.ac index 5ad713fe9ac..2fad30d1571 100644 --- a/configure.ac +++ b/configure.ac @@ -50,9 +50,44 @@ AS_IF([test "x${enable_version_check}" != "xno"], [ AC_MSG_ERROR([Your version of OCaml: $OCAMLVERSION is not supported])) ]) +AC_MSG_CHECKING([for compiler type]) +CCOMP_TYPE=`$OCAML shell/print_config.ml ccomp_type 2>/dev/null | fgrep -v "Cannot find" || $OCAMLC -config | tr -d '\r' | sed -n -e "s/ccomp_type: //p"` +AS_IF([ test "$?" -eq 0 ],,[AC_MSG_ERROR([failed])] ) +AC_MSG_RESULT([$CCOMP_TYPE]) +AC_MSG_CHECKING([for compiler architecture]) +ARCH=`$OCAML shell/print_config.ml arch 2>/dev/null | fgrep -v "Cannot find" || $OCAMLC -config | tr -d '\r' | sed -n -e "s/architecture: //p"` +AS_IF([ test "$?" -eq 0 ],,[AC_MSG_ERROR([failed])] ) +AC_MSG_RESULT([$ARCH]) + +LIB_PREPEND= +INC_PREPEND= # Need the C compiler used for OCaml (important on Windows, as both x86 and x64 are used) AS_IF([test "$OCAMLBEST" = "opt"],[OCAMLBESTCC=$OCAMLOPT],[OCAMLBESTCC=$OCAMLC]) -AC_PROG_CC([$($OCAMLBESTCC -config | sed -n -e "s/native_c_compiler: \(.*\) .*/\1/p") gcc cl cc]) +OCAML_CC="$($OCAMLBESTCC -config | sed -n -e "s/native_c_compiler: \(.*\) .*/\1/p")" +set dummy ${OCAML_CC}; OCAML_TEST_CC=$2 +AS_IF([test ! -x ${OCAML_TEST_CC}],[ + AS_IF([test "x${CCOMP_TYPE}" = "xmsvc"],[ + AS_IF([test "${ARCH}" = "i386"],[SDK_ARCH=x86],[SDK_ARCH=x64]) + AC_MSG_CHECKING([for an installed Microsoft C Compiler for ${SDK_ARCH}]) + eval `./shell/msvs-detect --arch=$SDK_ARCH; echo RESULT=$?` + AS_IF([ test "x$MSVS_NAME" = "x" ], [ + AS_IF([ test ${RESULT} -eq 0 ], [ + AC_MSG_RESULT([from PATH]) + ],[ + AC_MSG_ERROR([no]) + ]) + ],[ + AC_MSG_RESULT([from $MSVS_NAME]) + export PATH_PREPEND="${MSVS_PATH}:${PATH_PREPEND}" + export PATH="${PATH_PREPEND}$PATH" + LIB_PREPEND="${MSVS_LIB};" + INC_PREPEND="${MSVS_INC};" + export Lib="${MSVS_LIB};$LIB" + export Include="${MSVS_INC};$INCLUDE" + ]) + ]) +]) +AC_PROG_CC(["${OCAML_CC}" gcc cc]) AS_IF([test "x${enable_developer_mode}" = "xyes"], [AC_SUBST(DEVELOPER,true)], [AC_SUBST(DEVELOPER,false)]) @@ -78,9 +113,15 @@ AC_SUBST(EXE) AS_IF([ test ${WIN32} -eq 1 -a "$GCC" != "yes" ],[ AC_MSG_CHECKING([whether Microsoft Linker needs a PATH shim]) + PREV_PREPEND="$PATH_PREPEND" PATH_PREPEND=$(bash ./shell/check_linker) - AS_IF([test "x${PATH_PREPEND}" = "x" ],[PATH_PREPEND_RESULT=no],[PATH_PREPEND_RESULT=yes]) + AS_IF([test "x${PATH_PREPEND}" = "x${PREV_PREPEND}" ],[PATH_PREPEND_RESULT=no],[PATH_PREPEND_RESULT=yes]) + PATH_PREPEND=`echo "${PATH_PREPEND}" | sed -e 's/#/\\\\#/g' -e 's/\\$/$$/g'` + LIB_PREPEND=`echo ${LIB_PREPEND} | sed -e 's/#/\\\\#/g' -e 's/\\$/$$/g'` + INC_PREPEND=`echo ${INC_PREPEND} | sed -e 's/#/\\\\#/g' -e 's/\\$/$$/g'` AC_SUBST(PATH_PREPEND) + AC_SUBST(LIB_PREPEND) + AC_SUBST(INC_PREPEND) AC_MSG_RESULT([$PATH_PREPEND_RESULT]) ]) diff --git a/shell/msvs-detect b/shell/msvs-detect new file mode 100644 index 00000000000..fdbc5ab0293 --- /dev/null +++ b/shell/msvs-detect @@ -0,0 +1,1085 @@ +#!/bin/bash +# ################################################################################################ # +# MetaStack Solutions Ltd. # +# ################################################################################################ # +# Microsoft C Compiler Environment Detection Script # +# ################################################################################################ # +# Copyright (c) 2016, 2017, 2018 MetaStack Solutions Ltd. # +# ################################################################################################ # +# Author: David Allsopp # +# 16-Feb-2016 # +# ################################################################################################ # +# Redistribution and use in source and binary forms, with or without modification, are permitted # +# provided that the following two conditions are met: # +# 1. Redistributions of source code must retain the above copyright notice, this list of # +# conditions and the following disclaimer. # +# 2. Neither the name of MetaStack Solutions Ltd. nor the names of its contributors may be # +# used to endorse or promote products derived from this software without specific prior # +# written permission. # +# # +# This software is provided by the Copyright Holder 'as is' and any express or implied warranties # +# including, but not limited to, the implied warranties of merchantability and fitness for a # +# particular purpose are disclaimed. In no event shall the Copyright Holder be liable for any # +# direct, indirect, incidental, special, exemplary, or consequential damages (including, but not # +# limited to, procurement of substitute goods or services; loss of use, data, or profits; or # +# business interruption) however caused and on any theory of liability, whether in contract, # +# strict liability, or tort (including negligence or otherwise) arising in any way out of the use # +# use of this software, even if advised of the possibility of such damage. # +# ################################################################################################ # + +VERSION=0.3.2 + +# debug [level=2] message +debug () +{ + if [[ -z ${2+x} ]] ; then + DEBUG_LEVEL=2 + else + DEBUG_LEVEL=$1 + shift + fi + + if [[ $DEBUG -ge $DEBUG_LEVEL ]] ; then + echo "$1">&2 + fi +} + +# warning message +warning () +{ + if [[ $DEBUG -gt 0 ]] ; then + echo "Warning: $1">&2 + fi +} + +# reg_string key value +# Retrieves a REG_SZ value from the registry (redirected on WOW64) +reg_string () +{ + reg query "$1" /v "$2" 2>/dev/null | tr -d '\r' | sed -ne "s/ *$2 *REG_SZ *//p" +} + +# reg64_string key value +# As reg_string, but without WOW64 redirection (i.e. guaranteed access to 64-bit registry) +reg64_string () +{ + $REG64 query "$1" /v "$2" 2>/dev/null | tr -d '\r' | sed -ne "s/ *$2 *REG_SZ *//p" +} + +# find_in list file +# Increments $RET if file does not exist in any of the directories in the *-separated list +find_in () +{ + debug 4 "Looking for $2" + if [[ -z $1 ]] ; then + STATUS=1 + else + IFS=* + STATUS=1 + for f in $1; do + if [[ -e "$f/$2" ]] ; then + STATUS=0 + break + fi + done + unset IFS + fi + if [[ $STATUS -eq 1 ]] ; then + debug 4 "$2 not found" + fi + ((RET+=$STATUS)) +} + +# check_environment PATH INC LIB name arch +# By checking for the presence of various files, verifies that PATH, INC and LIB provide a complete +# compiler and indicates this in its return status. RET is assumed to be zero on entry. $ASSEMBLER +# will contain the name of assembler for this compiler series (ml.exe or ml64.exe). +# The following files are checked: +# cl.exe PATH Microsoft C compiler +# kernel32.lib LIB Implies Windows SDK present +# link.exe PATH Microsoft Linker +# ml[64].exe PATH Microsoft Assembler (ml.exe or ml64.exe) +# msvcrt.lib LIB Implies C Runtime Libraries present +# mt.exe PATH Microsoft Manifest Tool +# oldnames.lib LIB Implies C Runtime Libraries present +# rc.exe PATH Microsoft Resource Compiler (implies tools present) +# stdlib.h INC Implies Microsoft C Runtime Libraries present +# windows.h INC Implies Windows SDK present +# oldnames.lib is included, because certain SDKs and older versions don't correctly install the +# entire runtime if only some options (e.g. Dynamic Runtime and not Static) are selected. +check_environment () +{ + for tool in cl rc link ; do + find_in "$1" $tool.exe + done + + if [[ $RET -gt 0 ]] ; then + warning "Microsoft C Compiler tools not all found - $4 ($5) excluded" + return 1 + fi + + RET=0 + find_in "$2" windows.h + find_in "$3" kernel32.lib + if [[ $RET -gt 0 ]] ; then + warning "Windows SDK not all found - $4 ($5) excluded" + return 1 + fi + + RET=0 + find_in "$2" stdlib.h + find_in "$3" msvcrt.lib + find_in "$3" oldnames.lib + if [[ $RET -gt 0 ]] ; then + warning "Microsoft C runtime library not all found - $4 ($5) excluded" + return 1 + fi + + ASSEMBLER=ml${5#x} + ASSEMBLER=${ASSEMBLER%86}.exe + if [[ $ML_REQUIRED -eq 1 ]] ; then + RET=0 + find_in "$1" $ASSEMBLER + if [[ $RET -gt 0 ]] ; then + warning "Microsoft Assembler ($ASSEMBLER) not found - $4 ($5)" + return 1 + fi + fi + + if [[ $MT_REQUIRED -eq 1 ]] ; then + RET=0 + find_in "$1" mt.exe + if [[ $RET -gt 0 ]] ; then + warning "Microsoft Manifest Tool not found - $4 ($5)" + return 1 + fi + fi + + return 0 +} + +# output VAR value arch +# Outputs a command for setting VAR to value based on $OUTPUT. If $ENV_ARCH is arch, then an empty +# value (i.e. no change) is output. +output () +{ + if [[ $3 = $ENV_ARCH ]] ; then + VALUE= + else + VALUE=$2 + fi + case "$OUTPUT" in + 0) + echo "$1='${VALUE//\'/\'\"\'\"\'}'";; + 1) + VALUE=${VALUE//#/\\\#} + echo "$1=${VALUE//\$/\$\$}";; + esac +} + +# DEBUG Debugging level +# MODE Operation mode +# 0 - Normal +# 1 - --all +# 2 - --help +# 3 - --version +# OUTPUT --output option +# 0 - =shell +# 1 - =make +# MT_REQUIRED --with-mt +# ML_REQUIRED --with-assembler +# TARGET_ARCH Normalised --arch (x86, x64 or blank for both) +# LEFT_ARCH \ If $TARGET_ARCH is blank, these will be x86 and x64 respectively, otherwise they +# RIGHT_ARCH / equal $TARGET_ARCH +# SCAN_ENV Controls from parsing whether the environment should be queried for a compiler +DEBUG=0 +MODE=0 +OUTPUT=0 +MT_REQUIRED=0 +ML_REQUIRED=0 +TARGET_ARCH= +SCAN_ENV=0 + +# Parse command-line. At the moment, the short option which usefully combines with anything is -d, +# so for the time being, combining short options is not permitted, as the loop becomes even less +# clear with getopts. GNU getopt isn't installed by default on Cygwin... +if [[ $@ != "" ]] ; then + while true ; do + case "$1" in + # Mode settings ($MODE) + -a|--all) + MODE=1 + shift 1;; + -h|--help) + MODE=2 + shift;; + -v|--version) + MODE=3 + shift;; + + # Simple flags ($MT_REQUIRED and $ML_REQUIRED) + --with-mt) + MT_REQUIRED=1 + shift;; + --with-assembler) + ML_REQUIRED=1 + shift;; + + # -o, --output ($OUTPUT) + -o|--output) + case "$2" in + shell) + ;; + make) + OUTPUT=1;; + *) + echo "$0: unrecognised option for $1: '$2'">&2 + exit 2;; + esac + shift 2;; + -oshell|--output=shell) + shift;; + -omake|--output=make) + OUTPUT=1 + shift;; + -o*) + echo "$0: unrecognised option for -o: '${1#-o}'">&2 + exit 2;; + --output=*) + echo "$0: unrecognised option for --output: '${1#--output=}'">&2 + exit 2;; + + # -x, --arch ($TARGET_ARCH) + -x|--arch) + case "$2" in + 86|x86) + TARGET_ARCH=x86;; + 64|x64) + TARGET_ARCH=x64;; + *) + echo "$0: unrecognised option for $1: '$2'">&2 + exit 2 + esac + shift 2;; + -x86|-xx86|--arch=x86|--arch=86) + TARGET_ARCH=x86 + shift;; + -x64|-xx64|--arch=x64|--arch=64) + TARGET_ARCH=x64 + shift;; + -x*) + echo "$0: unrecognised option for -x: '${1#-x}'">&2 + exit 2;; + --arch=*) + echo "$0: unrecognised option for --arch: '${1#--arch}'">&2 + exit 2;; + + # -d, --debug ($DEBUG) + -d*) + DEBUG=${1#-d} + if [[ -z $DEBUG ]] ; then + DEBUG=1 + fi + shift;; + --debug=*) + DEBUG=${1#*=} + shift;; + --debug) + DEBUG=1 + shift;; + + # End of option marker + --) + shift + break;; + + # Invalid options + --*) + echo "$0: unrecognised option: '${1%%=*}'">&2 + exit 2;; + -*) + echo "$0: unrecognised option: '${1:1:1}'">&2 + exit 2;; + + # MSVS_PREFERENCE (without end-of-option marker) + *) + break;; + esac + done + + if [[ -n ${1+x} ]] ; then + if [[ $MODE -eq 1 ]] ; then + echo "$0: cannot specify MSVS_PREFERENCE and --all">&2 + exit 2 + else + MSVS_PREFERENCE="$@" + fi + fi +fi + +# Options sanitising +if [[ $MODE -eq 1 ]] ; then + if [[ -n $TARGET_ARCH ]] ; then + echo "$0: --all and --arch are mutually exclusive">&2 + exit 2 + fi + MSVS_PREFERENCE= + SCAN_ENV=1 +elif [[ -z ${MSVS_PREFERENCE+x} ]] ; then + MSVS_PREFERENCE='@;VS15.*;VS14.0;VS12.0;VS11.0;10.0;9.0;8.0;7.1;7.0' +fi + +MSVS_PREFERENCE=${MSVS_PREFERENCE//;/ } + +if [[ -z $TARGET_ARCH ]] ; then + LEFT_ARCH=x86 + RIGHT_ARCH=x64 +else + LEFT_ARCH=$TARGET_ARCH + RIGHT_ARCH=$TARGET_ARCH +fi + +# Command line parsing complete (MSVS_PREFERENCE pending) + +NAME="Microsoft C Compiler Environment Detection Script" +case $MODE in + 2) + echo "$NAME" + echo "Queries the environment and registry to locate Visual Studio / Windows SDK" + echo "installations and uses their initialisation scripts (SetEnv.cmd, vcvarsall.bat," + echo "etc.) to determine INCLUDE, LIB and PATH alterations." + echo + echo "Usage:" + echo " $0 [OPTIONS] [--] [MSVS_PREFERENCE]" + echo + echo "Options:" + echo " -a, --all Display all available compiler packages" + echo " -x, --arch=ARCH Only consider packages for ARCH (x86 or x64). Default is" + echo " to return packages containing both architectures" + echo " -d, --debug[=LEVEL] Set debug messages level" + echo " -h, --help Display this help screen" + echo " -o, --output=OUTPUT Set final output. Default is shell. Valid values:" + echo " shell - shell assignments, for use with eval" + echo " make - make assignments, for inclusion in a Makefile" + echo " -v, --version Display the version" + echo " --with-mt Only consider packages including the Manifest Tool" + echo " --with-assembler Only consider packages including an assembler" + echo + echo "If MSVS_PREFERENCE is not given, then the environment variable MSVS_PREFERENCE" + echo "is read. MSVS_PREFERENCE is a semicolon separated list of preferred versions." + echo "Three kinds of version notation are supported:" + echo " 1. @ - which refers to the C compiler found in PATH (if it can be identified)" + echo " (this allows the C compiler corresponding to the opposite architecture to" + echo " be selected, if possible)." + echo " 2. mm.n - which refers to a Visual Studio version (e.g. 14.0, 7.1) but which" + echo " also allows an SDK to provide the compiler (e.g. Windows SDK 7.1 provides" + echo " 10.0). Visual Studio packages are always preferred ahead of SDKs." + echo " 3. SPEC - an actual package specification. Visual Studio packages are VSmm.n" + echo " (e.g. VS14.0, VS7.1) and SDK packages are SDKm.n (e.g. SDK7.1)." + echo " Any Visual Studio 2017 update can be selected with VS15.*" + echo "The default behaviour is to match the environment compiler followed by the most" + echo "recent version of the compiler." + exit 0;; + 3) + echo "$NAME" + echo "Version $VERSION" + exit 0;; +esac + +# Known compiler packages. Visual Studio .NET 2002 onwards. Detection is in place for Visual Studio +# 2005 Express, but because it doesn't include a Windows SDK, it can only ever be detected if the +# script has been launched from within a Platform SDK command prompt (this provides the Windows +# Headers and Libraries which allows this script to detect the rest). +# Each element is either a Visual Studio or SDK package and the value is the syntax for a bash +# associative array to be eval'd. Each of these contains the following properties: +# NAME - the friendly name of the package +# ENV - (VS only) the version-specific portion of the VSCOMNTOOLS environment variable +# VERSION - (VS only) version number of the package +# ARCH - Lists the architectures available in this version +# ARCH_SWITCHES - The script is assumed to accept x86 and x64 to indicate architecture. This key +# contains another eval'd associative array allowing alternate values to be given +# SETENV_RELEASE - (SDK only) script switch necessary to select release than debugging versions +# EXPRESS - (VS only) the prefix to the registry key to detect the Express edition +# EXPRESS_ARCH - (VS only) overrides ARCH if Express edition is detected +# EXPRESS_ARCH_SWITCHES - (VS only) overrides ARCH_SWITCHES if Express edition is detected +# VC_VER - (SDK only) specifies the version of the C Compilers included in the SDK (SDK +# equivalent of the VERSION key) +# REG_KEY - (SDK only) registry key to open to identify this package installation +# REG_VALUE - (SDK only) registry value to query to identify this package installation +# VSWHERE - (VS 2017+) is 1 if the compiler can only be detected using vswhere +# For a while, Windows SDKs followed a standard pattern which is stored in the SDK element and +# copied to the appropriate version. SDKs after 7.1 do not include compilers, and so are not +# captured (as of Visual Studio 2015, the Windows SDK is official part of Visual Studio). +declare -A COMPILERS +SDK52_KEY='HKLM\SOFTWARE\Microsoft\MicrosoftSDK\InstalledSDKs\8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3' +COMPILERS=( + ["VS7.0"]='( + ["NAME"]="Visual Studio .NET 2002" + ["ENV"]="" + ["VERSION"]="7.0" + ["ARCH"]="x86")' + ["VS7.1"]='( + ["NAME"]="Visual Studio .NET 2003" + ["ENV"]="71" + ["VERSION"]="7.1" + ["ARCH"]="x86")' + ["VS8.0"]='( + ["NAME"]="Visual Studio 2005" + ["ENV"]="80" + ["VERSION"]="8.0" + ["EXPRESS"]="VC" + ["ARCH"]="x86 x64" + ["EXPRESS_ARCH"]="x86")' + ["VS9.0"]='( + ["NAME"]="Visual Studio 2008" + ["ENV"]="90" + ["VERSION"]="9.0" + ["EXPRESS"]="VC" + ["ARCH"]="x86 x64" + ["EXPRESS_ARCH"]="x86")' + ["VS10.0"]='( + ["NAME"]="Visual Studio 2010" + ["ENV"]="100" + ["VERSION"]="10.0" + ["EXPRESS"]="VC" + ["ARCH"]="x86 x64" + ["EXPRESS_ARCH"]="x86")' + ["VS11.0"]='( + ["NAME"]="Visual Studio 2012" + ["ENV"]="110" + ["VERSION"]="11.0" + ["EXPRESS"]="WD" + ["ARCH"]="x86 x64" + ["EXPRESS_ARCH_SWITCHES"]="([\"x64\"]=\"x86_amd64\")")' + ["VS12.0"]='( + ["NAME"]="Visual Studio 2013" + ["ENV"]="120" + ["VERSION"]="12.0" + ["EXPRESS"]="WD" + ["ARCH"]="x86 x64" + ["EXPRESS_ARCH_SWITCHES"]="([\"x64\"]=\"x86_amd64\")")' + ["VS14.0"]='( + ["NAME"]="Visual Studio 2015" + ["ENV"]="140" + ["VERSION"]="14.0" + ["ARCH"]="x86 x64")' + ["VS15.*"]='( + ["NAME"]="Visual Studio 2017" + ["VSWHERE"]="1")' + ["SDK5.2"]='( + ["NAME"]="Windows Server 2003 SP1 SDK" + ["VC_VER"]="8.0" + ["REG_KEY"]="$SDK52_KEY" + ["REG_VALUE"]="Install Dir" + ["SETENV_RELEASE"]="/RETAIL" + ["ARCH"]="x64" + ["ARCH_SWITCHES"]="([\"x64\"]=\"/X64\")")' + ["SDK"]='( + ["NAME"]="Generalised Windows SDK" + ["SETENV_RELEASE"]="/Release" + ["ARCH"]="x86 x64" + ["ARCH_SWITCHES"]="([\"x86\"]=\"/x86\" [\"x64\"]=\"/x64\")")' + ["SDK6.1"]='( + ["NAME"]="Windows Server 2008 with .NET 3.5 SDK" + ["VC_VER"]="9.0")' + ["SDK7.0"]='( + ["NAME"]="Windows 7 with .NET 3.5 SP1 SDK" + ["VC_VER"]="9.0")' + ["SDK7.1"]='( + ["NAME"]="Windows 7 with .NET 4 SDK" + ["VC_VER"]="10.0")' +) + +# FOUND is ultimately an associative array containing installed compiler packages. It's +# hijacked here as part of MSVS_PREFERENCE validation. +# Ultimately, it contains a copy of the value from COMPILERS with the following extra keys: +# IS_EXPRESS - (VS only) indicates whether the Express edition was located +# SETENV - (SDK only) the full location of the SetEnv.cmd script +# ASSEMBLER - the name of the assembler (ml or ml64) +# MSVS_PATH \ +# MSVS_INC > prefix values for PATH, INCLUDE and LIB determined by running the scripts. +# MSVS_LIB / +declare -A FOUND + +# Check that MSVS_PREFERENCE is valid and contains no repetitions. +for v in $MSVS_PREFERENCE ; do + if [[ -n ${FOUND[$v]+x} ]] ; then + echo "$0: corrupt MSVS_PREFERENCE: repeated '$v'">&2 + exit 2 + fi + if [[ $v != "@" ]] ; then + if [[ -z ${COMPILERS[$v]+x} && -z ${COMPILERS["VS$v"]+x} && -z ${COMPILERS[${v%.*}.*]+x} ]] ; then + echo "$0: corrupt MSVS_PREFERENCE: unknown compiler '$v'">&2 + exit 2 + fi + else + SCAN_ENV=1 + fi + FOUND["$v"]="" +done + +# Reset FOUND for later use. +FOUND=() + +# Scan the environment for a C compiler, and check that it's valid. Throughout the rest of the +# script, it is assumed that if ENV_ARCH is set then there is a valid environment compiler. +if [[ $SCAN_ENV -eq 1 ]] ; then + if which cl >/dev/null 2>&1 ; then + # Determine its architecture from the Microsoft Logo line. + ENV_ARCH=$(cl 2>&1 | head -1 | tr -d '\r') + case "${ENV_ARCH#* for }" in + x64|AMD64) + ENV_ARCH=x64;; + 80x86|x86) + ENV_ARCH=x86;; + *) + echo "Unable to identify C compiler architecture from '${ENV_ARCH#* for }'">&2 + echo "Environment C compiler discarded">&2 + unset ENV_ARCH;; + esac + + # Environment variable names are a bit of a nightmare on Windows - they are actually case + # sensitive (at the kernel level) but not at the user level! To compound the misery is that SDKs + # use Include and Lib where vcvars32 tends to use INCLUDE and LIB. Windows versions also contain + # a mix of Path and PATH, but fortunately Cygwin normalises that to PATH for us! For this + # reason, use env to determine the actual case of the LIB and INCLUDE variables. + if [[ -n ${ENV_ARCH+x} ]] ; then + RET=0 + ENV_INC=$(env | sed -ne 's/^\(INCLUDE\)=.*/\1/pi') + ENV_LIB=$(env | sed -ne 's/^\(LIB\)=.*/\1/pi') + if check_environment "${PATH//:/*}" \ + "${!ENV_INC//;/*}" \ + "${!ENV_LIB//;/*}" \ + "Environment C compiler" \ + "$ENV_ARCH" ; then + ENV_CL=$(which cl) + ENV_cl=${ENV_CL,,} + ENV_cl=${ENV_cl/bin\/*_/bin\/} + debug "Environment appears to include a compiler at $ENV_CL" + if [[ -n $TARGET_ARCH && $TARGET_ARCH != $ENV_ARCH ]] ; then + debug "But architecture doesn't match required value" + unset ENV_ARCH + fi + else + unset ENV_ARCH + fi + fi + fi +fi + +# Even if launched from a 64-bit Command Prompt, Cygwin is usually 32-bit and so the scripts +# executed will inherit that fact. This is a problem when querying the registry, but fortunately +# WOW64 provides a mechanism to break out of the 32-bit environment by mapping $WINDIR/sysnative to +# the real 64-bit programs. +# Thus: +# MS_ROOT is the 32-bit Microsoft Registry key (all Visual Studio keys are located there) +# REG64 is the processor native version of the reg utility (allowing 64-bit keys to be read for +# the SDKs) +if [[ -n ${PROCESSOR_ARCHITEW6432+x} ]] ; then + debug "WOW64 detected" + MS_ROOT='HKLM\SOFTWARE\Microsoft' + REG64=$WINDIR/sysnative/reg +else + MS_ROOT='HKLM\SOFTWARE\Wow6432Node\Microsoft' + REG64=reg +fi + +# COMPILER contains each eval'd element from COMPILERS +declare -A COMPILER + +# Scan the registry for compiler package (vswhere is later) +for i in "${!COMPILERS[@]}" ; do + eval COMPILER=${COMPILERS[$i]} + + if [[ -n ${COMPILER["ENV"]+x} ]] ; then + # Visual Studio package - test for its environment variable + ENV=VS${COMPILER["ENV"]}COMNTOOLS + if [[ -n ${!ENV+x} ]] ; then + debug "$ENV is a candidate" + TEST_PATH=${!ENV%\"} + TEST_PATH=$(cygpath -u -f - <<< ${TEST_PATH#\"}) + if [[ -e $TEST_PATH/vsvars32.bat ]] ; then + debug "Directory pointed to by $ENV contains vsvars32.bat" + EXPRESS=0 + # Check for the primary Visual Studio registry value indicating installation + INSTALL_DIR=$(reg_string "$MS_ROOT\\VisualStudio\\${COMPILER["VERSION"]}" InstallDir) + if [[ -z $INSTALL_DIR ]] ; then + if [[ -n ${COMPILER["EXPRESS"]+x} ]] ; then + TEST_KEY="$MS_ROOT\\${COMPILER["EXPRESS"]}Express\\${COMPILER["VERSION"]}" + INSTALL_DIR=$(reg_string "$TEST_KEY" InstallDir) + # Exception for Visual Studio 2005 Express, which doesn't set the registry correctly, so + # set INSTALL_DIR to a fake value to pass the next test. + if [[ ${COMPILER["VERSION"]} = "8.0" ]] ; then + INSTALL_DIR=$(cygpath -w "$TEST_PATH") + EXPRESS=1 + else + if [[ -z $INSTALL_DIR ]] ; then + warning "vsvars32.bat found, but registry value not located (Exp or Pro)" + else + EXPRESS=1 + fi + fi + else + warning "vsvars32.bat found, but registry value not located" + fi + fi + + if [[ -n $INSTALL_DIR ]] ; then + if [[ ${TEST_PATH%/} = $(cygpath -u "$INSTALL_DIR\\..\\Tools") ]] ; then + RESULT=${COMPILERS[$i]%)} + DISPLAY=${COMPILER["NAME"]} + if [[ $EXPRESS -eq 1 ]] ; then + DISPLAY="$DISPLAY Express" + fi + FOUND+=(["$i"]="$RESULT [\"DISPLAY\"]=\"$DISPLAY\" [\"IS_EXPRESS\"]=\"$EXPRESS\")") + debug "${COMPILER["NAME"]} accepted for further detection" + else + warning "$ENV doesn't agree with registry" + fi + else + warning "vsvars32.bat found, but registry settings not found" + fi + else + warning "$ENV set, but vsvars32.bat not found" + fi + fi + elif [[ -n ${COMPILER["REG_KEY"]+x} ]] ; then + # SDK with explicit registry detection value + INSTALL_DIR=$(reg64_string "${COMPILER["REG_KEY"]}" "${COMPILER["REG_VALUE"]}") + if [[ -n $INSTALL_DIR ]] ; then + TEST_PATH=$(cygpath -u "$INSTALL_DIR") + if [[ -e $TEST_PATH/SetEnv.cmd ]] ; then + RESULT=${COMPILERS[$i]%)} + FOUND+=(["$i"]="$RESULT [\"DISPLAY\"]=\"${COMPILER["NAME"]}\" [\"SETENV\"]=\"$INSTALL_DIR\\SetEnv.cmd\")") + debug "${COMPILER["NAME"]} accepted for further detection" + else + warning "Registry set for Windows Server 2003 SDK, but SetEnv.cmd not found" + fi + fi + fi +done + +# Now enumerate installed SDKs for v6.0+ +SDK_ROOT='HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows' +for i in $(reg query "$SDK_ROOT" 2>/dev/null | tr -d '\r' | sed -ne '/Windows\\v/s/.*\\//p') ; do + debug "Analysing SDK key $SDK_ROOT\\$i" + INSTALL_DIR=$(reg_string "$SDK_ROOT\\$i" InstallationFolder) + if [[ -n $INSTALL_DIR ]] ; then + TEST_PATH=$(cygpath -u "$INSTALL_DIR") + if [[ -e $TEST_PATH/Bin/SetEnv.cmd ]] ; then + if [[ -z ${COMPILERS["SDK${i#v}"]+x} ]] ; then + warning "SDK $i is not known to this script - assuming compatibility" + DISPLAY="Windows SDK $i" + else + eval COMPILER=${COMPILERS["SDK${i#v}"]} + DISPLAY=${COMPILER['NAME']} + fi + RESULT=${COMPILERS['SDK']%)} + FOUND+=(["SDK${i/v/}"]="$RESULT [\"DISPLAY\"]=\"$DISPLAY\" [\"SETENV\"]=\"$INSTALL_DIR\\Bin\\SetEnv.cmd\")") + else + if [[ -n ${COMPILERS["SDK${i#v}"]+x} ]] ; then + warning "Registry set for Windows SDK $i, but SetEnv.cmd not found" + fi + fi + else + warning "Registry key for Windows SDK $i doesn't contain expected InstallationFolder value" + fi +done + +# Now enumerate Visual Studio 2017+ instances +VSWHERE=$(dirname $(realpath $0))/vswhere.exe +if [[ ! -x $VSWHERE ]] ; then + VSWHERE="$(printenv 'ProgramFiles(x86)')\\Microsoft Visual Studio\\Installer\\vswhere.exe" + VSWHERE=$(echo $VSWHERE| cygpath -f -) +fi +if [[ -x $VSWHERE ]] ; then + debug "$VSWHERE found" + while IFS= read -r line; do + case ${line%: *} in + instanceId) + INSTANCE=${line#*: };; + installationPath) + INSTANCE_PATH=${line#*: };; + installationVersion) + INSTANCE_VER=${line#*: } + INSTANCE_VER=${INSTANCE_VER%.*} + INSTANCE_VER=${INSTANCE_VER%.*};; + displayName) + INSTANCE_NAME=${line#*: } + debug "Looking at $INSTANCE in $INSTANCE_PATH ($INSTANCE_VER $INSTANCE_NAME)" + if [[ -e "$(echo $INSTANCE_PATH| cygpath -f -)/VC/Auxiliary/Build/vcvarsall.bat" ]] ; then + debug "vcvarsall.bat found" + FOUND+=(["VS$INSTANCE_VER"]="([\"DISPLAY\"]=\"$INSTANCE_NAME\" [\"ARCH\"]=\"x86 x64\" [\"SETENV\"]=\"$INSTANCE_PATH\\VC\\Auxiliary\\Build\\vcvarsall.bat\" [\"SETENV_RELEASE\"]=\"\")") + else + warning "vcvarsall.bat not found for $INSTANCE" + fi;; + esac + done < <("$VSWHERE" -all -nologo | tr -d '\r') +fi + +if [[ $DEBUG -gt 1 ]] ; then + for i in "${!FOUND[@]}" ; do + echo "Inspect $i">&2 + done +fi + +# Basic scanning is complete, now interrogate the packages which seem to be installed and ensure +# that they pass the check_environment tests. + +# CANDIDATES is a hash table of the keys of FOUND. The result of the next piece of processing is to +# derive two arrays PREFERENCE and TEST. TEST will contain a list of the keys of FOUND in the order +# in which they should be evaluated. PREFERENCE contains a parsed version of MSVS_PREFERENCE but +# filtered on the basis of the compiler packages already identified. The current "hoped for" +# preference is stored in $pref (the index into PREFERENCE) and $PREF (which is +# ${PREFERENCE[$pref]}). These two arrays together allow testing to complete quickly if the desired +# version is found (note that often this won't be possible as the @ environment option requires all +# packages to be tested in order to be sure that the environment compiler is not ambiguous). +declare -A CANDIDATES +for i in "${!FOUND[@]}" ; do + CANDIDATES[$i]=""; +done + +# For --all, act as though MSVS_PREFERENCE were "@" because this causes all packages to be tested. +if [[ $MODE -eq 1 ]] ; then + PREFER_ENV=1 + PREFERENCE=("@") +else + PREFER_ENV=0 + PREFERENCE=() +fi + +TEST=() +for i in $MSVS_PREFERENCE ; do + if [[ $i = "@" ]] ; then + if [[ -n ${ENV_ARCH+x} ]] ; then + PREFERENCE+=("@") + PREFER_ENV=1 + else + debug "Preference @ ignored since no environment compiler selected" + fi + else + if [[ -n ${COMPILERS[$i]+x} || -n ${COMPILERS[${i%.*}.*]+x} ]] ; then + if [[ -n ${CANDIDATES[$i]+x} ]] ; then + unset CANDIDATES[$i] + TEST+=($i) + PREFERENCE+=($i) + elif [[ ${i#*.} = "*" ]] ; then + INSTANCES= + for j in "${!CANDIDATES[@]}" ; do + if [[ "${j%.*}.*" = $i ]] ; then + unset CANDIDATES[$j] + INSTANCES="$INSTANCES $j" + fi + done + INSTANCES="$(sort -r <<< "${INSTANCES// /$'\n'}")" + eval TEST+=($INSTANCES) + eval PREFERENCE+=($INSTANCES) + fi + else + if [[ -n ${CANDIDATES["VS$i"]+x} ]] ; then + unset CANDIDATES["VS$i"] + TEST+=("VS$i") + PREFERENCE+=("VS$i") + fi + SDKS= + for j in "${!COMPILERS[@]}" ; do + eval COMPILER=${COMPILERS[$j]} + if [[ -n ${COMPILER["VC_VER"]}+x ]] ; then + if [[ $i = ${COMPILER["VC_VER"]} && -n ${CANDIDATES[$j]+x} ]] ; then + unset CANDIDATES[$j] + SDKS="$j $SDKS" + fi + fi + done + SDKS=${SDKS% } + SDKS="$(sort -r <<< "${SDKS// /$'\n'}")" + SDKS=${SDKS//$'\n'/ } + eval TEST+=($SDKS) + eval PREFERENCE+=($SDKS) + fi + fi +done + +# If MSVS_PREFERENCE includes @, add any remaining items from CANDIDATES to TEST, otherwise remove +# them from FOUND so that they don't accidentally get reported on later. +for i in "${!CANDIDATES[@]}" ; do + if [[ $PREFER_ENV -eq 1 ]] ; then + TEST+=($i) + else + unset FOUND[$i] + fi +done + +# Initialise pref and PREF to ${PREFERENCE[0]} +pref=0 +PREF=${PREFERENCE[0]} + +if [[ $DEBUG -gt 1 ]] ; then + for i in "${!TEST[@]}" ; do + echo "Test ${TEST[$i]}">&2 + done +fi + + +# Now run each compiler's environment script and then test whether it is suitable. During this loop, +# attempt to identify the environment C compiler (if one was found). The environment C compiler is +# strongly identified if the full location of cl matches the one in PATH and both LIB and INCLUDE +# contain the strings returned by the script in an otherwise empty environment (if one or both of +# the LIB and INCLUDE variables do not contain the string returned, then the compiler is weakly +# identified). If the environment compiler is strongly identified by more than one package, then it +# is not identified at all; if it is strongly identified by no packages but weakly identified by +# exactly 1, then we grudgingly accept that that's probably the one. +ENV_COMPILER= +WEAK_ENV= + +# ARCHINFO contains the appropriate ARCH_SWITCHES associative array for each compiler. +declare -A ARCHINFO + +for i in "${TEST[@]}" ; do + CURRENT=${FOUND[$i]} + eval COMPILER=$CURRENT + # At the end of this process, the keys of FOUND will be augmented with the architecture found in + # each case (so if "VS14.0" was in FOUND from the scan and both the x86 and x64 compilers are + # valid, then at the end of this loop FOUND will contain "VS14.0-x86" and "VS14.0-x64"). + unset FOUND[$i] + + if [[ ${COMPILER["IS_EXPRESS"]}0 -gt 0 && -n ${COMPILER["EXPRESS_ARCH_SWITCHES"]+x} ]] ; then + eval ARCHINFO=${COMPILER["EXPRESS_ARCH_SWITCHES"]} + elif [[ -n ${COMPILER["ARCH_SWITCHES"]+x} ]] ; then + eval ARCHINFO=${COMPILER["ARCH_SWITCHES"]} + else + ARCHINFO=() + fi + + # Determine the script to be executed and any non-architecture specific switches needed. + # $ENV is will contain the value of the environment variable for the compiler (empty for an SDK) + # which is required for Visual Studio 7.x shim later. + if [[ -n ${COMPILER["ENV"]+x} ]] ; then + ENV=VS${COMPILER["ENV"]}COMNTOOLS + ENV=${!ENV%\"} + ENV=${ENV#\"} + if [[ ${COMPILER["ENV"]}0 -ge 800 ]] ; then + SCRIPT="$(cygpath -d -f - <<< $ENV)\\..\\..\\VC\\vcvarsall.bat" + SCRIPT_SWITCHES= + else + SCRIPT="$(cygpath -d -f - <<< $ENV)\\vsvars32.bat" + SCRIPT_SWITCHES= + fi + else + ENV= + SCRIPT=${COMPILER["SETENV"]} + SCRIPT_SWITCHES=${COMPILER["SETENV_RELEASE"]} + fi + # For reasons of escaping, the script is executed using its basename so the directory needs + # prepending to PATH. + DIR=$(dirname "$SCRIPT" | cygpath -u -f -) + + if [[ ${COMPILER["IS_EXPRESS"]} -gt 0 && -n ${COMPILER["EXPRESS_ARCH"]+x} ]] ; then + ARCHS=${COMPILER["EXPRESS_ARCH"]} + else + ARCHS=${COMPILER["ARCH"]} + fi + + for arch in $ARCHS ; do + # Determine the command line switch for this architecture + if [[ -n ${ARCHINFO[$arch]+x} ]] ; then + ARCH_SWITCHES=${ARCHINFO[$arch]} + else + ARCH_SWITCHES=$arch + fi + + # Run the script in order to determine changes made to PATH, INCLUDE and LIB. These scripts + # always prepend changes to the environment variables. + MSVS_PATH= + MSVS_LIB= + MSVS_INC= + + COMMAND='%EXEC_SCRIPT% && echo XMARKER && echo !PATH! && echo !LIB! && echo !INCLUDE!' + + # Note that EXEC_SCRIPT must have ARCH_SWITCHES first for older Platform SDKs (newer ones parse + # arguments properly) + if [[ $DEBUG -gt 3 ]] ; then + printf "Scanning %s... " "$(basename "$SCRIPT") $ARCH_SWITCHES $SCRIPT_SWITCHES">&2 + fi + num=0 + while IFS= read -r line; do + case $num in + 0) + MSVS_PATH=${line%% };; + 1) + MSVS_LIB=${line%% };; + 2) + MSVS_INC=${line%% };; + esac + ((num++)) + done < <(INCLUDE= LIB= PATH="$DIR:$PATH" \ + EXEC_SCRIPT="$(basename "$SCRIPT") $ARCH_SWITCHES $SCRIPT_SWITCHES" \ + cmd /v:on /c $COMMAND 2>/dev/null | fgrep XMARKER -A 3 | tr -d '\015' | tail -3) + if [[ $DEBUG -gt 3 ]] ; then + echo done>&2 + fi + + if [[ -n $MSVS_PATH ]] ; then + # Translate MSVS_PATH back to Cygwin notation (/cygdrive, etc. and colon-separated) + MSVS_PATH=$(cygpath "$MSVS_PATH" -p) + # Remove the actual PATH (and the extra $DIR added to run the script) + MSVS_PATH=${MSVS_PATH%:$DIR:$PATH} + # Guarantee that MSVS_PATH ends with a single : + MSVS_PATH="${MSVS_PATH%%:}:" + fi + # Ensure that both variables end with a semi-colon (it doesn't matter if for some erroneous + # reason they have come back blank, because check_environment will shortly fail) + MSVS_LIB="${MSVS_LIB%%;};" + MSVS_INC="${MSVS_INC%%;};" + + # Visual Studio .NET 2002 and 2003 do not include mt in PATH, for not entirely clear reasons. + # This shim detects that scenario and adds the winnt folder to MSVS_PATH. + RET=0 + if [[ ${i/.*/} = "VS7" ]] ; then + find_in "${MSVS_PATH//:/*}" mt.exe + if [[ $RET -eq 1 ]] ; then + MSVS_PATH="$MSVS_PATH$(cygpath -u -f - <<< $ENV\\Bin\\winnt):" + RET=0 + fi + fi + + # Ensure that these derived values give a valid compiler. + if check_environment "${MSVS_PATH//:/*}" "${MSVS_INC//;/*}" "${MSVS_LIB//;/*}" "$i" $arch ; then + # Put the package back into FOUND, but augmented with the architecture name and with the + # derived values. + FOUND["$i-$arch"]="${CURRENT%)} [\"MSVS_PATH\"]=\"$MSVS_PATH\" \ + [\"MSVS_INC\"]=\"$MSVS_INC\" \ + [\"MSVS_LIB\"]=\"$MSVS_LIB\" \ + [\"ASSEMBLER\"]=\"$ASSEMBLER\")" #"# fixes vim syn match error + + # Check to see if this is a match for the environment C compiler. + if [[ -n ${ENV_ARCH+x} ]] ; then + TEST_cl=$(PATH="$MSVS_PATH:$PATH" which cl) + TEST_cl=${TEST_cl,,} + TEST_cl=${TEST_cl/bin\/*_/bin\/} + if [[ $TEST_cl = $ENV_cl ]] ; then + if [[ ${!ENV_INC/"$MSVS_INC"/} != "${!ENV_INC}" && \ + ${!ENV_LIB/"$MSVS_LIB"/} != "${!ENV_LIB}" ]] ; then + debug "$i-$arch is a strong candidate for the Environment C compiler" + if [[ -n ${ENV_COMPILER+x} ]] ; then + if [[ -z ${ENV_COMPILER} ]] ; then + ENV_COMPILER=$i-$arch + unset WEAK_ENV + else + # More than one strong candidate - no fall back available + unset ENV_COMPILER + unset WEAK_ENV + fi + fi + else + debug "$i-$arch is a weak candidate for the Environment C compiler" + if [[ -n ${WEAK_ENV+x} ]] ; then + if [[ -z ${WEAK_ENV} ]] ; then + WEAK_ENV=$i-$arch + else + # More than one weak candidate - no fall back available + unset WEAK_ENV + fi + fi + fi + fi + fi + fi + done + + # Does this package match the current preference? Note that PREFERENCE and TEST are constructed in + # a cunning (and hopefully not too "You are not expected to understand this" way) such that $PREF + # will always equal $i, unless $PREF = "@". + if [[ $PREF = $i ]] ; then + # In which case, check that the architecture(s)s were found + if [[ -n ${FOUND["$i-$LEFT_ARCH"]+x} && -n ${FOUND["$i-$RIGHT_ARCH"]+x} ]] ; then + debug "Solved TARGET_ARCH=$TARGET_ARCH with $i" + SOLUTION=$i + break + fi + fi + + if [[ $PREF != "@" ]] ; then + ((pref++)) + PREF=${PREFERENCE[$pref]} + fi +done + +# If we got this far, then either we failed to find a compiler at all, or we were looking for the +# environment compiler (or --all was specified). + +# Adopt a weak match for the environment compiler, if that's the best we can do. +if [[ -n ${ENV_COMPILER+x} && -z ${ENV_COMPILER} && -n ${WEAK_ENV} ]] ; then + warning "Assuming Environment C compiler is $WEAK_ENV" + ENV_COMPILER=$WEAK_ENV +fi + +declare -A FLIP +FLIP=(["x86"]="x64" ["x64"]="x86") + +if [[ $MODE -eq 0 ]] ; then + if [[ $PREF = "@" && -n ${ENV_COMPILER} ]] ; then + SOLUTION=${ENV_COMPILER%-$ENV_ARCH} + # If --arch wasn't specified, then ensure that the other architecture was also found. If --arch + # was specified, then validate that the compiler was valid. This should always happen, unless + # something went wrong running the script to get MSVS_PATH, MSVS_LIB and MSVS_INC. + if [[ -n ${FOUND["$SOLUTION-${FLIP[$ENV_ARCH]}"]+x} || + -n ${FOUND["$SOLUTION-$TARGET_ARCH"]+x} ]] ; then + debug "Solved with $SOLUTION" + else + unset SOLUTION + unset ENV_ARCH + fi + fi + + if [[ -z ${SOLUTION+x} ]] ; then + ((pref++)) + debug "Search remaining: ${PREFERENCE[*]}" + TEST_ARCH=$TARGET_ARCH + for i in "${PREFERENCE[@]:$pref}" ; do + if [[ -n ${FOUND["$i-$LEFT_ARCH"]+x} && -n ${FOUND["$i-$RIGHT_ARCH"]+x} ]] ; then + debug "Solved TARGET_ARCH='$TARGET_ARCH' with $i" + SOLUTION=$i + break + fi + done + fi +fi + +debug "Solution: $SOLUTION" + +if [[ -n ${ENV_COMPILER} && $MODE -eq 1 ]] ; then + echo "Identified Environment C compiler as $ENV_COMPILER" +fi + +if [[ $MODE -eq 1 ]] ; then + echo "Installed and usable packages:" + for i in "${!FOUND[@]}" ; do + echo " $i" + done | sort + exit 0 +fi + +if [[ -n $SOLUTION ]] ; then + eval COMPILER=${FOUND[$SOLUTION-$LEFT_ARCH]} + output MSVS_NAME "${COMPILER["DISPLAY"]}" $LEFT_ARCH + output MSVS_PATH "${COMPILER["MSVS_PATH"]}" $LEFT_ARCH + output MSVS_INC "${COMPILER["MSVS_INC"]}" $LEFT_ARCH + output MSVS_LIB "${COMPILER["MSVS_LIB"]}" $LEFT_ARCH + if [[ $ML_REQUIRED -eq 1 ]] ; then + output MSVS_ML "${COMPILER["ASSEMBLER"]%.exe}" always + fi + if [[ -z $TARGET_ARCH ]] ; then + eval COMPILER=${FOUND[$SOLUTION-$RIGHT_ARCH]} + output MSVS64_PATH "${COMPILER["MSVS_PATH"]}" $RIGHT_ARCH + output MSVS64_INC "${COMPILER["MSVS_INC"]}" $RIGHT_ARCH + output MSVS64_LIB "${COMPILER["MSVS_LIB"]}" $RIGHT_ARCH + if [[ $ML_REQUIRED -eq 1 ]] ; then + output MSVS64_ML "${COMPILER["ASSEMBLER"]%.exe}" always + fi + fi + exit 0 +else + exit 1 +fi + From b1f3836c5efb025acadcc7a6a5ff17fcb0125fff Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Wed, 22 Jul 2015 10:42:42 +0100 Subject: [PATCH 05/10] Support make cold for building on native Windows Updates the bootstrap script to build any of the four Windows ports. On non-Windows OSes, no change in behaviour. On Windows, the variable OCAML_PORT will control which native Windows port is built - mingw64, mingw, msvc64 and msvc. If Cygwin's gcc is installed (not recommended when building for native Windows) then OCAML_PORT must be specified, as make cold will build the Cygwin version of OPAM. OCAML_PORT=auto causes the script to auto-detect available compilers in the order given above. Bootstrap compiler also bumped to 4.04.2 --- Makefile | 10 +++- shell/bootstrap-ocaml.sh | 113 +++++++++++++++++++++++++++++++++++---- 2 files changed, 111 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index a824bb8764a..a7d967dd34d 100644 --- a/Makefile +++ b/Makefile @@ -156,8 +156,16 @@ configure: configure.ac m4/*.m4 release-%: $(MAKE) -C release TAG="$*" +ifeq ($(OCAML_PORT),) +ifneq ($(COMSPEC),) +ifeq ($(shell which gcc 2>/dev/null),) +OCAML_PORT=auto +endif +endif +endif + cold: - env MAKE=$(MAKE) ./shell/bootstrap-ocaml.sh + env MAKE=$(MAKE) ./shell/bootstrap-ocaml.sh $(OCAML_PORT) env PATH="`pwd`/bootstrap/ocaml/bin:$$PATH" ./configure $(CONFIGURE_ARGS) env PATH="`pwd`/bootstrap/ocaml/bin:$$PATH" $(MAKE) lib-ext env PATH="`pwd`/bootstrap/ocaml/bin:$$PATH" $(MAKE) diff --git a/shell/bootstrap-ocaml.sh b/shell/bootstrap-ocaml.sh index 64f8e0feb94..ca68939ceba 100755 --- a/shell/bootstrap-ocaml.sh +++ b/shell/bootstrap-ocaml.sh @@ -2,20 +2,111 @@ V=ocaml-4.06.0 URL=http://caml.inria.fr/pub/distrib/ocaml-4.06/${V}.tar.gz +if command -v curl > /dev/null; then + CURL="curl -OLSs" +elif command -v wget > /dev/null; then + CURL=wget +else + echo "This script requires curl or wget" + exit 1 +fi mkdir -p bootstrap cd bootstrap if [ ! -e ${V}.tar.gz ]; then - if command -v curl > /dev/null; then - curl -OLSs ${URL} - elif command -v wget > /dev/null; then - wget ${URL} - else - echo "This script requires curl or wget" - exit 1 - fi + ${CURL} ${URL} fi tar -zxf ${V}.tar.gz cd ${V} -./configure -prefix "`pwd`/../ocaml" -${MAKE:-make} world opt.opt -${MAKE:-make} install +PATH_PREPEND= +if [ -n "$1" -a -n "${COMSPEC}" -a -x "${COMSPEC}" ] ; then + LIB_PREPEND= + INC_PREPEND= + + case "$1" in + "mingw"|"mingw64") + BUILD=$1 + ;; + "msvc") + BUILD=$1 + if ! command -v ml > /dev/null ; then + eval `../../shell/msvs-detect --arch=x86` + if [ -n "${MSVS_NAME}" ] ; then + PATH_PREPEND="${MSVS_PATH}" + LIB_PREPEND="${MSVS_LIB};" + INC_PREPEND="${MSVS_INC};" + fi + fi + ;; + "msvc64") + BUILD=$1 + if ! command -v ml64 > /dev/null ; then + eval `../../shell/msvs-detect --arch=x64` + if [ -n "${MSVS_NAME}" ] ; then + PATH_PREPEND="${MSVS_PATH}" + LIB_PREPEND="${MSVS_LIB};" + INC_PREPEND="${MSVS_INC};" + fi + fi + ;; + *) + if [ "$1" != "auto" ] ; then + echo "Compiler architecture $1 not recognised -- mingw64, mingw, msvc64, msvc (or auto)" + fi + if [ -n "${PROCESSOR_ARCHITEW6432}" -o "${PROCESSOR_ARCHITECTURE}" = "AMD64" ] ; then + TRY64=1 + else + TRY64=0 + fi + + if [ ${TRY64} -eq 1 ] && command -v x86_64-w64-mingw32-gcc > /dev/null ; then + BUILD=mingw64 + elif command -v i686-w64-mingw32-gcc > /dev/null ; then + BUILD=mingw + elif [ ${TRY64} -eq 1 ] && command -v ml64 > /dev/null ; then + BUILD=msvc64 + PATH_PREPEND=`bash ../../shell/check_linker` + elif command -v ml > /dev/null ; then + BUILD=msvc + PATH_PREPEND=`bash ../../shell/check_linker` + else + if [ ${TRY64} -eq 1 ] ; then + BUILD=msvc64 + BUILD_ARCH=x64 + else + BUILD=msvc + BUILD_ARCH=x86 + fi + eval `../../shell/msvs-detect --arch=${BUILD_ARCH}` + if [ -z "${MSVS_NAME}" ] ; then + echo "No appropriate C compiler was found -- unable to build OCaml" + exit 1 + else + PATH_PREPEND="${MSVS_PATH}" + LIB_PREPEND="${MSVS_LIB};" + INC_PREPEND="${MSVS_INC};" + fi + fi + ;; + esac + if [ -n "${PATH_PREPEND}" ] ; then + PATH_PREPEND="${PATH_PREPEND}:" + fi + PREFIX=`cd .. ; pwd | cygpath -f - -m`/ocaml + sed -e "s|^PREFIX=.*|PREFIX=${PREFIX}|" config/Makefile.${BUILD} > config/Makefile + cp config/s-nt.h byterun/caml/s.h + cp config/m-nt.h byterun/caml/m.h + FV=0.37 + cd .. + if [ ! -e ${FV}.zip ]; then + ${CURL} https://github.com/alainfrisch/flexdll/archive/${FV}.tar.gz + fi + cd ${V} + tar -xzf ../${FV}.tar.gz + rm -rf flexdll + mv flexdll-${FV} flexdll + PATH="${PATH_PREPEND}${PREFIX}/bin:${PATH}" Lib="${LIB_PREPEND}${Lib}" Include="${INC_PREPEND}${Include}" make flexdll world.opt install +else + ./configure -prefix "`pwd`/../ocaml" + ${MAKE:-make} world opt.opt + ${MAKE:-make} install +fi From bb871133bc58464c00055b755634d8cb722ae00e Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Wed, 22 Jul 2015 10:58:13 +0100 Subject: [PATCH 06/10] Support bootstrap compiler in configure Split the cold Makefile target into compiler and cold. Allows a compiler to be bootstrapped before running configure. configure updated so that if the boot strap has been built, PATH is altered to use it. The change is persisted in Makefile.config, along with OCAMLLIB. --- Makefile | 7 +++++-- Makefile.config.in | 4 +++- configure | 19 ++++++++++++++++--- configure.ac | 15 +++++++++++++-- m4/ocaml.m4 | 2 +- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index a7d967dd34d..9487b637843 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ OPAMINSTALLER_FLAGS += --mandir "$(DESTDIR)$(mandir)" ifdef OCAMLFIND ifndef DESTDIR ifneq ($(OCAMLFIND),no) - LIBINSTALL_DIR ?= $(shell $(OCAMLFIND) printconf destdir) + LIBINSTALL_DIR ?= $(shell PATH="$(PATH)" $(OCAMLFIND) printconf destdir) endif endif endif @@ -164,8 +164,11 @@ endif endif endif -cold: +.PHONY: compiler cold +compiler: env MAKE=$(MAKE) ./shell/bootstrap-ocaml.sh $(OCAML_PORT) + +cold: compiler env PATH="`pwd`/bootstrap/ocaml/bin:$$PATH" ./configure $(CONFIGURE_ARGS) env PATH="`pwd`/bootstrap/ocaml/bin:$$PATH" $(MAKE) lib-ext env PATH="`pwd`/bootstrap/ocaml/bin:$$PATH" $(MAKE) diff --git a/Makefile.config.in b/Makefile.config.in index 30070d93d36..e0a4875703c 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -10,6 +10,8 @@ CONF_OCAMLFLAGS = @CONF_OCAMLFLAGS@ MCCS_ENABLED = @MCCS_ENABLED@ +OCAMLLIB = @OCAMLLIB@ + OCAMLFIND = @OCAMLFIND@ OCAML = @OCAML@ OCAMLC = @OCAMLC@ @@ -28,4 +30,4 @@ LIB_PREFIX = @LIB_PREFIX@ CPATH = @CPATH@ LIBRARY_PATH = @LIBRARY_PATH@ -export OCAMLVERSION OCAMLFIND OCAML OCAMLC OCAMLOPT EXE PATH INCLUDE LIB CPATH LIBRARY_PATH +export OCAMLVERSION OCAMLFIND OCAML OCAMLC OCAMLOPT EXE PATH INCLUDE LIB CPATH LIBRARY_PATH OCAMLLIB diff --git a/configure b/configure index e69c58293d7..785cb01f95a 100755 --- a/configure +++ b/configure @@ -1817,6 +1817,18 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu +# If a bootstrap compiler has been built, always use it +PATH_PREPEND= +PRE_BOOTSTRAP_PATH="$PATH" +if test -x bootstrap/ocaml/bin/ocamlc -o -x bootstrap/ocaml/bin/ocamlopt ; then : + + echo Bootstrap compiler found -- activating + unset OCAMLLIB + export PATH_PREPEND=`pwd`/bootstrap/ocaml/bin: + export PATH="$PATH_PREPEND:$PATH" + +fi + # checking for ocamlc if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamlc", so it can be a program name with args. @@ -1917,7 +1929,7 @@ fi $as_echo "OCaml version is $OCAMLVERSION" >&6; } # If OCAMLLIB is set, use it if test "$OCAMLLIB" = ""; then - OCAMLLIB=`$OCAMLC -where 2>/dev/null || $OCAMLC -v|tail -1|cut -d ' ' -f 4` + OCAMLLIB=`$OCAMLC -where 2>/dev/null | tr -d '\015' || $OCAMLC -v|tail -1|cut -d ' ' -f 4` else { $as_echo "$as_me:${as_lineno-$LINENO}: result: OCAMLLIB previously set; preserving it." >&5 $as_echo "OCAMLLIB previously set; preserving it." >&6; } @@ -3213,7 +3225,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an installed Microsoft C Compiler for ${SDK_ARCH}" >&5 $as_echo_n "checking for an installed Microsoft C Compiler for ${SDK_ARCH}... " >&6; } - eval `./shell/msvs-detect --arch=$SDK_ARCH; echo RESULT=$?` + eval `PATH="$PRE_BOOTSTRAP_PATH" ./shell/msvs-detect --arch=$SDK_ARCH; echo RESULT=$?` if test "x$MSVS_NAME" = "x" ; then : if test ${RESULT} -eq 0 ; then : @@ -3232,7 +3244,8 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: from $MSVS_NAME" >&5 $as_echo "from $MSVS_NAME" >&6; } export PATH_PREPEND="${MSVS_PATH}:${PATH_PREPEND}" - export PATH="${PATH_PREPEND}$PATH" + # Note that we put ${MSVS_PATH} here NOT ${PATH_PREPEND} so that the bootstrap path isn't repeated + export PATH="${MSVS_PATH}:$PATH" LIB_PREPEND="${MSVS_LIB};" INC_PREPEND="${MSVS_INC};" export Lib="${MSVS_LIB};$LIB" diff --git a/configure.ac b/configure.ac index 2fad30d1571..0e04e379ecf 100644 --- a/configure.ac +++ b/configure.ac @@ -3,6 +3,16 @@ AC_COPYRIGHT(Copyright 2012-2017 OcamlPro SAS) AC_CONFIG_MACRO_DIR([m4]) +# If a bootstrap compiler has been built, always use it +PATH_PREPEND= +PRE_BOOTSTRAP_PATH="$PATH" +AS_IF([ test -x bootstrap/ocaml/bin/ocamlc -o -x bootstrap/ocaml/bin/ocamlopt ],[ + echo Bootstrap compiler found -- activating + unset OCAMLLIB + export PATH_PREPEND=`pwd`/bootstrap/ocaml/bin: + export PATH="$PATH_PREPEND:$PATH" +]) + AC_PROG_OCAML if test "x$OCAMLC" = "xno"; then AC_MSG_ERROR([You must install the OCaml compiler]) @@ -69,7 +79,7 @@ AS_IF([test ! -x ${OCAML_TEST_CC}],[ AS_IF([test "x${CCOMP_TYPE}" = "xmsvc"],[ AS_IF([test "${ARCH}" = "i386"],[SDK_ARCH=x86],[SDK_ARCH=x64]) AC_MSG_CHECKING([for an installed Microsoft C Compiler for ${SDK_ARCH}]) - eval `./shell/msvs-detect --arch=$SDK_ARCH; echo RESULT=$?` + eval `PATH="$PRE_BOOTSTRAP_PATH" ./shell/msvs-detect --arch=$SDK_ARCH; echo RESULT=$?` AS_IF([ test "x$MSVS_NAME" = "x" ], [ AS_IF([ test ${RESULT} -eq 0 ], [ AC_MSG_RESULT([from PATH]) @@ -79,7 +89,8 @@ AS_IF([test ! -x ${OCAML_TEST_CC}],[ ],[ AC_MSG_RESULT([from $MSVS_NAME]) export PATH_PREPEND="${MSVS_PATH}:${PATH_PREPEND}" - export PATH="${PATH_PREPEND}$PATH" + # Note that we put ${MSVS_PATH} here NOT ${PATH_PREPEND} so that the bootstrap path isn't repeated + export PATH="${MSVS_PATH}:$PATH" LIB_PREPEND="${MSVS_LIB};" INC_PREPEND="${MSVS_INC};" export Lib="${MSVS_LIB};$LIB" diff --git a/m4/ocaml.m4 b/m4/ocaml.m4 index 1c9efddb3f8..6b5da59a1f4 100644 --- a/m4/ocaml.m4 +++ b/m4/ocaml.m4 @@ -18,7 +18,7 @@ AC_DEFUN([AC_PROG_OCAML], AC_MSG_RESULT([OCaml version is $OCAMLVERSION]) # If OCAMLLIB is set, use it if test "$OCAMLLIB" = ""; then - OCAMLLIB=`$OCAMLC -where 2>/dev/null || $OCAMLC -v|tail -1|cut -d ' ' -f 4` + OCAMLLIB=`$OCAMLC -where 2>/dev/null | tr -d '\015' || $OCAMLC -v|tail -1|cut -d ' ' -f 4` else AC_MSG_RESULT([OCAMLLIB previously set; preserving it.]) fi From aa043dd2dd22737b6269fb146c250a42dbc99617 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Thu, 23 Jul 2015 15:34:14 +0100 Subject: [PATCH 07/10] Update bootstrap-ocaml.sh to work offline Archives downloaded by shell/bootstrap-ocaml.sh may be placed in src_ext/archives and will be cp'd if they exist (as for make lib-ext). --- shell/bootstrap-ocaml.sh | 17 +++++++++-------- src_ext/Makefile | 8 +++++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/shell/bootstrap-ocaml.sh b/shell/bootstrap-ocaml.sh index ca68939ceba..7b8294e5fb2 100755 --- a/shell/bootstrap-ocaml.sh +++ b/shell/bootstrap-ocaml.sh @@ -1,7 +1,5 @@ #!/bin/sh -e -V=ocaml-4.06.0 -URL=http://caml.inria.fr/pub/distrib/ocaml-4.06/${V}.tar.gz if command -v curl > /dev/null; then CURL="curl -OLSs" elif command -v wget > /dev/null; then @@ -12,8 +10,12 @@ else fi mkdir -p bootstrap cd bootstrap +URL=`sed -ne 's/URL_ocaml *= *//p' ../src_ext/Makefile | tr -d '\r'` +V=`echo ${URL}| sed -e 's/.*\/\([^\/]\+\)\.tar\.gz/\1/'` +FV_URL=`sed -ne 's/URL_flexdll *= *//p' ../src_ext/Makefile | tr -d '\r'` +FLEXDLL=`echo ${FV_URL}| sed -e 's/.*\/\([^\/]*\)/\1/'` if [ ! -e ${V}.tar.gz ]; then - ${CURL} ${URL} + cp ../src_ext/archives/${V}.tar.gz . 2>/dev/null || ${CURL} ${URL} fi tar -zxf ${V}.tar.gz cd ${V} @@ -95,15 +97,14 @@ if [ -n "$1" -a -n "${COMSPEC}" -a -x "${COMSPEC}" ] ; then sed -e "s|^PREFIX=.*|PREFIX=${PREFIX}|" config/Makefile.${BUILD} > config/Makefile cp config/s-nt.h byterun/caml/s.h cp config/m-nt.h byterun/caml/m.h - FV=0.37 cd .. - if [ ! -e ${FV}.zip ]; then - ${CURL} https://github.com/alainfrisch/flexdll/archive/${FV}.tar.gz + if [ ! -e ${FLEXDLL} ]; then + cp ../src_ext/archives/${FLEXDLL} . 2>/dev/null || ${CURL} ${FV_URL} fi cd ${V} - tar -xzf ../${FV}.tar.gz + tar -xzf ../${FLEXDLL} rm -rf flexdll - mv flexdll-${FV} flexdll + mv flexdll-* flexdll PATH="${PATH_PREPEND}${PREFIX}/bin:${PATH}" Lib="${LIB_PREPEND}${Lib}" Include="${INC_PREPEND}${Include}" make flexdll world.opt install else ./configure -prefix "`pwd`/../ocaml" diff --git a/src_ext/Makefile b/src_ext/Makefile index c41422059b5..c3bfa4dc90a 100644 --- a/src_ext/Makefile +++ b/src_ext/Makefile @@ -40,6 +40,12 @@ MD5_result = 3d5b66c5526918f0f2ca9d6811ef09c8 URL_jbuilder = https://github.com/janestreet/jbuilder/archive/08050696fb701dafcd1372aadfaa800a50bc01ca.tar.gz MD5_jbuilder = 53b65232ebb5fd319acf90922342615d +URL_ocaml = http://caml.inria.fr/pub/distrib/ocaml-4.06/ocaml-4.06.0.tar.gz +MD5_ocaml = 66e5439eb63dbb8b8224cba5d1b20947 + +URL_flexdll = https://github.com/alainfrisch/flexdll/archive/0.37.tar.gz +MD5_flexdll = cc456a89382e60d84130cddd53977486 + ifndef FETCH ifneq ($(shell command -v curl 2>/dev/null),) FETCH = curl -OLSs @@ -89,7 +95,7 @@ clone: $(JBUILDER_CLONE) $(SRC_EXTS:=.stamp) | ext-ignore archives: $(SRC_EXTS:=.download) @ -cache-archives: $(SRC_EXTS:=.cache) jbuilder.cache +cache-archives: $(SRC_EXTS:=.cache) jbuilder.cache ocaml.cache flexdll.cache @ %.cache: From c2bdf4ed61cde0dc313866376eecc97724084fd8 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Sat, 29 Aug 2015 10:25:25 +0100 Subject: [PATCH 08/10] Add Windows build instructions to README.md --- README.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/README.md b/README.md index 13eb2589aa9..fd4b8196bca 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,77 @@ it as a second step. If you are developing OPAM, you may enable developer features by including the `--enable-developer-mode` parameter with `./configure`. +## Compiling on Native Windows + +``` +BUILDING ON WINDOWS IS A WORK-IN-PROGRESS AND THESE INSTRUCTIONS WILL EVOLVE! +``` + +Cygwin (https://www.cygwin.com/setup-x86_64.exe) is always required to build opam on +Windows. Both the 64-bit and 32-bit versions of Cygwin may be used (you can build +32-bit opam using 64-bit Cygwin and vice versa though note that you must be running +64-bit Windows in order to build the 64-bit version). + +The following Cygwin packages are required: +* From Devel - `make` +* From Devel - `patch` (not required if OCaml and all required packages are + pre-installed) +* From Devel - `mingw64-i686-gcc-core` & `mingw64-x86_64-gcc-core` (not required if + building with MSVC) + +Alternatively, having downloaded Cygwin's setup program, Cygwin can be installed +using the following command line: + +`setup-x86_64 --root=C:\cygwin64 --quiet-mode --no-desktop --no-startmenu --packages=make,mingw64-i686-gcc-core,mingw64-x86_64-gcc-core,patch` + +The `--no-desktop` and `--no-startmenu` switches may be omitted in order to create +shortcuts on the Desktop and Start Menu respectively. Executed this way, setup will +still be interactive, but the packages will have been pre-selected. To make setup +fully unattended, choose a mirror URL from https://cygwin.com/mirrors.lst and add +the --site switch to the command line +(e.g. `--site=http://www.mirrorservice.org/sites/sourceware.org/pub/cygwin/`). + +It is recommended that you set the `CYGWIN` environment variable to +`nodosfilewarning winsymlinks:native`. + +Cygwin is started either from a shortcut or by running: + +``` +C:\cygwin64\bin\mintty - +``` + +It is recommended that opam be built outside Cygwin's root +(so in `/cygdrive/c/...`). From an elevated Cygwin shell, edit `/etc/fstab` and +ensure that the file's content is exactly: + +``` +none /cygdrive cygdrive noacl,binary,posix=0,user 0 0 +``` + +The change is the addition of the `noacl` option to the mount instructions for +`/cygdrive` and this stops from Cygwin from attempting to emulate POSIX permissions +over NTFS (which can result in strange and unnecessary permissions showing up in +Windows Explorer). It is necessary to close and restart all Cygwin terminal windows +after changing `/etc/fstab`. + +opam is able to be built **without** a pre-installed OCaml compiler. For the MSVC +ports of OCaml, the Microsoft Windows SDK 7 or later or Microsoft Visual Studio is +required (https://www.microsoft.com/en-gb/download/details.aspx?id=8442 - either x86 +or x64 may be installed, as appropriate to your system). It is not necessary to +modify PATH, INCLUDE or LIB - opam's build system will automatically detect the +required changes. + +If OCaml is not pre-installed, run: +``` +make compiler [OCAML_PORT=mingw64|mingw|msvc64|msvc|auto] +``` +The `OCAML_PORT` variable determines which flavour of Windows OCaml is compiled - +`auto` will attempt to guess. As long as `gcc` is **not** installed in Cygwin +(i.e. the native C compiler *for Cygwin*), `OCAML_PORT` does not need to be +specified and `auto` will be assumed. + +You can then `configure` and build opam as above. + ## Compiling without OCaml `make cold` is provided as a facility to compile OCaml, then bootstrap opam. From 60e607bd729aa8c90656555f37d5cdc69b1ed10d Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Tue, 2 Jan 2018 13:17:17 +0000 Subject: [PATCH 09/10] Full AppVeyor test matrix Signed-off-by: David Allsopp --- Makefile | 4 ++ appveyor.yml | 34 +++++++---- appveyor_build.cmd | 128 +++++++++++++++++++++++++++++++++++++++ appveyor_test.sh | 5 ++ shell/bootstrap-ocaml.sh | 1 + 5 files changed, 161 insertions(+), 11 deletions(-) create mode 100644 appveyor_build.cmd create mode 100644 appveyor_test.sh diff --git a/Makefile b/Makefile index 9487b637843..41f21789af8 100644 --- a/Makefile +++ b/Makefile @@ -175,3 +175,7 @@ cold: compiler cold-%: env PATH="`pwd`/bootstrap/ocaml/bin:$$PATH" $(MAKE) $* + +.PHONY: run-appveyor-test +run-appveyor-test: + env PATH="`pwd`/bootstrap/ocaml/bin:$$PATH" ./appveyor_test.sh diff --git a/appveyor.yml b/appveyor.yml index 17333451a21..80109a5eca5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,25 +1,37 @@ platform: - - x86 + - x64 + +image: Visual Studio 2017 environment: global: - CYG_ROOT: C:/cygwin + CYG_ROOT: cygwin64 + CYG_ARCH: x86_64 + OCAML_PORT: CYG_CACHE: C:/cygwin/var/cache/setup CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/ matrix: - - + - CYG_ROOT: cygwin CYG_ARCH: x86 + - CYG_ROOT: cygwin64 + CYG_ARCH: x86_64 + - OCAML_PORT: msvc + - OCAML_PORT: msvc64 + - OCAML_PORT: mingw + - OCAML_PORT: mingw64 + +cache: + - C:\projects\opam\bootstrap + - C:\projects\opam\src_ext\archives init: - - 'echo System architecture: %PLATFORM%' + - "echo System architecture: %PLATFORM%" install: - - 'appveyor DownloadFile http://cygwin.com/setup-%CYG_ARCH%.exe -FileName setup.exe' - - 'setup.exe -gqnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P make,git,gcc-core,gcc-g++,ocaml,ocaml-camlp4,ocaml-compiler-libs,libncurses-devel,unzip,libmpfr-devel,patch,flexdll,libglpk-devel >NUL' - - '%CYG_ROOT%/bin/bash -lc "cygcheck -dc cygwin gcc-core"' + - call "%APPVEYOR_BUILD_FOLDER%\appveyor_build.cmd" install build_script: - - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && env DJDIR="workaround" ./configure && make lib-ext && make && make install"' - - '%CYG_ROOT%/bin/bash -lc "opam init -y -a"' - - '%CYG_ROOT%/bin/bash -lc "opam config env"' - - '%CYG_ROOT%/bin/bash -lc "opam install -y -v ocamlfind"' + - call "%APPVEYOR_BUILD_FOLDER%\appveyor_build.cmd" build + +test_script: + - call "%APPVEYOR_BUILD_FOLDER%\appveyor_build.cmd" test diff --git a/appveyor_build.cmd b/appveyor_build.cmd new file mode 100644 index 00000000000..92e225501fb --- /dev/null +++ b/appveyor_build.cmd @@ -0,0 +1,128 @@ +@rem *********************************************************************** +@rem * * +@rem * opam * +@rem * * +@rem * David Allsopp, OCaml Labs, Cambridge. * +@rem * * +@rem * Copyright 2018 MetaStack Solutions Ltd. * +@rem * * +@rem * All rights reserved. This file is distributed under the terms of * +@rem * the GNU Lesser General Public License version 2.1, with the * +@rem * special exception on linking described in the file LICENSE. * +@rem * * +@rem *********************************************************************** + +@rem BE CAREFUL ALTERING THIS FILE TO ENSURE THAT ERRORS PROPAGATE +@rem IF A COMMAND SHOULD FAIL IT PROBABLY NEEDS TO END WITH +@rem || exit /b 1 +@rem BASICALLY, DO THE TESTING IN BASH... + +@rem Do not call setlocal! +@echo off + +goto %1 + +goto :EOF + +:CheckPackage +"%CYG_ROOT%\bin\bash.exe" -lc "cygcheck -dc %1" | findstr %1 > nul +if %ERRORLEVEL% equ 1 ( + echo Cygwin package %1 will be installed + set CYGWIN_INSTALL_PACKAGES=%CYGWIN_INSTALL_PACKAGES%,%1 +) +goto :EOF + +:UpgradeCygwin +if "%CYGWIN_INSTALL_PACKAGES%" neq "" "%CYG_ROOT%\setup-%CYG_ARCH%.exe" --quiet-mode --no-shortcuts --no-startmenu --no-desktop --only-site --root "%CYG_ROOT%" --site "%CYG_MIRROR%" --local-package-dir "%CYG_CACHE%" --packages %CYGWIN_INSTALL_PACKAGES:~1% > nul +for %%P in (%CYGWIN_COMMANDS%) do "%CYG_ROOT%\bin\bash.exe" -lc "%%P --help" > nul || set CYGWIN_UPGRADE_REQUIRED=1 +"%CYG_ROOT%\bin\bash.exe" -lc "cygcheck -dc %CYGWIN_PACKAGES%" +if %CYGWIN_UPGRADE_REQUIRED% equ 1 ( + echo Cygwin package upgrade required - please go and drink coffee + "%CYG_ROOT%\setup-%CYG_ARCH%.exe" --quiet-mode --no-shortcuts --no-startmenu --no-desktop --only-site --root "%CYG_ROOT%" --site "%CYG_MIRROR%" --local-package-dir "%CYG_CACHE%" --upgrade-also > nul + "%CYG_ROOT%\bin\bash.exe" -lc "cygcheck -dc %CYGWIN_PACKAGES%" +) +goto :EOF + +:install +set CYG_ROOT=C:\%CYG_ROOT% + +cd "%APPVEYOR_BUILD_FOLDER%" + +rem CYGWIN_PACKAGES is the list of required Cygwin packages (cygwin is included +rem in the list just so that the Cygwin version is always displayed on the log). +rem CYGWIN_COMMANDS is a corresponding command to run with --version to test +rem whether the package works. This is used to verify whether the installation +rem needs upgrading. +set CYGWIN_PACKAGES=cygwin make patch curl diffutils tar unzip +set CYGWIN_COMMANDS=cygcheck make patch curl diff tar unzip + +if "%OCAML_PORT%" equ "mingw" ( + set CYGWIN_PACKAGES=%CYGWIN_PACKAGES% mingw64-i686-gcc-g++ + set CYGWIN_COMMANDS=%CYGWIN_COMMANDS% i686-w64-mingw32-g++ +) +if "%OCAML_PORT%" equ "mingw64" ( + set CYGWIN_PACKAGES=%CYGWIN_PACKAGES% mingw64-x86_64-gcc-g++ + set CYGWIN_COMMANDS=%CYGWIN_COMMANDS% x86_64-w64-mingw32-g++ +) +if "%OCAML_PORT%" equ "" ( + set CYGWIN_PACKAGES=%CYGWIN_PACKAGES% gcc-g++ flexdll + set CYGWIN_COMMANDS=%CYGWIN_COMMANDS% g++ flexlink +) + +set CYGWIN_INSTALL_PACKAGES= +set CYGWIN_UPGRADE_REQUIRED=0 + +for %%P in (%CYGWIN_PACKAGES%) do call :CheckPackage %%P +call :UpgradeCygwin + +set INSTALLED_URL= +for /f "tokens=3" %%U in ('findstr /C:"URL_ocaml = " src_ext\Makefile') do set OCAML_URL=%%U +for /f "tokens=3" %%U in ('findstr /C:"URL_flexdll = " src_ext\Makefile') do set FLEXDLL_URL=%%U +if exist bootstrap\installed-tarball for /f "delims=" %%U in ('type bootstrap\installed-tarball') do set INSTALLED_URL=%%U +if "%INSTALLED_URL%" neq "%OCAML_URL% %FLEXDLL_URL%" if exist bootstrap\nul ( + echo Required: %OCAML_URL% %FLEXDLL_URL% + echo Compiled: %INSTALLED_URL% + echo Re-building bootstrap compiling + rd /s/q bootstrap + if exist src_ext\archives\nul rd /s/q src_ext\archives +) + +"%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER && make -C src_ext cache-archives" || exit /b 1 + +if not exist bootstrap\nul ( + "%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER && make compiler" || exit /b 1 + if "%CYG_ARCH%%OCAML_PORT%" equ "x86_64" ( + "%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER && rebase -b 0x7cd20000 bootstrap/ocaml/lib/ocaml/stublibs/dllunix.so" || exit /b 1 + "%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER && rebase -b 0x7cd20000 bootstrap/ocaml/lib/ocaml/stublibs/dllthreads.so" || exit /b 1 + ) + if exist bootstrap\ocaml-*.tar.gz del bootstrap\ocaml-*.tar.gz + if "%OCAML_PORT%" neq "" if exist bootstrap\flexdll-*.tar.gz del bootstrap\flexdll-*.tar.gz + del bootstrap\ocaml\bin\*.byte.exe + if "%OCAML_PORT%" equ "" ( + del bootstrap\ocaml\lib\ocaml\expunge.exe + ) else ( + del bootstrap\ocaml\lib\expunge.exe + ) + for /f %%D in ('dir /b/ad bootstrap\ocaml-*') do ( + rd /s/q bootstrap\%%D + if "%OCAML_PORT%" equ "" ( + rem Directory needs to exist, as the Cygwin bootstraps OCAMLLIB refers to it + md bootstrap\%%D + ) + ) +) + +goto :EOF + +:build +if "%OCAML_PORT%" equ "" ( + rem make install doesn't yet work for the native Windows builds + set POST_COMMAND=^&^& make opam-installer install +) +"%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER && ./configure && make lib-ext && make opam %POST_COMMAND%" || exit /b 1 +goto :EOF + +:test +rem Can't yet do an opam init with the native Windows builds +if "%OCAML_PORT%" equ "" "%CYG_ROOT%\bin\bash.exe" -lc "make -C $APPVEYOR_BUILD_FOLDER run-appveyor-test" || exit /b 1 +goto :EOF diff --git a/appveyor_test.sh b/appveyor_test.sh new file mode 100644 index 00000000000..5a6af18e198 --- /dev/null +++ b/appveyor_test.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +opam init -y -a +eval $(opam config env) +opam install -y -v ocamlfind diff --git a/shell/bootstrap-ocaml.sh b/shell/bootstrap-ocaml.sh index 7b8294e5fb2..7739abf37e7 100755 --- a/shell/bootstrap-ocaml.sh +++ b/shell/bootstrap-ocaml.sh @@ -111,3 +111,4 @@ else ${MAKE:-make} world opt.opt ${MAKE:-make} install fi +echo "${URL} ${FV_URL}" > ../installed-tarball From 2a54a9023e57e72707e7d18e639b8319b924434c Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Tue, 2 Jan 2018 13:17:17 +0000 Subject: [PATCH 10/10] Use dra27 jbuilder/ocaml-mccs/flexdll for AppVeyor - Need unreleased ocaml-mccs 1.1+5 to build mccs on Windows. - Need unreleased jbuilder beta17 to build mccs on MSVC. - Need unreleased flexdll 0.38 to build mccs on mingw. Signed-off-by: David Allsopp --- appveyor.patch | 49 ++++++++++++++++++++++++++++++++++++++++++++++ appveyor_build.cmd | 3 +++ 2 files changed, 52 insertions(+) create mode 100644 appveyor.patch diff --git a/appveyor.patch b/appveyor.patch new file mode 100644 index 00000000000..186199af69f --- /dev/null +++ b/appveyor.patch @@ -0,0 +1,49 @@ +From 083bae674ad77b6b5b5fafbff25b20473655cb2a Mon Sep 17 00:00:00 2001 +From: David Allsopp +Date: Wed, 27 Dec 2017 10:37:12 +0200 +Subject: [PATCH] Use dra27 jbuilder/ocaml-mccs/flexdll + + - Need unreleased ocaml-mccs 1.1+5 to build mccs on Windows. + - Need unreleased jbuilder beta17 to build mccs on MSVC. + - Need unreleased flexdll 0.38 to build mccs on mingw. +--- + src_ext/Makefile | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src_ext/Makefile b/src_ext/Makefile +index 64fdd8af..d1457b5f 100644 +--- a/src_ext/Makefile ++++ b/src_ext/Makefile +@@ -28,8 +28,8 @@ MD5_cudf = a4c0e652e56e74c7b388a43f9258d119 + URL_dose3 = https://gforge.inria.fr/frs/download.php/file/36063/dose3-5.0.1.tar.gz + MD5_dose3 = e7d4b1840383c6732f29a47c08ba5650 + +-URL_mccs = https://github.com/AltGr/ocaml-mccs/archive/1.1+4.tar.gz +-MD5_mccs = 1ff2d73ab5c69e1fb58160213fc2d4c9 ++URL_mccs = https://github.com/dra27/ocaml-mccs/archive/1.1+4-dra27.tar.gz ++MD5_mccs = 08e80e39a0d960c01955a970d13afb29 + + URL_opam-file-format = https://github.com/ocaml/opam-file-format/archive/2.0.0-beta5.tar.gz + MD5_opam-file-format = 5408798ca3af6e36379dd34b1b618b9c +@@ -37,14 +37,14 @@ MD5_opam-file-format = 5408798ca3af6e36379dd34b1b618b9c + URL_result = https://github.com/janestreet/result/archive/1.2.tar.gz + MD5_result = 3d5b66c5526918f0f2ca9d6811ef09c8 + +-URL_jbuilder = https://github.com/janestreet/jbuilder/archive/08050696fb701dafcd1372aadfaa800a50bc01ca.tar.gz +-MD5_jbuilder = 53b65232ebb5fd319acf90922342615d ++URL_jbuilder = https://github.com/dra27/jbuilder/archive/fix-copy.tar.gz ++MD5_jbuilder = cbf9d2e783feab1f4a61fea35ec96118 + + URL_ocaml = http://caml.inria.fr/pub/distrib/ocaml-4.06/ocaml-4.06.0.tar.gz + MD5_ocaml = 66e5439eb63dbb8b8224cba5d1b20947 + +-URL_flexdll = https://github.com/alainfrisch/flexdll/archive/0.37.tar.gz +-MD5_flexdll = cc456a89382e60d84130cddd53977486 ++URL_flexdll = https://github.com/dra27/flexdll/archive/linking-c++.tar.gz ++MD5_flexdll = 75bd0efc328ad9f8f2e01414464d217b + + ifndef FETCH + ifneq ($(shell command -v curl 2>/dev/null),) +-- +2.12.0.windows.1 + diff --git a/appveyor_build.cmd b/appveyor_build.cmd index 92e225501fb..450b658b895 100644 --- a/appveyor_build.cmd +++ b/appveyor_build.cmd @@ -75,6 +75,9 @@ set CYGWIN_UPGRADE_REQUIRED=0 for %%P in (%CYGWIN_PACKAGES%) do call :CheckPackage %%P call :UpgradeCygwin +rem Use dra27 jbuilder/ocaml-mccs/flexdll for native ports +if "%OCAML_PORT%" neq "" git apply appveyor.patch + set INSTALLED_URL= for /f "tokens=3" %%U in ('findstr /C:"URL_ocaml = " src_ext\Makefile') do set OCAML_URL=%%U for /f "tokens=3" %%U in ('findstr /C:"URL_flexdll = " src_ext\Makefile') do set FLEXDLL_URL=%%U