mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
examples/xedge_demo: Add Xedge IoT Toolkit with BAS integration
Add support for Xedge, an embedded software toolkit for IoT applications using Lua scripting with HTTP(S), WebSockets, MQTT, and device I/O. * netutils/xedge: Dependency manager that downloads BAS library and BAS-Resources, generates XedgeZip.c during build * examples/xedge_demo: Complete example showing Xedge integration with HTTP server, Lua runtime, and SNTP time synchronization Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This commit is contained in:
parent
72668d7234
commit
2de49b8b22
8 changed files with 495 additions and 0 deletions
41
examples/xedge_demo/Kconfig
Normal file
41
examples/xedge_demo/Kconfig
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config EXAMPLES_XEDGE_DEMO
|
||||
tristate "Xedge IoT Toolkit Demo"
|
||||
depends on NETUTILS_XEDGE && ALLOW_GPL_COMPONENTS
|
||||
default n
|
||||
---help---
|
||||
Simple demonstration of the Xedge IoT Toolkit library.
|
||||
|
||||
This example shows how to integrate and use the Xedge library
|
||||
in your NuttX application. Xedge provides a high-level development
|
||||
environment for creating IoT and industrial device applications
|
||||
using Lua scripting with access to HTTP(S), WebSockets, MQTT,
|
||||
file system, and device I/O.
|
||||
|
||||
Note: This example requires the NETUTILS_XEDGE library to be enabled.
|
||||
|
||||
if EXAMPLES_XEDGE_DEMO
|
||||
|
||||
config EXAMPLES_XEDGE_DEMO_PROGNAME
|
||||
string "Program name"
|
||||
default "xedge_demo"
|
||||
---help---
|
||||
This is the name of the ELF executable for the Xedge demo application in NSH.
|
||||
|
||||
config EXAMPLES_XEDGE_DEMO_PRIORITY
|
||||
int "Xedge demo task priority"
|
||||
default 100
|
||||
---help---
|
||||
Set the task priority for the Xedge demo application.
|
||||
|
||||
config EXAMPLES_XEDGE_DEMO_STACKSIZE
|
||||
int "Xedge demo stack size"
|
||||
default 20000
|
||||
---help---
|
||||
Set the stack size for the Xedge demo application.
|
||||
|
||||
endif
|
||||
25
examples/xedge_demo/Make.defs
Normal file
25
examples/xedge_demo/Make.defs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
############################################################################
|
||||
# apps/examples/xedge_demo/Make.defs
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_EXAMPLES_XEDGE_DEMO),)
|
||||
CONFIGURED_APPS += $(APPDIR)/examples/xedge_demo
|
||||
endif
|
||||
33
examples/xedge_demo/Makefile
Normal file
33
examples/xedge_demo/Makefile
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# ##############################################################################
|
||||
# apps/examples/xedge_demo/CMakeLists.txt
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
PROGNAME = $(CONFIG_EXAMPLES_XEDGE_DEMO_PROGNAME)
|
||||
PRIORITY = $(CONFIG_EXAMPLES_XEDGE_DEMO_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_EXAMPLES_XEDGE_DEMO_STACKSIZE)
|
||||
MODULE = $(CONFIG_EXAMPLES_XEDGE_DEMO)
|
||||
|
||||
MAINSRC = xedge_main.c
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
240
examples/xedge_demo/xedge_main.c
Normal file
240
examples/xedge_demo/xedge_main.c
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/***************************************************************************
|
||||
* apps/examples/xedge_demo/xedge_main.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* Xedge NuttX Startup Code (may need adjustments)
|
||||
*
|
||||
* Additional License Note: Xedge, based on the Barracuda
|
||||
* App Server, uses the license options explained here:
|
||||
* https://github.com/RealTimeLogic/BAS#license
|
||||
* This repo does not include Xedge and the Barracuda App Server
|
||||
* library and must be downloaded separately. The dependencies
|
||||
* are automatically downloaded in apps/netutils/xedge/.
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
* Included Files
|
||||
***************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
#include <pthread.h>
|
||||
#include <netutils/ntpclient.h>
|
||||
#include <HttpTrace.h>
|
||||
#include <BaDiskIo.h>
|
||||
#include <BaServerLib.h>
|
||||
#include "../../netutils/xedge/BAS/examples/xedge/src/xedge.h"
|
||||
|
||||
/***************************************************************************
|
||||
* Pre-processor Definitions
|
||||
***************************************************************************/
|
||||
|
||||
/* The code uses identifiers from the third-party Barracuda App Server
|
||||
* library, which follows a camelCase naming style:
|
||||
* https://realtimelogic.com/ba/doc/en/C/introduction.html#oo_c
|
||||
* These identifiers are used directly and will trigger "Mixed Case"
|
||||
* warnings in tools like nxstyle, which are safe to ignore in this case.
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
* Private Data
|
||||
***************************************************************************/
|
||||
|
||||
static int running = FALSE; /* Running mode: 2 running, 1 exiting, 0 stopped */
|
||||
|
||||
/* BAS is configured to use dlmalloc for NuttX. This is the pool.
|
||||
* 2M : recommended minimum
|
||||
*/
|
||||
|
||||
static char poolbuf[2 * 1024 * 1024];
|
||||
|
||||
extern LThreadMgr ltMgr; /* The LThreadMgr configured in xedge.c */
|
||||
|
||||
/***************************************************************************
|
||||
* External Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
/* barracuda(): BAS/examples/xedge/src/xedge.c */
|
||||
|
||||
extern void barracuda(void);
|
||||
extern void init_dlmalloc(char *heapstart, char *heapend); /* dlmalloc.c */
|
||||
extern int (*platformInitDiskIo)(DiskIo *io); /* xedge.c */
|
||||
|
||||
/***************************************************************************
|
||||
* Private Functions
|
||||
***************************************************************************/
|
||||
|
||||
/* The following two functions are copied from the example:
|
||||
* https://github.com/RealTimeLogic/BAS/blob/main/examples/xedge/src/led.c
|
||||
* Details:
|
||||
* https://realtimelogic.com/ba/examples/xedge/readme.html#time
|
||||
*/
|
||||
|
||||
/* This callback is called by one of the threads managed by LThreadMgr
|
||||
* when a job is taken off the queue and executed. The callback
|
||||
* attempts to find the global Lua function '_XedgeEvent', and if the
|
||||
* function is found, it will be executed as follows: _XedgeEvent("sntp")
|
||||
*/
|
||||
|
||||
static void execevent(ThreadJob *job, int msgh, LThreadMgr *mgr)
|
||||
{
|
||||
lua_State *L = job->Lt;
|
||||
lua_pushglobaltable(L);
|
||||
lua_getfield(L, -1, "_XedgeEvent");
|
||||
|
||||
if (lua_isfunction(L, -1))
|
||||
{
|
||||
lua_pushstring(L, "sntp");
|
||||
lua_pcall(L, 1, 0, msgh);
|
||||
}
|
||||
}
|
||||
|
||||
/* Thread started by xedgeOpenAUX() */
|
||||
|
||||
static void *checktimethread(void *arg)
|
||||
{
|
||||
ThreadMutex *dm = HttpServer_getMutex(ltMgr.server);
|
||||
const char *d = __DATE__;
|
||||
char buf[50];
|
||||
|
||||
(void)arg;
|
||||
|
||||
if (!(basnprintf(buf, sizeof(buf), "Mon, %c%c %c%c%c %s %s",
|
||||
d[4], d[5], d[0], d[1], d[2], d + 7, __TIME__) < 0))
|
||||
{
|
||||
BaTime t = baParseDate(buf);
|
||||
if (t)
|
||||
{
|
||||
t -= 24 * 60 * 60;
|
||||
while (baGetUnixTime() < t)
|
||||
{
|
||||
Thread_sleep(500);
|
||||
}
|
||||
|
||||
ThreadJob *job = ThreadJob_lcreate(sizeof(ThreadJob), execevent);
|
||||
ThreadMutex_set(dm);
|
||||
LThreadMgr_run(<Mgr, job);
|
||||
ThreadMutex_release(dm);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void panic(BaFatalErrorCodes ecode1,
|
||||
unsigned int ecode2,
|
||||
const char *file,
|
||||
int line)
|
||||
{
|
||||
syslog(LOG_ERR, "Fatal error in Barracuda %d %d %s %d\n",
|
||||
ecode1, ecode2, file, line);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Redirect server's HttpTrace to syslog.
|
||||
* https://realtimelogic.com/ba/doc/en/C/reference/html/structHttpTrace.html
|
||||
*/
|
||||
|
||||
static void flushtrace(char *buf, int buflen)
|
||||
{
|
||||
buf[buflen] = 0;
|
||||
syslog(LOG_INFO, "%s", buf);
|
||||
}
|
||||
|
||||
static void sighandler(int signo)
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
printf("\nGot SIGTERM; exiting...\n");
|
||||
setDispExit();
|
||||
|
||||
/* NuttX feature: Must wait for socket select() to return */
|
||||
|
||||
Thread_sleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Public Functions
|
||||
***************************************************************************/
|
||||
|
||||
/* xedge.c calls this to initialize the IO.
|
||||
* Change "/mnt/lfs" to your preference.
|
||||
*/
|
||||
|
||||
int xedgeInitDiskIo(DiskIo *io)
|
||||
{
|
||||
if (DiskIo_setRootDir(io, "/mnt/lfs"))
|
||||
{
|
||||
syslog(LOG_ERR, "Error: cannot set root to /mnt/lfs\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* xedge.c calls this; include your Lua bindings here.
|
||||
* Tutorial: https://tutorial.realtimelogic.com/Lua-Bindings.lsp
|
||||
*/
|
||||
|
||||
int xedgeOpenAUX(XedgeOpenAUX *aux)
|
||||
{
|
||||
pthread_t thread;
|
||||
pthread_attr_t attr;
|
||||
struct sched_param param;
|
||||
|
||||
(void)aux;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, 4096);
|
||||
param.sched_priority = SCHED_PRIORITY_DEFAULT;
|
||||
pthread_attr_setschedparam(&attr, ¶m);
|
||||
pthread_create(&thread, &attr, checktimethread, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
printf("Already running!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
signal(SIGINT, sighandler);
|
||||
signal(SIGTERM, sighandler);
|
||||
|
||||
ntpc_start();
|
||||
init_dlmalloc(poolbuf, poolbuf + sizeof(poolbuf));
|
||||
HttpTrace_setFLushCallback(flushtrace);
|
||||
HttpServer_setErrHnd(panic);
|
||||
|
||||
running = TRUE;
|
||||
barracuda();
|
||||
running = FALSE;
|
||||
|
||||
printf("Exiting Xedge\n");
|
||||
return 0;
|
||||
}
|
||||
3
netutils/xedge/.gitignore
vendored
Normal file
3
netutils/xedge/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/BAS
|
||||
/BAS-Resources
|
||||
/*.o
|
||||
23
netutils/xedge/Kconfig
Normal file
23
netutils/xedge/Kconfig
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config NETUTILS_XEDGE
|
||||
tristate "Xedge IoT Toolkit Dependencies"
|
||||
depends on ALLOW_GPL_COMPONENTS
|
||||
default n
|
||||
---help---
|
||||
Download and prepare Xedge IoT Toolkit dependencies (BAS and BAS-Resources).
|
||||
|
||||
Xedge is an embedded software toolkit designed to enable high-level developers
|
||||
(e.g., web and Lua programmers) to create sophisticated, secure IoT and industrial
|
||||
device applications. It abstracts low-level embedded development through a lightweight
|
||||
runtime built on top of the Barracuda App Server and Lua.
|
||||
|
||||
This option will download the required Barracuda App Server and BAS-Resources
|
||||
repositories during the build process, making them available for applications
|
||||
that want to use Xedge.
|
||||
|
||||
After enabling this, you can use the examples/xedge_demo as a reference
|
||||
for integrating Xedge into your own applications.
|
||||
35
netutils/xedge/Make.defs
Normal file
35
netutils/xedge/Make.defs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
############################################################################
|
||||
# apps/netutils/xedge/Make.defs
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_NETUTILS_XEDGE),)
|
||||
|
||||
CONFIGURED_APPS += $(APPDIR)/netutils/xedge
|
||||
|
||||
CFLAGS += ${INCDIR_PREFIX}$(APPDIR)/netutils/xedge/BAS/inc
|
||||
CFLAGS += ${INCDIR_PREFIX}$(APPDIR)/netutils/xedge/BAS/inc/arch/Posix
|
||||
CFLAGS += ${INCDIR_PREFIX}$(APPDIR)/netutils/xedge/BAS/inc/arch/NET/Posix
|
||||
|
||||
CFLAGS += -DNO_INIT_DISK_IO
|
||||
CFLAGS += -DUSE_DBGMON=1
|
||||
CFLAGS += -DUSE_IPV6
|
||||
|
||||
endif
|
||||
95
netutils/xedge/Makefile
Normal file
95
netutils/xedge/Makefile
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
############################################################################
|
||||
# apps/netutils/xedge/Makefile
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
BAS_UNPACKNAME = BAS
|
||||
BAS_HASH = 9f74a2f778b002ad8441471b8a7a5b13172dbe76
|
||||
BAS_RESOURCES_UNPACKNAME = BAS-Resources
|
||||
BAS_RESOURCES_HASH = 227a4b998300fa4cfde871dc7dac92c09e1636c2
|
||||
|
||||
BAS_ZIP_URL = https://github.com/RealTimeLogic/BAS/archive/$(BAS_HASH).zip
|
||||
BAS_RESOURCES_ZIP_URL = https://github.com/RealTimeLogic/BAS-Resources/archive/$(BAS_RESOURCES_HASH).zip
|
||||
|
||||
XEDGEZIP = BAS/examples/xedge/XedgeZip.c
|
||||
|
||||
BAS_SRC = $(BAS_UNPACKNAME)$(DELIM)src
|
||||
BAS_ARCH_SRC = $(BAS_SRC)$(DELIM)arch$(DELIM)Posix
|
||||
BAS_NET_SRC = $(BAS_SRC)$(DELIM)arch$(DELIM)NET$(DELIM)generic
|
||||
BAS_DISKIO_SRC = $(BAS_SRC)$(DELIM)DiskIo$(DELIM)posix
|
||||
BAS_XEDGE_SRC = $(BAS_UNPACKNAME)$(DELIM)examples$(DELIM)xedge$(DELIM)src
|
||||
|
||||
VPATH += $(BAS_SRC)
|
||||
VPATH += $(BAS_ARCH_SRC)
|
||||
VPATH += $(BAS_NET_SRC)
|
||||
VPATH += $(BAS_DISKIO_SRC)
|
||||
VPATH += $(BAS_XEDGE_SRC)
|
||||
VPATH += $(BAS_UNPACKNAME)/examples/xedge
|
||||
|
||||
CSRCS = BAS.c dlmalloc.c ThreadLib.c SoDisp.c BaFile.c xedge.c XedgeZip.c
|
||||
|
||||
# Download and prepare BAS and BAS-Resources
|
||||
xedge-deps:
|
||||
# ############################################################################
|
||||
# Config and Fetch xedge
|
||||
# ############################################################################
|
||||
|
||||
@if [ ! -d $(BAS_UNPACKNAME) ]; then \
|
||||
echo "Downloading BAS from hash $(BAS_HASH)..."; \
|
||||
curl -f -L $(BAS_ZIP_URL) -o bas-temp.zip || \
|
||||
(echo "Error downloading BAS"; exit 1); \
|
||||
unzip -q bas-temp.zip; \
|
||||
mv BAS-$(BAS_HASH) $(BAS_UNPACKNAME); \
|
||||
rm -f bas-temp.zip; \
|
||||
fi
|
||||
|
||||
@if [ ! -d $(BAS_RESOURCES_UNPACKNAME) ]; then \
|
||||
echo "Downloading BAS-Resources from hash $(BAS_RESOURCES_HASH)..."; \
|
||||
curl -f -L $(BAS_RESOURCES_ZIP_URL) -o resources-temp.zip || \
|
||||
(echo "Error downloading BAS-Resources"; exit 1); \
|
||||
unzip -q resources-temp.zip; \
|
||||
mv BAS-Resources-$(BAS_RESOURCES_HASH) $(BAS_RESOURCES_UNPACKNAME); \
|
||||
rm -f resources-temp.zip; \
|
||||
fi
|
||||
|
||||
# ############################################################################
|
||||
# Library Configuration
|
||||
# ############################################################################
|
||||
|
||||
@if [ ! -f "$(XEDGEZIP)" ]; then \
|
||||
echo "Creating XedgeZip.c"; \
|
||||
cd $(BAS_RESOURCES_UNPACKNAME)/build/ && \
|
||||
printf "n\nl\nn\n" | bash Xedge.sh > /dev/null && \
|
||||
cp XedgeZip.c ../../$(BAS_UNPACKNAME)/examples/xedge/ || exit 1; \
|
||||
fi
|
||||
|
||||
$(CSRCS:.c=$(OBJEXT)): xedge-deps
|
||||
|
||||
ifeq ($(wildcard $(BAS_UNPACKNAME)/.git),)
|
||||
distclean:: xedge-deps
|
||||
$(call DELDIR, $(BAS_UNPACKNAME))
|
||||
$(call DELDIR, $(BAS_RESOURCES_UNPACKNAME))
|
||||
|
||||
context:: xedge-deps
|
||||
endif
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
Loading…
Add table
Add a link
Reference in a new issue