Wtx ~ Wt Extension Library
WtxLib
Part 1 ~ Creating a Simple (linux) Wt4 "static file" Server from Scratch

This tutorial describes the steps necessary to install Wt-4 on a Linux computer and set up a simple web server, providing a base platform from which to develop sophisticated websites and web services using Wt. These instructions are applicable to the Wt-3 library version also, but this whole tutorial is written for Wt-4.

The steps are (relatively) fairly simple, as follows:

  1. download and install Wt
  2. create a project folder
  3. create project files
  4. build and run project

Note that it is possible to develop and deploy a Wt server a half-dozen different ways. The following notes describe how I do it, and, by no means, should be considered good or proper or right. These procedures work for me. Your mileage may vary.

If you have any comments or suggestions or additions, please email them to me at mark@.nosp@m.lori.nosp@m.marks.nosp@m.olut.nosp@m.ions..nosp@m.com.

1. download and install Wt

Instructions for downloading and installing Wt can be found directly on the Wt website:

https://www.webtoolkit.eu/wt/download

The procedure I use to build Wt is to fetch the source from their git repository directly. This insures that I have the latest source code, and can keep the libraries up to date at any point in time:

mark@lsus1 ~/projects $ git clone https://github.com/emweb/wt.git
Cloning into 'wt'...
remote: Counting objects: 36993, done.
remote: Compressing objects: 100% (272/272), done.
remote: Total 36993 (delta 269), reused 194 (delta 124), pack-reused 36596
Receiving objects: 100% (36993/36993), 29.56 MiB | 2.97 MiB/s, done.
Resolving deltas: 100% (30446/30446), done.
Checking connectivity... done.

There should now be a directory called 'wt' in the project folder, containing all of the Wt source codes. Next step is to enter in to the Wt folder and set up the build environment:

mark@lsus1 ~/projects $ cd wt
mark@lsus1 ~/projects/wt $ mkdir build
mark@lsus1 ~/projects/wt $ cd build
mark@lsus1 ~/projects/wt/build $

Now the source can be compiled. I use a set of build-flags to cause Wt to get installed in to a location that will uniquely separate it from any other Wt installations, allowing me to develop using the Wt3 library set or the Wt4 library set, independently and in parallel. There are a handful of compiler options that you should review to decide what features and functions you want in your library binaries.

There are times when I want to hack the Wt library, but not disturb the existing installation. So what I do is clone the wt directory in to a special directory, do my hacking, change the CMAKE_INSTALL_PREFIX to something different, recompile, install and get to testing.

mark@lsus1:~/projects/wt/build $ cmake \
> -DCMAKE_INSTALL_PREFIX=/opt/Wt4 \
> -DWT_WRASTERIMAGE_IMPLEMENTATION=GraphicsMagick \
> -DCONNECTOR_FCGI=OFF \
> ..
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info - done
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features - done
--
-- much talking...
--
-- Boost version: 1.58.0
-- Found the following Boost libraries:
-- program_options
-- date_time
-- atomic
-- Found png libraries
-- Found libharu libraries
-- Looking for sin
-- Looking for sin - not found
-- Found unsuitable Qt version "5.7.0" from /opt/Qt5.7.0/5.7/gcc_64/bin/qmake
** Wt::Dbo: building Postgres backend.
** Wt::Dbo: not building Firebird backend.
Indicate the location of your FirebirdSQL and IBPP installation using
** Wt::Dbo: not building Microsoft SQL Server backend.
** Disabling ISAPI.
-- Looking for crypt - not found
-- Looking for crypt in crypt
-- Looking for crypt in crypt - found
-- Build files have been written to: /home/mark/projects/wt/build

Placing the /opt/Wt4 on the install prefix setting causes the Wt target libraries to be installed in to that directory location. By installing the Wt libraries in to the /opt folder allows the library to be globally available to any user on the system. You can optionally install to the users /home causing the library to only be available to that user's folder with the following:

mark@lsus1:~/projects/wt/build $ cmake \
> -DCMAKE_INSTALL_PREFIX=~/builds/Wt4 \
> -DWT_WRASTERIMAGE_IMPLEMENTATION=GraphicsMagick \
> -DCONNECTOR_FCGI=OFF \
> ..

Now the library can be built.

mark@lsus1:~/projects/wt/build $ make
Scanning dependencies of target wtdbo
[ 0%] Generating JQuery_js.C
[ 1%] Generating Boot_html.C
[ 1%] Generating Boot_js.C
[ 1%] Building CXX object src/Wt/Dbo/CMakeFiles/wtdbo.dir/Call.C.o
[ 3%] Generating BootstrapTheme_xml.C
[ 3%] Building CXX object src/Wt/Dbo/CMakeFiles/wtdbo.dir/ptr.C.o
[ 3%] Building CXX object src/Wt/Dbo/CMakeFiles/wtdbo.dir/FixedSqlConnectionPool.C.o
[ 4%] Building CXX object src/Wt/Dbo/CMakeFiles/wtdbo.dir/Session.C.o
Scanning dependencies of target wt
--
-- much talking...
-
[ 93%] Linking CXX executable test.http
[ 93%] Building CXX object test/CMakeFiles/test.wt.dir/utf8/XmlTest.C.o
[ 93%] Built target test.http
[ 96%] Building CXX object test/CMakeFiles/test.wt.dir/signals/SignalTest.C.o
[ 96%] Building CXX object test/CMakeFiles/test.wt.dir/wdatetime/WDateTimeTest.C.o
[ 96%] Building CXX object test/CMakeFiles/test.wt.dir/paintdevice/WRasterTest.C.o
[ 96%] Linking CXX executable test.wt
[ 96%] Built target test.wt
[ 98%] Linking CXX executable test.sqlite3
[ 98%] Built target test.sqlite3
[100%] Linking CXX executable test.postgres
[100%] Built target test.postgres

Now we can install the library.

mark@lsus1:~/projects/wt/build $ sudo make install
[sudo] password for serveradmin:
[ 74%] Built target wt
[ 75%] Built target wttest
[ 80%] Built target wtdbo
[ 80%] Built target wtdbopostgres
[ 93%] Built target test.wt
[ 98%] Built target wthttp
[100%] Built target test.http
Install the project...
-- Install configuration: "RelWithDebInfo"
-- Up-to-date: /opt/Wt4/share/Wt//resources
-- Up-to-date: /opt/Wt4/share/Wt//resources/collapse.gif
--
-- much talking...
--
-- Up-to-date: /opt/Wt4/include/Wt/Render/WTextRenderer.h
-- Up-to-date: /opt/Wt4/include/Wt/Render/WPdfRenderer.h
-- Up-to-date: /opt/Wt4/lib/libwthttp.so
-- Installing: /opt/Wt4/lib/cmake/wt/wt-target-http-relwithdebinfo.cmake

Now in the /opt folder should be the Wt folders and files from the installation.

mark@lsus1:~/projects/wt/build $ ll /opt/Wt4
total 28
drwxr-xr-x 7 root root 4096 Oct 11 2017 ./
drwxrwxr-x 8 root root 4096 May 1 10:56 ../
drwxr-xr-x 3 root root 4096 Oct 11 2017 etc/
drwxr-xr-x 3 root root 4096 Oct 11 2017 include/
drwxr-xr-x 3 root root 4096 May 20 16:14 lib/
drwxr-xr-x 3 root root 4096 Oct 11 2017 share/
drwxr-xr-x 3 root root 4096 Oct 11 2017 var/

You now have the Wt library built from source and installed on your system. You're ready to build your first application.

2. create a project folder

When building Wt project, I like to stick with a fairly straight forward project folder setup. I keep the build files and source files separated and I use symbolic links to reference the resources folders and whatnot.

Make the project folder:
mark@lsus1:~/projects $ mkdir demoapp
mark@lsus1:~/projects $ cd demoapp
mark@lsus1:~/projects/demoapp $ mkdir src
mark@lsus1:~/projects/demoapp $ mkdir build
mark@lsus1:~/projects/demoapp $ cd src
mark@lsus1:~/projects/demoapp/src $ mkdir docroot
mark@lsus1:~/projects/demoapp/src $ cd ../build
mark@lsus1:~/projects/demoapp/build $ ln -s ../src/docroot docroot
mark@lsus1:~/projects/demoapp/build $ ll
total 4
drwxrwxr-x 1 mark mark 14 May 21 06:20 ./
drwxrwxr-x 1 mark mark 16 May 21 06:20 ../
lrwxrwxrwx 1 mark mark 14 May 21 06:20 docroot -> ../src/docroot/
mark@lsus1:~/projects/demoapp/build $ cd ..
mark@lsus1:~/projects/demoapp $ tree
.
├── build
│   └── docroot -> ../src/docroot
└── src
└── docroot
4 directories, 0 files

The 'src' and 'build' folders are pretty straight forward, and fairly common to find in most projects. But what is the 'docroot' folder?

The 'docroot' folder is the 'web-server-files' folder. This is the folder that (typically) contains everything the web server is going to 'serve' up to the browser. Any static html files (such as index.html) and image files are all served from this set of folders.

There is another folder that our webserver is going to be needing. When we built and installed Wt, the installation included a folder called '/opt/Wt4/share/Wt/resources'. This folder contains a whole pile of css files and other files that Wt likes to use. It is not an absolute requirement that the 'resources' folder be available to the Wt server, but when the web pages start to get constructed you'll find that some of the web-page formatting doesn't work without the resources folder. But, we'll be dealing with that in the next tutorial...

3. create project files

There are a few steps here to setting up a new project. These steps include creating the source file, creating the make file, creating the launch file, and so on. Hang in there while we work through these.

3.1 create the main.cpp

The main.cpp source file is very simple (for now):

mark@lsus1:~/projects/demoapp $ cd src
mark@lsus1:~/projects/demoapp/src $ cat main.cpp
#include <Wt/WServer.h>
int main(int argc, char** argv)
{
try
{
Wt::WServer server( argc, argv );
server.run();
}
catch( Wt::WServer::Exception & e )
{
std::cerr << e.what() << std::endl;
return -1;
}
return 0;
}

3.2 create the 'make' file

Now we need a 'make' file. The 'make' file contains all the codes necessary for identifying all the source files and library files that are required to get the project built. I use 'cmake' to generate my make files.

The CMakeLists.txt file is used by cmake to generate the make files for the project. This file should be placed in the root or the project directory tree:

mark@lsus1:~/projects/demoapp $ ls -la
total 4
drwxrwxr-x 1 mark mark 44 May 21 11:52 .
drwxrwxr-x 1 mark mark 304 May 21 06:19 ..
drwxrwxr-x 1 mark mark 14 May 21 06:20 build
-rw-rw-r-- 1 mark mark 293 May 21 11:52 CMakeLists.txt
drwxrwxr-x 1 mark mark 14 May 21 06:20 src
mark@lsus1:~/projects/demoapp $ cat CMakeLists.txt
cmake_minimum_required (VERSION 2.6)
set ( CMAKE_CXX_FLAGS "-std=c++17 -Wfatal-errors -g" )
add_definitions(-std=c++17)
include_directories(/opt/Wt4/include)
link_directories(/opt/Wt4/lib)
project(demoapp)
add_executable(demoapp src/main.cpp)
target_link_libraries(demoapp wt wthttp)

This very minimal CMakeLists.txt file contains just enough instruction to be able to compile and link a simple Wt application. The name of the application is going to be 'demoapp' and it is going to be based on the compiled contents of the main.cpp file found in the 'src' directory. This cmake file also directs where the compiler should go to look for the include files for the Wt installation.

Now it's time to generate the 'make' files inside the 'build' folder and get ready to compile the application.

mark@lsus1:~/projects/demoapp$ cd build
mark@lsus1:~/projects/demoapp/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mark/projects/demoapp/build

...and make it!

mark@lsus1:~/projects/demoapp/build$ make
[ 50%] Building CXX object CMakeFiles/demoapp.dir/src/main.cpp.o
[100%] Linking CXX executable demoapp
[100%] Built target demoapp

If everything worked correctly, you should end up with a handful of files in the build folder, containing a properly (and successfully) compiled executable binary

mark@lsus1:~/projects/demoapp/build$ ls -la
total 48
drwxrwxr-x 1 mark mark 130 May 21 17:52 .
drwxrwxr-x 1 mark mark 72 May 21 17:48 ..
-rw-rw-r-- 1 mark mark 11554 May 21 17:48 CMakeCache.txt
drwxrwxr-x 1 mark mark 388 May 21 17:52 CMakeFiles
-rw-rw-r-- 1 mark mark 1377 May 21 17:48 cmake_install.cmake
-rwxrwxr-x 1 mark mark 20392 May 21 17:52 demoapp <---------------- this is the executable
lrwxrwxrwx 1 mark mark 14 May 21 06:20 docroot -> ../src/docroot
-rw-rw-r-- 1 mark mark 4860 May 21 17:48 Makefile

Now the server should run. There are a few command line parameters that are required, I'll go through those one at a time.

mark@lsus1:~/projects/demoapp/build$ ./demoapp --http-address 0.0.0.0 --http-port 8910 --docroot=docroot
[2018-May-21 17:57:45.971] 3776 - [info] "config: reading Wt config file: /opt/Wt4/etc/wt/wt_config.xml (location = './demoapp')"
[2018-May-21 17:57:45.972] 3776 - [info] "WServer/wthttp: initializing built-in wthttpd"
[2018-May-21 17:57:45.972] 3776 - [info] "wthttp: started server: http://0.0.0.0:8910"
http-address
this sets the 'listening' address. If set to 0.0.0.0 then the server will listen on any interface.
http-port
this sets the listening port. This has to be a port that is available to an ordinary mortal, unless you plan to run the server as root (bad idea, double-unrecommended)
docroot
this is the server document root folder. Files placed in this folder become visible to browsers.

For a complete description on the command line parameters for the Wt server, you can refer to the Wt documentation directly at https://www.webtoolkit.eu/wt/doc/reference/html/InstallationUnix.html

With the server now running, you should be able to browse to it with any browser. When you do, the server will spit out a handful of messages indicating that it was poked by someone. If the browser is pointed to http://localhost:8910 you should see a "404 Not Found" message in the browser window. And this is what you should see on the server:

mark@lsus1:~/projects/wt/demoapp/build$ ./demoapp --http-port 8910 --http-address 0.0.0.0 --docroot=docroot
[2018-May-21 18:08:31.729] 10836 - [info] "config: reading Wt config file: /opt/Wt4/etc/wt/wt_config.xml (location = './demoapp')"
[2018-May-21 18:08:31.730] 10836 - [info] "WServer/wthttp: initializing built-in wthttpd"
[2018-May-21 18:08:31.730] 10836 - [info] "wthttp: started server: http://0.0.0.0:8910"
192.168.1.33 - - [2018-May-21 18:08:39.274] "GET / HTTP/1.1" 404 85 <--------------- note the request, and 404 response

If you attempt to call up a file with the browser, you will see something on the order of "404 Not Found" and on the server, you should see the request for the page, and the 404 code that it was not found:

[2018-May-23 14:22:25.703] 19664 - [info] "config: reading Wt config file: /opt/Wt4/etc/wt/wt_config.xml (location = './demoapp')"
[2018-May-23 14:22:25.704] 19664 - [info] "WServer/wthttp: initializing built-in wthttpd"
[2018-May-23 14:22:25.704] 19664 - [info] "wthttp: started server: http://0.0.0.0:8910"
192.168.1.33 - - [2018-May-23 14:22:38.776] "GET /testpage.html HTTP/1.1" 404 85 <--------- request for page that doesn't exist

To satisfy the request for a file, it is now a simple matter of adding the file to the 'docroot' folder, and it will be immediately available to the browser:

mark@lsus1:~/projects/wt/demoapp/build/ $ echo "<html><body>this is a test</body></html>" > docroot/testpage.html
mark@lsus1:~/projects/wt/demoapp/build$ ./demoapp --http-port 8910 --http-address 0.0.0.0 --docroot=docroot
[2018-May-23 14:26:24.632] 22345 - [info] "config: reading Wt config file: /opt/Wt4/etc/wt/wt_config.xml (location = './demoapp')"
[2018-May-23 14:26:24.633] 22345 - [info] "WServer/wthttp: initializing built-in wthttpd"
[2018-May-23 14:26:24.633] 22345 - [info] "wthttp: started server: http://0.0.0.0:8910"
192.168.1.33 - - [2018-May-23 14:26:28.135] "GET /testpage.html HTTP/1.1" 200 41 <------ wholla! file was found, fetched, and displayed!

What happened here is, the WServer engine started up and immediately created what's called a static "file" resource (WFileResource) and directed it to respond to HTTP requests for files located in the docroot folder. This was automatic and handy because the docroot folder is likely to fill up with all kinds of site-support files, such as static html files and images, and it also is going to contain the Wt 'resources' that contains all the .css formatting files, and the only thing you needed to do to have that happen is specify the docroot folder location. Pretty sniffty!

So you now have a "static file" web server, in Wt, ready to serve up static files. These files can be of any type, html, binary, pdf... you name it. But they are static, and, so therefore, you're not really using the "phenominal cosmic powa" of Wt... but, fret not, that's next!

Tune in to Part 2 ~ Creating an "active" web server with Wt to turn this 'static-file' server in to an actual "active" Wt web server with real-live widgets.

Notes on cmake and Qt
https://blog.kitware.com/cmake-finding-qt5-the-right-way/