Forum Navigation
Building tango with gdc/mingw32
Posted: 06/21/07 13:47:12 Modified: 06/21/07 15:24:26Builing tango 0.98 - ok
examples - mostly ok (fiber_test freaks out on "Testing throwYield" and something strange is going on with path routines)How-to
1. Files
gdmd (this is port of perl version to bash with additional features):#!/bin/sh # Port of original gdmd to bash by John 'Profic' Ustiuzhanin. gdc= gcc_maj= gcc_min= gcc_target= gcc_host= with_exe=0 path_sep=: output_directory= output_parents=0 output_file= assemble=1 link=1 run=0 verbose=0 show_commands=0 seen_all_sources_flag=0 first_input_file= sources=() isources=0 objects=() iobjects=0 dobjects=() idobjects=0 out=() iout=0 link_out=() ilink_out=0 run_args=() temp_var= #gdc=`type -p $0 | sed -e 's/\(.*[\/-]\)g\?dmd/\1gdc/'` gdc=`type -p $0` if [ "${gdc: -4}" == gdmd ]; then gdc="${gdc%gdmd}gdc" elif [ "${gdc: -3}" == dmd ]; then gdc="${gdc%dmd}gdc" fi function printUsage() { cat<<"EOHELP" Documentation: www.digitalmars.com/d/index.html http://dgcc.sourceforge.net/ Usage: gdmd files.d ... { -switch } dmd switches: files.d D source files -c do not link -D generate documentation -Dddocdir write documentation file to docdir directory -Dffilename write documentation file to filename -d allow deprecated features -debug compile in debug code -debug=level compile in debug code <= level -debug=ident compile in debug code identified by ident -g add symbolic debug info -gc add symbolic debug info, pretend to be C -H generate 'header' file -Hdhdrdir write 'header' file to hdrdir directory -Hffilename write 'header' file to filename --help print help -Ipath where to look for imports -Jpath where to look for string imports -inline do function inlining -Llinkerflag pass linkerflag to link -nofloat do not emit reference to floating point -O optimize -o- do not write object file -odobjdir write object files to directory objdir -offilename name output file to filename -op do not strip paths from source file -profile profile runtime performance of generated code -quiet suppress unnecessary messages -release compile release version -run srcfile args... run resulting program, passing args -unittest compile in unit tests -v verbose -v1 D language version 1 -version=level compile in version code >= level -version=ident compile in version code identified by ident -w enable warnings gdc/script switches: -arch ... pass an -arch ... option to gdc -f... pass an -f... option to gdc -framework ... pass a -framework ... option to gdc -m... pass an -m... option to gdc -q,arg1,... pass arg1, arg2, etc. to to gdc -q,-S compile only, do not assemble or link -vdmd print commands run by this script environment variables: DNOVERSIONS comma-separated list of excluded versions for gdc EOHELP } function error() { echo "dmd: $2" exit $1; } function checkArg() { [ ! "$2" ] && error 1 "argument expected for switch '$name'" } function addSourceFile() { if [ ! "$first_input_file" ]; then first_input_file=$1 fi sources[isources++]=$1 } if [ ! -f "$gdc" ]; then error 1 "no gdc alongside" fi temp_var=`"$gdc" -dumpversion` temp_var=${temp_var%.*} gcc_maj=${temp_var%.*} gcc_min=${temp_var#*.} gcc_target=`"$gdc" -dumpmachine` gcc_host=`uname` # TODO: Add more things with .exe extension. if [ "${gcc_target/[Mm][Ii][Nn][Gg][Ww]32}" != "$gcc_target" ]; then with_exe=1 fi if [ "${gcc_host/[Mm][Ii][Nn][Gg][Ww]32}" != "$gcc_host" ]; then path_sep=; elif [ "${gcc_host/[Dd][Aa][Rr][Ww][Ii][Nn]}" != "$gcc_host" ]; then path_sep=, fi # For use of this var look at processing of -version=*. if [ "$DNOVERSIONS" -a "${DNOVERSIONS:0:1}" != "," -a "${DNOVERSIONS: -1}" != "," ]; then DNOVERSIONS=,$DNOVERSIONS, fi while [ "$1" ]; do arg="$1" shift case "$arg" in -c) link=0 ;; -cov) out[iout++]=-fprofile-arcs out[iout++]=-ftest-coverage ;; -D) out[iout++]=-fdoc ;; -Dd*) checkArg -Dd "${arg:3}" out[iout++]="-fdoc-dir=${arg:3}" ;; -Df*) checkArg -Df "${arg:3}" out[iout++]="-fdoc-file=${arg:3}" ;; -d) out[iout++]=-fdeprecated ;; -debug) out[iout++]=-fdebug ;; -debug=*) checkArg -debug ${arg:7} out[iout++]=-fdebug=${arg:7} ;; -g) out[iout++]=-g ;; -gc) out[iout++]=-fdebug-c ;; -gt) error 1 "use -profile instead of -gt" #out[iout++]=-pg ;; -H) out[iout++]=-fintfc ;; -Hd*) checkArg -Hd "${arg:3}" out[iout++]="-fintfc-dir=${arg:3}" ;; -Hf*) checkArg -Hf "${arg:3}" out[iout++]="-fintfc-file=${arg:3}" ;; --help) printUsage exit 0 ;; -I* | -J*) checkArg -I/-J "${arg:2}" temp_var="${arg:2}" eval temp_var=(\"${temp_var//"$path_sep"/\" \"}\") for temp_var in "${temp_var[@]}"; do out[iout++]="-I$temp_var" done ;; -inline) out[iout++]=-finline-functions ;; -L*) checkArg -L "${arg:2}" link_out[ilink_out++]=-Wl,${arg:2} ;; -nofloat) ;; # Do nothing. -O) out[iout++]=-O3 temp_var="${out[@]} $@" if [ "${temp_var/-finline-function}" == "$temp_var" -a "${temp_var/-inline}" == "$temp_var" ]; then out[iout++]=-fno-inline-functions fi if [ $gcc_maj -lt 4 ]; then out[iout++]=-frename-registers fi if [ $gcc_maj -gt 3 -o \( $gcc_maj -eq 3 -a $gcc_min -ge 4 \) ]; then out[iout++]=-fweb fi ;; -o-) out[iout++]=-fsyntax-only link=0 ;; -od*) checkArg -od "${arg:3}" output_directory="${arg:3}" ;; -of*) checkArg -of "${arg:3}" output_file="${arg:3}" ;; -op) output_parents=1 ;; -profile) out[iout++]=-pg ;; -quiet) ;; # Ignored. -release) out[iout++]=-frelease ;; -run) run=1 checkArg -run "$1" addSourceFile "$1" shift run_args=("$@") break ;; -unittest) out[iout++]=-funittest ;; -v) out[iout++]=-fd-verbose verbose=1 ;; -v1) out[iout++]=-fd-version=1 ;; -version=*) checkArg -version ${arg:9} temp_var=${arg:9} if [ "$DNOVERSIONS" -a "${DNOVERSIONS/,$temp_var,}" != "$DNOVERSIONS" ]; then temp_var= fi if [ "$temp_var" ]; then out[iout++]=-fversion=$temp_var fi ;; -w) out[iout++]=-Wall ;; -arch) checkArg -arch "$1" out[iout++]=-arch out[iout++]="$1" shift ;; -fall-sources) seen_all_sorces_flag=1 #out[iout++]=$arg ;; -f?*) # Pass -fxxx options out[iout++]="$arg" ;; -framework) checkArg -framework "$1" link_out[ilink_out++]=-framework link_out[ilink_out++]="$1" shift ;; -m?*) # Pass -mxxx options out[iout++]="$arg" ;; -q,-S) assemble=0 link=0 #out[iout++]=-S ;; -q,*) checkArg -q "${arg:3}" temp_var="${arg:3}" eval temp_var=(\"${temp_var//,/\" \"}\") for temp_var in "${temp_var[@]}"; do out[iout++]="$temp_var" done ;; -vdmd) show_commands=1 ;; -?*) error 1 "unrecognized switch '$arg'" ;; *.[Dd] | *.[Hh][Tt][Mm] | *.[Hh][Tt][Mm][Ll] | *.[Xx][Hh][Tt][Mm][Ll]) addSourceFile "$arg" ;; *.[Dd][Dd][Oo][Cc]) out[iout++]=-fdoc-inc="$arg" ;; *.[Ee][Xx][Ee]) if [ ! "$first_input_file" ]; then first_input_file="$arg" fi if [ $with_exe -ne 0 ]; then output_file="$arg" else output_file="${arg%.[Ee][Xx][Ee]}" fi ;; *) if [ "${arg/.}" == "$arg" ]; then addSourceFile "$arg.d" else objects[iobjects++]="$arg" fi ;; esac done # Slightly different from dmd... allows -of to specify the name of the executable. if [ $link -eq 0 -a $isources -gt 1 -a "$output_file" ]; then error 1 "output file name specified with multiple source files" fi if [ $run -ne 0 -a $link -eq 0 ]; then error 1 "flags conflict with -run" fi if [ $link -ne 0 -a ! "$output_file" -a "$first_input_file" ]; then # Doing here what I think perl is doing here :). output_file="${first_input_file%.*}" if [ $with_exe -ne 0 ]; then output_file=${output_file##*/}.exe else output_file=${output_file##*/} fi fi if [ $isources -eq 0 -a ! \( $link -ne 0 -a $iobjects -ne 0 \) ]; then "$gdc" --version "${out[@]}" &> /dev/null || exit $? printUsage exit 1 fi for source in "${sources[@]}"; do srcf="$source" outf= outbits=() ioutbits=0 # Step 1: Determine the object file path. if [ $link -eq 0 -a "$output_file" ]; then outf="$output_file" else if [ "$output_directory" ]; then outbits[ioutbits++]="$output_directory/" fi if [ $output_parents -ne 0 -a "${srcf%/*}" != "$srcf" ]; then outbits[ioutbits++]="${srcf%/*}/" fi if [ $ioutbits -ne 0 ]; then mkdir -p "${outbits[*]}" || error 1 "could not create ${outbits[*]}" fi temp_var="${srcf##*/}" if [ $assemble -ne 0 ]; then outbits[ioutbits++]="${temp_var%.[Dd]}.o" else outbits[ioutbits++]="${temp_var%.[Dd]}.s" fi outf="${outbits[*]}" fi dobjects[idobjects++]="$outf" all_sources_hack=() if [ $seen_all_sources_flag -ne 0 ]; then all_sources_hack=("${sources[@]}") srcf="-fonly=$srcf" fi # Step 2: Run the compiler driver. temp_var=-c if [ $assemble -eq 0 ]; then temp_var=-S fi cmd=("$gdc" "${out[@]}" $temp_var "${all_sources_hack[@]}" "$srcf" -o "$outf") if [ $show_commands -ne 0 ]; then echo "${cmd[@]}" fi "${cmd[@]}" || exit $? done if [ $link -ne 0 ]; then cmd=("$gdc" "${out[@]}" "${dobjects[@]}" "${objects[@]}" "${link_out[@]}") if [ "$output_file" ]; then cmd[${#cmd[@]}]=-o cmd[${#cmd[@]}]="$output_file" fi if [ $show_commands -ne 0 ]; then echo "${cmd[@]}" fi "${cmd[@]}" || exit $? fi if [ $run -ne 0 ]; then cmd=(`realpath "$output_file"` "${run_args[@]}") if [ $verbose -ne 0 ]; then echo "${cmd[@]}" fi "${cmd[@]}" || exit $? fi exit 0tango-mgw-build-tango.patch:
--- ./build-tango.sh.orig 2007-05-15 13:12:48.000000000 +0400 +++ ./build-tango.sh 2007-06-20 03:16:18.000000000 +0400 @@ -1,79 +1,102 @@ #!/bin/bash +x -# A simple script to build libtango.a/libgtango +# A simple script to build libtango.a/libgtango.a # Copyright (C) 2007 Lars Ivar Igesund +# Modifications (to build on mingw32 and more) by John 'Profic' Ustiuzhanin # Permission is granted to do anything you please with this software. # This software is provided with no warranty, express or implied, within the # bounds of applicable law. +DC= +LIB= + +UNAME=`uname` + +FILTER=filterPosix +if [ "${UNAME/[Mm][Ii][Nn][Gg][Ww]32}" != "$UNAME" ] +then + FILTER=filterMingw32 +fi + die() { echo "$1" exit $2 } -DC= -LIB= - -# This filter can probably be improved quite a bit, but should work -# on the supported platforms as of May 2007 -filter() { - +# This filter seems to work on the supported platforms as of May 2007. +filterPosix() { FILE=$1 - if [ "`echo $FILE | grep win32`" -o "`echo $FILE | grep Win32`" ] + + if [ "${FILE/[Ww]in32}" != "$FILE" ] then return 1 fi - if [ "`echo $FILE | grep darwin`" ] + if [ "${FILE/darwin}" != "$FILE" -a "$UNAME" == Linux ] then - if [ `uname` == Linux ] - then - return 1 - else - return 0 - fi + return 1 fi - if [ "`echo $FILE | grep linux`" ] + if [ "${FILE/linux}" != "$FILE" -a "$UNAME" != Linux ] then - if [ ! `uname` == Linux ] - then - return 1 - fi + return 1 + fi + + return 0 +} + +# This filter seems to work for mingw32 as of June 2007. +filterMingw32() { + FILE=$1 + + if [ "${FILE/[Pp]osix}" != "$FILE" ]; then + return 1 + fi + if [ "${FILE/[Ll]inux}" != "$FILE" ]; then + return 1 + fi + if [ "${FILE/[Dd]arwin}" != "$FILE" ]; then + return 1 fi return 0 } compile() { - FILENAME=$1 - OBJNAME=`echo $1 | sed -e 's/\.d//' | sed -e 's/\//\./g'` - OBJNAME=${OBJNAME}.o + SRCNAME=$1 + OBJNAME=${SRCNAME%.d} + OBJNAME=${OBJNAME//\//.}.o - if filter $OBJNAME + if $FILTER $OBJNAME then - $DC -c -inline -release -O -version=Posix -version=Tango -of$OBJNAME $FILENAME - ar -r lib/$LIB $OBJNAME + echo "+ $SRCNAME" + $DC -c -inline -release -O -version=Posix -version=Tango -of$OBJNAME $SRCNAME + if [ "`nm -g $OBJNAME`" ]; then + # Adding only objects with defined global symbols. + ar -r lib/$LIB $OBJNAME + else + echo "~ $SRCNAME" + fi rm $OBJNAME + else + echo "- $SRCNAME" fi } build() { - DC=$1 LIB=$2 if [ ! -e "$3" ] then - die "Dependency not present, run build-yourcompiler.sh first" 1 + die "Dependency $3 not present, run build-yourcompiler.sh first" 1 fi - if ! $DC --help >& /dev/null + if ! $DC --help &> /dev/null then - echo "$DC not found on your \$PATH!" + die "$DC not found on your \$PATH!" 1 else - - cd .. + pushd .. for file in `find tango -name '*.d'` do @@ -82,12 +105,11 @@ ranlib lib/$LIB - cd lib + popd fi } -ORIGDIR=`pwd` -if [ ! "`basename $ORIGDIR`" = "lib" ] +if [ "${PWD##*/}" != lib ] then die "You must run this script from the lib directory." 1 fi @@ -99,6 +121,5 @@ then build gdmd libgtango.a libgphobos.a else - build dmd libtango.a libphobos.a - build gdmd libgtango.a libgphobos.a + die "Usage: $0 {dmd|gdc}" 1 fitango-mgw-common.patch:
--- ./common/tango/posix.mak.orig 2007-04-22 23:10:56.000000000 +0400 +++ ./common/tango/posix.mak 2007-06-20 03:42:44.000000000 +0400 @@ -66,6 +66,7 @@ ###################################################### +ifneq ($(OSTYPE),msys) OBJ_CORE= \ core/Exception.o \ core/Memory.o \ @@ -82,6 +83,19 @@ $(OBJ_CORE) \ $(OBJ_STDC) \ $(OBJ_STDC_POSIX) +else +OBJ_CORE= \ + core/Exception.o \ + core/Memory.o \ + core/Thread.o + +OBJ_STDC= \ + stdc/wrap.o + +ALL_OBJS= \ + $(OBJ_CORE) \ + $(OBJ_STDC) +endif ###################################################### @@ -96,6 +110,16 @@ tango.lib : libtango.a +ifeq ($(OSTYPE),msys) +# HACK: Gdc/Mingw32 0.23 has problems compiling core/Thread.d. +core/Thread.o: core/Thread.d + $(DC) -q,-S $(DFLAGS) -v1 -Hf$*.di $< -of$*.s + cp $*.s $*.s.orig + sed -e 's/%fs:$$/%fs:0/' < $*.s.orig > $*.s + rm $*.s.orig + $(CC) -c $(CFLAGS) $*.s -o$@ +endif + libtango.a : $(ALL_OBJS) $(RM) $@ $(LC) $@ $(ALL_OBJS)tango-mgw-gdc-posix.patch:
--- ./gdc-posix.mak.orig 2007-04-13 23:16:52.000000000 +0400 +++ ./gdc-posix.mak 2007-06-18 15:49:26.000000000 +0400 @@ -15,7 +15,7 @@ MD=mkdir -p CC=gcc -LC=$(AR) -qsv +LC=$(AR) -qsPv DC=gdmd ADD_CFLAGS=tango-mgw-examples.sh:
TANGO_DIR=.. DC=gdc DFLAGS="-nostdinc -g -fdebug -funittest -I$TANGO_DIR -I$TANGO_DIR/lib/compiler/gdc -L$TANGO_DIR/lib" DLIBS="-lgtango -lws2_32" filter() { FILE=$1 if [ "${FILE/GlueFlectioned}" != "$FILE" ]; then return 2 fi if [ "${FILE/FileBucket}" != "$FILE" ]; then return 1 fi return 0 } compile() { SRCFILE=$1 filter $file filterResult=$? if [ $filterResult -eq 0 ]; then EXEFILE=${SRCFILE%.d}.exe echo "+ $SRCFILE => $EXEFILE" $DC $DFLAGS $SRCFILE -o $EXEFILE $DLIBS || exit $? elif [ $filterResult -eq 1 ]; then OBJFILE=${SRCFILE%.d}.o echo "+ $SRCFILE => $OBJFILE" $DC $DFLAGS -c $SRCFILE -o $EXEFILE || exit $? else echo "- $SRCFILE" fi } if [ "$1" == build ]; then for file in `find . -name '*.d' -print`; do compile $file done elif [ "$1" == run ]; then for file in `find . -name '*.exe' -print`; do echo $file $file done elif [ "$1" == clean ]; then find . -name '*.exe' -print | xargs rm -f find . -name '*.o' -print | xargs rm -f find . -name '*.bin' -print | xargs rm -f find . -name '*.log' -print | xargs rm -f elif [ -e "$1" -a "${1: -2}" == .d ]; then compile $1 else echo "Usage: $0 {build|run|clean}" fi
2. Instructions:
Instructions are provided by means of entered commands with comments. In this instructions it is assumed that gdc is install to c:\devel\gdc and all files mentioned above are located in c:\devel\d-sandbox.- Install new gdmd over original one:
C:\devel\d-sandbox>ren c:\devel\gdc\bin\gdmd gdmd.orig
C:\devel\d-sandbox>copy gdmd c:\devel\gdc\bin
If needed process may be repeated with mingw32-gdmd as well.- Unpack tango to current directory
- Patching tango:
C:\devel\d-sandbox>cd tango-0.98-src\lib
C:\devel\d-sandbox\tango-0.98-src\lib>patch -p0 < ..\..\tango-mgw-build-tango.patch
C:\devel\d-sandbox\tango-0.98-src\lib>patch -p0 < ..\..\tango-mgw-common.patch
C:\devel\d-sandbox\tango-0.98-src\lib>patch -p0 < ..\..\tango-mgw-gdc-posix.patch- Build tango:
C:\devel\d-sandbox\tango-0.98-src\lib>sh
sh-2.04$ DNOVERSIONS=Posix sh build-gdc.sh
sh-2.04$ DNOVERSIONS=Posix sh build-tango.sh gdc
sh-2.04$ exit- Build examples:
C:\devel\d-sandbox\tango-0.98-src\lib>cd ..\examples
C:\devel\d-sandbox\tango-0.98-src\examples>sh ..\..\tango-mgw-examples.sh build
C:\devel\d-sandbox\tango-0.98-src\examples>
Thanks for your attention.
Wbr, John 'Profic' Ustiuzhanin