1#!/bin/bash
2#
3# make-vcproj.sh YYMMDD -- Make sln and vcproj files from CMakeLists.txt and qhull-all.pro
4#       eg/make-vcproj.sh qhull-x -- Derive src/qhull-x/ from src/libqhull_r
5#
6# Design
7#       CMake vcproj files includes absolute paths and does not handle 'd' annotatios for debug versions
8#       Remove CMake targets
9#       Change absolute paths to '../..'
10#       Append '_d' to debug products
11#       Write targets to '../lib/' and ../bin/'
12#
13# $Id: //main/2019/qhull/eg/make-vcproj.sh#1 $$Change: 2661 $
14# $DateTime: 2019/05/24 20:09:58 $$Author: bbarber $
15
16if [[ "$1" != "" && "$1" != "Win64" && "$1" != "qhull-x" && "$1" != "sed-only" ]]; then
17    echo "eg/make-vcproj.sh Win64|sed-only|qhull-x"
18    echo "Written for 'sed 4.0.7', 'Visual Studio 11 2012 Win64', and 'Visual Studio 8 2005'"
19    echo "Other variations are likely to fail"
20    exit
21fi
22if [[ "$1" == "qhull-x" ]]; then
23    set -v
24    win64=1
25    if [[ ! -w build/qhull.sln || ! -r build/qhull-64.vcxproj || ! -d src/libqhull_r ]]; then
26        echo "Excute 'eg/make-vcproj.sh qhull-x' from qhull directory with build/qhull.sln, build/qhull-64.vcxproj, src/libqhull_r"
27        exit
28    fi
29
30    SOURCEDIR=.
31    SOURCE=$SOURCEDIR/src/libqhull_r
32    SOURCE2=$SOURCEDIR/src/qhull
33    SOURCE3=$SOURCEDIR/src/rbox
34    DEST=/c/bash/local/qhull/src/qhull-x
35    DEST2=$DEST
36    # SOURCE=../qhull-y/src/libqhull_r
37    # SOURCE2=src/qhull
38    # DEST=src/qhull-x
39    # DEST2=../../../qhull/$DEST # relative to SOURCE
40    if [[ -d $DEST ]]; then
41        echo "To rebuild $DEST from $SOURCE and $SOURCE2 -- rm -r $DEST; eg/make-vcproj.sh qhull-x"
42    else
43        echo Create $DEST from $SOURCE and $SOURCE2
44        mkdir $DEST || exit 1
45        pushd $SOURCE || exit 1
46        sed -e 's/_r/_x/g' -e 's/_xbox/_rbox/g' Makefile >$DEST2/Makefile || exit 1
47        for F in *_r.c; do
48            G=${F%_r.c}_x.c; echo $G; cp -p $F $DEST2/$G || exit 1
49        done
50        for F in *_r.h; do
51            G=${F%_r.h}_x.h; echo $G; cp -p $F $DEST2/$G || exit 1
52        done
53        for F in *_ra.h; do
54            G=${F%_ra.h}_xa.h; echo $G; cp -p $F $DEST2/$G || exit 1
55        done
56        popd
57        pushd $SOURCE2 || exit 1
58        for F in *_r.c; do
59            G=${F%_r.c}_x.c; echo $G; cp -p $F $DEST2/$G || exit 1
60        done
61        popd
62        pushd $SOURCE3 || exit 1
63        for F in *_r.c; do
64            G=${F%_r.c}_x.c; echo $G; cp -p $F $DEST2/$G || exit 1
65        done
66        popd
67
68        echo "Substitute *_x for *_r"
69        sed -i 's/_r\.h/_x.h/' $DEST/*
70        sed -i 's/_ra\.h/_xa.h/' $DEST/*
71        sed -i 's|libqhull_r/libqhull_x|libqhull_x|' $DEST/*
72        sed -i 's|libqhull_r/random_x|random_x|' $DEST/*
73
74        echo "Restrict Makefile to qhull-x and rbox"
75        sed -i ' /^all. / s/qhull_links//' $DEST/Makefile
76        sed -i ' /-f .*exe/ s/qconvex.*exe/core rbox qhull-x *.exe/' $DEST/Makefile
77        sed -i ' /-p .*BINDIR/ s/qconvex.*rbox/qhull-x/' $DEST/Makefile
78        sed -i ' /-o qhull/ s/qhull/qhull-x/' $DEST/Makefile
79        sed -i '\|\./qhull| s/qhull/qhull-x/' $DEST/Makefile
80        sed -i 's|\.\./qconvex.*|unix_x.c|' $DEST/Makefile
81        sed -i ' /^qhull_all. / s/qconvex.*testqset_x.o/unix_x.o rbox_x.o/' $DEST/Makefile
82        for D in qconvex qdelaunay qhalf qvoronoi user_eg testqset libqhullstatic DOCDIR INCDIR LIBDIR MANDIR; do
83          sed -i " /$D/ d" $DEST/Makefile
84        done
85        sed -i " /ln -s / d" $DEST/Makefile
86    fi
87
88    pushd build/ || exit 1
89    SOURCE=../src/qhull-x
90    VCXPROJ=qhull-x-64.vcxproj
91    GUID=3192557A-C34A-426E-A51B-2BCE463EAD02
92    VCXPROJ2=qhull-64.vcxproj
93    GUID2=E8BF0EA0-A09D-4155-BCEC-CC1B0DF8A67E
94    echo Create $VCXPROJ from $VCXPROJ2
95    if ! grep $GUID qhull-64.sln >/dev/null; then
96        echo add GUID for $VCXPROJ to qhull-64.sln -- $GUID
97    fi
98    cp $VCXPROJ2 $VCXPROJ || exit 1
99    grep $GUID2 $VCXPROJ2 >/dev/null || (echo unknown GUID for $VCXPROJ2 -- $GUID2; exit 1)
100    sed -i s/$GUID2/$GUID/g $VCXPROJ
101    sed -i 's/ProjectReference Include=.*/ProjectReference>/' $VCXPROJ
102    sed -i 's/<Project>.*//' $VCXPROJ
103    # need to delete 3 lines
104    sed -i -r 's/;...lib.qhullstatic_rd?.lib//' $VCXPROJ
105    sed -i 's/qhull/qhull-x/g' $VCXPROJ
106    # Since qhull pulls object files from libqhullstatic_r.lib, order unknown, may be in specified order
107    for F in $SOURCE/*_x.h; do
108        sed -i " /ClCompile.*_r.c/ i <ClInclude Include=\"$F\" />"  $VCXPROJ
109    done
110    for F in $SOURCE/*_x.c; do
111        sed -i " /ClCompile.*_r.c/ i <ClCompile Include=\"$F\" />"  $VCXPROJ
112    done
113    sed -i ' /_r.c/ d' $VCXPROJ
114    popd
115    exit
116elif [[ "$1" == "Win64" ]]; then
117    if [[ "$2" != "" && "$2" != "sed-only" ]]; then
118        echo "eg/make-vcproj.sh [Win64] [sed-only]"
119        exit
120    fi
121    win64=1
122else
123    win64=0
124fi
125
126if [[ "$1" == "sed-only" || "$2" == "sed-only" ]]; then
127    echo Skip creating buildvc/ and buildqt/
128else # else execute to 'fi ... sed-only'
129
130if [[ ! -f CMakeLists.txt || ! -f src/qhull-all.pro ]]; then
131    echo "Excute eg/make-vcproj.sh from qhull directory with CMakeLists.txt and src/qhull-all.pro"
132    exit
133fi
134
135echo "Set up build directories..."
136if [[ ! -d build-prev ]]; then
137    echo "Backup previous build"
138    cp -r build build-prev && rm -rf build
139fi
140rm -rf buildvc buildqt
141mkdir -p build
142mkdir -p build/qhulltest
143mkdir -p buildvc
144mkdir -p buildqt
145echo "Create vcproj files with cmake and qmake..."
146if [[ $win64 -eq 1 ]]; then
147    echo Running -- cmake -G "Visual Studio 11 2012 Win64"
148    cd buildvc && cmake -G "Visual Studio 11 2012 Win64" .. && cmake ..
149else
150    echo Running -- cmake -G "Visual Studio 8 2005"
151    cd buildvc && cmake -G "Visual Studio 8 2005" .. && cmake ..
152fi
153cd ..
154cd buildqt && qmake -tp vc -r ../src/qhull-all.pro
155cd ..
156if [[ ! -f CMakeLists.txt ]]; then
157    echo "Missing CMakeLists.txt.  Cannot run cmake"
158    exit
159elif [[ (! -f buildvc/qhull.vcproj && ! -f buildvc/qhull.vcxproj) || (! -f buildqt/qhulltest/qhulltest.vcproj && ! -f buildqt/qhulltest/qhulltest.vcxproj) ]]; then
160    echo "qmake and cmake did not build vcproj or vcxproj files in buildvc/ and buildqt/"
161    exit
162fi
163
164echo
165echo 'Create build/*.vcproj by converting absolute paths to relative paths'
166echo Removes INSTALL/ALL_BUILD/ZERO_CHECK/RUN_TESTS projects
167echo Turn off LinkIncremental and RuntimeTypeInfo
168echo Add 'd' flags to debug lib/dll files...
169echo 'Delete  <file> CMake...</file> and other instances of CMake'
170echo 'WARN: These sed replacements depend on how CMake creates vcproj or vcxproj files.  It is likely to change.'
171
172fi # Skipped if 'sed-only'
173
174for f in buildvc/*.vc*proj buildqt/qhulltest/*.vc*proj; do
175    echo -n $f
176    if [[ ! ${f##*INSTALL*} || ! ${f##*ALL_BUILD*} || ! ${f##*ZERO_CHECK*} || ! ${f##*RUN_TESTS*}  ]]; then
177        echo " removed"
178        continue
179    fi
180    if [[ $win64 -eq 1 ]]; then
181        ext=${f##*.}
182        base=${f#*\/}
183        base=${base%.*}
184        dest=build/$base-64.$ext
185        echo " => $dest"
186        # sed requires a blank or \ before address ranges
187        # sed requires a \/ for s|...|...| !
188        # the ConfigurationType clauses depend on Debug being first
189        sed -r \
190            -e ' /CustomBuild.*CMake/,/CustomBuild/ d' \
191            -e ' /ZERO_CHECK/,/ProjectReference/ d' \
192            -e ' />qhulltest<S/,/Project>/ s|[cC]:\\bash\\local\\qhull|..\\..|g' \
193            -e ' />qhulltest</,/Project>/ s|[cC]:\/bash\/local\/qhull|..\/..|g' \
194            -e 's|[cC]:\\bash\\local\\qhull|..|g' \
195            -e 's|[cC]:\/bash\/local\/qhull|..|g' \
196            -e '\|CMake| d' \
197            -e '\|VCWebServiceProxyGeneratorTool| d' \
198            -e 's/;CMAKE_INTDIR=[^;]*;/;/' \
199            -e 's/;[a-zA-Z]*\\([_a-z0-9]*\.lib[;<])/;..\\lib\\\1/g' \
200            -e ' /LinkIncremental/ s/true/false/' \
201            -e 's/buildvc/build/g' \
202            -e 's/buildqt/build/g' \
203            -e 's/c:\\qt\\[0-9]\.[0-9]\.[0-9]/\$(QTDIR)/g' \
204            -e 's|..\/build\/[a-zA-Z]*[\\/]([_a-z0-9]*.pdb)|..\/bin\/\1|g' \
205            -e 's|..\/build\/[a-zA-Z]*[\\/]([_a-z0-9]*.exe)|..\/bin\/\1|g' \
206            -e 's|..\/build\/[a-zA-Z]*[\\/]([_a-z0-9]*.lib)|..\/lib\/\1|g' \
207            -e 's|..\/build\/[a-zA-Z]*[\\/]([_a-z0-9]*.dll)|..\/bin\/\1|g' \
208            -e 's| [a-zA-Z]*[\\/]([_a-z0-9]*\.lib)| ..\\lib\\\1|g' \
209            -e 's/"([_a-z0-9]*.exe)/"..\\bin\\\1/g' \
210            -e ' /ConfigurationType>Application/,/ClInclude/ s/(OutDir.*\.\.)[\\a-zA-Z]*</\1\\bin\\</' \
211            -e ' /ConfigurationType>DynamicLibrary/,/ClInclude/ s/(OutDir.*\.\.)[\\a-zA-Z]*</\1\\bin\\</' \
212            -e ' /ConfigurationType>DynamicLibrary/,/ImportLibrary/ s/(ImportLibrary.*_[rp])\.lib</\1d.lib</' \
213            -e ' /ConfigurationType>DynamicLibrary/,/ImportLibrary/ s/(ImportLibrary.*[^d])\.lib</\1_d.lib</' \
214            -e ' /ConfigurationType>DynamicLibrary/,/TargetName.*Debug/ s/(TargetName.*_[pr])</\1d</' \
215            -e ' /ConfigurationType>DynamicLibrary/,/TargetName.*Debug/ s/(TargetName.*Debug.*[^d])</\1_d</' \
216            -e ' /ConfigurationType>DynamicLibrary/,/ProgramDataBaseFile/ s/(ProgramDataBaseFile.*_[pr])\.pdb/\1d.pdb/' \
217            -e ' /ConfigurationType>DynamicLibrary/,/ProgramDataBaseFile/ s/(ProgramDataBaseFile.*[^d])\.pdb/\1_d.pdb/' \
218            -e ' /ConfigurationType>StaticLibrary/,/ClInclude/ s/(OutDir.*\.\.)[\\a-zA-Z]*</\1\\lib\\</' \
219            -e ' /ConfigurationType>StaticLibrary/,/ImportLibrary/ s/(ImportLibrary.*_[rp])\.lib</\1d.lib</' \
220            -e ' /ConfigurationType>StaticLibrary/,/ImportLibrary/ s/(ImportLibrary.*[^d])\.lib</\1_d.lib</' \
221            -e ' /ConfigurationType>StaticLibrary/,/TargetName.*Debug/ s/(TargetName.*_[pr])</\1d</' \
222            -e ' /ConfigurationType>StaticLibrary/,/TargetName.*Debug/ s/(TargetName.*Debug.*[^d])</\1_d</' \
223            -e ' /ConfigurationType>StaticLibrary/,/ProgramDataBaseFile/ s/(ProgramDataBaseFile.*_[pr])\.pdb/\1d.pdb/' \
224            -e ' /ConfigurationType>StaticLibrary/,/ProgramDataBaseFile/ s/(ProgramDataBaseFile.*[^d])\.pdb/\1_d.pdb/' \
225            -e ' /ItemDefinitionGroup.*Debug/,/AdditionalDependencies/ s/(AdditionalDependencies.*_r)\.lib/\1d.lib/g' \
226            -e ' /ItemDefinitionGroup.*Debug/,/AdditionalDependencies/ s/(AdditionalDependencies.*qhull[a-z]*[^d])\.lib/\1_d.lib/g' \
227            -e ' /AdditionalDependencies/ s/;[a-zA-Z]*\\/;..\\lib\\/g' \
228            -e 's/[cC]:\\[qQ]t\\[qQt0-9.\\]*msvc[_0-9]*/\$(QTDIR)/g' \
229            -e 's/[cC]:\\[qQ]t\\[qQt0-9.\\]*/\$(QTDIR)\\..\\/g' \
230            -e 's/([|>])Win32/\1x64/' \
231            -e 's/machine:X86/machine:x64/' \
232            -e 's/\.vcxproj/-64.vcxproj/' \
233            $f | awk '/<File$/ && !SkipFirstFile,/<\/File>/{ next } /<Filter$/{SkipFirstFile=1} {print $0}' > $dest
234    else
235        dest=build/${f##*\/}
236        # sed requires a blank or \ before address ranges
237        sed -r -e 's|[cC]:\\bash\\local\\qhull|..|g' \
238            -e 's|[cC]:/bash/local/qhull|..|g' \
239            -e '\|CMake| d' \
240            -e '\|VCWebServiceProxyGeneratorTool| d' \
241            -e 's/;CMAKE_INTDIR=..quot;[A-Za-z]*..quot;//' \
242            -e 's/LinkIncremental="2"/LinkIncremental="1"/' \
243            -e 's/RuntimeLibrary[=]/RuntimeTypeInfo="false"  RuntimeLibrary=/' \
244            -e 's/.*RuntimeTypeInfo."TRUE".*//' \
245            -e 's/buildvc/build/g' \
246            -e 's/buildqt/build/g' \
247            -e 's/\.\.\\\.\./../g' \
248            -e 's|\.\./\.\.|..|g' \
249            -e 's/c:\\qt\\[0-9]\.[0-9]\.[0-9]/\$(QTDIR)/g' \
250            -e 's|..\\build\\[a-zA-Z]*[\\/]([_a-z0-9]*.pdb)|..\\bin\\\1|g' \
251            -e 's|..\\build\\[a-zA-Z]*[\\/]([_a-z0-9]*.exe)|..\\bin\\\1|g' \
252            -e 's|..\\build\\[a-zA-Z]*[\\/]([_a-z0-9]*.lib)|..\\lib\\\1|g' \
253            -e 's|..\\build\\[a-zA-Z]*[\\/]([_a-z0-9]*.dll)|..\\bin\\\1|g' \
254            -e 's| [a-zA-Z]*[\\/]([_a-z0-9]*\.lib)| ..\\lib\\\1|g' \
255            -e 's/"([_a-z0-9]*.exe)/"..\\bin\\\1/g' \
256            -e ' /Name="Debug/,/OutputFile/ s/(OutputFile.*_[rp])\.(dll|lib)"/\1d.\2"/' \
257            -e ' /Name="Debug/,/OutputFile/ s/(OutputFile.*[^d])\.(dll|lib)"/\1_d.\2"/' \
258            -e ' /Name="Debug/,/ImportLibrary/ s/(ImportLibrary.*_[rp])\.lib"/\1d.lib"/' \
259            -e ' /Name="Debug/,/ImportLibrary/ s/(ImportLibrary.*[^d])\.lib"/\1_d.lib"/' \
260            -e ' /Name="Debug/,/AdditionalDependencies/ s/(AdditionalDependencies.*_[rp])\.lib/\1d.lib/' \
261            -e ' /Name="Debug/,/AdditionalDependencies/ s/(AdditionalDependencies.*qhull[a-z]*[^d])\.lib/\1_d.lib/' \
262            -e ' /Name="Debug/,/ProgramDatabaseFile/ s/(ProgramDatabaseFile.*_r)\.pdb/\1d.pdb/' \
263            -e ' /Name="Debug/,/ProgramDatabaseFile/ s/(ProgramDatabaseFile.*qhull[a-z]*[^d])\.pdb/\1_d.pdb/' \
264            -e 's/[cC]:\\Qt\\[0-9.]*/\$(QTDIR)/g' \
265            -e 's/\.vcxproj/-32.vcxproj/' \
266            $f | awk '/<File$/ && !SkipFirstFile,/<\/File>/{ next } /<Filter$/{SkipFirstFile=1} {print $0}' > $dest
267    fi
268    # grep -E '\.\.[\\/]|_[a-z]?d[^a-z]' $dest
269done
270
271echo
272echo Create build/qhull.sln or build/qhull-64.sln from buildvc/qhull.sln
273if [[ $win64 -eq 1 ]]; then
274    echo Create qhull-64.sln
275    sed -r \
276        -e '\|Project.*ALL_BUILD|,\|EndProject$| d' \
277        -e '\|Project.*INSTALL|,\|EndProject$| d' \
278        -e '\|Project.*ZERO_CHECK|,\|EndProject$| d' \
279        -e '\|Project.*RUN_TESTS|,\|EndProject$| d' \
280        -e '\|ProjectDependencies|,\| = | s/^.* = \{.*$//' \
281        -e 's/\.vcxproj/-64.vcxproj/' \
282        buildvc/qhull.sln >build/qhull-64.sln
283
284    echo Create qhull-32.sln from qhull-64 with 32 GUIDs
285    # Need to keep the original GUIDs.  Otherwise get -- can't locate project ''
286    sed -r \
287        -e 's/-64\.vcxproj/-32.vcxproj/' \
288        -e 's/([|>])x64/\1Win32/g' \
289        build/qhull-64.sln >build/qhull-32.sln
290
291    echo Create *-32.vcxproj with 32 GUIDs
292    for f in build/*-64.vcxproj build/qhulltest/*-64.vcxproj; do
293        dest=${f%64.vcxproj}32.vcxproj
294        sed -r \
295            -e 's/([|>])x64/\1Win32/' \
296            -e 's/machine:x64/machine:X86/' \
297             $f >$dest
298    done
299
300    echo Convert vcxproj/sln files to DOS format
301    for f in build/*.vcxproj build/*-32.sln build/*-64.sln; do
302        u2d $f
303    done
304else
305    sed -e '\|Project.*ALL_BUILD|,\|EndProject$| d' \
306        -e '\|Project.*INSTALL|,\|EndProject$| d' \
307        -e '\|Project.*ZERO_CHECK|,\|EndProject$| d' \
308        -e '\|Project.*RUN_TESTS|,\|EndProject$| d' \
309        buildvc/qhull.sln >build/qhull.sln
310    echo Convert vcproj/sln files to DOS format
311    for f in build/*.vcproj build/*.sln; do
312        u2d $f
313    done
314fi
315
316echo
317echo 'Add qhulltest.vcproj to qhull.sln'
318echo '  Open qhull.sln with DevStudio'
319echo '  Add build/qhulltest/qhulltest.vcproj or qhulltest-64.vcxproj'
320echo '  Add dependencies on qhullcpp (user_eg3, qhulltest)'
321echo '  Add dependencies on qhullstatic (rbox, qconvex, etc)'
322echo '  Add dependencies on qhullstatic_r (qhull, user_eg2)'
323echo '  Add dependencies on libqhull_r (user_eg) and qhullstatic_r'
324echo '  Remove qhulltest via Configuration Manager from Release,Debug,etc. Qt is optional'
325echo
326echo 'Update Perforce for build/...vcproj, otherwise qhull-zip.sh will revert the files'
327