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