defconfig_builder.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. #!/bin/bash
  2. #
  3. # defconfig_builder.sh
  4. #
  5. # Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
  6. # ALL RIGHTS RESERVED
  7. #
  8. # This script will perform a merge of config fragment files into a defconfig
  9. # based on a map file. The map file defines the defconfig options that have
  10. # been tested by TI to boot and compile.
  11. #
  12. # This program is free software; you can redistribute it and/or modify
  13. # it under the terms of the GNU General Public License as published by
  14. # the Free Software Foundation; either version 2 of the License.
  15. #
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU General Public License for more details.
  20. #
  21. # For more information type defconfig_builder.sh -?
  22. #
  23. # IMPORTANT NOTE: All modifications to this script must be verified by running
  24. # 'shellcheck --shell=bash defconfig_builder.sh' See 'Installing' section in:
  25. # https://github.com/koalaman/shellcheck/blob/master/README.md
  26. # Also note that shellcheck must be at least at revision 0.3.3
  27. DEBUG_CONFIG_TAG="debug_options"
  28. CONFIG_FRAGMENT_TAG="config-fragment="
  29. DISCLAIMER="\n*Please be advised that the Debug Option defconfigs may\nimpact \
  30. performance and should only be used for debugging.\n"
  31. # Template for temporary build files.. use PID to differentiate
  32. TMP_PREFIX=ti_defconfig_builder_$$
  33. TMP_TEMPLATE="$TMP_PREFIX"_XXXXX.tmp
  34. set_working_directory() {
  35. # Sanity checkup kernel build location.
  36. if [ ! -d "$WORKING_PATH" ]; then
  37. WORKING_PATH=$(pwd)
  38. fi
  39. ORIGINAL_DIR=$(pwd)
  40. if [ "$ORIGINAL_DIR" != "$WORKING_PATH" ]; then
  41. cd "$WORKING_PATH"
  42. WORKING_PATH=$(pwd)
  43. fi
  44. TI_WORKING_PATH="$WORKING_PATH/ti_config_fragments"
  45. DEFCONFIG_KERNEL_PATH="$WORKING_PATH/arch/arm/configs"
  46. DEFCONFIG_MAP_FILE="$TI_WORKING_PATH/defconfig_map.txt"
  47. }
  48. prepare_for_exit() {
  49. D=$(dirname "$PROCESSOR_FILE")
  50. rm -f "$PROCESSOR_FILE"
  51. rm -f "$BUILD_TYPE_FILE"
  52. rm -f "$TEMP_TYPE_FILE"
  53. if [ -s "$OLD_CONFIG" ]; then
  54. mv "$OLD_CONFIG" "$WORKING_PATH"/.config
  55. fi
  56. # Clean everyone else up if we missed any
  57. rm -f "$D"/"$TMP_PREFIX"*.tmp
  58. exit
  59. }
  60. check_for_config_existance() {
  61. # Check to make sure that the config fragments exist
  62. TEMP_EXTRA_CONFIG_FILE=$(echo "$BUILD_DETAILS" | cut -d: -f6)
  63. if [ -z "$TEMP_EXTRA_CONFIG_FILE" ]; then
  64. CONFIG_FRAGMENTS=
  65. else
  66. for CONFIG_FRAGMENT_FILE in $TEMP_EXTRA_CONFIG_FILE;
  67. do
  68. # If we do already point to existing file, we are good.
  69. if [ -e "$CONFIG_FRAGMENT_FILE" ]; then
  70. CONFIG_FRAG="$CONFIG_FRAGMENT_FILE"
  71. else
  72. # Assume it is present in TI working path
  73. CONFIG_FRAG="$TI_WORKING_PATH/$CONFIG_FRAGMENT_FILE"
  74. fi
  75. if [ ! -e "$CONFIG_FRAG" ]; then
  76. CONFIG_FRAGMENTS="N/A"
  77. fi
  78. done
  79. fi
  80. if ! grep -qc "$BT_TEMP" "$BUILD_TYPE_FILE"; then
  81. # If the config file and config fragments are available
  82. # add it to the list.
  83. CONFIG_FILE=$(echo "$BUILD_DETAILS" | awk '{print$8}')
  84. if [ "$CONFIG_FILE" = "None" ]; then
  85. CONFIG_FILE=
  86. else
  87. if [ -e "$TI_WORKING_PATH""/""$CONFIG_FILE" ]; then
  88. CONFIG_FILE=
  89. fi
  90. fi
  91. # If the check for the config file and the config fragments
  92. # pass then these two variables should be empty. If
  93. # they fail then they should be N/A.
  94. if [ -z "$CONFIG_FILE" -a -z "$CONFIG_FRAGMENTS" ]; then
  95. max_configs=$((max_configs+1))
  96. echo -e '\t'"$max_configs". "$BT_TEMP" >> "$BUILD_TYPE_FILE"
  97. fi
  98. fi
  99. }
  100. choose_build_type() {
  101. TEMP_BT_FILE=$(mktemp -t $TMP_TEMPLATE)
  102. TEMP_BUILD_FILE=$(mktemp -t $TMP_TEMPLATE)
  103. grep "$DEFCONFIG_FILTER" "$DEFCONFIG_MAP_FILE" | grep "^classification:" | awk '{print$4}' > "$TEMP_BUILD_FILE"
  104. max_configs=0
  105. while true;
  106. do
  107. CONFIG_FILE=
  108. CONFIG_FRAGMENTS=
  109. BT_TEMP=$(head -n 1 "$TEMP_BUILD_FILE")
  110. if [ -z "$BT_TEMP" ]; then
  111. break
  112. fi
  113. BUILD_DETAILS=$(grep -w "$BT_TEMP" "$DEFCONFIG_MAP_FILE")
  114. check_for_config_existance
  115. sed -i "1d" "$TEMP_BUILD_FILE"
  116. done
  117. NUM_OF_BUILDS=$(wc -l "$BUILD_TYPE_FILE" | awk '{print$1}')
  118. if [ "$NUM_OF_BUILDS" -eq 0 ]; then
  119. echo "Sorry no build targets for this configuration. Are you on the right branch?"
  120. prepare_for_exit
  121. fi
  122. # Force the user to answer. Maybe the user does not want to continue
  123. while true;
  124. do
  125. echo -e "Available ""$DEFCONFIG_FILTER"" defconfig build options:\n"
  126. cat "$BUILD_TYPE_FILE"
  127. echo ""
  128. read -p "Please enter the number of the defconfig to build or 'q' to exit: " REPLY
  129. if [ "$REPLY" = "q" -o "$REPLY" = "Q" ]; then
  130. prepare_for_exit
  131. elif ! [[ "$REPLY" =~ ^[0-9]+$ ]]; then
  132. echo -e "\n$REPLY is not a number of the defconfig. Please try again!\n"
  133. continue
  134. elif [ "$REPLY" -gt '0' -a "$REPLY" -le "$NUM_OF_BUILDS" ]; then
  135. CHOSEN_BUILD_TYPE=$(grep -w "$REPLY" "$BUILD_TYPE_FILE" | awk '{print$2}')
  136. break
  137. else
  138. echo -e "\n'$REPLY' is not a valid choice. Please \
  139. choose a value between '1' and '$max_configs':\n"
  140. fi
  141. done
  142. rm "$TEMP_BT_FILE"
  143. rm "$TEMP_BUILD_FILE"
  144. }
  145. list_all_targets() {
  146. TMP_MAP=$(mktemp -t $TMP_TEMPLATE)
  147. cat "$DEFCONFIG_MAP_FILE" > "$TMP_MAP"
  148. while true;
  149. do
  150. CONFIG_FILE=
  151. CONFIG_FRAGMENTS=
  152. BT_TEMP=$(head -n 1 "$TMP_MAP" | awk '{print$4}')
  153. BUILD_DETAILS=$(head -n 1 "$TMP_MAP")
  154. if [ -z "$BUILD_DETAILS" ]; then
  155. break
  156. fi
  157. check_for_config_existance
  158. sed -i "1d" "$TMP_MAP"
  159. done
  160. rm "$TMP_MAP"
  161. cat "$BUILD_TYPE_FILE"
  162. }
  163. get_build_details() {
  164. BUILD_DETAILS=$(grep -w "$CHOSEN_BUILD_TYPE" "$DEFCONFIG_MAP_FILE")
  165. if [ -z "$BUILD_DETAILS" ]; then
  166. echo "Cannot find the build type or a match for $CHOSEN_BUILD_TYPE"
  167. TEMP_BUILD_FILE=$(mktemp -t $TMP_TEMPLATE)
  168. grep "$CHOSEN_BUILD_TYPE" "$DEFCONFIG_MAP_FILE" > "$TEMP_BUILD_FILE"
  169. while true;
  170. do
  171. CONFIG_FILE=
  172. CONFIG_FRAGMENTS=
  173. BT_TEMP=$(head -n 1 "$TEMP_BUILD_FILE" | awk '{print$4}')
  174. if [ -z "$BT_TEMP" ]; then
  175. break
  176. fi
  177. BUILD_DETAILS=$(grep -w "$BT_TEMP" "$DEFCONFIG_MAP_FILE")
  178. check_for_config_existance
  179. sed -i "1d" "$TEMP_BUILD_FILE"
  180. done
  181. rm -rf "$TEMP_BUILD_FILE"
  182. NUM_OF_BUILDS=$(wc -l "$BUILD_TYPE_FILE" | awk '{print$1}')
  183. if [ "$NUM_OF_BUILDS" -eq 0 ]; then
  184. echo "Maybe try one of the following:"
  185. list_all_targets
  186. else
  187. echo "Did you mean any of the following?"
  188. cat "$BUILD_TYPE_FILE"
  189. fi
  190. return 1
  191. fi
  192. DEFCONFIG=$(echo "$BUILD_DETAILS" | awk '{print$6}')
  193. DEFCONFIG="$DEFCONFIG_KERNEL_PATH""/""$DEFCONFIG"
  194. CONFIG_FILE=$(echo "$BUILD_DETAILS" | awk '{print$8}')
  195. # There may be a need to just build with the config fragments themselves
  196. if [ "$CONFIG_FILE" = "None" ]; then
  197. CONFIG_FILE=
  198. fi
  199. if [ ! -e "$TI_WORKING_PATH/$CONFIG_FILE" ]; then
  200. echo "$TI_WORKING_PATH/$CONFIG_FILE does not exist"
  201. return 1
  202. fi
  203. TEMP_EXTRA_CONFIG_FILE=$(echo "$BUILD_DETAILS" | cut -d: -f6)
  204. for CONFIG_FRAGMENT_FILE in $TEMP_EXTRA_CONFIG_FILE;
  205. do
  206. # If we do already point to existing file, we are good.
  207. if [ -e "$CONFIG_FRAGMENT_FILE" ]; then
  208. CONFIG_FRAG="$CONFIG_FRAGMENT_FILE"
  209. else
  210. # Assume it is present in TI working path
  211. CONFIG_FRAG="$TI_WORKING_PATH/$CONFIG_FRAGMENT_FILE"
  212. fi
  213. if [ -e "$CONFIG_FRAG" ]; then
  214. EXTRA_CONFIG_FILE="$EXTRA_CONFIG_FILE $CONFIG_FRAG"
  215. else
  216. echo "$CONFIG_FRAG" does not exist
  217. fi
  218. done
  219. }
  220. build_defconfig() {
  221. if [ ! -z "$CONFIG_FILE" -a -e "$TI_WORKING_PATH/$CONFIG_FILE" ]; then
  222. CONFIGS=$(grep "$CONFIG_FRAGMENT_TAG" "$TI_WORKING_PATH/$CONFIG_FILE" | cut -d= -f2)
  223. fi
  224. "$WORKING_PATH"/scripts/kconfig/merge_config.sh -m -r "$DEFCONFIG" \
  225. "$CONFIGS" "$EXTRA_CONFIG_FILE" > /dev/null
  226. if [ "$?" = "0" ];then
  227. echo "Creating defconfig file ""$WORKING_PATH""/arch/arm/configs/""$CHOSEN_BUILD_TYPE"_defconfig
  228. mv .config "$DEFCONFIG_KERNEL_PATH"/"$CHOSEN_BUILD_TYPE"_defconfig
  229. else
  230. echo "Defconfig creation failed"
  231. return 1
  232. fi
  233. }
  234. choose_defconfig_type() {
  235. TEMP_TYPE_FILE=$(mktemp -t $TMP_TEMPLATE)
  236. TYPE_FILE=$(awk '{print$2}' "$DEFCONFIG_MAP_FILE" | sort -u | grep -i "SDK_")
  237. max_types=0
  238. for TYPE_TMP in $TYPE_FILE;
  239. do
  240. max_types=$((max_types+1))
  241. echo -e '\t' "$max_types." "$TYPE_TMP" >> "$TEMP_TYPE_FILE"
  242. done
  243. echo >> "$TEMP_TYPE_FILE"
  244. while true;
  245. do
  246. cat "$TEMP_TYPE_FILE"
  247. read -p "Please choose a defconfig type to build for or 'q' to exit: " REPLY
  248. if [ "$REPLY" = "q" -o "$REPLY" = "Q" ]; then
  249. prepare_for_exit
  250. elif ! [[ "$REPLY" =~ ^[0-9]+$ ]]; then
  251. echo -e "\n'$REPLY' is not a number for the build type. Please try again!\n"
  252. continue
  253. elif [ "$REPLY" -gt '0' -a "$REPLY" -le "$max_types" ]; then
  254. REPLY="$REPLY""."
  255. DEFCONFIG_FILTER=$(awk '{if ($1 == "'"$REPLY"'") print $2;}' "$TEMP_TYPE_FILE")
  256. break
  257. else
  258. echo -e "\n'$REPLY' is not a valid choice. Please \
  259. choose a value between '1' and '$max_types':\n"
  260. fi
  261. done
  262. DEBUG_BUILD=$(grep "$DEFCONFIG_FILTER" "$DEFCONFIG_MAP_FILE" | grep -wc "$DEBUG_CONFIG_TAG" )
  263. if [ "$DEBUG_BUILD" -gt '0' ]; then
  264. echo -e "$DISCLAIMER"
  265. fi
  266. }
  267. usage() {
  268. cat << EOF
  269. This script will perform a merge of config fragment files into a defconfig
  270. based on a map file. The map file defines the defconfig options that have
  271. been tested by TI to boot and compile.
  272. Optional:
  273. -w - Location of the TI Linux kernel
  274. -t - Indicates the type of defconfig to build. This will force the
  275. defconfig to build without user interaction.
  276. -l - List all buildable defconfig options
  277. Command line example to generate the TI SDK AM335x processor defconfig automatically
  278. without user interaction:
  279. ti_config_fragments/defconfig_builder.sh -t ti_sdk_am3x_release
  280. Command line Example if building from the ti_config_fragments directory:
  281. defconfig_builder.sh -w ../.
  282. User interactive command line example:
  283. ti_config_fragments/defconfig_builder.sh
  284. EOF
  285. }
  286. #########################################
  287. # Script Start
  288. #########################################
  289. while getopts "?w:t:l" OPTION
  290. do
  291. case $OPTION in
  292. w)
  293. WORKING_PATH=$OPTARG;;
  294. t)
  295. CHOSEN_BUILD_TYPE=$OPTARG;;
  296. l)
  297. LIST_TARGETS="y";;
  298. ?)
  299. usage
  300. exit;;
  301. esac
  302. done
  303. trap prepare_for_exit SIGHUP EXIT SIGINT SIGTERM
  304. set_working_directory
  305. if [ ! -e "$DEFCONFIG_MAP_FILE" ]; then
  306. echo "No defconfig map file found"
  307. exit 1
  308. fi
  309. BUILD_TYPE_FILE=$(mktemp -t $TMP_TEMPLATE)
  310. if [ ! -z "$LIST_TARGETS" ]; then
  311. echo "The following are a list of buildable defconfigs:"
  312. list_all_targets
  313. exit 0
  314. fi
  315. PROCESSOR_FILE=$(mktemp -t $TMP_TEMPLATE)
  316. OLD_CONFIG=$(mktemp -t $TMP_TEMPLATE)
  317. if [ -f "$WORKING_PATH"/.config ]; then
  318. mv "$WORKING_PATH"/.config "$OLD_CONFIG"
  319. fi
  320. if [ ! -z "$CHOSEN_BUILD_TYPE" ]; then
  321. get_build_details
  322. if [ "$?" -gt 0 ]; then
  323. exit 1
  324. fi
  325. build_defconfig
  326. if [ "$?" -gt 0 ]; then
  327. exit 1
  328. fi
  329. exit 0
  330. fi
  331. choose_defconfig_type
  332. choose_build_type
  333. get_build_details
  334. build_defconfig