configure.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597
  1. /****************************************************************************
  2. * tools/configure.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <sys/stat.h>
  24. #include <stdint.h>
  25. #include <stdbool.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <stdarg.h>
  29. #include <unistd.h>
  30. #include <fcntl.h>
  31. #include <string.h>
  32. #include <dirent.h>
  33. #include <libgen.h>
  34. #include <errno.h>
  35. #include "cfgparser.h"
  36. /****************************************************************************
  37. * Pre-processor Definitions
  38. ****************************************************************************/
  39. #define BUFFER_SIZE 1024
  40. #ifdef WIN32
  41. # define strndup(x, y) strdup(x)
  42. #endif
  43. #define HOST_NOCHANGE 0
  44. #define HOST_LINUX 1
  45. #define HOST_MACOS 2
  46. #define HOST_WINDOWS 3
  47. #define WINDOWS_NATIVE 1
  48. #define WINDOWS_CYGWIN 2
  49. #define WINDOWS_MSYS 3
  50. /****************************************************************************
  51. * Private Function Prototypes
  52. ****************************************************************************/
  53. static void show_usage(const char *progname, int exitcode);
  54. static void dumpcfgs(void);
  55. static void debug(const char *fmt, ...);
  56. static void parse_args(int argc, char **argv);
  57. static int run_make(const char *arg);
  58. static bool filecmp(const char *f1, const char *f2);
  59. static bool check_directory(const char *directory);
  60. static void verify_directory(const char *directory);
  61. static bool verify_optiondir(const char *directory);
  62. static bool verify_file(const char *path);
  63. static void find_topdir(void);
  64. typedef void (*config_callback)(const char *boarddir, const char *archname,
  65. const char *chipname, const char *boardname,
  66. const char *configname, void *data);
  67. static void config_search(const char *boarddir,
  68. config_callback callback, void *data);
  69. static void archname_callback(const char *boarddir, const char *archname,
  70. const char *chipname, const char *boardname,
  71. const char *configname, void *data);
  72. static void find_archname(void);
  73. static void enumerate_callback(const char *boarddir, const char *archname,
  74. const char *chipname, const char *boardname,
  75. const char *configname, void *data);
  76. static void enumerate_configs(void);
  77. static void check_configdir(void);
  78. static void check_configured(void);
  79. static void read_configfile(void);
  80. static void read_versionfile(void);
  81. static void get_verstring(void);
  82. static bool verify_appdir(const char *appdir);
  83. static void check_appdir(void);
  84. static void check_configuration(void);
  85. static void copy_file(const char *srcpath,
  86. const char *destpath, mode_t mode);
  87. static void substitute(char *str, int ch1, int ch2);
  88. static char *double_appdir_backslashes(char *old_appdir);
  89. static void copy_optional(void);
  90. static void enable_feature(const char *destconfig, const char *varname);
  91. static void disable_feature(const char *destconfig, const char *varname);
  92. static void set_host(const char *destconfig);
  93. static void configure(void);
  94. static void refresh(void);
  95. /****************************************************************************
  96. * Private Data
  97. ****************************************************************************/
  98. #ifdef CONFIG_WINDOWS_NATIVE
  99. static char g_delim = '\\'; /* Delimiter to use when forming paths */
  100. static bool g_winpaths = true; /* True: Windows style paths */
  101. #else
  102. static char g_delim = '/'; /* Delimiter to use when forming paths */
  103. static bool g_winpaths = false; /* False: POSIX style paths */
  104. #endif
  105. static bool g_debug = false; /* Enable debug output */
  106. static bool g_enforce = false; /* Enfore distclean */
  107. static bool g_distclean = false; /* Distclean if configured */
  108. static const char *g_appdir = NULL; /* Relative path to the application directory */
  109. static const char *g_archdir = NULL; /* Name of architecture subdirectory */
  110. static const char *g_chipdir = NULL; /* Name of chip subdirectory */
  111. static const char *g_boarddir = NULL; /* Name of board subdirectory */
  112. static char *g_configdir = NULL; /* Name of configuration subdirectory */
  113. static char *g_topdir = NULL; /* Full path to top-level NuttX build directory */
  114. static char *g_apppath = NULL; /* Full path to the application directory */
  115. static char *g_configtop = NULL; /* Full path to the top-level configuration directory */
  116. static char *g_configpath = NULL; /* Full path to the configuration sub-directory */
  117. static char *g_scriptspath = NULL; /* Full path to the scripts sub-directory */
  118. static char *g_verstring = "0.0"; /* Version String */
  119. static char *g_srcdefconfig = NULL; /* Source defconfig file */
  120. static char *g_srcmakedefs = NULL; /* Source Make.defs file */
  121. static char **g_makeargv = NULL; /* Arguments pass to make */
  122. static bool g_winnative = false; /* True: Windows native configuration */
  123. static bool g_oldnative = false; /* True: Was Windows native configuration */
  124. static bool g_needapppath = true; /* Need to add app path to the .config file */
  125. static uint8_t g_host = HOST_NOCHANGE;
  126. static uint8_t g_windows = WINDOWS_CYGWIN;
  127. static char g_buffer[BUFFER_SIZE]; /* Scratch buffer for forming full paths */
  128. static struct variable_s *g_configvars = NULL;
  129. static struct variable_s *g_versionvars = NULL;
  130. /* Optional configuration files */
  131. static const char *g_optfiles[] =
  132. {
  133. ".gdbinit",
  134. ".cproject",
  135. ".project"
  136. };
  137. #define N_OPTFILES (sizeof(g_optfiles) / sizeof(const char *))
  138. /****************************************************************************
  139. * Private Functions
  140. ****************************************************************************/
  141. static void show_usage(const char *progname, int exitcode)
  142. {
  143. fprintf(stderr, "\nUSAGE: %s [-d] [-E] [-e] [-b|f] [-L] [-l|m|c|g|n] "
  144. "[-a <app-dir>] <board-name>:<config-name> [make-opts]\n",
  145. progname);
  146. fprintf(stderr, "\nUSAGE: %s [-h]\n", progname);
  147. fprintf(stderr, "\nWhere:\n");
  148. fprintf(stderr, " -d:\n");
  149. fprintf(stderr, " Enables debug output\n");
  150. fprintf(stderr, " -E:\n");
  151. fprintf(stderr, " Enforce distclean if already configured\n");
  152. fprintf(stderr, " -e:\n");
  153. fprintf(stderr, " Performs distclean if configuration changed\n");
  154. fprintf(stderr, " -b:\n");
  155. #ifdef CONFIG_WINDOWS_NATIVE
  156. fprintf(stderr, " Informs the tool that it should use Windows style\n");
  157. fprintf(stderr, " paths like C:\\Program Files instead of POSIX\n");
  158. fprintf(stderr, " style paths are used like /usr/local/bin. Windows\n");
  159. fprintf(stderr, " style paths are used by default.\n");
  160. #else
  161. fprintf(stderr, " Informs the tool that it should use Windows style\n");
  162. fprintf(stderr, " paths like C:\\Program Files. By default, POSIX\n");
  163. fprintf(stderr, " style paths like /usr/local/bin are used.\n");
  164. #endif
  165. fprintf(stderr, " -f:\n");
  166. #ifdef CONFIG_WINDOWS_NATIVE
  167. fprintf(stderr, " Informs the tool that it should use POSIX style\n");
  168. fprintf(stderr, " paths like /usr/local/bin. By default, Windows\n");
  169. fprintf(stderr, " style paths like C:\\Program Files are used.\n");
  170. #else
  171. fprintf(stderr, " Informs the tool that it should use POSIX style\n");
  172. fprintf(stderr, " paths like /usr/local/bin instead of Windows\n");
  173. fprintf(stderr, " style paths like C:\\Program Files are used.\n");
  174. fprintf(stderr, " POSIX style paths are used by default.\n");
  175. #endif
  176. fprintf(stderr, " [-l|m|c|g|n]\n");
  177. fprintf(stderr, " Selects the host environment.\n");
  178. fprintf(stderr, " -l Selects the Linux (l) host environment.\n");
  179. fprintf(stderr, " -m Selects the macOS (m) host environment.\n");
  180. fprintf(stderr, " -c Selects the Windows Cygwin (c) environment.\n");
  181. fprintf(stderr, " -g Selects the Windows MinGW/MSYS environment.\n");
  182. fprintf(stderr, " -n Selects the Windows native (n) environment.\n");
  183. fprintf(stderr, " Default: Use host setup in the defconfig file.\n");
  184. fprintf(stderr, " Default Windows: Cygwin.\n");
  185. fprintf(stderr, " -L:\n");
  186. fprintf(stderr, " Lists all available configurations.\n");
  187. fprintf(stderr, " -a <app-dir>:\n");
  188. fprintf(stderr, " Informs the configuration tool where the\n");
  189. fprintf(stderr, " application build directory. This is a relative\n");
  190. fprintf(stderr, " path from the top-level NuttX build directory.\n");
  191. fprintf(stderr, " But default, this tool will look in the usual\n");
  192. fprintf(stderr, " places to locate the application directory:\n");
  193. fprintf(stderr, " ..%capps or\n", g_delim);
  194. fprintf(stderr, " ..%capps-xx.yy where xx.yy is the version number.\n",
  195. g_delim);
  196. fprintf(stderr, " <board-name>:\n");
  197. fprintf(stderr, " Identifies the board. This must correspond to a\n");
  198. fprintf(stderr, " board directory under nuttx%cboards%c.\n",
  199. g_delim, g_delim);
  200. fprintf(stderr, " <config-name>:\n");
  201. fprintf(stderr, " Identifies the specific configuration for the\n");
  202. fprintf(stderr, " selected <board-name>. This must correspond to\n");
  203. fprintf(stderr, " a sub-directory under the board directory at\n");
  204. fprintf(stderr, " under nuttx%cboards%c<board-name>%cconfigs%c.\n",
  205. g_delim, g_delim, g_delim, g_delim);
  206. fprintf(stderr, " [make-opts]:\n");
  207. fprintf(stderr, " Options directly pass to make\n");
  208. fprintf(stderr, " -h:\n");
  209. fprintf(stderr, " Prints this message and exits.\n");
  210. exit(exitcode);
  211. }
  212. static void dumpcfgs(void)
  213. {
  214. find_topdir();
  215. snprintf(g_buffer, BUFFER_SIZE, "%s%cboards", g_topdir, g_delim);
  216. verify_directory(g_buffer);
  217. g_configtop = strdup(g_buffer);
  218. enumerate_configs();
  219. free(g_configtop);
  220. exit(EXIT_SUCCESS);
  221. }
  222. static void debug(const char *fmt, ...)
  223. {
  224. va_list ap;
  225. if (g_debug)
  226. {
  227. va_start(ap, fmt);
  228. vprintf(fmt, ap);
  229. va_end(ap);
  230. }
  231. }
  232. static void parse_args(int argc, char **argv)
  233. {
  234. char *ptr;
  235. int ch;
  236. /* Parse command line options */
  237. while ((ch = getopt(argc, argv, "a:bcdEefghLlmnu")) > 0)
  238. {
  239. switch (ch)
  240. {
  241. case 'a' :
  242. g_appdir = optarg;
  243. break;
  244. case 'b' :
  245. g_delim = '\\';
  246. g_winpaths = false;
  247. break;
  248. case 'c' :
  249. g_host = HOST_WINDOWS;
  250. g_windows = WINDOWS_CYGWIN;
  251. break;
  252. case 'd' :
  253. g_debug = true;
  254. break;
  255. case 'E' :
  256. g_enforce = true;
  257. break;
  258. case 'e' :
  259. g_distclean = true;
  260. break;
  261. case 'f' :
  262. g_delim = '/';
  263. g_winpaths = true;
  264. break;
  265. case 'g' :
  266. g_host = HOST_WINDOWS;
  267. g_windows = WINDOWS_MSYS;
  268. break;
  269. case 'h' :
  270. show_usage(argv[0], EXIT_SUCCESS);
  271. case 'L' :
  272. dumpcfgs();
  273. case 'l' :
  274. g_host = HOST_LINUX;
  275. break;
  276. case 'm' :
  277. g_host = HOST_MACOS;
  278. break;
  279. case 'n' :
  280. g_host = HOST_WINDOWS;
  281. g_windows = WINDOWS_NATIVE;
  282. break;
  283. case '?' :
  284. fprintf(stderr, "ERROR: Unrecognized option: %c\n", optopt);
  285. show_usage(argv[0], EXIT_FAILURE);
  286. case ':' :
  287. fprintf(stderr, "ERROR: Missing option argument, option: %c\n",
  288. optopt);
  289. show_usage(argv[0], EXIT_FAILURE);
  290. default:
  291. fprintf(stderr, "ERROR: Unexpected option: %c\n", ch);
  292. show_usage(argv[0], EXIT_FAILURE);
  293. }
  294. }
  295. /* There should be exactly one argument following the options */
  296. if (optind >= argc)
  297. {
  298. fprintf(stderr, "ERROR: Missing <board-name>:<config-name>\n");
  299. show_usage(argv[0], EXIT_FAILURE);
  300. }
  301. /* The required option should be the board directory name and the
  302. * configuration directory name separated by ':', '/' or '\'. Any are
  303. * acceptable in this context. Or using the custom board relative or
  304. * absolute path directly here.
  305. */
  306. g_boarddir = argv[optind];
  307. optind++;
  308. if (!verify_optiondir(g_boarddir))
  309. {
  310. ptr = strchr(g_boarddir, ':');
  311. if (ptr == NULL)
  312. {
  313. ptr = strchr(g_boarddir, '/');
  314. if (!ptr)
  315. {
  316. ptr = strchr(g_boarddir, '\\');
  317. }
  318. }
  319. if (ptr == NULL)
  320. {
  321. fprintf(stderr, "ERROR: Invalid <board-name>:<config-name>\n");
  322. show_usage(argv[0], EXIT_FAILURE);
  323. }
  324. *ptr++ = '\0';
  325. g_configdir = ptr;
  326. }
  327. else
  328. {
  329. /* custom board case with relative or absolute path */
  330. g_configpath = strdup(g_boarddir);
  331. }
  332. /* The left arguments will pass to make */
  333. g_makeargv = &argv[optind];
  334. }
  335. static int run_make(const char *arg)
  336. {
  337. char **argv;
  338. snprintf(g_buffer, BUFFER_SIZE, "make %s", arg);
  339. for (argv = g_makeargv; *argv; argv++)
  340. {
  341. strncat(g_buffer, " ", BUFFER_SIZE - 1);
  342. strncat(g_buffer, *argv, BUFFER_SIZE - 1);
  343. }
  344. return system(g_buffer);
  345. }
  346. static bool filecmp(const char *f1, const char *f2)
  347. {
  348. FILE *stream1;
  349. FILE *stream2;
  350. char ch1;
  351. char ch2;
  352. stream1 = fopen(f1, "r");
  353. stream2 = fopen(f2, "r");
  354. if (stream1 == NULL || stream2 == NULL)
  355. {
  356. return false;
  357. }
  358. do
  359. {
  360. ch1 = fgetc(stream1);
  361. ch2 = fgetc(stream2);
  362. if (ch1 != ch2)
  363. {
  364. return false;
  365. }
  366. }
  367. while (ch1 != EOF && ch2 != EOF);
  368. fclose(stream1);
  369. fclose(stream2);
  370. return true;
  371. }
  372. static bool check_directory(const char *directory)
  373. {
  374. struct stat buf;
  375. if (stat(directory, &buf) < 0)
  376. {
  377. debug("stat of %s failed: %s\n", directory, strerror(errno));
  378. return false;
  379. }
  380. if (!S_ISDIR(buf.st_mode))
  381. {
  382. debug("%s exists but is not a directory\n", directory);
  383. return false;
  384. }
  385. return true;
  386. }
  387. static void verify_directory(const char *directory)
  388. {
  389. struct stat buf;
  390. if (stat(directory, &buf) < 0)
  391. {
  392. fprintf(stderr, "ERROR: stat of %s failed: %s\n",
  393. directory, strerror(errno));
  394. exit(EXIT_FAILURE);
  395. }
  396. if (!S_ISDIR(buf.st_mode))
  397. {
  398. fprintf(stderr, "ERROR: %s exists but is not a directory\n",
  399. directory);
  400. exit(EXIT_FAILURE);
  401. }
  402. }
  403. static bool verify_optiondir(const char *directory)
  404. {
  405. struct stat buf;
  406. if (stat(directory, &buf) < 0)
  407. {
  408. /* It may be okay if the directory does not exist */
  409. /* It may be okay if the file does not exist */
  410. int errcode = errno;
  411. if (errcode == ENOENT)
  412. {
  413. debug("verify_optiondir: stat of %s failed: %s\n",
  414. directory, strerror(errno));
  415. return false;
  416. }
  417. else
  418. {
  419. fprintf(stderr, "ERROR: stat of %s failed: %s\n",
  420. directory, strerror(errno));
  421. exit(EXIT_FAILURE);
  422. }
  423. }
  424. if (!S_ISDIR(buf.st_mode))
  425. {
  426. fprintf(stderr, "ERROR: %s exists but is not a directory\n",
  427. directory);
  428. exit(EXIT_FAILURE);
  429. }
  430. return true;
  431. }
  432. static bool verify_file(const char *path)
  433. {
  434. struct stat buf;
  435. if (stat(path, &buf) < 0)
  436. {
  437. /* It may be okay if the file does not exist */
  438. int errcode = errno;
  439. if (errcode == ENOENT)
  440. {
  441. debug("verify_file: stat of %s failed: %s\n",
  442. path, strerror(errno));
  443. return false;
  444. }
  445. else
  446. {
  447. fprintf(stderr, "ERROR: stat of %s failed: %s\n",
  448. path, strerror(errno));
  449. exit(EXIT_FAILURE);
  450. }
  451. }
  452. if (!S_ISREG(buf.st_mode))
  453. {
  454. fprintf(stderr, "ERROR: %s exists but is not a regular file\n", path);
  455. exit(EXIT_FAILURE);
  456. }
  457. return true;
  458. }
  459. static void find_topdir(void)
  460. {
  461. char *currdir;
  462. /* Get and verify the top-level NuttX directory */
  463. /* First get the current directory. We expect this to be either
  464. * the nuttx root directory or the tools subdirectory.
  465. */
  466. if (getcwd(g_buffer, BUFFER_SIZE) == NULL)
  467. {
  468. fprintf(stderr, "ERROR: getcwd failed: %s\n", strerror(errno));
  469. exit(EXIT_FAILURE);
  470. }
  471. /* Assume that we are in the tools sub-directory and the directory above
  472. * is the nuttx root directory.
  473. */
  474. currdir = strdup(g_buffer);
  475. g_topdir = strdup(dirname(g_buffer));
  476. debug("get_topdir: Checking parent directory: %s\n", g_topdir);
  477. verify_directory(g_topdir);
  478. /* Check if the current directory is the nuttx root directory.
  479. * If so, then the tools directory should be a sub-directory.
  480. */
  481. snprintf(g_buffer, BUFFER_SIZE, "%s%ctools", currdir, g_delim);
  482. debug("get_topdir: Checking topdir/tools=%s\n", g_buffer);
  483. if (check_directory(g_buffer))
  484. {
  485. /* There is a tools sub-directory under the current directory.
  486. * We must have already been in the nuttx root directory. We
  487. * will find out for sure in later tests.
  488. */
  489. free(g_topdir);
  490. g_topdir = currdir;
  491. }
  492. else
  493. {
  494. /* Yes, we are probably in the tools/ sub-directory */
  495. free(currdir);
  496. if (chdir(g_topdir) < 0)
  497. {
  498. fprintf(stderr, "ERROR: Failed to ch to %s\n", g_topdir);
  499. exit(EXIT_FAILURE);
  500. }
  501. }
  502. }
  503. static void config_search(const char *boarddir,
  504. config_callback callback, void *data)
  505. {
  506. DIR *dir;
  507. struct dirent *dp;
  508. struct stat buf;
  509. char *parent;
  510. char *child;
  511. /* Skip over any leading '/' or '\\'. This happens on the first second
  512. * call because the starting boarddir is ""
  513. */
  514. if (boarddir[0] == g_delim)
  515. {
  516. boarddir++;
  517. }
  518. /* Get the full directory path and open it */
  519. snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_configtop, g_delim, boarddir);
  520. dir = opendir(g_buffer);
  521. if (!dir)
  522. {
  523. fprintf(stderr, "ERROR: Could not open %s: %s\n",
  524. g_buffer, strerror(errno));
  525. return;
  526. }
  527. /* Make a copy of the path to the directory */
  528. parent = strdup(g_buffer);
  529. /* Visit each entry in the directory */
  530. while ((dp = readdir(dir)) != NULL)
  531. {
  532. /* Ignore directory entries that start with '.' */
  533. if (dp->d_name[0] == '.')
  534. {
  535. continue;
  536. }
  537. /* Get a properly terminated copy of d_name (if d_name is long it may
  538. * not include a NUL terminator.
  539. */
  540. child = strndup(dp->d_name, NAME_MAX);
  541. /* Get the full path to d_name and stat the file/directory */
  542. snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", parent, g_delim, child);
  543. if (stat(g_buffer, &buf) < 0)
  544. {
  545. fprintf(stderr, "ERROR: stat of %s failed: %s\n",
  546. g_buffer, strerror(errno));
  547. free(child);
  548. continue;
  549. }
  550. /* If it is a directory, then recurse */
  551. if (S_ISDIR(buf.st_mode))
  552. {
  553. char *tmppath;
  554. snprintf(g_buffer, BUFFER_SIZE, "%s%c%s",
  555. boarddir, g_delim, child);
  556. tmppath = strdup(g_buffer);
  557. config_search(tmppath, callback, data);
  558. free(tmppath);
  559. }
  560. /* If it is a regular file named 'defconfig' then we have found a
  561. * configuration directory. We could terminate the search in this case
  562. * because we do not expect sub-directories within configuration
  563. * directories.
  564. */
  565. else if (S_ISREG(buf.st_mode) && strcmp("defconfig", child) == 0)
  566. {
  567. char *archname;
  568. char *chipname;
  569. char *boardname;
  570. char *configname;
  571. char *delim;
  572. /* Get the board directory near the beginning of the 'boarddir':
  573. * <archdir>/<chipdir>/<boarddir>/configs/<configdir>
  574. */
  575. /* Make a modifiable copy */
  576. strncpy(g_buffer, boarddir, BUFFER_SIZE - 1);
  577. /* Save the <archdir> */
  578. archname = g_buffer;
  579. delim = strchr(g_buffer, g_delim);
  580. if (delim == NULL)
  581. {
  582. debug("ERROR: delimiter not found in path: %s\n", boarddir);
  583. }
  584. else
  585. {
  586. /* Save the <chipdir> */
  587. *delim = '\0';
  588. chipname = delim + 1;
  589. delim = strchr(chipname, g_delim);
  590. if (delim == NULL)
  591. {
  592. debug("ERROR: delimiter not found in path: %s\n",
  593. chipname);
  594. }
  595. else
  596. {
  597. /* Save the <boardir> */
  598. *delim = '\0';
  599. boardname = delim + 1;
  600. delim = strchr(boardname, g_delim);
  601. if (delim == NULL)
  602. {
  603. debug("ERROR: delimiter not found in path: %s\n",
  604. boardname);
  605. }
  606. else
  607. {
  608. /* Save the <configdir> */
  609. *delim = '\0';
  610. delim = strrchr(delim + 1, g_delim);
  611. if (delim == NULL)
  612. {
  613. debug("ERROR: directory not found in path: %s\n",
  614. boardname);
  615. }
  616. else
  617. {
  618. configname = delim + 1;
  619. callback(boarddir, archname, chipname,
  620. boardname, configname, data);
  621. }
  622. }
  623. }
  624. }
  625. }
  626. free(child);
  627. }
  628. free(parent);
  629. closedir(dir);
  630. }
  631. static void archname_callback(const char *boarddir, const char *archname,
  632. const char *chipname, const char *boardname,
  633. const char *configname, void *data)
  634. {
  635. if (strcmp(g_boarddir, boardname) == 0 &&
  636. strcmp(g_configdir, configname) == 0)
  637. {
  638. g_archdir = strdup(archname);
  639. g_chipdir = strdup(chipname);
  640. }
  641. }
  642. static void find_archname(void)
  643. {
  644. config_search("", archname_callback, NULL);
  645. if (g_archdir == NULL || g_chipdir == NULL)
  646. {
  647. g_archdir = "unknown";
  648. g_chipdir = "unknown";
  649. }
  650. }
  651. static void enumerate_callback(const char *boarddir, const char *archname,
  652. const char *chipname, const char *boardname,
  653. const char *configname, void *data)
  654. {
  655. fprintf(stderr, " %s:%s\n", boardname, configname);
  656. }
  657. static void enumerate_configs(void)
  658. {
  659. fprintf(stderr, "Options for <board-name>:<config-name> include:\n\n");
  660. config_search("", enumerate_callback, NULL);
  661. }
  662. static void check_configdir(void)
  663. {
  664. if (verify_optiondir(g_configpath))
  665. {
  666. /* Get the path to the custom board scripts directory */
  667. snprintf(g_buffer, BUFFER_SIZE, "%s%c..%c..%cscripts",
  668. g_configpath, g_delim, g_delim, g_delim);
  669. if (verify_optiondir(g_buffer))
  670. {
  671. g_scriptspath = strdup(g_buffer);
  672. }
  673. }
  674. else
  675. {
  676. /* Get the path to the top level configuration directory: boards/ */
  677. snprintf(g_buffer, BUFFER_SIZE, "%s%cboards", g_topdir, g_delim);
  678. debug("check_configdir: Checking configtop=%s\n", g_buffer);
  679. verify_directory(g_buffer);
  680. g_configtop = strdup(g_buffer);
  681. /* Get and verify the path to the selected configuration:
  682. * boards/<archdir>/<chipdir>/<boarddir>/configs/<configdir>
  683. */
  684. find_archname();
  685. snprintf(g_buffer, BUFFER_SIZE, "%s%cboards%c%s%c%s%c%s%cconfigs%c%s",
  686. g_topdir, g_delim, g_delim, g_archdir, g_delim, g_chipdir,
  687. g_delim, g_boarddir, g_delim, g_delim, g_configdir);
  688. debug("check_configdir: Checking configpath=%s\n", g_buffer);
  689. if (!verify_optiondir(g_buffer))
  690. {
  691. fprintf(stderr, "ERROR: No configuration at %s\n", g_buffer);
  692. fprintf(stderr, "Run tools/configure -L"
  693. " to list available configurations.\n");
  694. exit(EXIT_FAILURE);
  695. }
  696. g_configpath = strdup(g_buffer);
  697. /* Get and verify the path to the scripts directory:
  698. * boards/<archdir>/<chipdir>/<boarddir>/scripts
  699. */
  700. snprintf(g_buffer, BUFFER_SIZE, "%s%cboards%c%s%c%s%c%s%cscripts",
  701. g_topdir, g_delim, g_delim, g_archdir, g_delim,
  702. g_chipdir, g_delim, g_boarddir, g_delim);
  703. debug("check_configdir: Checking scriptspath=%s\n", g_buffer);
  704. g_scriptspath = NULL;
  705. if (verify_optiondir(g_buffer))
  706. {
  707. g_scriptspath = strdup(g_buffer);
  708. }
  709. }
  710. }
  711. static void check_configured(void)
  712. {
  713. /* If we are already configured then there will be a .config and
  714. * a Make.defs file in the top-level directory.
  715. */
  716. snprintf(g_buffer, BUFFER_SIZE, "%s%c.config", g_topdir, g_delim);
  717. debug("check_configured: Checking %s\n", g_buffer);
  718. if (!verify_file(g_buffer))
  719. {
  720. return;
  721. }
  722. if (g_enforce)
  723. {
  724. run_make("distclean");
  725. }
  726. else
  727. {
  728. char *defcfgpath = NULL;
  729. snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig",
  730. g_configpath, g_delim);
  731. defcfgpath = strdup(g_buffer);
  732. snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig",
  733. g_topdir, g_delim);
  734. if (filecmp(g_buffer, defcfgpath))
  735. {
  736. fprintf(stderr, "No configuration change.\n");
  737. free(defcfgpath);
  738. exit(EXIT_SUCCESS);
  739. }
  740. else
  741. {
  742. free(defcfgpath);
  743. if (g_distclean)
  744. {
  745. run_make("distclean");
  746. }
  747. else
  748. {
  749. fprintf(stderr, "Already configured!\n");
  750. fprintf(stderr, "Please 'make distclean' and try again.\n");
  751. exit(EXIT_FAILURE);
  752. }
  753. }
  754. }
  755. }
  756. static void read_configfile(void)
  757. {
  758. FILE *stream;
  759. snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_configpath, g_delim);
  760. stream = fopen(g_buffer, "r");
  761. if (!stream)
  762. {
  763. fprintf(stderr, "ERROR: failed to open %s for reading: %s\n",
  764. g_buffer, strerror(errno));
  765. exit(EXIT_FAILURE);
  766. }
  767. parse_file(stream, &g_configvars);
  768. fclose(stream);
  769. }
  770. static void read_versionfile(void)
  771. {
  772. FILE *stream;
  773. snprintf(g_buffer, BUFFER_SIZE, "%s%c.version", g_topdir, g_delim);
  774. stream = fopen(g_buffer, "r");
  775. if (!stream)
  776. {
  777. /* It may not be an error if there is no .version file */
  778. debug("Failed to open %s for reading: %s\n",
  779. g_buffer, strerror(errno));
  780. }
  781. else
  782. {
  783. parse_file(stream, &g_versionvars);
  784. fclose(stream);
  785. }
  786. }
  787. static void get_verstring(void)
  788. {
  789. struct variable_s *var;
  790. if (g_versionvars)
  791. {
  792. var = find_variable("CONFIG_VERSION_STRING", g_versionvars);
  793. if (var && var->val)
  794. {
  795. g_verstring = strdup(var->val);
  796. }
  797. }
  798. debug("get_verstring: Version string=%s\n", g_verstring);
  799. }
  800. static bool verify_appdir(const char *appdir)
  801. {
  802. /* Does this directory exist? */
  803. snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_topdir, g_delim, appdir);
  804. debug("verify_appdir: Checking apppath=%s\n", g_buffer);
  805. if (verify_optiondir(g_buffer))
  806. {
  807. /* Yes.. Use this application directory path */
  808. g_appdir = strdup(appdir);
  809. g_apppath = strdup(g_buffer);
  810. return true;
  811. }
  812. debug("verify_appdir: apppath=%s does not exist\n", g_buffer);
  813. return false;
  814. }
  815. static void check_appdir(void)
  816. {
  817. char tmp[16];
  818. /* Get and verify the full path to the application directory */
  819. /* Was the appdir provided on the command line? */
  820. debug("check_appdir: Command line appdir=%s\n",
  821. g_appdir ? g_appdir : "<null>");
  822. if (!g_appdir)
  823. {
  824. /* If no application directory was provided on the command line and we
  825. * are switching between a windows native host and some other host then
  826. * ignore any path to the apps/ directory in the defconfig file. It
  827. * will most certainly not be in a usable form.
  828. */
  829. if (g_winnative == g_oldnative)
  830. {
  831. /* No, was the path provided in the configuration? */
  832. struct variable_s *var =
  833. find_variable("CONFIG_APPS_DIR", g_configvars);
  834. if (var != NULL)
  835. {
  836. debug("check_appdir: Config file appdir=%s\n",
  837. var->val ? var->val : "<null>");
  838. /* Yes.. does this directory exist? */
  839. if (var->val && verify_appdir(var->val))
  840. {
  841. /* We are using the CONFIG_APPS_DIR setting already in the
  842. * defconfig file.
  843. */
  844. g_needapppath = false;
  845. return;
  846. }
  847. }
  848. }
  849. /* Now try some canned locations */
  850. /* Try ../apps-xx.yy where xx.yy is the version string */
  851. snprintf(tmp, 16, "..%capps-%s", g_delim, g_verstring);
  852. debug("check_appdir: Try appdir=%s\n", tmp);
  853. if (verify_appdir(tmp))
  854. {
  855. return;
  856. }
  857. /* Try ../apps with no version */
  858. snprintf(tmp, 16, "..%capps", g_delim);
  859. debug("check_appdir: Try appdir=%s\n", tmp);
  860. if (verify_appdir(tmp))
  861. {
  862. return;
  863. }
  864. /* Try ../apps-xx.yy where xx.yy are the NuttX version number */
  865. fprintf(stderr, "ERROR: Could not find the path to the appdir\n");
  866. exit(EXIT_FAILURE);
  867. }
  868. else if (!verify_appdir(g_appdir))
  869. {
  870. fprintf(stderr, "ERROR: Command line path to appdir does not exist\n");
  871. exit(EXIT_FAILURE);
  872. }
  873. }
  874. static void check_configuration(void)
  875. {
  876. struct variable_s *var;
  877. /* Check if this is a Windows native configuration */
  878. var = find_variable("CONFIG_WINDOWS_NATIVE", g_configvars);
  879. if (var && var->val && strcmp("y", var->val) == 0)
  880. {
  881. debug("check_configuration: Windows native configuration\n");
  882. g_oldnative = true;
  883. }
  884. /* If we are going to some host other than windows native or to a windows
  885. * native host, then don't ignore what is in the defconfig file.
  886. */
  887. if (g_host == HOST_NOCHANGE)
  888. {
  889. /* Use whatever we found in the configuration file */
  890. g_winnative = g_oldnative;
  891. }
  892. else if (g_host == HOST_WINDOWS && g_windows == WINDOWS_NATIVE)
  893. {
  894. /* The new configuration is windows native */
  895. g_winnative = true;
  896. }
  897. /* All configurations must provide a defconfig and Make.defs file */
  898. snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_configpath, g_delim);
  899. debug("check_configuration: Checking %s\n", g_buffer);
  900. if (!verify_file(g_buffer))
  901. {
  902. fprintf(stderr, "ERROR: No configuration in %s\n", g_configpath);
  903. fprintf(stderr, " No defconfig file found.\n");
  904. fprintf(stderr, "Run tools/configure -L"
  905. " to list available configurations.\n");
  906. exit(EXIT_FAILURE);
  907. }
  908. g_srcdefconfig = strdup(g_buffer);
  909. /* Try the Make.defs file */
  910. snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs", g_configpath, g_delim);
  911. debug("check_configuration: Checking %s\n", g_buffer);
  912. if (!verify_file(g_buffer))
  913. {
  914. /* An alternative location is the scripts/ directory */
  915. if (g_scriptspath != NULL)
  916. {
  917. snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs",
  918. g_scriptspath, g_delim);
  919. debug("check_configuration: Checking %s\n", g_buffer);
  920. if (!verify_file(g_buffer))
  921. {
  922. fprintf(stderr, "ERROR: No Make.defs file in %s\n",
  923. g_configpath);
  924. fprintf(stderr, " No Make.defs file in %s\n",
  925. g_scriptspath);
  926. fprintf(stderr, "Run tools/configure -L"
  927. " to list available configurations.\n");
  928. exit(EXIT_FAILURE);
  929. }
  930. }
  931. else
  932. {
  933. fprintf(stderr, "ERROR: No Make.defs file in %s\n", g_configpath);
  934. fprintf(stderr, "Run tools/configure -L"
  935. " to list available configurations.\n");
  936. exit(EXIT_FAILURE);
  937. }
  938. }
  939. g_srcmakedefs = strdup(g_buffer);
  940. }
  941. static void copy_file(const char *srcpath,
  942. const char *destpath, mode_t mode)
  943. {
  944. int nbytesread;
  945. int nbyteswritten;
  946. int rdfd;
  947. int wrfd;
  948. /* Open the source file for reading */
  949. rdfd = open(srcpath, O_RDONLY);
  950. if (rdfd < 0)
  951. {
  952. fprintf(stderr, "ERROR: Failed to open %s for reading: %s\n",
  953. srcpath, strerror(errno));
  954. exit(EXIT_FAILURE);
  955. }
  956. /* Now open the destination for writing */
  957. wrfd = open(destpath, O_WRONLY | O_CREAT | O_TRUNC, mode);
  958. if (wrfd < 0)
  959. {
  960. fprintf(stderr, "ERROR: Failed to open %s for writing: %s\n",
  961. destpath, strerror(errno));
  962. exit(EXIT_FAILURE);
  963. }
  964. /* Now copy the file */
  965. for (; ; )
  966. {
  967. do
  968. {
  969. nbytesread = read(rdfd, g_buffer, BUFFER_SIZE);
  970. if (nbytesread == 0)
  971. {
  972. /* End of file */
  973. close(rdfd);
  974. close(wrfd);
  975. return;
  976. }
  977. else if (nbytesread < 0)
  978. {
  979. /* EINTR is not an error (but will still stop the copy) */
  980. fprintf(stderr, "ERROR: Read failure: %s\n", strerror(errno));
  981. exit(EXIT_FAILURE);
  982. }
  983. }
  984. while (nbytesread <= 0);
  985. do
  986. {
  987. nbyteswritten = write(wrfd, g_buffer, nbytesread);
  988. if (nbyteswritten >= 0)
  989. {
  990. nbytesread -= nbyteswritten;
  991. }
  992. else
  993. {
  994. /* EINTR is not an error (but will still stop the copy) */
  995. fprintf(stderr, "ERROR: Write failure: %s\n", strerror(errno));
  996. exit(EXIT_FAILURE);
  997. }
  998. }
  999. while (nbytesread > 0);
  1000. }
  1001. }
  1002. static void substitute(char *str, int ch1, int ch2)
  1003. {
  1004. for (; *str; str++)
  1005. {
  1006. if (*str == ch1)
  1007. {
  1008. *str = ch2;
  1009. }
  1010. }
  1011. }
  1012. static char *double_appdir_backslashes(char *old_appdir)
  1013. {
  1014. char *new_appdir = NULL;
  1015. char *p_old = NULL;
  1016. char *p_new = NULL;
  1017. int oldlen = 0;
  1018. int occurrences = 0;
  1019. int alloclen = 0;
  1020. p_old = old_appdir;
  1021. while ((p_old = strchr(p_old, '\\')) != NULL)
  1022. {
  1023. occurrences++;
  1024. p_old++;
  1025. }
  1026. if (occurrences != 0)
  1027. {
  1028. oldlen = strlen(old_appdir);
  1029. alloclen = oldlen + occurrences + sizeof((char) '\0');
  1030. new_appdir = malloc(alloclen);
  1031. if (new_appdir != NULL)
  1032. {
  1033. p_old = old_appdir;
  1034. p_new = new_appdir;
  1035. while (oldlen)
  1036. {
  1037. if (*p_old != '\\')
  1038. {
  1039. *p_new++ = *p_old;
  1040. }
  1041. else
  1042. {
  1043. *p_new++ = '\\';
  1044. *p_new++ = '\\';
  1045. }
  1046. ++p_old;
  1047. --oldlen;
  1048. }
  1049. *p_new = '\0';
  1050. }
  1051. }
  1052. else
  1053. {
  1054. new_appdir = strdup(old_appdir);
  1055. }
  1056. return new_appdir;
  1057. }
  1058. static void copy_optional(void)
  1059. {
  1060. int i;
  1061. for (i = 0; i < N_OPTFILES; i++)
  1062. {
  1063. snprintf(g_buffer, BUFFER_SIZE, "%s%c%s",
  1064. g_configpath, g_delim, g_optfiles[i]);
  1065. if (verify_file(g_buffer))
  1066. {
  1067. char *optsrc = strdup(g_buffer);
  1068. snprintf(g_buffer, BUFFER_SIZE, "%s%c%s",
  1069. g_topdir, g_delim, g_optfiles[i]);
  1070. debug("copy_optional: Copying from %s to %s\n", optsrc, g_buffer);
  1071. copy_file(optsrc, g_buffer, 0644);
  1072. free(optsrc);
  1073. }
  1074. }
  1075. }
  1076. static void enable_feature(const char *destconfig, const char *varname)
  1077. {
  1078. int ret;
  1079. snprintf(g_buffer, BUFFER_SIZE,
  1080. "kconfig-tweak --file %s --enable %s",
  1081. destconfig, varname);
  1082. ret = system(g_buffer);
  1083. #ifdef WEXITSTATUS
  1084. if (ret < 0 || WEXITSTATUS(ret) != 0)
  1085. #else
  1086. if (ret < 0)
  1087. #endif
  1088. {
  1089. fprintf(stderr, "ERROR: Failed to enable %s\n", varname);
  1090. fprintf(stderr, " command: %s\n", g_buffer);
  1091. exit(EXIT_FAILURE);
  1092. }
  1093. }
  1094. static void disable_feature(const char *destconfig, const char *varname)
  1095. {
  1096. int ret;
  1097. snprintf(g_buffer, BUFFER_SIZE,
  1098. "kconfig-tweak --file %s --disable %s",
  1099. destconfig, varname);
  1100. ret = system(g_buffer);
  1101. #ifdef WEXITSTATUS
  1102. if (ret < 0 || WEXITSTATUS(ret) != 0)
  1103. #else
  1104. if (ret < 0)
  1105. #endif
  1106. {
  1107. fprintf(stderr, "ERROR: Failed to disable %s\n", varname);
  1108. fprintf(stderr, " command: %s\n", g_buffer);
  1109. exit(EXIT_FAILURE);
  1110. }
  1111. }
  1112. /* Select the host build development environment */
  1113. static void set_host(const char *destconfig)
  1114. {
  1115. switch (g_host)
  1116. {
  1117. case HOST_LINUX:
  1118. {
  1119. printf(" Select the Linux host\n");
  1120. enable_feature(destconfig, "CONFIG_HOST_LINUX");
  1121. disable_feature(destconfig, "CONFIG_HOST_WINDOWS");
  1122. disable_feature(destconfig, "CONFIG_HOST_MACOS");
  1123. disable_feature(destconfig, "CONFIG_WINDOWS_NATIVE");
  1124. disable_feature(destconfig, "CONFIG_WINDOWS_CYGWIN");
  1125. disable_feature(destconfig, "CONFIG_WINDOWS_MSYS");
  1126. disable_feature(destconfig, "CONFIG_WINDOWS_OTHER");
  1127. enable_feature(destconfig, "CONFIG_SIM_X8664_SYSTEMV");
  1128. disable_feature(destconfig, "CONFIG_SIM_X8664_MICROSOFT");
  1129. }
  1130. break;
  1131. case HOST_MACOS:
  1132. {
  1133. printf(" Select the macOS host\n");
  1134. disable_feature(destconfig, "CONFIG_HOST_LINUX");
  1135. disable_feature(destconfig, "CONFIG_HOST_WINDOWS");
  1136. enable_feature(destconfig, "CONFIG_HOST_MACOS");
  1137. disable_feature(destconfig, "CONFIG_WINDOWS_NATIVE");
  1138. disable_feature(destconfig, "CONFIG_WINDOWS_CYGWIN");
  1139. disable_feature(destconfig, "CONFIG_WINDOWS_MSYS");
  1140. disable_feature(destconfig, "CONFIG_WINDOWS_OTHER");
  1141. enable_feature(destconfig, "CONFIG_SIM_X8664_SYSTEMV");
  1142. disable_feature(destconfig, "CONFIG_SIM_X8664_MICROSOFT");
  1143. }
  1144. break;
  1145. case HOST_WINDOWS:
  1146. {
  1147. enable_feature(destconfig, "CONFIG_HOST_WINDOWS");
  1148. disable_feature(destconfig, "CONFIG_HOST_LINUX");
  1149. disable_feature(destconfig, "CONFIG_HOST_MACOS");
  1150. disable_feature(destconfig, "CONFIG_WINDOWS_OTHER");
  1151. enable_feature(destconfig, "CONFIG_SIM_X8664_MICROSOFT");
  1152. disable_feature(destconfig, "CONFIG_SIM_X8664_SYSTEMV");
  1153. switch (g_windows)
  1154. {
  1155. case WINDOWS_CYGWIN:
  1156. printf(" Select Windows/Cygwin host\n");
  1157. enable_feature(destconfig, "CONFIG_WINDOWS_CYGWIN");
  1158. disable_feature(destconfig, "CONFIG_WINDOWS_MSYS");
  1159. disable_feature(destconfig, "CONFIG_WINDOWS_NATIVE");
  1160. break;
  1161. case WINDOWS_MSYS:
  1162. printf(" Select Windows/MSYS host\n");
  1163. disable_feature(destconfig, "CONFIG_WINDOWS_CYGWIN");
  1164. enable_feature(destconfig, "CONFIG_WINDOWS_MSYS");
  1165. disable_feature(destconfig, "CONFIG_WINDOWS_NATIVE");
  1166. break;
  1167. case WINDOWS_NATIVE:
  1168. printf(" Select Windows native host\n");
  1169. disable_feature(destconfig, "CONFIG_WINDOWS_CYGWIN");
  1170. disable_feature(destconfig, "CONFIG_WINDOWS_MSYS");
  1171. enable_feature(destconfig, "CONFIG_WINDOWS_NATIVE");
  1172. break;
  1173. default:
  1174. fprintf(stderr,
  1175. "ERROR: Unrecognized windows configuration: %d\n",
  1176. g_windows);
  1177. exit(EXIT_FAILURE);
  1178. }
  1179. }
  1180. break;
  1181. case HOST_NOCHANGE:
  1182. break;
  1183. default:
  1184. {
  1185. fprintf(stderr, "ERROR: Unrecognized host configuration: %d\n",
  1186. g_host);
  1187. exit(EXIT_FAILURE);
  1188. }
  1189. }
  1190. }
  1191. static void configure(void)
  1192. {
  1193. char *destconfig;
  1194. /* Copy the defconfig to toplevel */
  1195. snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_topdir, g_delim);
  1196. copy_file(g_srcdefconfig, g_buffer, 0644);
  1197. /* Copy the defconfig file as .config */
  1198. snprintf(g_buffer, BUFFER_SIZE, "%s%c.config", g_topdir, g_delim);
  1199. destconfig = strdup(g_buffer);
  1200. debug("configure: Copying from %s to %s\n", g_srcdefconfig, destconfig);
  1201. copy_file(g_srcdefconfig, destconfig, 0644);
  1202. /* Copy the Make.defs file as Make.defs */
  1203. snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs", g_topdir, g_delim);
  1204. debug("configure: Copying from %s to %s\n", g_srcmakedefs, g_buffer);
  1205. copy_file(g_srcmakedefs, g_buffer, 0644);
  1206. /* Copy optional files */
  1207. copy_optional();
  1208. /* Select the host build development environment */
  1209. set_host(destconfig);
  1210. /* If we did not use the CONFIG_APPS_DIR that was in the defconfig config
  1211. * file, then append the correct application information to the tail of the
  1212. * .config file
  1213. */
  1214. if (g_needapppath)
  1215. {
  1216. FILE *stream;
  1217. char *appdir = strdup(g_appdir);
  1218. /* One complexity is if we are using Windows paths, but the
  1219. * configuration needs POSIX paths (or vice versa).
  1220. */
  1221. if (g_winpaths != g_winnative)
  1222. {
  1223. /* Not the same */
  1224. if (g_winpaths)
  1225. {
  1226. /* Using Windows paths, but the configuration wants POSIX
  1227. * paths.
  1228. */
  1229. substitute(appdir, '\\', '/');
  1230. }
  1231. else
  1232. {
  1233. /* Using POSIX paths, but the configuration wants Windows
  1234. * paths.
  1235. */
  1236. substitute(appdir, '/', '\\');
  1237. }
  1238. }
  1239. /* Looks like prebuilt winnative kconfig-conf interprets "..\apps" as
  1240. * "..apps" (possibly '\a' as escape-sequence) so expand winnative path
  1241. * to double-backslashed variant "..\\apps".
  1242. */
  1243. if (g_winnative)
  1244. {
  1245. char *tmp_appdir = double_appdir_backslashes(appdir);
  1246. if (NULL == tmp_appdir)
  1247. {
  1248. fprintf(stderr,
  1249. "ERROR: Failed to double appdir backslashes\n");
  1250. exit(EXIT_FAILURE);
  1251. }
  1252. free(appdir);
  1253. appdir = tmp_appdir;
  1254. }
  1255. /* Open the file for appending */
  1256. stream = fopen(destconfig, "a");
  1257. if (!stream)
  1258. {
  1259. fprintf(stderr,
  1260. "ERROR: Failed to open %s for append mode mode: %s\n",
  1261. destconfig, strerror(errno));
  1262. exit(EXIT_FAILURE);
  1263. }
  1264. fprintf(stream, "\n# Application configuration\n\n");
  1265. fprintf(stream, "CONFIG_APPS_DIR=\"%s\"\n", appdir);
  1266. fclose(stream);
  1267. free(appdir);
  1268. }
  1269. free(destconfig);
  1270. }
  1271. static void refresh(void)
  1272. {
  1273. int ret;
  1274. printf(" Refreshing...\n");
  1275. fflush(stdout);
  1276. ret = run_make("olddefconfig");
  1277. putchar('\n');
  1278. #ifdef WEXITSTATUS
  1279. if (ret < 0 || WEXITSTATUS(ret) != 0)
  1280. #else
  1281. if (ret < 0)
  1282. #endif
  1283. {
  1284. fprintf(stderr, "ERROR: Failed to refresh configurations\n");
  1285. fprintf(stderr, " kconfig-conf --olddefconfig Kconfig\n");
  1286. }
  1287. }
  1288. /****************************************************************************
  1289. * Public Functions
  1290. ****************************************************************************/
  1291. int main(int argc, char **argv, char **envp)
  1292. {
  1293. debug("main: Checking arguments\n");
  1294. parse_args(argc, argv);
  1295. debug("main: Checking NuttX Directories\n");
  1296. find_topdir();
  1297. check_configdir();
  1298. check_configured();
  1299. debug("main: Reading the configuration/version files\n");
  1300. read_configfile();
  1301. read_versionfile();
  1302. get_verstring();
  1303. debug("main: Checking Configuration Directory\n");
  1304. check_configuration();
  1305. debug("main: Checking Application Directories\n");
  1306. check_appdir();
  1307. debug("main: Using apppath=%s\n", g_apppath ? g_apppath : "<null>");
  1308. debug("main: Configuring\n");
  1309. configure();
  1310. debug("main: Refresh configuration\n");
  1311. refresh();
  1312. return EXIT_SUCCESS;
  1313. }