Main  /  Edit  /  History  /   /  Users Area

Templates: Building and Loading (v 1.x)

Overview

The process of building CppCMS templates is following:

  1. Compile all sources of specific view together into single C++ file using cppcms_tmpl_cc.
  2. Compile C++ file into object file.
  3. Link it together with program or create dynamically loadable object that can be loaded by CppCMS program.

Creation of C++ code

Can be done by invoking cppcms_tmpl_cc with a list of files, for example:

cppcms_tmpl_cc -o view.cpp main.tmpl page.tmpl article.tmpl

Note, when you derive classes from parents, you should compile them together in correct order.

For example for following hierarchy.

            [master]
          /         \
    [page]           [summary]
    /    \           /       \
[post] [info.] [archive] [recent_posts]

You should compile files as:

cppcms_tmpl_cc master.tmpl page.tmpl post.tmpl \
               info.tmpl summary.tmpl archive.tmpl \
               recent_posts.tmpl -o my_view.cpp

When you share some templates between various skins, and compile all then using empty skin name. You should specify parameter: -s skin_name.

By default, templates compiler puts all translation strings in the domain that is named by skin name. So if you compile with -s skin1 all you strings would be taken from skin1 domain. It can be overridden by specifying -d domain_name switch.

Generally you want to put all skins to same domain as the main program.

How templates are loaded

Each C++ file that is generated from the template includes static global constructor that registers all classes of specific view in libcppcms.

When programmer wants to use some class from specific view he calls render() function of application class that seeks for registered skins and uses them.

Thus, everything you need to do is link this object with your library or load it dynamically.

Static Linking with Compiled Object

This is the simplest way to add the template, for example:

cppcms_tmpl_cc -o view.cpp master.tmpl ...
g++ -O2 -Wall view.cpp -o view.o
g++ application_objects.o view.o -lcppcms -o app

Using Libraries of Views

Sometimes, you may create a library of several views and try to link with them. For example:

g++ -fPIC -DPIC view1.cpp -o view1.o
g++ -fPIC -DPIC view2.cpp -o view2.o
g++ -shared view1.o view2.o -lcppcms -o libview.so

Now you link this library directly with your program:

g++ application_objects.o -L. -lview -lcppcms -o app

You can also create static library and link with it.

g++ view1.cpp -o view1.o
g++ view2.cpp -o view2.o
ar cru libview.a view1.o view2.o
ranlib libview.a

Now, if you link static the library as is, it would not work!!! At least with GNU linker.

GNU linker "optimizes" the code and discovers that there is no symbols in application objects that refer to the symbols of libview.a and would not include it in link process.

In order to make everything work you should link as following:

g++ application_objects.o \
  -Wl,--whole-archive libview.a -Wl,--no-whole-archive \
  -lcppcms -o app

It would force the linker include all objects from libview.a and cause everything work correctly.

Note: You do not need this for dynamically loaded libraries like so or dll. Because, by default they include whole archive.

Dynamic Loading of Views

You have an option load all views dynamically from shared object or dll. This option have following restrictions:

  1. You should compile your program with --export-dynamic or -rdynamic option, otherwise dynamic casting would not work and you'll get error "incorrect content type" trying to render your skins.
  2. Windows platform has strong restriction on undefined symbols in dll's. Thus you should not refer directly to any undefined member functions of your content objects, otherwise you would get linker errors trying to build dll.

    In order to override this and still call functions placed in content class, you may define its members as virtual or just use std, std::tr1, booster or boost function class for callback

  3. Windows skin dlls require link to booster library along with cppcms library as well.

    And the link must be dynamic, i.e. skin dll should be linked to cppcms.dll and booster.dll.

For example:

Build your loadable view:

cppcms_tmpl_cc -o view.cpp master.tmpl ...
g++ -fPIC -DPIC view.cpp -o view.o
g++ -shared view.o -lcppcms -o libview.so

Link your program

g++ --export-dynamic app_objects.o -lcppcms -o app

Now add to your configuration file path to directory where libview.so is placed.

  1. views.paths configuration should be an array of strings where each string represents the path to location of the views.
  2. views.skins is an array strings - skins names that should be loaded
  3. views.default_skin allows you to specify the default skin that should be used, if not defined the first one in views.skins will be used.
  4. views.auto_reload boolean variable allow you to enable auto-reloading skins for faster debugging, where the application would reload the dll or shared object if it was recompiled without restarting the application.

    Note: this may significantly reduce application performance. Use this only for debugging.

For example, a part of config.js:

"views" : {
  "paths" : [ "/usr/lib/app" , "/usr/local/lib/app" ],
  "skins" : [ "blue", "orange" , "green" ] 
}

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page



Valid CSS | Valid XHTML 1.0