Monday, September 19, 2016

Create a Windows Installer using CMake and CPack

CMake can be used to create a Windows installer with CPack and NSIS (Nullsoft Scriptable Install System). NSIS can be downloaded from http://nsis.sourceforge.net. This post follows and extends the tutorial from the CMake Wiki at https://cmake.org/Wiki/CMake:Component_Install_With_CPack.

I wanted to build a Windows installer for a 64 bit Visual Studio application that was build-managed using CMake. This post makes use of the example source code downloadable from https://cmake.org/Wiki/File:ComponentExampleStart.zip.

Add in CPACK macros to CMakeLists.txt
  1. Download and extract the example zip file into a folder e.g. D:\Temp\ComponentExampleStart\ as shown below. I then created a build sub-folder build underneath the D:\Temp\ComponentExampleStart\Source\ folder.
  2. Use a text editor and edit the CMakeLists.txt file to add in CPACK macros according to the Wiki. An edited example is shown below.
cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
project(MyLib)

add_library(mylib mylib.cpp)

add_executable(mylibapp mylibapp.cpp)
target_link_libraries(mylibapp mylib)

install(
  TARGETS mylib 
  ARCHIVE
  DESTINATION lib
  COMPONENT libraries
  )
install(
  TARGETS mylibapp
  RUNTIME
  DESTINATION bin
  COMPONENT applications
  )
install(
  FILES mylib.h
  DESTINATION include
  COMPONENT headers
  )
#
# CPACK macros below here
#
set (CPACK_PACKAGE_NAME "MyLib")
set (CPACK_PACKAGE_VENDOR "CMake.org")
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyLib - CPack Component Installation Example")
set (CPACK_PACKAGE_VERSION "1.0.0")
set (CPACK_PACKAGE_VERSION_MAJOR "1")
set (CPACK_PACKAGE_VERSION_MINOR "0")
set (CPACK_PACKAGE_VERSION_PATCH "0")
set (CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example")

# Define components and their display names
set (CPACK_COMPONENTS_ALL applications libraries headers)
set (CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "MyLib Applications")
set (CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
set (CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")

# Human readable component descriptions
set (CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
  "An extremely useful application that makes use of MyLib")
set (CPACK_COMPONENT_LIBRARIES_DESCRIPTION
  "Static libraries used to build programs with MyLib")
set (CPACK_COMPONENT_HEADERS_DESCRIPTION
  "C/C++ header files for use with MyLib")

# Define dependencies between components
set (CPACK_COMPONENT_HEADERS_DEPENDS libraries)

# Define groups
set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_HEADERS_GROUP "Development")

set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
   "All of the tools you'll ever need to develop software")

# Define NSIS installation types
set(CPACK_ALL_INSTALL_TYPES Full Developer)
set(CPACK_COMPONENT_LIBRARIES_INSTALL_TYPES Developer Full)
set(CPACK_COMPONENT_HEADERS_INSTALL_TYPES Developer Full)
set(CPACK_COMPONENT_APPLICATIONS_INSTALL_TYPES Full)
 
# Must be after the last CPACK macros
include(CPack)

Generate the Visual Studio solution

  1. Open up a Command Prompt. Change to the build directory.

    D:> cd \temp\ComponentExampleStart\Source\build
  2. Use the cmake command to generate the build files.

    D:> cmake -G "Visual Studio 14 2015 Win64" ..

    The build files are generated.
Build the Visual Studio solution and generate the installer
  1. Using Visual Studio, open up the generated solution e.g. MyLib.sln.

  2. Since I wanted a release build, in Visual Studio I changed from Debug to Release, as shown below. Then I selected Build.

    The release binaries are generated.
  3. Next, in the Solution Explorer, select and mouse right click on the PACKAGE project.

    A pop down menu appears.
  4. Choose Build.



    CPack processing message appears.


    The NSIS installer is generated.


Monday, September 12, 2016

C++ example code for reading an Sqlite database from multiple threads

SQLite works well with threads as long as a single thread has its own database connection, or so they say in the documentation. I wanted to make a lot of database read only select calls on a table from multiple threads and I coded my C++ program according to the guidelines. But I found out some of the threads will get a "database is locked" exception after a while, and any subsequent calls to the database will raise a "library routine called out of sequence" exception. Changing the SQL connection to other types such as SQLITE_OPEN_FULLMUTEX, SQLITE_OPEN_NOMUTEX, and or permutations did not solve my problem.

Eventually I decided on a workaround to give each thread an in-memory copy of the database. The following code snippets show a simple example. The example uses the light weight C++ SQLite wrapper from https://github.com/aminroosta/sqlite_modern_cpp

The runThread function creates a copy of the original source database example.sqlite and puts it in memory with a unique connection string. Subsequently, it performs some read operations on the in-memory database.
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
int runThread(int threadNumber) {
 try {
  cout << "[" << threadNumber << "]" << "Running" << endl;
  stringstream ss;

  // Form the connection string to the in-memory database
  ss << "file:memory" << threadNumber << "?mode=memory";
  string inMemoryDbConnectString = ss.str();
  ss.str("");

  // Open a database connection to the in-memory database
  database inMemoryDb(inMemoryDbConnectString);

  // Open a database connection to the original source database
  database sourceDb("example.sqlite");

  // Copy the source database to memory
  auto sourceConnection = sourceDb.connection();
  auto state = 
   std::unique_ptr<sqlite3_backup, decltype(&sqlite3_backup_finish)>(
    sqlite3_backup_init(inMemoryDb.connection().get(), "main", sourceConnection.get(), "main"),
    sqlite3_backup_finish
    );
  if (state) {
   int rc;
   // Each iteration of this loop copies 500 database pages from database db to the backup database.
   do {
    rc = sqlite3_backup_step(state.get(), 500);
//std::cout << "Remaining " << sqlite3_backup_remaining(state.get()) << "/" << sqlite3_backup_pagecount(state.get()) << "\n";
   } while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED);

   // Do some reading from the in-memory database table
   for (int i = 0; i < 10000; i++) {

    double seconds = 452220.0 + (double)threadNumber + (double)i;
    double lower = seconds - 1;
    double upper = seconds + 1;

    ss
     << "SELECT seconds, x, y, z FROM attendance WHERE seconds >="
     << lower
     << " AND seconds <="
     << upper
     << " ORDER BY seconds ASC";

    inMemoryDb << ss.str() >> [&](
     double seconds, double x, double y, double z) {

     // do something with the returned records

    };
    ss.str("");
   }
  }
 }
 catch (sqlite_exception &e) {
  cout << "[" << threadNumber << "]" << "Error:" << e.what() << endl;
 }
 cout << "[" << threadNumber << "]" << "End" << endl;

 return 0;
}


Finally, the main function that creates multiple threads and waits for them to complete.

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
int main(int argc, char **argv)
{
 // Create threads and put them into an array
 thread threads[3];
 for (int i = 0; i < 3; i++) {
  threads[i] = thread(runThread, i);
 }

 // Wait for the threads to complete
 for (int i = 0; i < 3; i++) {
  threads[i].join();
 }

 return 0;
}

An screenshot of the program in execution. Since each thread has a copy of the database, the database is never locked by other threads and I will never encounter the "database is locked" exception.

Note that this workaround will not work if read and write operations are required.


Tuesday, August 30, 2016

Identifying deprecated classes and methods in Android Studio with "Recompile with -Xlink:deprecation"

When upgrading an Android project to a newer Android version, Google may deprecate some of the previously used Android classes and methods. By default, the gradle compilation process will only print out a summary message "Some input files use or override a deprecated API", as shown in the Android Studio screenshot below:

To enable the compilation process to print out a verbose message of the deprecated API, one or more of the build.gradle file may need to be edited to add in the -Xlint:deprecation option. In the example, the top most or project level build.gradle file was edited.


  1. In Android Studio, open up the project build.gradle file. Scroll to the allprojects section.


  2. Add in the gradle.projectsEvaluated sub section with the -Xlint:deprecation option as shown below.

  3. Save. Now when building the Android project, the deprecated API will be printed in the console.


Monday, August 22, 2016

WebApp for viewing City of Tulsa, Oklahoma's Fire Department's dispatches

Users can make use of this WebApp to monitor the City of Tulsa, Oklahoma's Fire Department fire dispatch data (updated every minute) on a Google Maps backdrop. The incidents are shown as clickable icons with tool tips on Google Maps. Clicking an icon will bring up more details about the incident.

Users can utilise additional built-in Google Maps features such as Street View to immerse themselves into the environment of the incident.

The pane on the right can display a list of the fire incidents. The list can be sorted by category, date-time and address - either in ascending or descending order. Clicking the Maps hyperlink will automatically locate, zoom and center the incident in the Map View.

The WebApp can be launched from this link https://dominoc925-pages.appspot.com/webapp/tulsa911mon/.

Monday, August 15, 2016

Use CMake to develop an SQLite Visual Studio C++ application

I wanted to write a Windows 64 bit C++ executable that makes use of a SQLite database using CMake to generate a Visual Studio solution.

Prepare SQLite

  1. The simplest way to use SQLite in my code is to download and use the amalgamated source files and binaries from the SQLite website https://www.sqlite.org/download.html.
  2. Extract the amalgamated SQLite source files into a folder e.g. c:\path\to\sqlite\include\.


  3. Extract the compiled SQLite binaries into a folder e.g. c:\path\to\sqlite\lib\.

  4. In order to link the SQLite dll into a C++ executable, the dll needs to have a exported library. This can be done by opening a Visual Studio Command Prompt. Select Start | Visual Studio 2015 | VS2015 x64 Native Tools Command Prompt.
  5. In the Command Prompt, change directory to the location of the SQLite binaries e.g. C:\path\to\sqlite\lib\. Type in the LIB command:

    C:\> LIB /def:sqlite3.def


    The files sqlite3.lib and sqlite3.exp are generated.

Create your application's CMakeLists.txt
  1. In your C++ application's root folder e.g. C:\path\to\sqliteexample\, use a text editor to create a CMakeLists.txt file.

  2. In the CMakeLists.txt, define the SQLite library name and locations of the headers and library, as shown below.
An example CMakeLists.txt

cmake_minimum_required(VERSION 2.8.6)
project(sqliteexample)

# compile all *.cpp files
file (GLOB SOURCES "src/*.cpp")

# define libraries to link to final executable
set (PROJECT_LINK_LIBS sqlite3.dll)

# define the sqlite header include file directory
set (SQLITE_INCLUDE ../sqlite/include)

# define the sqlite link library directory
set (SQLITE_LINK_DIR ../sqlite/lib)

# define the directories to search for libraries
link_directories ( ${SQLITE_LINK_DIR})

# define the directories to search for headers
include_directories (include ${SQLITE_INCLUDE})

# define the final executable
add_executable(sqliteexample ${SOURCES})

# define the libraries to link to the final executable
target_link_libraries (sqliteexample ${PROJECT_LINK_LIBS})


Generate the Visual Studio solution files

  1. Write the C++ source code e.g. main.cpp in the C++ application source folder e.g. C:\path\to\sqliteexample\src\.
  2. Create a build folder underneath the C++ application root folder e.g. C:\path\to\sqliteexample\.
  3. Open up the Visual Studio x64 Command Prompt. Change directory to the build folder, e.g. C:\path\to\sqliteexample\build\.
  4. In the Command Prompt, type in the cmake command:

    C:\> cmake -G "Visual Studio 14 2015 Win64" ..


    The Visual Studio solution files are generated.

  5. Next, open up the generated Visual Studio solution e.g. sqliteexample.sln in Visual Studio.
  6. Select Build | Build Solution to compile your SQLite C++ application.

Monday, August 8, 2016

Use CMake to help build and use a Windows dll

I wanted to use Windows c++ classes and use them in another c++ applications through shared Windows DLLs, while using CMake to generate build files and Visual Studio to compile into final executables. I spent some time figuring out how to do it and the following steps illustrate a simple example.

Create a Windows DLL
The first step is to create a Windows DLL and export the functions that will be called by other methods.

Listing of Animal.h
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <string>

using namespace std;

class Animal {
private:
    string name;
public:
    Animal(string);
    virtual void print_name();
};

Listing of Animal.cpp
1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <iostream>
#include "Animal.h"

using namespace std;

Animal::Animal(string name):name (name){}

void Animal::print_name(){
    cout << "Name is " << this->name << endl;
}

The Animal.h and Animal.cpp files are placed in the include and src folders under the [example root folder]\animallib_shared\ folder, as shown below.


The next thing to do is to create the CMakeLists.txt in the Windows DLL project e.g. [example root folder]\animallib_shared\ folder.
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cmake_minimum_required(VERSION 2.8.6)
project (animallib)
set (CMAKE_BUILD_TYPE Debug)

#include *.h files under include folder and  
#the project's output folder e.g. Debug
include_directories (include ${PROJECT_BINARY_DIR})

#compile all *.cpp source files under src folder
file (GLOB SOURCES "src/*.cpp")

#output library as animallib.*

#output library export file *.lib and
#output macro definitions include file
include (GenerateExportHeader)
add_library(animallib SHARED ${SOURCES})
GENERATE_EXPORT_HEADER (animallib
    BASE_NAME animallib
    EXPORT_MACRO_NAME animallib_EXPORT
    EXPORT_FILE_NAME animallib_Export.h
    STATIC_DEFINE animallib_BUILT_AS_STATIC
)

Next, we have to modify the header (*.h) and source code (*.cpp) files to add in the Windows export macro animallib_EXPORT and cmake generated header file animallib_Export.h.
Listing of modified animal.h
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <string>

#include "animallib_Export.h"

using namespace std;

class Animal {
private:
    string name;
public:
    animallib_EXPORT Animal(string);
    virtual animallib_EXPORT void print_name();
};
Listing of modified Animal.cpp

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <iostream>
#include "Animal.h"

#include "animallib_Export.h"

using namespace std;

animallib_EXPORT Animal::Animal(string name):name (name){}

animallib_EXPORT void Animal::print_name(){
    cout << "Name is " << this->name << endl;
}

Open up a Windows Command prompt and change directory to the build folder of the Windows DLL project e.g. [example root folder]\animallib_shared\build\ folder.

Type in the cmake command (assuming cmake is in the PATH environment variable):
C:> cd \path\to\example\animallib_shared\build
C:> cmake ..
Build files are generated
The generated build files
Open up the generated Visual Studio solution file [example root folder]\animallib_shared\build\animallib.sln in Visual Studio. Then select Build | Build Solution to compile the Windows DLL.
Compilation messages
The generated *.dll and export library *.lib files under [example root folder]\animallib_shared\build\Debug\
Using the Windows DLL in a separate C++ application
Now that the Windows DLL has been generated and the functions exported, the next thing is to use the DLL's classes and functions in an application e.g. UseAnimalLib project under [example root folder]\useanimallib\]

Listing of uselib.cpp

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include "Animal.h"

#include "animallib_Export.h"

int main(int argc, char *argv[]){
    //Create a new animal instance with name Dog
    Animal animal("Dog");

    //try to call the class's print_name method
    animal.print_name();
    return (0);
}

Then create a CMakeLists.txt file under the [example root folder]\useanimallib\ folder.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
cmake_minimum_required(VERSION 2.8.6)
project (UseAnimalLib)

set (EXAMPLE_DIR d:/path/to/example/root/folder)

set (PROJECT_LINK_LIBS animallib.dll)
link_directories (${EXAMPLE_DIR}/animallib_shared/build/Debug)

include_directories (${EXAMPLE_DIR}/animallib_shared/include ${EXAMPLE_DIR}/animallib_shared/build)

#compile all *.cpp source files under src folder
file (GLOB SOURCES "src/*.cpp")

add_executable(uselib ${SOURCES})
target_link_libraries (uselib ${PROJECT_LINK_LIBS})

Open up a Windows Command Prompt. Change directory to the [example root folder]\useanimallib\build folder.
C:> cd \path\to\example\useanimallib\build
C:> cmake ..

The build files are generated



The generated build files


Open up the generated solution file e.g. [example root folder]\useanimallib\build\Debug\uselib.sln using Visual Studio and build the solution.
Building the solution
The executable that uses the Windows DLL can now be run in a Command Prompt, assuming the DLL is in the PATH environment variable, as shown below.

Monday, August 1, 2016

Resolving com.android.build.api.transform.TransformException for task transformClassesWithDexForDebug

I encountered an Android Studio build exception while compiling an Android application to run on a device. The error message is shown in the screen shot below:


The message about classes and Dex gave a huge clue about the cause of the exception; I came across somewhere that there is a limit to the number of classes in a Dex file and Google Play Services use a lot of classes. My app's build.gradle has the dependency to the full com.google.android.gms:play-services:x:x:x file, as shown below.



So one method to reduce the number of classes is to use subsets of the Google Play Services library. Instead of the full com.google.android.gms:play-services dependency, my build.gradle file now has the following dependency line:
compile 'com.google.android.gms:play-services-maps:x.x.x'

Following this change, the application builds successfully, as shown in the console screen shot below.


Related Posts with Thumbnails