Browse code

add dependency resolver

Nat! authored on 29/08/2016 14:44:32
Showing 9 changed files
... ...
@@ -10,6 +10,8 @@ gems, mulle-bootstrap can now claim to do only project relative installs.
10 10
  more proper way, didn't work with cmake generated xcode projects.
11 11
 * reorganized repository structure a bit
12 12
 * You can now specify ALL (always YES) or NONE (always NO) at the y/n prompt.
13
+* Support for MINGW (Windows) for cmake (experimental)
14
+* Finally added a proper dependency resolver
13 15
 
14 16
 
15 17
 1.1
16 18
new file mode 100755
... ...
@@ -0,0 +1,251 @@
0
+#! /bin/sh
1
+#
2
+#   Copyright (c) 2016 Nat! - Mulle kybernetiK
3
+#   All rights reserved.
4
+#
5
+#   Redistribution and use in source and binary forms, with or without
6
+#   modification, are permitted provided that the following conditions are met:
7
+#
8
+#   Redistributions of source code must retain the above copyright notice, this
9
+#   list of conditions and the following disclaimer.
10
+#
11
+#   Redistributions in binary form must reproduce the above copyright notice,
12
+#   this list of conditions and the following disclaimer in the documentation
13
+#   and/or other materials provided with the distribution.
14
+#
15
+#   Neither the name of Mulle kybernetiK nor the names of its contributors
16
+#   may be used to endorse or promote products derived from this software
17
+#   without specific prior written permission.
18
+#
19
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+#   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+#   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+#   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+#   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+#   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+#   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+#   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+#   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+#   POSSIBILITY OF SUCH DAMAGE.
30
+#
31
+
32
+# declare "fail" outside
33
+# array contents can contain any characters except newline
34
+
35
+array_key_check()
36
+{
37
+    local n
38
+
39
+    n=`echo "$1" | wc -l`
40
+    [ $n -eq 0 ] && fail "empty key"
41
+    [ $n -ne 1 ] && fail "key has linebreaks"
42
+
43
+    echo "$1" | tr '>' '|'
44
+}
45
+
46
+
47
+array_value_check()
48
+{
49
+    local n
50
+
51
+    n=`echo "$1" | wc -l`
52
+    [ $n -eq 0 ] && fail "empty value"
53
+    [ $n -ne 1 ] && fail "value has linebreaks"
54
+
55
+    echo "$1"
56
+}
57
+
58
+
59
+array_add()
60
+{
61
+    local array
62
+    local value
63
+
64
+    array="${1}"
65
+    value="`array_value_check "$2"`"
66
+
67
+    if [ -z "${array}" ]
68
+    then
69
+        echo "${value}"
70
+    else
71
+        echo "${array}
72
+${value}"
73
+    fi
74
+}
75
+
76
+
77
+array_count()
78
+{
79
+    local array
80
+
81
+    array="$1"
82
+
83
+    local n
84
+
85
+    n=`echo "${array}" | wc -l`
86
+    echo ${n}
87
+}
88
+
89
+
90
+array_get()
91
+{
92
+    local array
93
+    local i
94
+
95
+    array="${1}"
96
+    i="$2"
97
+
98
+    local n
99
+
100
+    n="`array_count "${array}"`"
101
+
102
+    if [ ${i} -lt ${n} ]
103
+    then
104
+        fail "index ${i} out of bounds ${n}"
105
+    fi
106
+
107
+    echo "${array}" | head -${n} | tail -1
108
+}
109
+
110
+
111
+array_get_last()
112
+{
113
+    local array
114
+
115
+    array="${1}"
116
+
117
+    echo "${array}" | tail -1
118
+}
119
+
120
+
121
+
122
+array_remove()
123
+{
124
+    local array
125
+    local value
126
+
127
+    array="${1}"
128
+    value="`array_value_check "$2"`"
129
+
130
+    if [ ! -z "${array}" ]
131
+    then
132
+        echo "${array}" | fgrep -v -x "${value}"
133
+    fi
134
+}
135
+
136
+
137
+array_contains()
138
+{
139
+    local array
140
+    local value
141
+
142
+    array="${1}"
143
+    value="`array_value_check "$2"`"
144
+
145
+    local found
146
+
147
+    found="`echo "${array}" | fgrep -x "${value}"`"
148
+    [ ! -z "${found}" ]
149
+}
150
+
151
+
152
+#
153
+# declare "fail" outside
154
+# assoc array contents can contain any characters except newline
155
+# assoc array keys can contain any characters except newline
156
+# but be careful, that > chars are translated to |, so
157
+# get 'a|' and get 'a>' match
158
+#
159
+
160
+
161
+_assoc_array_add()
162
+{
163
+    local array
164
+    local key
165
+    local value
166
+
167
+    array="${1}"
168
+    key="`array_key_check "$2"`"
169
+    value="`array_value_check "$3"`"
170
+
171
+    local value
172
+
173
+    value="<${key}>${value}"
174
+    if [ -z "${array}" ]
175
+    then
176
+        echo "${value}"
177
+    else
178
+        echo "${array}
179
+${value}"
180
+    fi
181
+}
182
+
183
+
184
+_assoc_array_remove()
185
+{
186
+    local array
187
+    local key
188
+
189
+    array="${1}"
190
+    key="`array_key_check "$2"`"
191
+
192
+    local line
193
+
194
+    if [ ! -z "${array}" ]
195
+    then
196
+        echo "${array}" | fgrep -v "<${key}>"
197
+    fi
198
+}
199
+
200
+
201
+assoc_array_get()
202
+{
203
+    local array
204
+    local key
205
+
206
+    array="${1}"
207
+    key="`array_key_check "$2"`"
208
+
209
+    echo "${array}" | fgrep "<${key}>" | sed -n 's/^<.*>\(.*\)$/\1/p'
210
+}
211
+
212
+
213
+assoc_array_get_last()
214
+{
215
+    local array
216
+
217
+    array="${1}"
218
+
219
+    echo "${array}" | tail -1 | sed -n 's/^<.*>\(.*\)$/\1/p'
220
+}
221
+
222
+
223
+
224
+assoc_array_set()
225
+{
226
+    local array
227
+    local key
228
+    local value
229
+    local old_value
230
+
231
+    array="${1}"
232
+    key="${2}"
233
+    value="${3}"
234
+
235
+    if [ -z "${value}" ]
236
+    then
237
+        _assoc_array_remove "${array}" "${key}"
238
+        return
239
+    fi
240
+
241
+    local old_value
242
+
243
+    old_value="`assoc_array_get "${array}" "${key}"`"
244
+    if [ ! -z "${old_value}" ]
245
+    then
246
+        array="`_assoc_array_remove "${array}" "${key}"`"
247
+    fi
248
+
249
+    _assoc_array_add "${array}" "${key}" "${value}"
250
+}
... ...
@@ -35,11 +35,8 @@
35 35
 # You can also specify a list of "brew" dependencies. That
36 36
 # will be third party libraries, you don't tag or debug
37 37
 #
38
-INHERIT_SETTINGS='taps
39
-brews
38
+INHERIT_SETTINGS='brews
40 39
 repositories
41
-pips
42
-gems
43 40
 settings/build_order
44 41
 settings/build_ignore'
45 42
 
... ...
@@ -84,7 +84,7 @@ EOF
84 84
          :
85 85
       ;;
86 86
 
87
-      *)   
87
+      *)
88 88
          cat <<EOF >&2
89 89
    -j         :  number of cores parameter for make (${CORES})
90 90
 EOF
... ...
@@ -655,7 +655,7 @@ ${C_MAGENTA}${C_BOLD}${sdk}${C_INFO} in \"${builddir}\" ..."
655 655
    local local_make_flags
656 656
 
657 657
    if [ ! -z "${CORES}" ]
658
-   then  
658
+   then
659 659
       local_make_flags="-j ${CORES}"
660 660
    fi
661 661
 
... ...
@@ -878,7 +878,7 @@ ${C_MAGENTA}${C_BOLD}${sdk}${C_INFO} in \"${builddir}\" ..."
878 878
 
879 879
    local owd
880 880
    local nativewd
881
-   
881
+
882 882
    owd="${PWD}"
883 883
    nativewd="`pwd ${BUILD_PWD_OPTIONS}`"
884 884
 
885 885
new file mode 100644
... ...
@@ -0,0 +1,159 @@
0
+#! /bin/sh
1
+#
2
+#   Copyright (c) 2016 Nat! - Mulle kybernetiK
3
+#   All rights reserved.
4
+#
5
+#   Redistribution and use in source and binary forms, with or without
6
+#   modification, are permitted provided that the following conditions are met:
7
+#
8
+#   Redistributions of source code must retain the above copyright notice, this
9
+#   list of conditions and the following disclaimer.
10
+#
11
+#   Redistributions in binary form must reproduce the above copyright notice,
12
+#   this list of conditions and the following disclaimer in the documentation
13
+#   and/or other materials provided with the distribution.
14
+#
15
+#   Neither the name of Mulle kybernetiK nor the names of its contributors
16
+#   may be used to endorse or promote products derived from this software
17
+#   without specific prior written permission.
18
+#
19
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+#   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+#   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+#   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+#   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+#   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+#   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+#   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+#   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+#   POSSIBILITY OF SUCH DAMAGE.
30
+#
31
+#
32
+
33
+. mulle-bootstrap-array.sh
34
+
35
+
36
+escape_array()
37
+{
38
+   local text
39
+
40
+   text="`echo "$@" | sed -e 's/|/\\|/g'`"
41
+   /bin/echo -n "${text}" | tr '\012' '|'
42
+}
43
+
44
+
45
+unescape_array()
46
+{
47
+   echo "$@" | tr '|' '\012' | sed -e 's/\\$/|/g' -e '/^$/d'
48
+}
49
+
50
+
51
+_dependency_resolve()
52
+{
53
+   local map
54
+   local name
55
+
56
+   map="${1}"
57
+   name="${2}"
58
+
59
+   local escaped_dependencies
60
+   local dependencies
61
+
62
+   escaped_dependencies="`assoc_array_get "${map}" "${name}"`"
63
+   dependencies="`unescape_array "${escaped_dependencies}"`"
64
+
65
+   UNRESOLVED_DEPENDENCIES="`array_add "${UNRESOLVED_DEPENDENCIES}" "${name}"`"
66
+
67
+   local sub_name
68
+   local old
69
+
70
+   old="${IFS}"
71
+   IFS="
72
+"
73
+   for sub_name in ${dependencies}
74
+   do
75
+      IFS="${old}"
76
+
77
+      if array_contains "${RESOLVED_DEPENDENCIES}" "${sub_name}"
78
+      then
79
+         continue
80
+      fi
81
+
82
+      if array_contains "${UNRESOLVED_DEPENDENCIES}" "${sub_name}"
83
+      then
84
+         fail "circular dependency ${sub_name} and ${name}"
85
+      fi
86
+
87
+      _dependency_resolve "${map}" "${sub_name}"
88
+   done
89
+   IFS="${old}"
90
+
91
+   UNRESOLVED_DEPENDENCIES="`array_remove "${UNRESOLVED_DEPENDENCIES}" "${name}"`"
92
+   RESOLVED_DEPENDENCIES="`array_add "${RESOLVED_DEPENDENCIES}" "${name}"`"
93
+}
94
+
95
+
96
+dependency_add()
97
+{
98
+   local map
99
+
100
+   map="$1"
101
+
102
+   local name
103
+   local sub_name
104
+
105
+   name="$2"
106
+   sub_name="$3"
107
+
108
+   local escaped_dependencies
109
+   local dependencies
110
+
111
+   escaped_dependencies="`assoc_array_get "${map}" "${name}"`"
112
+   dependencies="`unescape_array "${escaped_dependencies}"`"
113
+
114
+   if array_contains "${dependencies}" "${sub_name}"
115
+   then
116
+      if [ ! -z "${map}" ]
117
+      then
118
+         echo "${map}"
119
+      fi
120
+      return
121
+   fi
122
+
123
+   dependencies="`array_add "${dependencies}" "${sub_name}"`"
124
+   escaped_dependencies="`escape_array "${dependencies}"`"
125
+
126
+   assoc_array_set "${map}" "${name}" "${escaped_dependencies}"
127
+}
128
+
129
+
130
+dependency_resolve()
131
+{
132
+   local map
133
+   local name
134
+
135
+   map="$1"
136
+   name="$2"
137
+
138
+   RESOLVED_DEPENDENCIES=
139
+   UNRESOLVED_DEPENDENCIES=
140
+
141
+   _dependency_resolve "${map}" "${name}"
142
+
143
+   local rval
144
+
145
+   rval=1
146
+   if [ -z "${UNRESOLVED_DEPENDENCIES}" ]
147
+   then
148
+      echo "${RESOLVED_DEPENDENCIES}"
149
+      rval=0
150
+   fi
151
+
152
+   RESOLVED_DEPENDENCIES=
153
+   UNRESOLVED_DEPENDENCIES=
154
+
155
+   return $rval
156
+}
157
+
158
+
... ...
@@ -727,7 +727,9 @@ checkout_repository()
727 727
 
728 728
       run_build_settings_script "${name}" "${url}" "${dstdir}" "post-${COMMAND}" "$@"
729 729
 
730
+      #
730 731
       # means we recursed and should start fetch from top
732
+      #
731 733
       if [ ${flag} -eq 0 ]
732 734
       then
733 735
          return 1
... ...
@@ -742,7 +744,6 @@ checkout_repository()
742 742
 }
743 743
 
744 744
 
745
-
746 745
 clone_repository()
747 746
 {
748 747
    local name
... ...
@@ -671,7 +671,7 @@ dir_has_files()
671 671
    local empty
672 672
    local result
673 673
 
674
-   empty="`find "${path}" -xdev -mindepth 1 -maxdepth 1 -name "[a-zA-Z0-9_-]*" ${flags} "$@" -print 2> /dev/null`"  
674
+   empty="`find "${path}" -xdev -mindepth 1 -maxdepth 1 -name "[a-zA-Z0-9_-]*" ${flags} "$@" -print 2> /dev/null`"
675 675
    [ "$empty" != "" ]
676 676
    result=$?
677 677
 
... ...
@@ -101,6 +101,7 @@ refresh_repositories_settings()
101 101
    local stop
102 102
    local refreshed
103 103
    local match
104
+   local map
104 105
 
105 106
    old="${IFS:-" "}"
106 107
 
... ...
@@ -116,6 +117,7 @@ refresh_repositories_settings()
116 116
       then
117 117
          IFS="
118 118
 "
119
+         map=""
119 120
          for clone in ${clones}
120 121
          do
121 122
             IFS="${old}"
... ...
@@ -141,6 +143,19 @@ ${clone}"
141 141
                tag="`read_repo_setting "${name}" "tag"`" #repo (sic)
142 142
                dstdir="${CLONESFETCH_SUBDIR}/${name}"
143 143
 
144
+               #
145
+               # dependency management, it could be nicer, but isn't
146
+               # currently match only URLs
147
+               #
148
+               local sub_repos
149
+
150
+               sub_repos="`_read_setting "${dstdir}/${BOOTSTRAP_SUBDIR}/repositories"`"
151
+               if [ ! -z "${sub_repos}" ]
152
+               then
153
+                  map="`dependency_add "${map}" "**ROOT**" "${url}"`"
154
+                  map="`dependency_add "${map}" "${url}" "${sub_repos}"`"
155
+               fi
156
+
144 157
                bootstrap_auto_update "${name}" "${url}" "${dstdir}"
145 158
                flag=$?
146 159
 
... ...
@@ -154,6 +169,17 @@ ${clone}"
154 154
    done
155 155
 
156 156
    IFS="${old}"
157
+
158
+   #
159
+   # output true repository dependencies
160
+   #
161
+   local repositories
162
+
163
+   repositories="`dependency_resolve "${map}" "**ROOT**" | fgrep -v -x "**ROOT**"`"
164
+   if [ ! -z "${repositories}" ]
165
+   then
166
+      echo "${repositories}" > "${BOOTSTRAP_SUBDIR}.auto/repositories"
167
+   fi
157 168
 }
158 169
 
159 170
 
160 171
new file mode 100755
... ...
@@ -0,0 +1,63 @@
0
+#! /bin/sh
1
+
2
+. mulle-bootstrap-dependency-resolve.sh
3
+. mulle-bootstrap-functions.sh
4
+
5
+
6
+test_dependencies()
7
+{
8
+   local map
9
+
10
+   map="`dependency_add "${map}" "a" "b"`"
11
+   map="`dependency_add "${map}" "b" "c"`"
12
+   map="`dependency_add "${map}" "a" "c"`"
13
+   map="`dependency_add "${map}" "b" "d"`"
14
+   map="`dependency_add "${map}" "d" "e"`"
15
+
16
+   set -x
17
+   dependency_resolve "${map}" "a"
18
+}
19
+
20
+
21
+test_array()
22
+{
23
+    local array
24
+
25
+    array="`array_add "${array}" "VfL"`"
26
+    array="`array_add "${array}" "Bochum"`"
27
+    array="`array_add "${array}" "1848"`"
28
+
29
+    array="`array_remove "${array}" "Bochum"`"
30
+    echo "${array}"
31
+}
32
+
33
+
34
+test_assoc_array()
35
+{
36
+    local array
37
+
38
+    array="`assoc_array_set "${array}" "1" "Riemann"`"
39
+    array="`assoc_array_set "${array}" "21" "Celozzi"`"
40
+    array="`assoc_array_set "${array}" "2" "Hoogland"`"
41
+    array="`assoc_array_set "${array}" "5" "Bastians"`"
42
+    array="`assoc_array_set "${array}" "24" "Perthel"`"
43
+    array="`assoc_array_set "${array}" "8" "Losilla"`"
44
+    array="`assoc_array_set "${array}" "39" "Steipermann"`"
45
+    array="`assoc_array_set "${array}" "23" "Weilandt"`"
46
+    array="`assoc_array_set "${array}" "10" "Eisfeld"`"
47
+    array="`assoc_array_set "${array}" "22" "Stoeger"`"
48
+    array="`assoc_array_set "${array}" "9" "Wurtz"`"
49
+
50
+    echo "pre remove: " `assoc_array_get "${array}" "10"`
51
+    array="`assoc_array_set "${array}" "10"`"
52
+    echo "post remove: " `assoc_array_get "${array}" "10"`
53
+
54
+    echo "pre set: " `assoc_array_get "${array}" "39"`
55
+    array="`assoc_array_set "${array}" "39" "Stiepermann"`"
56
+    echo "post remove: " `assoc_array_get "${array}" "39"`
57
+}
58
+
59
+
60
+test_array
61
+test_assoc_array
62
+test_dependencies
0 63
\ No newline at end of file