diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-01-04 21:37:31 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-01-04 21:37:31 +0000 |
commit | 5c572a3cb50e6e52a641ee652d9e151b4c70661c (patch) | |
tree | 2b41449055995be18eb86ace4329a08f1536374c /nuttx | |
parent | b66a46decca8ba8bc3570ca5d91d908f2e339c0d (diff) | |
download | px4-firmware-5c572a3cb50e6e52a641ee652d9e151b4c70661c.tar.gz px4-firmware-5c572a3cb50e6e52a641ee652d9e151b4c70661c.tar.bz2 px4-firmware-5c572a3cb50e6e52a641ee652d9e151b4c70661c.zip |
Add tools/configure.c and configure.bat
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5478 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/ChangeLog | 11 | ||||
-rw-r--r-- | nuttx/Documentation/NuttxPortingGuide.html | 31 | ||||
-rw-r--r-- | nuttx/Makefile.win | 2 | ||||
-rw-r--r-- | nuttx/README.txt | 21 | ||||
-rw-r--r-- | nuttx/TODO | 16 | ||||
-rw-r--r-- | nuttx/configs/README.txt | 24 | ||||
-rw-r--r-- | nuttx/configs/stm32f4discovery/README.txt | 5 | ||||
-rw-r--r-- | nuttx/configs/xtrs/README.txt | 15 | ||||
-rw-r--r-- | nuttx/tools/README.txt | 27 | ||||
-rw-r--r-- | nuttx/tools/cfgparser.c | 3 | ||||
-rw-r--r-- | nuttx/tools/configure.bat | 128 | ||||
-rw-r--r-- | nuttx/tools/configure.c | 763 |
12 files changed, 1003 insertions, 43 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 2762faf66..710ffdceb 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -3861,4 +3861,13 @@ * libc/misc/Make.defs: Fix error in conditional for KBD CODEC. * libc/Kconfig and configs/*/defconfig (several): The default setting should be CONFIG_LIB_KBDCODEC=n - + * tools/configure.c: configure.c can be used to build a work-alike + program as a replacement for configure.sh. This work-alike + program would be used in environments that do not support Bash + scripting (such as the Windows native environment). + * tools/configure.bat: configure.bat is a small Windows batch + file that can be used as a replacement for configure.sh in a + Windows native environment. configure.bat is actually just a + thin layer that execuates configure.exe if it is available. If + configure.exe is not available, then configure.bat will attempt + to build it first. diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index e626bf7a5..559253d45 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -1263,23 +1263,23 @@ tools/ |-- Makefile.host |-- Makefile.export |-- README.txt -|-- configure.sh +|-- configure.sh / configure.bat |-- cfgparser.c |-- cfgparser.h -|-- copydir.sh -|-- define.sh -|-- incdir.sh +|-- copydir.sh / copydir.bat +|-- define.sh / define.bat +|-- incdir.sh / indir.bat |-- indent.sh -|-- link.sh +|-- link.sh / link.bat |-- mkconfig.c -|-- mkdeps.sh +|-- mkdeps.sh / mkdeps.bat |-- mkexport.sh |-- mkimage.sh |-- mknulldeps.sh |-- mkromfsimg.sh |-- mksyscall.c |-- mkversion.c -|-- unlink.sh +|-- unlink.sh / unlink.bat |-- version.sh `-- zipme.sh </pre></ul> @@ -1416,17 +1416,28 @@ netutils/ </p> <ul><pre> cd tools - ./configure.sh <i><board-name></i></i>[/<i><config-dir></i>] + ./configure.sh <i><board-name></i>[/<i><config-dir></i>] </pre></ul> <p> - And if <code>configs/</code><i><board-name></i><code>/[</code><i><config-dir></i><code>/appconfig</code> + There is an alternative Windows batch file, <code>configure.bat</code>, that can be used insteach of <code>configure.sh</code> in the windows native enironment like: +</p> +<ul><pre> + cd tools + configure.bat <i><board-name></i>[\<i><config-dir></i>] +</pre></ul> +<p> + See <code>tools/README.txt</code> for more information about these scripts. +</p> + +<p> + If <code>configs/</code><i><board-name></i><code>/[</code><i><config-dir></i>]<code>/appconfig</code> exists and your application directory is not in the standard loction (<config>../apps</config>), then you should also specify the location of the application directory on the command line like: </p> <ul><pre> cd tools - ./configure.sh -a <app-dir> <i><board-name></i></i>[/<i><config-dir></i>] + ./configure.sh -a <app-dir> <i><board-name></i>[/<i><config-dir></i>] </pre></ul> <p> diff --git a/nuttx/Makefile.win b/nuttx/Makefile.win index fcf971d32..803d073b2 100644 --- a/nuttx/Makefile.win +++ b/nuttx/Makefile.win @@ -452,7 +452,7 @@ clean_context: # check_context # # This target checks if NuttX has been configured. NuttX is configured using -# the script tools\configure.sh. That script will install certain files in +# the script tools\configure.bat. That script will install certain files in # the top-level NuttX build directory. This target verifies that those # configuration files have been installed and that NuttX is ready to be built. diff --git a/nuttx/README.txt b/nuttx/README.txt index bfd057351..717c129b0 100644 --- a/nuttx/README.txt +++ b/nuttx/README.txt @@ -257,6 +257,14 @@ easier. It is used as follows: cd ${TOPDIR}/tools ./configure.sh <board-name>/<config-dir> +There is an alternative Windows batch file that can be used in the +windows native enironment like: + + cd ${TOPDIR}\tools + configure.bat <board-name>\<config-dir> + +See tools/README.txt for more information about these scripts. + NuttX Configuration Tool ------------------------ @@ -401,6 +409,8 @@ Converting Older Configurations to use the Configuration Tool cd tools ./configure.sh <board>/<condfiguration> + (or configure.bat for the case of the Windows native build). + NOTE: If CONFIG_APPS_DIR is not defined in the defconfig file, the configure.sh script will find and add the new, correct path to the application directory (CONFIG_APPS_DIR) when it copies the @@ -682,10 +692,15 @@ Native Windows Build the you not install the optional MSYS components as there may be conflicts. This capability should still be considered a work in progress because: + (1) It has not been verfied on all targets and tools, and - (2) itstill lacks some of the creature-comforts of the more mature environments - (like a functional configure.sh script and 'make menuconfig' support. - See the section "NuttX Configuration Tool under DOS" above). + (2) it still lacks some of the creature-comforts of the more mature environments + (like 'make menuconfig' support. See the section "NuttX Configuration Tool + under DOS" above). + + There is an alternative to the setenv.sh script available for the Windows + native environment: tools/configure.bat. See tools/README.txt for additional + information. Installing GNUWin32 ------------------- diff --git a/nuttx/TODO b/nuttx/TODO index d37231e1d..4a70e577f 100644 --- a/nuttx/TODO +++ b/nuttx/TODO @@ -19,7 +19,7 @@ nuttx/ (5) Graphics subystem (graphics/) (1) Pascal add-on (pcode/) (1) Documentation (Documentation/) - (8) Build system / Toolchains + (7) Build system / Toolchains (5) Linux/Cywgin simulation (arch/sim) (6) ARM (arch/arm/) (1) ARM/C5471 (arch/arm/src/c5471/) @@ -1037,20 +1037,6 @@ o Build system Status: Open, there are some workarounds, but none are good. Priority: High - Title: configure.sh NOT AVAILABLE IN NATIVE WINDOWS BUILD - Description: configure.sh is a Bash script and cannot be used from a Windows - CMD.exe window. I started a configure.bat script, but I do - not have the batch file programming skills to duplicate some - of the more complex operations. - - I also considered adding a configure.c file that could be - compiled and then executed by configure.bat (and configure.sh?). - But I have not gone down that path yet. - - The current work-around is to configure under Cygwin. - Status: Open - Priority: High - o Linux/Cywgin simulation (arch/sim) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt index 4e9bcca14..6e7526ed0 100644 --- a/nuttx/configs/README.txt +++ b/nuttx/configs/README.txt @@ -1960,16 +1960,24 @@ tools/configure.sh There is a script that automates these steps. The following steps will accomplish the same configuration: - cd tools - ./configure.sh <board-name>/<config-dir> + cd tools + ./configure.sh <board-name>/<config-dir> -And if configs/<board-name>/<config-dir>/appconfig exists and your -application directory is not in the standard loction (../apps), then -you should also specify the location of the application directory on the -command line like: + There is an alternative Windows batch file that can be used in the + windows native enironment like: - cd tools - ./configure.sh -a <app-dir> <board-name>/<config-dir> + cd ${TOPDIR}\tools + configure.bat <board-name>\<config-dir> + + See tools/README.txt for more information about these scripts. + + And if configs/<board-name>/<config-dir>/appconfig exists and your + application directory is not in the standard loction (../apps), then + you should also specify the location of the application directory on the + command line like: + + cd tools + ./configure.sh -a <app-dir> <board-name>/<config-dir> Building Symbol Tables ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/nuttx/configs/stm32f4discovery/README.txt b/nuttx/configs/stm32f4discovery/README.txt index 571385abb..28072f44b 100644 --- a/nuttx/configs/stm32f4discovery/README.txt +++ b/nuttx/configs/stm32f4discovery/README.txt @@ -1011,6 +1011,11 @@ can be selected as follow: cd - . ./setenv.sh +If this is a Windows native build, then configure.bat should be used +instead of configure.sh: + + configure.bat STM32F4Discovery\<subdir> + Where <subdir> is one of the following: cxxtest: diff --git a/nuttx/configs/xtrs/README.txt b/nuttx/configs/xtrs/README.txt index 1a63d3a90..d462dcab1 100644 --- a/nuttx/configs/xtrs/README.txt +++ b/nuttx/configs/xtrs/README.txt @@ -59,6 +59,11 @@ Configuring NuttX setenv.bat make + If this is a Windows native build, then configure.bat should be used + in step 1) instead of configure.sh: + + configure.bat xtrs\ostest + The setenv.bat will need to be updated to include the PATH to the XTRS hex2cmd program. @@ -90,6 +95,11 @@ Configuring NuttX setenv.bat make + If this is a Windows native build, then configure.bat should be used + in step 1) instead of configure.sh: + + configure.bat xtrs\nsh + The setenv.bat will need to be updated to include the PATH to the XTRS hex2cmd program. @@ -128,6 +138,11 @@ Configuring NuttX setenv.bat make + If this is a Windows native build, then configure.bat should be used + in step 1) instead of configure.sh: + + configure.bat xtrs\pashello + The setenv.bat will need to be updated to include the PATH to the XTRS hex2cmd program. diff --git a/nuttx/tools/README.txt b/nuttx/tools/README.txt index f9e2d1099..5651ff2f0 100644 --- a/nuttx/tools/README.txt +++ b/nuttx/tools/README.txt @@ -26,12 +26,35 @@ Config.mk override these default definitions as necessary. configure.sh +configure.bat +configure.c, cfgparser.c, and cfgparser.h ------------ - This is a bash script that is used to configure NuttX for a given - target board. See configs/README.txt or Documentation/NuttxPortingGuide.html + configure.sh is a bash script that is used to configure NuttX for a given + target board in a environment that supports POSIX paths (Linux, Cygwin, + OSX, or similar). See configs/README.txt or Documentation/NuttxPortingGuide.html for a description of how to configure NuttX with this script. + configure.c, cfgparser.c, and cfgparser.h can be used to build a work-alike + program as a replacement for configure.sh. This work-alike program would be + used in environments that do not support Bash scripting (such as the Windows + native environment). + + configure.bat is a small Windows batch file that can be used as a replacement + for configure.sh in a Windows native environment. configure.bat is actually + just a thin layer that execuates configure.exe if it is available. If + configure.exe is not available, then configure.bat will attempt to build it + first. + + In order two build configure.exe from configure.c in the Windows native + environment, two assumptions are made: + + 1) You have installed the MinGW GCC toolchain. This toolchain can be + downloaded from http://www.mingw.org/. Tt is recommended the you not + install the optional MSYS components as there may be conflicts. + 2) That path to bin bin/ directory containing mingw-gcc.exe must be + included in the PATH variable. + discover.py ----------- diff --git a/nuttx/tools/cfgparser.c b/nuttx/tools/cfgparser.c index cb4ab4c52..ac25bd26b 100644 --- a/nuttx/tools/cfgparser.c +++ b/nuttx/tools/cfgparser.c @@ -281,9 +281,6 @@ void parse_file(FILE *stream, struct variable_s **list) struct variable_s *find_variable(const char *varname, struct variable_s *list) { - char *varval1; - char *varval2; - while (list) { if (strcmp(varname, list->var) == 0) diff --git a/nuttx/tools/configure.bat b/nuttx/tools/configure.bat new file mode 100644 index 000000000..c28558fbb --- /dev/null +++ b/nuttx/tools/configure.bat @@ -0,0 +1,128 @@ +@echo off
+
+rem tools/configure.bat
+rem
+rem Copyright (C) 2012 Gregory Nutt. All rights reserved.
+rem Author: Gregory Nutt <gnutt@nuttx.org>
+rem
+rem Redistribution and use in source and binary forms, with or without
+rem modification, are permitted provided that the following conditions
+rem are met:
+rem
+rem 1. Redistributions of source code must retain the above copyright
+rem notice, this list of conditions and the following disclaimer.
+rem 2. Redistributions in binary form must reproduce the above copyright
+rem notice, this list of conditions and the following disclaimer in
+rem the documentation and/or other materials provided with the
+rem distribution.
+rem 3. Neither the name NuttX nor the names of its contributors may be
+rem used to endorse or promote products derived from this software
+rem without specific prior written permission.
+rem
+rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+rem FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+rem COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+rem INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+rem BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+rem OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+rem AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+rem LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+rem ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+rem POSSIBILITY OF SUCH DAMAGE.
+rem
+
+rem Parse command line arguments
+
+set debug=
+set fmt=-w
+set posix=
+set help=
+set appdir=
+set config=
+
+:ArgLoop
+if "%1"=="" goto :NoConfig
+if "%1"=="-h" goto :ShowUsage
+if "%1"=="-d" goto :SetDebug
+if "%1"=="-w" goto :SetWindows
+if "%1"=="-l" goto :SetPosix
+if "%1"=="-a" goto :SetAppDir
+
+set config=%1
+goto EndOfLoop
+
+:SetDebug
+set debug=-d
+goto :NextArg
+
+:SetWindows
+set fmt=-w
+goto :NextArg
+
+:SetWindows
+set fmt=-l
+goto :NextArg
+
+:SetAppDir
+shift
+set appdir=-a %1
+
+:NextArg
+shift
+goto :ArgLoop
+
+:EndOfLoop
+
+rem Check if we have to build configure.exe
+
+if exist configure.exe goto :HaveConfigureExe
+
+set cc=mingw32-gcc.exe
+set cflags=-Wall -Wstrict-prototypes -Wshadow -g -pipe -I. -DCONFIG_WINDOWS_NATIVE=y
+%cc% %cflags% -o configure.exe configure.c cfgparser.c
+if errorlevel 1 (
+ echo ERROR: %cc% failed
+ echo Is ming32-gcc.exe installed? Is it in the PATH variable?
+ goto End
+)
+
+:HaveConfigureExe
+configure.exe %debug% %fmt% %appdir% %config%
+if errorlevel 1 echo configure.exe failed
+goto End
+
+
+:NoConfig
+echo Missing ^<board-name^>/^<config-name^> argument
+
+:ShowUsage
+echo USAGE: %0 [-d] [-w] [-l] [-h] [-a ^<app-dir^>] ^<board-name^>\^<config-name^>
+echo\nWhere:
+echo ^<board-name^>:
+echo Identifies the board. This must correspond to a board directory
+echo under nuttx/configs/.
+echo ^<config-name^>:
+echo Identifies the specific configuratin for the selected ^<board-name^>.
+echo This must correspond to a sub-directory under the board directory at
+echo under nuttx/configs/^<board-name^>/.
+echo ^<-d^>:
+echo Enables debug output
+echo ^<-w^>:
+echo Informs the tool that it should use Windows style paths like C:\\Program Files
+echo instead of POSIX style paths are used like /usr/local/bin. Windows
+echo style paths are used by default.
+echo ^<-l^>:
+echo Informs the tool that it should use POSIX style paths like /usr/local/bin.
+echo By default, Windows style paths like C:\\Program Files are used.
+echo -a ^<app-dir^>:
+echo Informs the configuration tool where the application build
+echo directory. This is a relative path from the top-level NuttX
+echo build directory. But default, this tool will look in the usual
+echo places to try to locate the application directory: ../apps or
+echo ../apps-xx.yy where xx.yy is the NuttX version number.
+echo ^<-h^>:
+echo Prints this message and exits.
+
+:End
diff --git a/nuttx/tools/configure.c b/nuttx/tools/configure.c new file mode 100644 index 000000000..f189f5b98 --- /dev/null +++ b/nuttx/tools/configure.c @@ -0,0 +1,763 @@ +/**************************************************************************** + * tools/configure.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <sys/stat.h> + +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <libgen.h> +#include <errno.h> + +#include "cfgparser.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BUFFER_SIZE 1024 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_WINDOWS_NATIVE +static char g_delim = '\\'; /* Delimiter to use when forming paths */ +static bool g_winpaths = true; /* True: Windows style paths */ +#else +static char g_delim = '/'; /* Delimiter to use when forming paths */ +static bool g_winpaths = false; /* False: POSIX style paths */ +#endif +static bool g_debug = false; /* Enable debug output */ + +static const char *g_appdir = NULL; /* Relative path to the applicatin directory */ +static const char *g_boarddir = NULL; /* Name of board subdirectory */ +static char *g_configdir = NULL; /* Name of configuration subdirectory */ + +static char *g_topdir = NULL; /* Full path to top-level NuttX build directory */ +static char *g_apppath = NULL; /* Full path to the applicatino directory */ +static char *g_configpath = NULL; /* Full path to the configuration directory */ +static char *g_verstring = "0.0"; /* Version String */ + +static char *g_srcdefconfig = NULL; /* Source defconfig file */ +static char *g_srcmakedefs = NULL; /* Source Make.defs file */ +static char *g_srcappconfig = NULL ; /* Source appconfig file (optional) */ +static char *g_srcsetenvsh = NULL; /* Source setenv.sh file (optional) */ +static char *g_srcsetenvbat = NULL; /* Source setenv.bat file (optional) */ + +static bool g_newconfig = false; /* True: New style configuration */ +static bool g_winnative = false; /* True: Windows native configuration */ +static bool g_needapppath = true; /* Need to add app path to the .config file */ + +static char g_buffer[BUFFER_SIZE]; /* Scratch buffer for forming full paths */ + +static struct variable_s *g_configvars = NULL; +static struct variable_s *g_versionvars = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void show_usage(const char *progname, int exitcode) +{ + fprintf(stderr, "\nUSAGE: %s [-d] [-w] [-l] [-h] [-a <app-dir>] <board-name>%c<config-name>\n", progname, g_delim); + fprintf(stderr, "\nWhere:\n"); + fprintf(stderr, " <board-name>:\n"); + fprintf(stderr, " Identifies the board. This must correspond to a board directory\n"); + fprintf(stderr, " under nuttx%cconfigs%c.\n", g_delim, g_delim); + fprintf(stderr, " <config-name>:\n"); + fprintf(stderr, " Identifies the specific configuratin for the selected <board-name>.\n"); + fprintf(stderr, " This must correspond to a sub-directory under the board directory at\n"); + fprintf(stderr, " under nuttx%cconfigs%c<board-name>%c.\n", g_delim, g_delim, g_delim); + fprintf(stderr, " <-d>:\n"); + fprintf(stderr, " Enables debug output\n"); + fprintf(stderr, " <-w>:\n"); +#ifdef CONFIG_WINDOWS_NATIVE + fprintf(stderr, " Informs the tool that it should use Windows style paths like C:\\Program Files\n"); + fprintf(stderr, " instead of POSIX style paths are used like /usr/local/bin. Windows\n"); + fprintf(stderr, " style paths are used by default.\n"); +#else + fprintf(stderr, " Informs the tool that it should use Windows style paths like C:\\Program Files.\n"); + fprintf(stderr, " By default, POSIX style paths like /usr/local/bin are used.\n"); +#endif + fprintf(stderr, " <-l>:\n"); +#ifdef CONFIG_WINDOWS_NATIVE + fprintf(stderr, " Informs the tool that it should use POSIX style paths like /usr/local/bin.\n"); + fprintf(stderr, " By default, Windows style paths like C:\\Program Files are used.\n"); +#else + fprintf(stderr, " Informs the tool that it should use POSIX style paths like /usr/local/bin\n"); + fprintf(stderr, " instead of Windows style paths like C:\\Program Files are used. POSIX\n"); + fprintf(stderr, " style paths are used by default.\n"); +#endif + fprintf(stderr, " -a <app-dir>:\n"); + fprintf(stderr, " Informs the configuration tool where the application build\n"); + fprintf(stderr, " directory. This is a relative path from the top-level NuttX\n"); + fprintf(stderr, " build directory. But default, this tool will look in the usual\n"); + fprintf(stderr, " places to try to locate the application directory: ..%capps or\n", g_delim); + fprintf(stderr, " ..%capps-xx.yy where xx.yy is the NuttX version number.\n", g_delim); + fprintf(stderr, " <-h>:\n"); + fprintf(stderr, " Prints this message and exits.\n"); + exit(exitcode); +} + +static void debug(const char *fmt, ...) +{ + va_list ap; + + if (g_debug) + { + va_start(ap, fmt); + (void)vprintf(fmt, ap); + va_end(ap); + } +} + +static void parse_args(int argc, char **argv) +{ + char *ptr; + int ch; + + /* Parse command line options */ + + g_debug = false; + + while ((ch = getopt(argc, argv, ":a:dwlh")) > 0) + { + switch (ch) + { + case 'a' : + g_appdir = optarg; + break; + + case 'd' : + g_debug = true; + break; + + case 'w' : + g_delim = '/'; + g_winpaths = true; + break; + + case 'l' : + g_delim = '\\'; + g_winpaths = false; + break; + + case 'h' : + show_usage(argv[0], EXIT_SUCCESS); + + case '?' : + fprintf(stderr, "ERROR: Unrecognized option: %c\n", optopt); + show_usage(argv[0], EXIT_FAILURE); + + case ':' : + fprintf(stderr, "ERROR: Missing option argument, option: %c\n", optopt); + show_usage(argv[0], EXIT_FAILURE); + + break; + fprintf(stderr, "ERROR: Unexpected option: %c\n", ch); + show_usage(argv[0], EXIT_FAILURE); + } + } + + /* There should be exactly one argument following the options */ + + if (optind >= argc) + { + fprintf(stderr, "ERROR: Missing <board-name>%c<config-name>\n", g_delim); + show_usage(argv[0], EXIT_FAILURE); + } + + /* The required option should be the board directory name and the + * configuration directory name separated by '/' or '\'. Either is + * acceptable in this context. + */ + + g_boarddir = argv[optind]; + optind++; + + ptr = strchr(g_boarddir, '/'); + if (!ptr) + { + ptr = strchr(g_boarddir, '\\'); + } + + if (!ptr) + { + fprintf(stderr, "ERROR: Invalid <board-name>%c<config-name>\n", g_delim); + show_usage(argv[0], EXIT_FAILURE); + } + + *ptr++ = '\0'; + g_configdir = ptr; + + if (optind < argc) + { + fprintf(stderr, "Unexpected garbage at the end of the line\n"); + show_usage(argv[0], EXIT_FAILURE); + } +} + +static void verify_directory(const char *directory) +{ + struct stat buf; + + if (stat(directory, &buf) < 0) + { + fprintf(stderr, "ERROR: stat of %s failed: %s\n", directory, strerror(errno)); + exit(EXIT_FAILURE); + } + + if (!S_ISDIR(buf.st_mode)) + { + fprintf(stderr, "ERROR: %s exists but is not a directory\n", directory); + exit(EXIT_FAILURE); + } +} + +static bool verify_optiondir(const char *directory) +{ + struct stat buf; + + if (stat(directory, &buf) < 0) + { + /* It may be okay if the dirctory does not exist */ + + debug("verify_optiondir: stat of %s failed: %s\n", directory, strerror(errno)); + return false; + } + + if (!S_ISDIR(buf.st_mode)) + { + fprintf(stderr, "ERROR: %s exists but is not a directory\n", directory); + exit(EXIT_FAILURE); + } + + return true; +} + +static void verify_file(const char *path) +{ + struct stat buf; + + if (stat(path, &buf) < 0) + { + fprintf(stderr, "ERROR: stat of %s failed: %s\n", path, strerror(errno)); + exit(EXIT_FAILURE); + } + + if (!S_ISREG(buf.st_mode)) + { + fprintf(stderr, "ERROR: %s exists but is not a regular file\n", path); + exit(EXIT_FAILURE); + } +} + +static bool verify_optionfile(const char *path) +{ + struct stat buf; + + if (stat(path, &buf) < 0) + { + /* It may be okay if the file does not exist */ + + debug("verify_optionfile: stat of %s failed: %s\n", path, strerror(errno)); + return false; + } + + if (!S_ISREG(buf.st_mode)) + { + fprintf(stderr, "ERROR: %s exists but is not a regular file\n", path); + exit(EXIT_FAILURE); + } + + return true; +} + +static void get_topdir(void) +{ + /* Get and verify the top-level NuttX directory */ + + if (getcwd(g_buffer, BUFFER_SIZE) == NULL) + { + fprintf(stderr, "ERROR: getcwd failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + g_topdir = strdup(dirname(g_buffer)); + debug("get_topdir: Checking topdir=%s\n", g_topdir); + verify_directory(g_topdir); +} + +static void check_configdir(void) +{ + /* Get and verify the path to the selected configuration */ + + snprintf(g_buffer, BUFFER_SIZE, "%s%cconfigs%c%s%c%s", + g_topdir, g_delim, g_delim, g_boarddir, g_delim, g_configdir); + g_configpath = strdup(g_buffer); + debug("check_configdir: Checking configpath=%s\n", g_configpath); + verify_directory(g_configpath); +} + +static void read_configfile(void) +{ + FILE *stream; + + snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_configpath, g_delim); + stream = fopen(g_buffer, "r"); + if (!stream) + { + fprintf(stderr, "ERROR: failed to open %s for reading: %s\n", + g_buffer, strerror(errno)); + exit(EXIT_FAILURE); + } + + parse_file(stream, &g_configvars); + fclose(stream); +} + +static void read_versionfile(void) +{ + FILE *stream; + + snprintf(g_buffer, BUFFER_SIZE, "%s%c.version", g_topdir, g_delim); + stream = fopen(g_buffer, "r"); + if (!stream) + { + /* It may not be an error if there is no .version file */ + + debug("Failed to open %s for reading: %s\n", + g_buffer, strerror(errno)); + } + else + { + parse_file(stream, &g_versionvars); + fclose(stream); + } +} + +static void get_verstring(void) +{ + struct variable_s *var; + + if (g_versionvars) + { + var = find_variable("CONFIG_VERSION_STRING", g_versionvars); + if (var && var->val) + { + g_verstring = strdup(var->val); + } + } + + debug("get_verstring: Version string=%s\n", g_verstring); +} + +static bool verify_appdir(const char *appdir) +{ + /* Does this directory exist? */ + + snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_topdir, g_delim, appdir); + debug("verify_appdir: Checking apppath=%s\n", g_buffer); + if (verify_optiondir(g_buffer)) + { + /* Yes.. Use this application directory path */ + + g_appdir = strdup(appdir); + g_apppath = strdup(g_buffer); + return true; + } + + debug("verify_appdir: apppath=%s does not exist\n", g_buffer); + return false; +} + +static void check_appdir(void) +{ + char tmp[16]; + + /* Get and verify the full path to the application directory */ + /* Was the appdir provided on the command line? */ + + debug("check_appdir: Command line appdir=%s\n", + g_appdir ? g_appdir : "<null>"); + + if (!g_appdir) + { + /* No, was the path provided in the configuration? */ + + struct variable_s *var = find_variable("CONFIG_APP_DIR", g_configvars); + if (var) + { + debug("check_appdir: Config file appdir=%s\n", + var->val ? var->val : "<null>"); + + /* Yes.. does this directory exist? */ + + if (var->val && verify_appdir(var->val)) + { + /* We are using the CONFIG_APP_DIR setting already + * in the defconfig file. + */ + + g_needapppath = false; + return; + } + } + + /* Now try some canned locations */ + + /* Try ../apps-xx.yy where xx.yy is the version string */ + + snprintf(tmp, 16, ".%capps-%s", g_delim, g_verstring); + debug("check_appdir: Try appdir=%s\n", tmp); + if (verify_appdir(tmp)) + { + return; + } + + /* Try ../apps with no version */ + + snprintf(tmp, 16, "..%capps", g_delim); + debug("check_appdir: Try appdir=%s\n", tmp); + if (verify_appdir(tmp)) + { + return; + } + + /* Try ../apps-xx.yy where xx.yy are the NuttX version number */ + + fprintf(stderr, "ERROR: Could not find the path to the application directory\n"); + exit(EXIT_FAILURE); + } + else + { + snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_topdir, g_delim, g_appdir); + if (!verify_appdir(g_buffer)) + { + fprintf(stderr, "ERROR: Command line path to application directory does not exist\n"); + exit(EXIT_FAILURE); + } + } +} + +static void check_configuration(void) +{ + struct variable_s *var; + + /* Check if this the new style configuration based on kconfig-fontends */ + + var = find_variable("CONFIG_NUTTX_NEWCONFIG", g_configvars); + if (var && var->val && strcmp("y", var->val) == 0) + { + debug("check_configuration: New style configuration\n"); + g_newconfig = true; + } + + /* Check if this is a Windows native configuration */ + + var = find_variable("CONFIG_WINDOWS_NATIVE", g_configvars); + if (var && var->val && strcmp("y", var->val) == 0) + { + debug("check_configuration: Windows native configuration\n"); + g_winnative = true; + } + + /* All configurations must provide a defconfig and Make.defs file */ + + snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_configpath, g_delim); + debug("check_configuration: Checking %s\n", g_buffer); + verify_file(g_buffer); + g_srcdefconfig = strdup(g_buffer); + + snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs", g_configpath, g_delim); + debug("check_configuration: Checking %s\n", g_buffer); + verify_file(g_buffer); + g_srcmakedefs = strdup(g_buffer); + + /* Windows native configurations may provide setenv.bat; POSIX + * configurations may provide a setenv.sh. + */ + + if (g_winnative) + { + snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.bat", g_configpath, g_delim); + debug("check_configuration: Checking %s\n", g_buffer); + if (verify_optionfile(g_buffer)) + { + g_srcsetenvbat = strdup(g_buffer); + } + } + else + { + snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.sh", g_configpath, g_delim); + debug("check_configuration: Checking %s\n", g_buffer); + if (verify_optionfile(g_buffer)) + { + g_srcsetenvsh = strdup(g_buffer); + } + } + + /* Old style configurations MUST provide an appconfig file */ + + if (!g_newconfig) + { + snprintf(g_buffer, BUFFER_SIZE, "%s%cappconfig", g_configpath, g_delim); + debug("check_configuration: Checking %s\n", g_buffer); + verify_file(g_buffer); + g_srcappconfig = strdup(g_buffer); + } +} + +static void copy_file(const char *srcpath, const char *destpath) +{ + int nbytesread; + int nbyteswritten; + int rdfd; + int wrfd; + + /* Open the source file for reading */ + + rdfd = open(srcpath, O_RDONLY); + if (rdfd < 0) + { + fprintf(stderr, "ERROR: Failed to open %s for reading: %s\n", srcpath, strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Now open the destination for writing*/ + + wrfd = open(destpath, O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (wrfd < 0) + { + fprintf(stderr, "ERROR: Failed to open %s for writing: %s\n", destpath, strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Now copy the file */ + + for (;;) + { + do + { + nbytesread = read(rdfd, g_buffer, BUFFER_SIZE); + if (nbytesread == 0) + { + /* End of file */ + + close(rdfd); + close(wrfd); + return; + } + else if (nbytesread < 0) + { + /* EINTR is not an error (but will still stop the copy) */ + + fprintf(stderr, "ERROR: Read failure: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + } + while (nbytesread <= 0); + + do + { + nbyteswritten = write(wrfd, g_buffer, nbytesread); + if (nbyteswritten >= 0) + { + nbytesread -= nbyteswritten; + } + else + { + /* EINTR is not an error (but will still stop the copy) */ + + fprintf(stderr, "ERROR: Write failure: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + } + while (nbytesread > 0); + } +} + +static void substitute(char *str, int ch1, int ch2) +{ + for (; *str; str++) + { + if (*str == ch1) + { + *str = ch2; + } + } +} + +static void configure(void) +{ + char *destconfig; + + /* Copy the defconfig file as .config */ + + snprintf(g_buffer, BUFFER_SIZE, "%s%c.config", g_topdir, g_delim); + destconfig = strdup(g_buffer); + debug("configure: Copying from %s to %s\n", g_srcdefconfig, destconfig); + copy_file(g_srcdefconfig, destconfig); + + /* Copy the Make.defs file as Make.defs */ + + snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs", g_topdir, g_delim); + debug("configure: Copying from %s to %s\n", g_srcmakedefs, g_buffer); + copy_file(g_srcmakedefs, g_buffer); + + /* Copy the setenv.sh file if have one and need one */ + + if (g_srcsetenvsh) + { + snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.sh", g_topdir, g_delim); + debug("configure: Copying from %s to %s\n", g_srcsetenvsh, g_buffer); + copy_file(g_srcsetenvsh, g_buffer); + + /* Mark the file executable */ + + if (chmod(g_buffer, 0777) != 0) + { + fprintf(stderr, "ERROR: Failed to make setenv.sh executable: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + } + + /* Copy the setenv.bat file if have one and need one */ + + if (g_srcsetenvbat) + { + snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.bat", g_topdir, g_delim); + debug("configure: Copying from %s to %s\n", g_srcsetenvbat, g_buffer); + copy_file(g_srcsetenvbat, g_buffer); + } + + /* Copy the appconfig file to ../apps/.config if have one and need one */ + + if (g_srcappconfig) + { + snprintf(g_buffer, BUFFER_SIZE, "%s%c.config", g_apppath, g_delim); + debug("configure: Copying from %s to %s\n", g_srcappconfig, g_buffer); + copy_file(g_srcappconfig, g_buffer); + } + + /* If we did not use the CONFIG_APPS_DIR that was in the defconfig config file, + * then append the correct application information to the tail of the .config + * file + */ + + if (g_needapppath) + { + FILE *stream; + char *appdir = strdup(g_appdir); + + /* One complexity is if we are using Windows paths, but the configuration + * needs POSIX paths (or vice versa). + */ + + if (g_winpaths != g_winnative) + { + /* Not the same */ + + if (g_winpaths) + { + /* Using Windows paths, but the configuration wants POSIX paths */ + + substitute(appdir, '\\', '/'); + } + else + { + /* Using POSIX paths, but the configuration wants Windows paths */ + + substitute(appdir, '/', '\\'); + } + } + + /* Open the file for appending */ + + stream = fopen(destconfig, "a"); + if (!stream) + { + fprintf(stderr, "ERROR: Failed to open %s for append mode mode: %s\n", + destconfig, strerror(errno)); + exit(EXIT_FAILURE); + } + + fprintf(stream, "\n# Application configuration\n\n"); + fprintf(stream, "CONFIG_APPS_DIR=\"%s\"\n", appdir); + fclose(stream); + free(appdir); + } + + free(destconfig); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + debug("main: Checking arguments\n"); + parse_args(argc, argv); + + debug("main: Checking Nuttx Directories\n"); + get_topdir(); + check_configdir(); + + debug("main: Reading the configuration/version files\n"); + read_configfile(); + read_versionfile(); + get_verstring(); + + debug("main: Checking Configuration Directory\n"); + check_configuration(); + + debug("main: Checking Application Directories\n"); + check_appdir(); + debug("main: Using apppath=%s\n", g_apppath ? g_apppath : "<null>"); + + debug("main: Configuring\n"); + configure(); + return EXIT_SUCCESS; +} |