1#! /bin/sh
2#
3# %CopyrightBegin%
4#
5# Copyright Ericsson AB 2002-2020. All Rights Reserved.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11#     http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# %CopyrightEnd%
20#
21# Icky cl wrapper that does it's best to behave like a Unixish cc.
22# Made to work for Erlang builds and to make configure happy, not really
23# general I suspect.
24# set -x
25# Save the command line for debug outputs
26
27SAVE="$@"
28
29# Constants
30COMMON_CFLAGS="-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT -D_CRT_SECURE_NO_DEPRECATE"
31
32# Variables
33# The stdout and stderr for the compiler
34MSG_FILE=/tmp/cl.exe.$$.1
35ERR_FILE=/tmp/cl.exe.$$.2
36
37# "Booleans" determined during "command line parsing"
38# If the stdlib option is explicitly passed to this program
39MD_FORCED=false
40# If we're preprocession (only) i.e. -E
41PREPROCESSING=false
42# If we're generating dependencies (implies preprocesing)
43DEPENDENCIES=false
44# If this is supposed to be a debug build
45DEBUG_BUILD=false
46# If this is supposed to be an optimized build (there can only be one...)
47OPTIMIZED_BUILD=false
48# If we're linking or only compiling
49LINKING=true
50
51# This data is accumulated during command line "parsing"
52# The stdlibrary option, default multithreaded dynamic
53MD=-MD
54# Flags for debug compilation
55DEBUG_FLAGS=""
56# Flags for optimization
57OPTIMIZE_FLAGS=""
58# The specified output filename (if any), may be either object or exe.
59OUTFILE=""
60# Unspecified command line options for the compiler
61CMD=""
62# All the c source files, in unix style
63SOURCES=""
64# All the options to pass to the linker, kept in Unix style
65LINKCMD=""
66
67
68# Loop through the parameters and set the above variables accordingly
69# Also convert some cygwin filenames to "mixed style" dito (understood by the
70# compiler very well), except for anything passed to the linker, that script
71# handles those and the sources, which are also kept unixish for now
72
73while test -n "$1" ; do
74    x="$1"
75    case "$x" in
76	-Wall)
77	    ;;
78	-c)
79	    LINKING=false;;
80	    #CMD="$CMD -c";;
81	-MM)
82	    PREPROCESSING=true;
83	    LINKING=false;
84	    DEPENDENCIES=true;;
85	-E)
86	    PREPROCESSING=true;
87	    LINKING=false;; # Obviously...
88	    #CMD="$CMD -E";;
89	-Owx)
90	    # Optimization hardcoded of wxErlang, needs to disable debugging too
91	    OPTIMIZE_FLAGS="-Ob2ity -Gs -Zi";
92	    DEBUG_FLAGS="";
93	    DEBUG_BUILD=false;
94	    if [ $MD_FORCED = false ]; then
95		MD=-MD;
96	    fi
97	    OPTIMIZED_BUILD=true;;
98	-O*)
99	    # Optimization hardcoded, needs to disable debugging too
100	    OPTIMIZE_FLAGS="-Ox -Zi";
101	    DEBUG_FLAGS="";
102	    DEBUG_BUILD=false;
103	    if [ $MD_FORCED = false ]; then
104		MD=-MD;
105	    fi
106	    OPTIMIZED_BUILD=true;;
107	-g|-ggdb)
108	    if [ $OPTIMIZED_BUILD = false ];then
109		# Hardcoded windows debug flags
110		DEBUG_FLAGS="-Z7";
111		if [ $MD_FORCED = false ]; then
112		    MD=-MDd;
113		fi
114		LINKCMD="$LINKCMD -g";
115		DEBUG_BUILD=true;
116	    fi;;
117	# Allow forcing of stdlib
118	-mt|-MT)
119	    MD="-MT";
120	    MD_FORCED=true;;
121	-md|-MD)
122	    MD="-MD";
123	    MD_FORCED=true;;
124	-ml|-ML)
125	    MD="-ML";
126	    MD_FORCED=true;;
127	-mdd|-MDD|-MDd)
128	    MD="-MDd";
129	    MD_FORCED=true;;
130	-mtd|-MTD|-MTd)
131	    MD="-MTd";
132	    MD_FORCED=true;;
133	-mld|-MLD|-MLd)
134	    MD="-MLd";
135	    MD_FORCED=true;;
136	-o)
137	    shift;
138	    OUTFILE="$1";;
139	-o*)
140	    y=`echo $x | sed 's,^-[Io]\(.*\),\1,g'`;
141	    OUTFILE="$y";;
142	-I/*)
143	    y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
144	    z=`echo $x | sed 's,^-\([Io]\)\(/.*\),\1,g'`;
145	    MPATH=`echo $y`;
146	    CMD="$CMD -$z\"$MPATH\"";;
147	-I*)
148	    y=`echo $x | sed 's,",\\\",g'`;
149	    CMD="$CMD $y";;
150	-D*)
151	    y=`echo $x | sed 's,",\\\",g'`;
152	    CMD="$CMD $y";;
153	-EH*)
154	    y=`echo $x | sed 's,",\\\",g'`;
155	    CMD="$CMD $y";;
156	-TP|-Tp)
157	    y=`echo $x | sed 's,",\\\",g'`;
158	    CMD="$CMD $y";;
159	-l*)
160	    y=`echo $x | sed 's,^-l\(.*\),\1,g'`;
161	    LINKCMD="$LINKCMD $x";;
162	/*.c)
163	    SOURCES="$SOURCES $x";;
164	*.c)
165	    SOURCES="$SOURCES $x";;
166	/*.cc)
167	    SOURCES="$SOURCES $x";;
168	*.cc)
169	    SOURCES="$SOURCES $x";;
170	/*.cpp)
171	    SOURCES="$SOURCES $x";;
172	*.cpp)
173	    SOURCES="$SOURCES $x";;
174	/*.o)
175	    LINKCMD="$LINKCMD $x";;
176	*.o)
177	    LINKCMD="$LINKCMD $x";;
178	*)
179	    # Try to quote uninterpreted options
180	    y=`echo $x | sed 's,",\\\",g'`;
181	    LINKCMD="$LINKCMD $y";;
182    esac
183    shift
184done
185
186#Return code from compiler, linker.sh and finally this script...
187RES=0
188
189# Accumulated object names
190ACCUM_OBJECTS=""
191
192# A temporary object file location
193TMPOBJDIR=/tmp/tmpobj$$
194mkdir $TMPOBJDIR
195
196# Compile
197for x in $SOURCES; do
198    # Compile each source
199    if [ $LINKING = false ]; then
200	# We should have an output defined, which is a directory
201	# or an object file
202	case $OUTFILE in
203	    /*.o)
204		# Simple output, SOURCES should be one single
205		n=`echo $SOURCES | wc -w`;
206		if [ $n -gt 1 ]; then
207		    echo "cc.sh:Error, multiple sources, one object output.";
208		    exit 1;
209		else
210		    output_filename=`echo $OUTFILE`;
211		fi;;
212	    *.o)
213		# Relative path needs no translation
214		n=`echo $SOURCES | wc -w`
215		if [ $n -gt 1 ]; then
216		    echo "cc.sh:Error, multiple sources, one object output."
217		    exit 1
218		else
219		    output_filename=$OUTFILE
220		fi;;
221	    /*)
222		# Absolute directory
223		o=`echo $x | sed 's,.*/,,' | sed 's,\.c$,.o,'`
224		output_filename=`echo $OUTFILE`
225		output_filename="$output_filename/${o}";;
226	    *)
227		# Relative_directory or empty string (.//x.o is valid)
228		o=`echo $x | sed 's,.*/,,' | sed 's,\.cp*$,.o,'`
229		output_filename="./${OUTFILE}/${o}";;
230	esac
231    else
232	# We are linking, which means we build objects in a temporary
233	# directory and link from there. We should retain the basename
234	# of each source to make examining the exe easier...
235	o=`echo $x | sed 's,.*/,,' | sed 's,\.c$,.o,'`
236	output_filename=$TMPOBJDIR/$o
237	ACCUM_OBJECTS="$ACCUM_OBJECTS $output_filename"
238    fi
239    # Now we know enough, lets try a compilation...
240    MPATH=`echo $x`
241    if [ $PREPROCESSING = true ]; then
242	output_flag="-E"
243    else
244	output_flag="-FS -c -Fo`cmd //C echo ${output_filename}`"
245    fi
246    params="$COMMON_CFLAGS $MD $DEBUG_FLAGS $OPTIMIZE_FLAGS \
247	    $CMD ${output_flag} $MPATH"
248    if [ "X$CC_SH_DEBUG_LOG" != "X" ]; then
249	echo cc.sh "$SAVE" >>$CC_SH_DEBUG_LOG
250	echo cl.exe $params >>$CC_SH_DEBUG_LOG
251    fi
252    # MSYS2 (currently) converts the paths wrong, avoid it
253    export MSYS2_ARG_CONV_EXCL=-FoC
254    eval cl.exe $params >$MSG_FILE 2>$ERR_FILE
255    RES=$?
256    if test $PREPROCESSING = false; then
257	cat $ERR_FILE >&2
258	tail -n +2 $MSG_FILE
259    else
260	tail -n +2 $ERR_FILE >&2
261	if test $DEPENDENCIES = true; then
262	    perl -e '
263my $file = "'$x'";
264while (<>) {
265      next unless /^#line/;
266      next if /$file/o;
267      (undef,$_) = split(/\"/);
268      next if / /;
269      $all{$_} = 1;
270}
271foreach (sort keys %all) {
272      s@^([A-Za-z]):@/$1@;
273      s@\\\\@/@g;
274      push @f, "\\\n $_ ";
275}
276if (@f) {
277     my $oname = $file;
278     $oname =~ s@.*/@@;
279     $oname =~ s@[.]cp*@.o@;
280     print $oname, ":", @f;
281     print "\n\n";
282     print STDERR "Made dependencies for $file\n";
283}' $MSG_FILE
284	else
285	    cat $MSG_FILE
286	fi
287    fi
288    rm -f $ERR_FILE $MSG_FILE
289    if [ $RES != 0 ]; then
290	echo Failed: cl.exe $params
291	rm -rf $TMPOBJDIR
292	exit $RES
293    fi
294done
295
296# If we got here, we succeeded in compiling (if there were anything to compile)
297# The output filename should name an executable if we're linking
298if [ $LINKING = true ]; then
299    case $OUTFILE in
300	"")
301	    # Use the first source name to name the executable
302	    first_source=""
303	    for x in $SOURCES; do first_source=$x; break; done;
304	    if [ -n "$first_source" ]; then
305		e=`echo $x | sed 's,.*/,,' | sed 's,\.c$,.exe,'`;
306		out_spec="-o $e";
307	    else
308		out_spec="";
309	    fi;;
310	*)
311	    out_spec="-o $OUTFILE";;
312    esac
313    # Descide which standard library to link against
314    case $MD in
315	-ML)
316	    stdlib="-lLIBC";;
317	-MLd)
318	    stdlib="-lLIBCD";;
319	-MD)
320	    stdlib="-lMSVCRT";;
321	-MDd)
322	    stdlib="-lMSVCRTD";;
323	-MT)
324	    stdlib="-lLIBCMT";;
325	-MTd)
326	    stdlib="-lLIBMTD";;
327    esac
328    # And finally call the next script to do the linking...
329    params="$out_spec $LINKCMD $stdlib"
330    if [ "X$CC_SH_DEBUG_LOG" != "X" ]; then
331	echo ld.sh $ACCUM_OBJECTS $params
332    fi
333    eval ld.sh $ACCUM_OBJECTS $params
334    RES=$?
335fi
336rm -rf $TMPOBJDIR
337
338exit $RES
339