summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-04 21:37:31 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-04 21:37:31 +0000
commitb0e850297d6e54d9d7b825c27f371cd93d3b4771 (patch)
tree2b41449055995be18eb86ace4329a08f1536374c
parent3f81b4dd94a7ad8cf65490fc12248e16f718f31d (diff)
downloadnuttx-b0e850297d6e54d9d7b825c27f371cd93d3b4771.tar.gz
nuttx-b0e850297d6e54d9d7b825c27f371cd93d3b4771.tar.bz2
nuttx-b0e850297d6e54d9d7b825c27f371cd93d3b4771.zip
Add tools/configure.c and configure.bat
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5478 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog11
-rw-r--r--nuttx/Documentation/NuttxPortingGuide.html31
-rw-r--r--nuttx/Makefile.win2
-rw-r--r--nuttx/README.txt21
-rw-r--r--nuttx/TODO16
-rw-r--r--nuttx/configs/README.txt24
-rw-r--r--nuttx/configs/stm32f4discovery/README.txt5
-rw-r--r--nuttx/configs/xtrs/README.txt15
-rw-r--r--nuttx/tools/README.txt27
-rw-r--r--nuttx/tools/cfgparser.c3
-rw-r--r--nuttx/tools/configure.bat128
-rw-r--r--nuttx/tools/configure.c763
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>&lt;board-name&gt;</i></i>[/<i>&lt;config-dir&gt;</i>]
+ ./configure.sh <i>&lt;board-name&gt;</i>[/<i>&lt;config-dir&gt;</i>]
</pre></ul>
<p>
- And if <code>configs/</code><i>&lt;board-name&gt;</i><code>/[</code><i>&lt;config-dir&gt;</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>&lt;board-name&gt;</i>[\<i>&lt;config-dir&gt;</i>]
+</pre></ul>
+<p>
+ See <code>tools/README.txt</code> for more information about these scripts.
+</p>
+
+<p>
+ If <code>configs/</code><i>&lt;board-name&gt;</i><code>/[</code><i>&lt;config-dir&gt;</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 &lt;app-dir&gt; <i>&lt;board-name&gt;</i></i>[/<i>&lt;config-dir&gt;</i>]
+ ./configure.sh -a &lt;app-dir&gt; <i>&lt;board-name&gt;</i>[/<i>&lt;config-dir&gt;</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;
+}