depends.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include "talloc/talloc.h"
  2. #include "string/string.h"
  3. #include "tools.h"
  4. #include <err.h>
  5. #include <stdbool.h>
  6. #include <unistd.h>
  7. static char ** __attribute__((format(printf, 3, 4)))
  8. lines_from_cmd(const void *ctx, unsigned int *num, char *format, ...)
  9. {
  10. va_list ap;
  11. char *cmd, *buffer;
  12. FILE *p;
  13. va_start(ap, format);
  14. cmd = talloc_vasprintf(ctx, format, ap);
  15. va_end(ap);
  16. p = popen(cmd, "r");
  17. if (!p)
  18. err(1, "Executing '%s'", cmd);
  19. buffer = grab_fd(ctx, fileno(p), NULL);
  20. if (!buffer)
  21. err(1, "Reading from '%s'", cmd);
  22. pclose(p);
  23. return strsplit(ctx, buffer, "\n", num);
  24. }
  25. static int unlink_info(char *infofile)
  26. {
  27. unlink(infofile);
  28. return 0;
  29. }
  30. /* Be careful about trying to compile over running programs (parallel make) */
  31. static char *compile_info(const void *ctx, const char *dir)
  32. {
  33. char *infofile = talloc_asprintf(ctx, "%s/_info.%u", dir, getpid());
  34. char *cmd = talloc_asprintf(ctx, "cc " CFLAGS " -o %s %s/_info.c",
  35. infofile, dir);
  36. talloc_set_destructor(infofile, unlink_info);
  37. if (system(cmd) != 0)
  38. return NULL;
  39. return infofile;
  40. }
  41. static char **get_one_deps(const void *ctx, const char *dir, unsigned int *num)
  42. {
  43. char **deps, *cmd, *infofile;
  44. infofile = compile_info(ctx, dir);
  45. if (!infofile)
  46. errx(1, "Could not compile _info for '%s'", dir);
  47. cmd = talloc_asprintf(ctx, "%s depends", infofile);
  48. deps = lines_from_cmd(cmd, num, "%s", cmd);
  49. if (!deps)
  50. err(1, "Could not run '%s'", cmd);
  51. return deps;
  52. }
  53. static bool have_dep(char **deps, unsigned int num, const char *dep)
  54. {
  55. unsigned int i;
  56. for (i = 0; i < num; i++)
  57. if (streq(deps[i], dep))
  58. return true;
  59. return false;
  60. }
  61. /* Gets all the dependencies, recursively. */
  62. char **get_deps(const void *ctx, const char *dir)
  63. {
  64. char **deps;
  65. unsigned int i, num;
  66. deps = get_one_deps(ctx, dir, &num);
  67. for (i = 0; i < num; i++) {
  68. char **newdeps;
  69. unsigned int j, newnum;
  70. if (!strstarts(deps[i], "ccan/"))
  71. continue;
  72. newdeps = get_one_deps(ctx, deps[i], &newnum);
  73. /* Should be short, so brute-force out dups. */
  74. for (j = 0; j < newnum; j++) {
  75. if (have_dep(deps, num, newdeps[j]))
  76. continue;
  77. deps = talloc_realloc(NULL, deps, char *, num + 2);
  78. deps[num++] = newdeps[j];
  79. deps[num] = NULL;
  80. }
  81. }
  82. return deps;
  83. }