Static link sqlite in Lazarus - sqlite

I am building an application with Lazarus where I use a sqlite database to store thousands of records. Right now I am linking to the sqlite library dynamically via the sqlite3.dll.
Is it possible to link to it statically? Where can I find the Lazarus compatible lib file to do that?
Note:
I only started using Lazarus and Free Pascal a month ago so something that might look very obvious to one, might not be for me. So bear with me a bit.
Cheers

Actual static linking is difficult since the TSQLite3Connection component is inherently designed to actively load the SQLite3 DLL. In other words, it's not linking against the library when you compile the program, the component is coded to dynamically load the DLL at run time.
If you are looking to have a totally self contained program, then you can accomplish this two different ways.
Create a new TSQLite3Connection component that links statically against sqlite3 instead of loading the DLL dynamically.
Include the sqlite3.dll as a resource in your program and have your program automatically deploy it before it runs.
Solution #1 is not trivial and not for the faint of heart. I've done it, and I intended to include a link to the component, but the result isn't stable. The problem is that you have to compile a static version of sqlite3, which isn't a real problem, but you have to do it with something like gcc under MinGW and that introduces issues. Compiling with gcc under MinGW means you have to then link in libgcc.a, and because FreePascal's internal linker doesn't know how to interpret stdcall symbols properly, you also have to link against MinGW's libkernel32.a, and libmsvcrt.a. The result just isn't stable. Crashes galore.
Solution #2 should be fairly easy, but the Lazarus maintainers make it a little hard. The part where you store the dll inside the executable as a resource is easy enough to do. And so is writing it out as a temp file. The problem is that you can't tell the TSQLite3Connection component where to find it after. So it looks in the executable's folder, or in system folders. Neither of which can necessarily be written to by the executable. The only place you can guarantee that your program will be able to write to is a temp folder. So what I did is created a new version of TSQLite3Connection component call TSQLite3DynConnection, meaning you can dynamically specify where the DLL is. I made a published property called ClientLibrary where you can specify the location of the dll (it doesn't have to end in .dll, so you can use system temp filename generation routines). You can get this component at: http://icculus.org/~kfitzner/misc/sqlite3dyndll.zip. It will compile against Lazarus 1.6.2 FP 3.0.0, or FP 1.0.6 / FP 2.6.0, which are the two versions I use.
I'll update this answer if I can get the statically linked version stable.
2 Dec 2016 update: I managed to get a static version stable.

Related

Modules of Qt 5.1 and their interdependency?

I am looking for a way to create a minimal static build of Qt 5.1. By minimal, I mean a build with only the basic set of widget classes available (including 2D graphics acceleration through an OpenGL canvas/widget). I am aiming for a static build on Windows 7 32-bit using MinGW-builds GCC 4.8.1 as well as their bundle of MSYS and tools.
I have downloaded the entire source tree, and have met some problems with compiling due to the dependency of packages such as OpenSSL and ICU (the latest OpenSSL did not compile). I wanted to see, if I could avoid dependencies of these packages and, at the same time, achieve a minimal static build of Qt 5.1 so my final executable is not gigantic in size.
I took a look at this list:
http://download.qt-project.org/official_releases/qt/5.1/5.1.0/submodules/.
Q1: Which of these modules, do I need to select to have a basic Qt build without all the fancy stuff?
Q2: Are these modules interdependent on each other in some way (I assume they are all dependent on "qtbase")?
Q3: Do I use the names from that list, (for example: "qtxmlpatterns", "qtx11extras", "qtwebkit", etc.), to deselect them in the configuration of my Qt build?
It would also be nice, with an explanation of the various submodules of Qt 5? If someone could point to any links or docs with illuminating words on this subject, that would also be great.
I shared this same goal. I wanted to "minify" Qt, building only a small subset of the libraries/DLL(s) and omitting the rest.
I did succeed, at least on Mac OS X. I assume that this approach will work on other platforms, too.
I thought that the trick would be to find some kind of exclusion flags for the "configure" script, but that turned out not to be the case.
Here is what I did:
Download the source distribution (in my case, qt-everywhere-opensource-src-5.1.1). of course, extract it all.
Edit the following three "pro" files. these files are in a qt-specific format (but plain text). They are platform-independent project files that Qt (via qmake) uses to generate makefiles.
qtbase/src/src.pro
qtbase/src/plugins/plugins.pro
qtbase/examples/examples.pro
All the changes that I made to the "pro" files were deletions. I deleted references to: dbus, ipc, network, qtconcurrent, sql, xml, sqldrivers, qdbusxml2cpp, qdbuscpp2xml, src_dbus, src_concurrent, src_sql, src_network.
That last part may sound scary. It really wasn't.
The pro files contain a list of module names, plugin names, and directory names. It seemed fairly straightforward how to delete (for example) all SQL-related lines.
Step 3.
The usual configure/make/install. However, note the "module-qtbase" argument passed to make:
./configure -prefix ~/my_test_dir/
make -j2 module-qtbase
make -j2 module-qtbase-install_subtargets
Success. This built and installed only the essentials (QtCore, QtGui, QtOpenGL, QtWidgets) and skipped all the supporting dylibs like QtConcurrent, QtMultimedia, QtSql, and QtWebKit.
ICU can link statically, and you can customize it (see docs) to reduce size. By default the data is also large, I don't know how much data you need. You could include only enough data to run in one language.
Only part of an answer.
There's no need to disable Qt modules. Each application that uses Qt decides what modules it uses and links with. A basic console-only application may use the core module only. That's what you'd use when creating, say, a web service in Qt.

VC6 project missing msvcp71d.dll?

I've been searching for a while now, and i came to understand that msvcp71d.dll is for dynamic linking - debug - CRT library for .Net 2003?
Now the project is to be used in VS.net 2003 OR VC6, that's what's written in the readme file.
So i opened the project in VC6 (which i'm more used to, concerning C++) and I don't understand why it's requiring (when debugging) the dll of 71d, shouldn't be asking for msvcpd.dll or msvcp60d.dll?
I think that the project is being linked to a wrong CRT library, probably due to being converted to VC.net 2003 . So i'm wondering if there's a way to link the project back to the older CRT library of VC6?
You need to point the linker the right lib you want to use.
.libs come always by couple:
- a big static one or
- a small one that will require a dll at execution time, each small one is related to a specific dll. so you need to ask the linker:
please use this mylib..v6...lib so I'll need the corresponding mylib..6...dll when executing.

Qt and zip files

I'm trying to write a simple Qt app that will access zip files and read the content of these zip files (the content are text files). Many posts says that Quazip is the solution.
Being new to Qt and coming from .Net background, I really don't know how to use the Quazip, I downloaded the Quazip source but I'm not sure, should I compile it or should I use the source code in my project. I really have no clue.
Any help is much appreciated.
Regards.
It seems as you have various options. You can use source code immediately by copying the relevant files into your project. By default however a static library is compiled when you run
> make install
and in that case you need to add the relevant path to your .pro file so that it finds is static library.
Well, you have several options:
Just add the sources to your project. Pros: you can modify them if you want without affecting your other projects. Cons: updating QuaZip is probably going to be a maintenance headache.
Compile it as a static library (qmake CONFIG+=staticlib). Pros: updating is easier as you don't have to deal with structural changes, only recompile QuaZip and rebuild/relink your projects. Cons: you still have to recompile and relink.
Compile QuaZip as a shared (DLL) library. Pros: updating is extremely easy provided that the new version maintains binary compatibility, plus the code is shared among various applications running at the same time. Cons: it will break everything (that is, until you rebuild/relink your apps) if the new version doesn't maintain binary compatibility.
If you just need to read some zip files in some random project, any of these three will do fine. You probably won't have to update QuaZip either, unless you find some bugs that need to be fixed.
As for the binary compatibility: it is guaranteed that third level version changes (x.y.z1 -> x.y.z2) are binary compatible. As for minor version changes (x.y1 -> x.y2), they probably won't be binary compatible for some time, until the Pimpl idiom is implemented properly.

How to make Qt aware of the QMYSQL driver

I'm trying to access a MySql database from a Qt application but I get the following error:
QSqlDatabase: QMYSQL driver not loaded
QSqlDatabase: available drivers: QSQLITE QSQLITE2
I find this very strange cause I have libqsqlmysql.so on my Qt folder. I have even tried to compile the MySql driver as a static plugin and add it to my .pro file as:
QTPLUGIN += qsqlmysql
But this also generates the same runtime error (it must've found the plugin cause there's no error compiling the application)
What am I missing? I would like to avoid having to compile Qt from source cause this will have to work seamlessly on the deploy machines as well.
BTW: Even though I'm developing and testing on Linux I will need to support Windows. Will I experience this same issue on Windows? How can I compile and link the MySql driver in both Linux and Windows?
The solution:
After following #Sergey's recommendations I did an strace of the application redirecting the output to grep so I could search for 'mysql' and for my surprise the application wasn't looking for the plugin at QTDIR/plugins/sqldrivers where I had libqsqlmysql.so, it was looking at QTDIR/lib. After copying the plugin to the lib folder the MySql connection worked.
Try opening the shared library with dlopen() and see if it loads and if not, what dlerror() tells you. I always run into similar problems on Windows. LoadLibrary()/GetLastError() saved me numerous times (last time it was because of a wrong version of some libiconv/libintl DLL). Running ldd on the plugin may also help.
If dlopen() works fine, try to load the plugin with QPluginLoader. If it doesn't load, then check the buildkey of the plugin. I usually do it the dirty way by running strings on the plugin and then looking for strings like "buildkey" or "QT_PLUGIN_VERIFICATION_DATA". Just looking at the build key and around it may give you an idea. For example, you may realize that you have compiled your plugin in the release mode while your application is compiled in the debug mode. In such case the build key won't match and the plugin won't load. Everything in the build key must match your configuration. Note that the version and the build key are checked differently: the build key must match exactly (or match some black magic called QT_BUILD_KEY_COMPAT), but in the version only the major version must match exactly, the minor version must be the version of Qt the plugin was compiled with or later and the patch level is ignored. So if your plugin was compiled with Qt 4.x.y then it will work with Qt versions 4.z.* where z>=x. This actually makes sense.
If the build key looks okay (which is unlikely if you got to this point), you may wish to look at QLibraryPrivate::isPlugin() source code to figure out what's wrong, but that doesn't look like an easy task to me (although running this in a debugger may help).
If QPluginLoader does load the plugin, check if it is in the right directory and has correct permissions. If you still didn't solve the problem by this point, it's time to look at the SQL module source code that actually loads these plugins. But it is extremely unlikely. I ran into this problem many, many times and it was always either the library not loading or the build key not matching.
Another way to go after QPluginLoader loads the plugin successfully is to use strace to figure out whether the program at least tries to open the plugin file. Searching for something like "sqldrivers" or "plugins" in the strace output should also give away the directory where Qt is searching for its plugins and specifically SQL drivers.
Update
Is it possible to compile the driver as a static plugin and don't worry about anything? Let's try:
d:\Qt4\src\plugins\sqldrivers\psql>qmake CONFIG+=static LIBS+=-Ld:/programs/Post
greSQL/lib INCLUDEPATH+=d:/programs/PostgreSQL/include
d:\Qt4\src\plugins\sqldrivers\psql>make
It compiles fine and now I got libqsqlpsql.a (release) and libqsqlpsqld.a (debug) in QTDIR/plugins/sqldrivers (it is the right place on Windows). I am using PostgreSQL driver here, but I don't think it will be any different for MySQL which I just don't have installed. Ok, let's compile some real program with it:
d:\alqualos\pr\archserv>qmake QTPLUGIN+=qsqlpsql PREFIX=d:/alqualos LIBS+=-Ld:/g
nu/lib INCLUDEPATH+=d:/gnu/include LIBS+=-Ld:/programs/PostgreSQL/lib LIBS+=-lpq
Note that I had to manually link to libpq, otherwise the linker would complain about undefined references. The funny thing is, qmake knows that qsqlpsql is located in QTDIR/plugins/sqldrivers and sets compiler and linker options accordingly. So it still needs to be in the right place to work, only you don't have to worry about your users running into the same problem as it is only used during compilation. An alternative would be to just use LIBS+=-Lpath/to/plugin LIBS+=-lqsqlpsql instead of QTPLUGIN+=qsqlpsql, at least the docs say that it should work, but I haven't tested it.
In order for the application to actually use the plugin I had to put the following in my main unit (CPP file):
#include <QtPlugin>
Q_IMPORT_PLUGIN(qsqlpsql)
It works! Also, from what I've been able to figure out from the sources, the build key and the version are checked only when a plugin is dynamically loaded (all the relevant stuff is in the QLibrary's private class, not even QPluginLoader's). So the resulting executable may (or may not, depending on the binary compatibility) work even with different versions and builds of Qt, although using it with older versions may trigger some bugs that were fixed later.
It is also worth noting that the order for loading SQL drivers is this: use the driver statically linked into Qt if available, then look for a driver registered manually with QSqlDatabase::registerSqlDriver(), then look for a driver statically imported into the application (the way described above), and finally try to load a shared plugin. So when you link statically, your users won't be able to use dynamically linked drivers they may already have, but will be able to use drivers linked statically into Qt (like in Ubuntu).
I compiled QT first and then realised that I need mysql as well. So I compiled mysql plugin by
executing following command in QT-DIR\src\plugins\sqldrivers\mysql folder.
Mysql plugin compile command
qmake "INCLUDEPATH+=$$quote(C:\Program Files\MySQL\MySQL Server 5.5\include)" "LIBS+=$$quote(C:\Program Files\MySQL\MySQL Server 5.5\lib\libmysql.lib)" mysql.pro
Plugings are then created in created in folder QT-DIR\plugins\sqldrivers.
However, when I tried to use it in my code. It failed with following error.
Error msg
QSqlDatabase: QMYSQLDriver driver not loaded
Solution
After some googling and checking Path variable I realised that the Mysql server lib
( C:\Program Files\MySQL\MySQL Server 5.5\lib) directory was not in my Path variable. I expect that the dll in this folder are used by the plugin at runtime. After including Mysql server lib in Path variable everything worked smoothly. Hope this information saves some hair on other programmers scalp, as I uprooted quite a few. :D
Last time I looked at this you needed to rebuild Qt from source and include the appropriate MySQL source.
Building Qt from the sources is not hard, it just takes a while. You are likely to have the required tools already.
A possible workaround may be to access the back-end over ODBC instead.
In order for your app to pick up the plugin at runtime, the shared library implementing the MySQL plugin needs to be placed in the correct directory. The best way of determining that directory is to check the output of QCoreApplication::libraryPaths. You can also force specific paths by using a qt.conf file.
Please note that plugins must be placed in subdirectories within the plugin path, and the final part of the path name (i.e., the parent directory of the shared libraries) cannot be changed. SQL drivers need to go in a directory named sqldrivers, i.e. <pluginpath>/sqldrivers. For more details on plugin directories, see How to Create Qt Plugins.
I was experiencing this same issue as well. I've been installing and experimenting with a lot of different Python tools and UIs. I then uninstalled everything python related. I did a fresh install of Python 3.2, PyQT 3.2, and Eric5. No more errors with the QMySQL driver.
well i have had this issue, and after a lot of time, and different tools, i found that QT ( on windows, have not been able to test on Linux.) loads the "QSQLMYSQL.." when requested, but before runtime the lib ("QSQLMYSQL..") file must reside on one of the searched paths (QApp.libraryPaths()) inside a folder called "sqldrivers".. otherwise QT will just ignore the file, even if it is at some other point inside the searched path.
what i did was to monitor the dependency of a sample app, and when i removed the "QSQLMYSQL.." dll from "plugins\sqldrivers\" it failed, but when i maded a folder inside the app folder, called "sqldrivers" and placed the "QSQLMYSQL..." inside there, it loaded.
what i have is mysql 5.5, qt 4.7.4.
hope anyone can use this, and if anyone knows more about it, i would like to know where to find it(http://doc.qt.nokia.com/stable/sql-driver.html, is the closest you can get to the information about the folder structur). :P
This may also happen if your QMYSQL plugin is linked against the "wrong" mysql_client.a or it isn't in the LD_LIBRARY_PATH. I had this problem on OSX because mysql was installed via ports, and I fixed it with:
install_name_tool -change libmysqlclient.18.dylib /usr/local/mysql/lib/libmysqlclient_r.18.dylib libqsqlmysql.dylib

Automatic BizTalk Versioning in My Build Process

In all of my other .net apps my build process (a mixture of nant and custom tasks) automatically updates the [AssemblyVersionAttribute] AssemblyInfo.cs with the current build number before the call to msbuild, stamping in the build number in the version number.
I'm now working on my first BizTalk project and I'd like to do the same thing with the version numbers of the BizTalk assemblies, but I've run into trouble!
First of all the aseembly version numbers are stored in the btproj files, so I did some googling and found www.codeplex.com/biztalk which looked like the answer to my problem, but there is a deeper problem!
I have a project for my schemas and another for my pipelines, the pipelines project references my schemas project as I have a flat file dis/assemblers. The problem comes when I update the version numbers, as updating them even from within visual studio does not update the pipeline components references to the schemas.
So if I update all the version numbers manually in the VS IDE from 1.0.0.0 to 1.1.0.0, the build fails as the pipeline components flat file dis/assemblers still reference the old 1.0.0.0 version of the schemas! They don't automatically update!
Is this really a manual process of updating the version numbers of the BizTalk projects in the property pages, then building the projects and manually updating the references to them in the properties of all the pipeline components that reference them?
This means that I can't have my build process control the build number part of my version numbers!
Or is there a better method of managing the version numbers of the BizTalk assemblies?
I'm sorry to disappoint you but I've been down the exact some road I had to give up. I guess it could be possible to achieve it but it would require a lot of changes to both the binding files and other XML files (as you mentioned and even more if you have published services etc).
Maybe it could be possible to wrap all these necessary changes in a build step (a MSBuild step or similar in other build frameworks) - that would be useful!
Developer- :)
We had the similar problem and we ended up developing a small utility which would change the version number in all the projects i.e. *.csproj (asssemblyinfo.cs), *.btproj accordingly. Apart from this it would open and modify the *.btp files with the new version of schemas. In nutshell, what all you have to do is to configure this utility in your VS.net tools menu and execute it.
I guess its not very difficult to develop such utility in any .net lanagauge.
Caveat: Do not forget to save the files after updates with the same encoding as they were originally.
Cheers!
Gutted, thought that might be the case. Maybe BizTalk 2009 projects will play more nicely when updating references when changing version numbers.
I started to go through and automate it manually, and when I realised what needed to be done, I took a biiig step back when I realised just how many places I'd have to modify to get it working. Thank god for Undo Checkout.
I do have a standard C# class library included in my project (various helper functions), which i am able to update the version number of during my build process, so I'm basically using that one assembly to version the whole application. If anyone wants to know what version is in any environment, check out the version number of that one assembly.
Not ideal, but it's working.
We've done this successfully on our project - I'll see if I can get the developer of the tool to post details...
This problem arises when you perform an integration build to the latest versions of your dependent components as file references (aka schemas here).
Keep in mind that upgrading the assemblyversion must always performed manually, that way you are always in charge of changes to assemblyversions.
A possible solution to solve the buildbreaks issue is to file reference to a specific version of a dependent component build and not to the latest version and use a subst drive and a copy script to get the latest component builds.
For example:
SchemaA, assembly version 1.0.0.0
PipelineA (with pipelinecomponent XMLValidator for example), assembly version 1.0.0.0
PipelineA has a file reference to a subst drive(say R drive, which maps to a workspace D:\MyComponents) and version 1.0.0.0 of SchemaA as follows:
R:\SchemaA\1.0.0.0\SchemaA.dll.
The copy-script copies the buildoutput of SchemaA locally to your R drive.
When schema A updates to version 1.1.0.0 you don't have any issues because you still use version 1.0.0.0 and YOU have the choice to use the 1.1.0.0 version of your schema. When you want to upgrade, you have to alter your copy-script and replace the file reference to R:\SchemaA\1.1.0.0\SchemaA.dll.

Resources