common.sh (5517B)
1 #!/bin/sh 2 3 set -eu 4 5 : "${KIT:=./build/kit}" 6 7 c_source() { 8 "$KIT" build source "$1" 9 } 10 11 c_config() { 12 key=$1 13 def=$2 14 "$KIT" build config-get --default "$def" "$key" 15 } 16 17 c_config_merge() { 18 key=$1 19 def=$2 20 profile=$(c_config profile "") 21 base=$(c_config "$key" "$def") 22 prof="" 23 extra=$(c_config "$key.extra" "") 24 if [ -n "$profile" ]; then 25 prof=$(c_config "profile.$profile.$key" "") 26 fi 27 printf '%s\n' "$base $prof $extra" | awk '{$1=$1; print}' 28 } 29 30 c_toolchain_init() { 31 C_CC=$(c_config tool.c.cc "$(c_config cc "${CC:-cc}")") 32 C_AR=$(c_config tool.c.ar "$(c_config ar "${AR:-ar}")") 33 C_CFLAGS=$(c_config_merge tool.c.cflags "") 34 C_LDFLAGS=$(c_config_merge tool.c.ldflags "") 35 C_LDLIBS=$(c_config_merge tool.c.ldlibs "") 36 } 37 38 c_glob() { 39 "$KIT" build glob "$1" 40 } 41 42 c_depfile() { 43 if [ -s "$1" ]; then 44 dep=$1 45 if command -v c_depfile_filter >/dev/null 2>&1; then 46 norm="$dep.norm" 47 c_depfile_filter "$dep" > "$norm" 48 dep=$norm 49 fi 50 "$KIT" build depfile "$dep" >/dev/null 51 rm -f "$1" "${1}.norm" 52 fi 53 } 54 55 c_compile() { 56 src=$1 57 obj=$2 58 flags=$3 59 mkdir -p "$(dirname "$obj")" 60 dep="$obj.d" 61 "$C_CC" $C_CFLAGS $flags -MMD -MP -MF "$dep" -c "$src" -o "$obj" 62 c_depfile "$dep" 63 } 64 65 c_need() { 66 label=$1 67 case "$label" in 68 :*|//*|@*) "$KIT" build need "$label" ;; 69 *) "$KIT" build need ":$label" ;; 70 esac 71 } 72 73 c_target_local() { 74 if [ -n "${KIT_BUILD_LOCAL:-}" ]; then 75 printf '%s\n' "$KIT_BUILD_LOCAL" 76 else 77 printf '%s\n' "${KIT_BUILD_TARGET##*:}" 78 fi 79 } 80 81 c_require_hook() { 82 if ! command -v "$1" >/dev/null 2>&1; then 83 echo "missing C rule hook: $1" >&2 84 exit 1 85 fi 86 } 87 88 c_flags_init_default() { 89 if command -v c_flags_init >/dev/null 2>&1; then 90 c_flags_init 91 else 92 c_toolchain_init 93 fi 94 } 95 96 c_default_object() { 97 c_flags_init_default 98 c_require_hook c_object_plan_find 99 local=$(c_target_local) 100 line=$(c_object_plan_find "$local") || { 101 echo "no C object plan for target: $KIT_BUILD_TARGET" >&2 102 exit 1 103 } 104 105 target=${line%%|*} 106 rest=${line#*|} 107 src=${rest%%|*} 108 rest=${rest#*|} 109 obj_rel=${rest%%|*} 110 flags=${rest#*|} 111 112 [ "$target" = "$local" ] || exit 1 113 114 mkdir -p "$KIT_BUILD_OUT/obj" 115 c_compile "$src" "$KIT_BUILD_OUT/obj/$local" "$flags" 116 printf '%s\n' "obj/$local" > "$KIT_BUILD_OUT/object.list" 117 printf '%s\n' "$obj_rel" > "$KIT_BUILD_OUT/object.rel" 118 printf '%s\n' "$src" > "$KIT_BUILD_OUT/source.txt" 119 } 120 121 c_default_objects() { 122 c_flags_init_default 123 c_require_hook c_object_plan 124 local=$(c_target_local) 125 mkdir -p "$KIT_BUILD_OUT" 126 objects="$KIT_BUILD_OUT/objects.list" 127 : > "$objects" 128 129 c_object_plan "$local" | while IFS='|' read -r _target src obj_rel flags; do 130 [ -n "$src" ] || continue 131 dst="$KIT_BUILD_OUT/$obj_rel" 132 mkdir -p "$(dirname "$dst")" 133 c_compile "$src" "$dst" "$flags" 134 printf '%s\n' "$obj_rel" >> "$objects" 135 done 136 } 137 138 c_default_archive() { 139 c_flags_init_default 140 c_require_hook c_archive_output 141 c_require_hook c_archive_object_sets 142 local=$(c_target_local) 143 mkdir -p "$KIT_BUILD_OUT" 144 archive=$(c_archive_output "$local") 145 objects="$KIT_BUILD_OUT/archive-objects.list" 146 : > "$objects" 147 148 c_archive_object_sets "$local" | while IFS= read -r set_target; do 149 [ -n "$set_target" ] || continue 150 dep=$(c_need "$set_target") 151 while IFS= read -r obj; do 152 [ -n "$obj" ] || continue 153 printf '%s/%s\n' "$dep" "$obj" >> "$objects" 154 done < "$dep/objects.list" 155 done 156 157 rm -f "$KIT_BUILD_OUT/$archive" 158 # shellcheck disable=SC2046 159 "$C_AR" rcs "$KIT_BUILD_OUT/$archive" $(cat "$objects") 160 rm -f "$objects" 161 } 162 163 c_default_executable() { 164 c_flags_init_default 165 c_require_hook c_executable_output 166 local=$(c_target_local) 167 mkdir -p "$KIT_BUILD_OUT" 168 exe=$(c_executable_output "$local") 169 objs= 170 libs= 171 172 if command -v c_executable_object_sets >/dev/null 2>&1; then 173 for set_target in $(c_executable_object_sets "$local"); do 174 dep=$(c_need "$set_target") 175 while IFS= read -r obj; do 176 [ -n "$obj" ] || continue 177 objs="$objs $dep/$obj" 178 done < "$dep/objects.list" 179 done 180 fi 181 182 if command -v c_executable_libraries >/dev/null 2>&1; then 183 c_executable_libraries "$local" | while IFS='|' read -r label file; do 184 [ -n "$label" ] || continue 185 dep=$(c_need "$label") 186 printf '%s/%s\n' "$dep" "$file" >> "$KIT_BUILD_OUT/.link-libs" 187 done 188 if [ -f "$KIT_BUILD_OUT/.link-libs" ]; then 189 while IFS= read -r lib; do 190 libs="$libs $lib" 191 done < "$KIT_BUILD_OUT/.link-libs" 192 rm -f "$KIT_BUILD_OUT/.link-libs" 193 fi 194 fi 195 196 target_ldflags="" 197 target_ldlibs="" 198 if command -v c_executable_ldflags >/dev/null 2>&1; then 199 target_ldflags=$(c_executable_ldflags "$local") 200 fi 201 if command -v c_executable_ldlibs >/dev/null 2>&1; then 202 target_ldlibs=$(c_executable_ldlibs "$local") 203 fi 204 205 # shellcheck disable=SC2086 206 "$C_CC" $C_LDFLAGS $target_ldflags -o "$KIT_BUILD_OUT/$exe" \ 207 $objs $libs $target_ldlibs $C_LDLIBS 208 209 if command -v c_executable_after_link >/dev/null 2>&1; then 210 c_executable_after_link "$local" 211 fi 212 }