Building ESP Applications
ESP applications are comprised of ESP layouts, content pages, partial pages, stylesheets, client-side Javascripts, images, databases and server-side controllers. To build an ESP application involves selecting, preparing and processing each of these elements into their final form.
The essential steps in building ESP applications are:
- Templating — Insert page layouts and partial pages into content pages to create composite pages.
- Compile — ESP pages and controllers into machine code and save as shared libraries.
- Transform — Content and resources into desired final formats.
- Select files — Select appropriate file versions and formats (minified or not).
- Post Process — Compress files.
- Package — Bundle and package application for deployment.
One Step Building
The ESP web framework provides an integrated way to easily build ESP applications with a one step command. If you started your application with an ESP skeleton, you will be already configured to use the Expansive web site manager to build your ESP application. Expansive provides comprehensive support for all the steps required to build a web or ESP application.
You do not have to use Expansive to build if you do not wish to. There are other 3rd party web tooling programs that can be used. You can use these tools and then invoke the esp compile command to compile the ESP pages and controllers in your web application. However, the ESP skeletons are created and configured to use Expansive by default to render the site.
To build an ESP application using Expansive, use the expansive render command. For example:
$ expansive render [Render] dist/index.esp [Render] dist/post/edit.esp [Render] dist/post/list.esp [Render] dist/css/all.css [Post] compile-esp [Compile] esp compile [Info] Rendered 5 files to "dist". Elapsed time 0.56 secs.
To see all the steps performed, run with the -v verbose switch.
$ expansive -v render
Compiling
During development ESP will automatically compile controllers and web pages in response to client requests — this happens transparently. Despite the fact that ESP pages and controllers are C code, ESP will deliver "script-like" functionality and if ESP pages or controllers are modified, they will be quickly and automatically recompiled and reloaded. For production releases, however, you typically want to pre-build the application to eliminate the cost of compiling.
The esp command builds the application's ESP pages and controllers via esp compile. This will compile the ESP controllers and web pages and save as machine code binary in shared libraries. When the application is run, it will load the shared libraries for the relevant controllers or web pages from the cache directory without delay.
$ esp compile
This will compile and link all controllers and pages and save the generated shared libraries (DLLs) in the cache directory. If you are using Expansive, you will normally not need to run esp compile as expansive will do that for you.
Compile Filters
If esp compile is run with one or more paths on the command line, these paths will act as filters such that only the designated paths will be compiled. For example:
$ esp compile web/test.esp $ esp compile myapp $ esp compile views $ esp compile /path/to/my/app $ esp compile /directory/of/apps
These paths are interpreted as filenames relative to the current directory. If a controller, web page filename is provided, only that resource will be compiled. If a directory that is part of an MVC application is provided, then all resources under that directory will be compiled. If a directory that is a parent directory of ESP applications or web pages, then all those resources contained by that directory will be compiled.
You may also use the --routeName or --routePrefix switches to select a specific ESP route. Then only the resources managed by that route will be compiled.
Custom Compiler Options
If you have custom compiler flags or libraries, you can pass these to esp by defining the CFLAGS environment variable. For example:
$ CFLAGS="-DMY_MODE=test -lmylib" esp compile
This same approach will work for Expansive.
$ CFLAGS="-DMY_MODE=test -lmylib" expansive render
Compilation Rules
ESP includes a pre-configured set of compilation commands for major operating systems. These are represented as compile and link templates in the /usr/local/lib/esp/*/esp-compile.json. This file is located at /Program Files/Embedthis ESP/bin on windows. If you need to use different compilation options, you can modify this file. Here is a portion:
{ macosx: { compile: '${CC} -c ${DEBUG} -Wall -DPIC -fPIC -arch → ${GCC_ARCH} -I. -I${APPINC} -I${INC} ${SRC} -o ${OBJ}' } }
A better approach than modifying the standard file is to copy it and specify the new file in the esp.compile property in your application's esp.json file. For example:
{ "esp": { "compile": "/path/to/my/esp-compile.json" } }
The various {tokens} are expanded at runtime. The esp-compile.json configuration file has conditional sections for Windows, Mac OS X, Linux and VxWorks.
Keep Source
When compiling ESP pages, the http.keep property in the esp.json file directive will determine if the generated C source code for ESP pages is preserved after compilation. This can sometimes be helpful for debugging. You also preserve the generated source via the esp --keep compile option.
Building for Target Systems
If your target production system is of a different machine architecture or operating system to that of your development system, you will need to either:
- Cross-compile on your development system for the target system.
- Compile the ESP controllers and pages on the target system.
Compiling on the Target
You can re-compile a built ESP application on the target by invoking esp compile on the target. This will compile all ESP controllers and pages for the target architecture. If using Appweb, remember to use appweb-esp compile.
Cross-compiling
If cross-compiling, you must specify the target platform architecture when compiling ESP pages and controllers and then link against a cross-compiled version of ESP for the required target architecture. This means you must build ESP from source for that target, and when compiling ESP applications you can specify the target platform via the --platform switch. For example:
$ esp --platform vxworks-arm-debug compile
This will compile the application for VxWorks on Arm. Of course, the resulting module cannot be run on the development system if cross-compiling. You should issue the compile command from the esp application directory.
If using Appweb, you should issue the appweb-esp command from the Appweb home directory. It is essential that the relative path from the Appweb home directory to the esp application or directory containing the esp pages be identical on the target system to that on the development system when the esp assets were compiled.
The --platform option will search the current directory and parent directories for an ESP platform directory of the same name. You can provide a full path name as an argument to the --platform switch if your application is outside the ESP source tree.
If using Expansive to build, you can define the services.compile-esp.command property in the expansive.json file to set the compilation command used by esp. For example:
{ services: { "compile-esp": { command: 'esp --platform vxworks-arm-debug compile' } } }
Debugging and Optimizing
When development, you often want ESP controllers and pages to be compiled with symbolic debug information. However, for production release, you want compilation to be optimized without debug symbols. The optimization setting can be controlled via the esp.optimize property in esp.json. Set this to true to enable optimization for a production release. Set to false to compile with symbolic debug symbols. Defaults to false.
esp: { optimize: true }
Bundling and Packaging
For deployment in a production environment, it optimal to compile the entire application including all controllers, views and web pages into a single library. This is referred to as combining the application and is enabled by setting the esp.combine property in esp.json to true.
esp: { combine: true }
This will catenate all the controller and view page source into a single file. This is then compiled into a single library. This source file will contain a single initializer function: esp_app_NAME_combine that will register all your controller actions and view pages. If you are using static linking, you must call this function from your main program. For example:
ESP_EXPORT int esp_app_kickstart_combine(HttpRoute *route) { esp_controller_kickstart_port(route); esp_view_b839216b9138e38baf8851c81761c2d5(route); return 0; }
Cleaning
To clean files under the cache directory:
$ esp clean