create-ccan-tree 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #!/bin/bash
  2. progname=$(basename $0)
  3. usage() {
  4. cat >&2 <<EOF
  5. Usage: $progname [options] <outdir> <depends>...
  6. options:
  7. -a, --copy-all copy all files in module tree (not just sources
  8. required for build)
  9. -b, --build-type=TYPE generate build infrastructure of TYPE
  10. (one of 'make', 'make+config', 'automake', 'waf')
  11. EOF
  12. }
  13. # parse options, setting the following flags
  14. copy_all=
  15. build_type=
  16. opts=$(getopt -o ab: --long copy-all,build-type: -n $progname -- "$@")
  17. if [ $? != 0 ]
  18. then
  19. usage
  20. exit 1
  21. fi
  22. eval set -- "$opts"
  23. while :
  24. do
  25. case "$1" in
  26. -a|--copy-all)
  27. copy_all=1
  28. shift
  29. ;;
  30. -b|--build-type)
  31. build_type="$2"
  32. shift 2
  33. ;;
  34. --)
  35. shift
  36. break
  37. ;;
  38. *)
  39. echo "Internal error!">&2
  40. exit 1
  41. ;;
  42. esac
  43. done
  44. # we need at least two non-option arguments: outdir and a list of ccan
  45. # modules
  46. if [ $# -lt 2 ]
  47. then
  48. usage
  49. exit 1
  50. fi
  51. # check --build-type argument sanity
  52. case "$build_type" in
  53. ''|'make'|'make+config'|'automake'|'waf')
  54. ;;
  55. *)
  56. echo "Invalid build type '$build_type'" >&2
  57. exit 1
  58. esac
  59. srcdir=$(dirname $0)/../
  60. outdir="$1"
  61. shift
  62. modules="$@"
  63. if [ -e "$outdir" ]
  64. then
  65. echo "Output directory '$outdir' already exists" >&2
  66. exit 1
  67. fi
  68. tmpdir="$(mktemp -d)"
  69. # sanity check, we don't want to be overwriting stuff in arbitrary dirs
  70. [ $? -eq 0 -a -d "${tmpdir}" ] || exit 1
  71. # We'll need the ccan_depends tool, but also a clean source tree. Build
  72. # tools/ccan_depends, and store it in $tmpdir for later use
  73. echo "Building ccan_depends"
  74. ccan_depends="$tmpdir/ccan_depends"
  75. make -s -C "$srcdir" tools/ccan_depends
  76. [ $? -eq 0 ] || exit 1
  77. cp "$srcdir/tools/ccan_depends" "$ccan_depends"
  78. echo "Cleaning source tree"
  79. make -s -C "$srcdir" clean
  80. [ $? -eq 0 ] || exit 1
  81. # clean up on error
  82. trap 'rm -rf $tmpdir' EXIT
  83. copy_ccan_module() {
  84. module_dir="$1"
  85. module_srcdir="$srcdir/$module_dir"
  86. module_destdir="$tmpdir/$module_dir"
  87. if [ -n "$copy_all" ]
  88. then
  89. # bulk copy
  90. mkdir -p "$(dirname "$module_destdir")"
  91. cp -a "$module_srcdir" "$module_destdir"
  92. else
  93. mkdir -p "$module_destdir"
  94. # only copy sources & license
  95. license="$module_srcdir/LICENSE"
  96. cp -a "$module_srcdir"/*.[ch] "$module_destdir"
  97. [ -e "$license" ] && cp -a "$license" "$module_destdir"
  98. fi
  99. }
  100. # generate list of directories to copy
  101. for module in $modules
  102. do
  103. # ccan_depends takes a directory name
  104. module_dir="$srcdir/ccan/$module"
  105. # we need the module itself...
  106. echo "ccan/$module"
  107. # .. plus dependencies
  108. "$ccan_depends" "$module_dir"
  109. if [ $? -ne 0 ]
  110. then
  111. echo "Invalid ccan module '$module'?" >&2
  112. exit 1
  113. fi
  114. done |
  115. sort -u |
  116. while read dir
  117. do
  118. echo "Adding $dir"
  119. copy_ccan_module $dir
  120. done
  121. # we're done with the dependency-tracking, remove the tool from our
  122. # temporary directory
  123. rm "$ccan_depends"
  124. echo "Adding licenses"
  125. license_dir="$tmpdir/licenses"
  126. mkdir "$license_dir"
  127. find "$tmpdir" -type l -name LICENSE |
  128. while read license
  129. do
  130. license_link=$(readlink "$license")
  131. licence_file=$(basename "$license_link")
  132. license_src="$srcdir/licenses/$licence_file"
  133. license_dest="$license_dir/$license_file"
  134. cp "$license_src" "$license_dest"
  135. done
  136. echo "Adding build infrastructure"
  137. # generate automake Makefile.am
  138. automakefile="$tmpdir/Makefile.am"
  139. if [ "$build_type" = "automake" ]
  140. then
  141. (
  142. echo "noinst_LIBRARIES = libccan.a"
  143. echo "libccan_a_SOURCES = \\"
  144. cd "$tmpdir"
  145. find ccan -maxdepth 2 -name '*.[ch]' |
  146. sed -e 's,^,\t,;$!s,$, \\,'
  147. ) > "$automakefile"
  148. fi
  149. makefile="$tmpdir/Makefile"
  150. if [ "$build_type" = "make" -o "$build_type" = "make+config" ]
  151. then
  152. # add ccan Makefile
  153. cp "$srcdir/Makefile-ccan" "$tmpdir/"
  154. # add top-level Makefile
  155. cat > "$makefile" << EOF
  156. all: libccan.a
  157. include Makefile-ccan
  158. EOF
  159. fi
  160. # optionally add configurator, and relevant parts to top-level Makefile
  161. if [ "$build_type" = "make+config" ]
  162. then
  163. echo "Adding configurator"
  164. mkdir -p "$tmpdir/tools/configurator"
  165. cp -a "$srcdir/tools/configurator" "$tmpdir/tools/"
  166. cat >> "$makefile" <<EOF
  167. tools/configurator/configurator: tools/configurator/configurator.c
  168. config.h: tools/configurator/configurator Makefile Makefile-ccan
  169. tools/configurator/configurator \$(CC) \$(CCAN_CFLAGS) > \$@ \\
  170. || rm -f \$@
  171. objs = \$(patsubst %.c, %.o, \$(wildcard ccan/*/*.c))
  172. \$(objs): config.h
  173. EOF
  174. fi
  175. if [ "$build_type" = "waf" ]
  176. then
  177. echo "Adding waf wscript"
  178. cat > "$tmpdir/wscript" << EOF
  179. def build(ctx):
  180. ctx(features = 'c cstlib',
  181. source = ctx.path.ant_glob('**/*.c'),
  182. target = 'ccan',
  183. includes = '.')
  184. EOF
  185. fi
  186. mv "$tmpdir" "$outdir"
  187. echo "Done. ccan source tree built in $outdir"
  188. trap - EXIT