ext-toolchain-wrapper.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * Buildroot wrapper for external toolchains. This simply executes the real
  3. * toolchain with a number of arguments (sysroot/arch/..) hardcoded,
  4. * to ensure the external toolchain uses the correct configuration.
  5. * The hardcoded path arguments are defined relative to the actual location
  6. * of the binary.
  7. *
  8. * (C) 2011 Peter Korsgaard <jacmet@sunsite.dk>
  9. * (C) 2011 Daniel Nyström <daniel.nystrom@timeterminal.se>
  10. * (C) 2012 Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
  11. * (C) 2013 Spenser Gilliland <spenser@gillilanding.com>
  12. *
  13. * This file is licensed under the terms of the GNU General Public License
  14. * version 2. This program is licensed "as is" without any warranty of any
  15. * kind, whether express or implied.
  16. */
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <limits.h>
  20. #include <unistd.h>
  21. #include <stdlib.h>
  22. static char path[PATH_MAX];
  23. static char sysroot[PATH_MAX];
  24. /**
  25. * GCC errors out with certain combinations of arguments (examples are
  26. * -mfloat-abi={hard|soft} and -m{little|big}-endian), so we have to ensure
  27. * that we only pass the predefined one to the real compiler if the inverse
  28. * option isn't in the argument list.
  29. * This specifies the worst case number of extra arguments we might pass
  30. * Currently, we have:
  31. * -mfloat-abi=
  32. * -march=
  33. * -mtune=
  34. * -mcpu=
  35. */
  36. #define EXCLUSIVE_ARGS 4
  37. static char *predef_args[] = {
  38. path,
  39. "--sysroot", sysroot,
  40. #ifdef BR_ABI
  41. "-mabi=" BR_ABI,
  42. #endif
  43. #ifdef BR_FPU
  44. "-mfpu=" BR_FPU,
  45. #endif
  46. #ifdef BR_SOFTFLOAT
  47. "-msoft-float",
  48. #endif /* BR_SOFTFLOAT */
  49. #ifdef BR_MODE
  50. "-m" BR_MODE,
  51. #endif
  52. #ifdef BR_64
  53. "-m64",
  54. #endif
  55. #ifdef BR_BINFMT_FLAT
  56. "-Wl,-elf2flt",
  57. #endif
  58. #ifdef BR_MIPS_TARGET_LITTLE_ENDIAN
  59. "-EL",
  60. #endif
  61. #ifdef BR_MIPS_TARGET_BIG_ENDIAN
  62. "-EB",
  63. #endif
  64. #ifdef BR_ADDITIONAL_CFLAGS
  65. BR_ADDITIONAL_CFLAGS
  66. #endif
  67. };
  68. int main(int argc, char **argv)
  69. {
  70. char **args, **cur;
  71. char *relbasedir, *absbasedir;
  72. char *progpath = argv[0];
  73. char *basename;
  74. char *env_debug;
  75. int ret, i, count = 0, debug;
  76. /* Calculate the relative paths */
  77. basename = strrchr(progpath, '/');
  78. if (basename) {
  79. *basename = '\0';
  80. basename++;
  81. relbasedir = malloc(strlen(progpath) + 7);
  82. if (relbasedir == NULL) {
  83. perror(__FILE__ ": malloc");
  84. return 2;
  85. }
  86. sprintf(relbasedir, "%s/../..", argv[0]);
  87. absbasedir = realpath(relbasedir, NULL);
  88. } else {
  89. basename = progpath;
  90. absbasedir = malloc(PATH_MAX + 1);
  91. ret = readlink("/proc/self/exe", absbasedir, PATH_MAX);
  92. if (ret < 0) {
  93. perror(__FILE__ ": readlink");
  94. return 2;
  95. }
  96. absbasedir[ret] = '\0';
  97. for (i = ret; i > 0; i--) {
  98. if (absbasedir[i] == '/') {
  99. absbasedir[i] = '\0';
  100. if (++count == 3)
  101. break;
  102. }
  103. }
  104. }
  105. if (absbasedir == NULL) {
  106. perror(__FILE__ ": realpath");
  107. return 2;
  108. }
  109. /* Fill in the relative paths */
  110. #ifdef BR_CROSS_PATH_REL
  111. ret = snprintf(path, sizeof(path), "%s/" BR_CROSS_PATH_REL "/%s", absbasedir, basename);
  112. #else /* BR_CROSS_PATH_ABS */
  113. ret = snprintf(path, sizeof(path), BR_CROSS_PATH_ABS "/%s", basename);
  114. #endif
  115. if (ret >= sizeof(path)) {
  116. perror(__FILE__ ": overflow");
  117. return 3;
  118. }
  119. ret = snprintf(sysroot, sizeof(sysroot), "%s/" BR_SYSROOT, absbasedir);
  120. if (ret >= sizeof(sysroot)) {
  121. perror(__FILE__ ": overflow");
  122. return 3;
  123. }
  124. cur = args = malloc(sizeof(predef_args) +
  125. (sizeof(char *) * (argc + EXCLUSIVE_ARGS)));
  126. if (args == NULL) {
  127. perror(__FILE__ ": malloc");
  128. return 2;
  129. }
  130. /* start with predefined args */
  131. memcpy(cur, predef_args, sizeof(predef_args));
  132. cur += sizeof(predef_args) / sizeof(predef_args[0]);
  133. #ifdef BR_FLOAT_ABI
  134. /* add float abi if not overridden in args */
  135. for (i = 1; i < argc; i++) {
  136. if (!strncmp(argv[i], "-mfloat-abi=", strlen("-mfloat-abi=")) ||
  137. !strcmp(argv[i], "-msoft-float") ||
  138. !strcmp(argv[i], "-mhard-float"))
  139. break;
  140. }
  141. if (i == argc)
  142. *cur++ = "-mfloat-abi=" BR_FLOAT_ABI;
  143. #endif
  144. #if defined(BR_ARCH) || \
  145. defined(BR_TUNE) || \
  146. defined(BR_CPU)
  147. /* Add our -march/cpu/tune/abi flags, but only if none are
  148. * already specified on the commandline
  149. */
  150. for (i = 1; i < argc; i++) {
  151. if (!strncmp(argv[i], "-march=", strlen("-march=")) ||
  152. !strncmp(argv[i], "-mtune=", strlen("-mtune=")) ||
  153. !strncmp(argv[i], "-mcpu=", strlen("-mcpu=" )))
  154. break;
  155. }
  156. if (i == argc) {
  157. #ifdef BR_ARCH
  158. *cur++ = "-march=" BR_ARCH;
  159. #endif
  160. #ifdef BR_TUNE
  161. *cur++ = "-mtune=" BR_TUNE;
  162. #endif
  163. #ifdef BR_CPU
  164. *cur++ = "-mcpu=" BR_CPU;
  165. #endif
  166. }
  167. #endif /* ARCH || TUNE || CPU */
  168. /* append forward args */
  169. memcpy(cur, &argv[1], sizeof(char *) * (argc - 1));
  170. cur += argc - 1;
  171. /* finish with NULL termination */
  172. *cur = NULL;
  173. /* Debug the wrapper to see actual arguments passed to
  174. * the compiler:
  175. * unset, empty, or 0: do not trace
  176. * set to 1 : trace all arguments on a single line
  177. * set to 2 : trace one argument per line
  178. */
  179. if ((env_debug = getenv("BR2_DEBUG_WRAPPER"))) {
  180. debug = atoi(env_debug);
  181. if (debug > 0) {
  182. fprintf(stderr, "Toolchain wrapper executing:");
  183. for (i = 0; args[i]; i++)
  184. fprintf(stderr, "%s'%s'",
  185. (debug == 2) ? "\n " : " ", args[i]);
  186. fprintf(stderr, "\n");
  187. }
  188. }
  189. if (execv(path, args))
  190. perror(path);
  191. free(args);
  192. return 2;
  193. }