10

I have MinGW and I wish to compile the SQLite amalgamation source into a 64-bit dll. I'm fairly new to this sort of compilation and my efforts so far have resulted in failure. (I first started using the autoconf amalgamation and used the configure & make tool on Linux. But apparently that will never work for Windows binaries.)

Anyway, I've been told I need the following preprocessor defines:

Here are the compiler pre-processor defines I use for a 64-bit release build:

  • WIN64 NDEBUG
  • _WINDOWS
  • _USRDLL
  • NO_TCL
  • _CRT_SECURE_NO_DEPRECATE
  • THREADSAFE=1
  • TEMP_STORE=1
  • SQLITE_MAX_EXPR_DEPTH=0

Here are the compiler pre-processor defines I use for a 32-bit release build:

  • WIN32
  • NDEBUG
  • _WINDOWS
  • _USRDLL
  • NO_TCL
  • _CRT_SECURE_NO_DEPRECATE
  • THREADSAFE=1
  • TEMP_STORE=1
  • SQLITE_MAX_EXPR_DEPTH=0

I had no idea where to put these in. I eventually took an educated guess, made a new file (for neatness) called sqlite3w64.h and pasted in the following:

#define WIN64 NDEBUG
#define _WINDOWS
#define _USRDLL
#define NO_TCL
#define _CRT_SECURE_NO_DEPRECATE
#define THREADSAFE 1
#define TEMP_STORE 1
#define SQLITE_MAX_EXPR_DEPTH 0

I then compiled the source with the following command:

gcc sqlitew64.h sqlite3.h sqlite3ext.h shell.c sqlite3.c -o sqlite_x64.dll

What resulted was a 733KB DLL file. Nice! Did it actually work? Did it nuts - I got a BadImageFormatException. I also then tried doing an x86 compilation using the same method. Once again, I got a 733KB DLL file (that's odd?) and once again, I got a BadImageFormatException.

Help.

Update

Used the following command instead:

gcc -shared -DWIN64 -DNDEBUG -D_WINDOWS -D_USRDLL -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -DTHREADSAFE=1 -DTEMP_STORE=1 -DSQLITE_MAX_EXPR_DEPTH=0 -I. shell.c sqlite3.c -o sqlite_x64.dll -Wl,--out-implib,sqlite3.a

Resulted in a 740KB DLL file which still gives a BadImageFormatException.

Final Update

Turns out my MinGW build was 32-bit only. Getting a 64-bit version then allowed me to make SQLite for 64-bit. Adding the flag -m64 sets the compiler into 64-bit mode.

64-bit:

gcc -shared -DWIN64 -DNDEBUG -D_WINDOWS -D_USRDLL -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -DTHREADSAFE=1 -DTEMP_STORE=1 -DSQLITE_MAX_EXPR_DEPTH=0 -m64 -I. shell.c sqlite3.c -o sqlite3_x64.dll -Wl,--out-implib,sqlite3_x64.a

32-bit:

gcc -shared -DWIN32 -D_WINDOWS -D_USRDLL -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -DTHREADSAFE=1 -DTEMP_STORE=1 -DSQLITE_MAX_EXPR_DEPTH=0 -m32 -I. shell.c sqlite3.c -o sqlite3_x86.dll -Wl,--out-implib,sqlite3_x86.a

MinGW-64 Precompiled: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Automated%20Builds/mingw-w64-bin_i686-mingw_20111220.zip/download?use_mirror=ignum

Installation Instructions: http://code.google.com/p/tonatiuh/wiki/InstallingMinGWForWindows64

Chris Watts
  • 6,197
  • 7
  • 49
  • 98
  • 1
    That said, you *could* link SQLite directly into your program, in fact, it's a recommended way to use SQLite. Then you need either the .o or .a file. – Prof. Falken Jun 11 '12 at 12:21
  • Hmm, not sure if that'll work. I'm doing this because I can't compile my program into a single exe with the C# wrapper for SQLite as it is mixed-mode. Instead I am using their Managed-Only version, but I need to compile my own sqlite3.dll to work with it (mainly because there is no 64-bit readily available). – Chris Watts Jun 11 '12 at 15:40
  • But if you can find out for me how to put it as an .o or .a file into my Visual C# program and be able to switch it around for x86 or x64 whilst satisfying System.Data.SQLite; go ahead! – Chris Watts Jun 11 '12 at 15:42
  • Are you *sure* the DLL is actually 64-bit? – Prof. Falken Jun 12 '12 at 08:18
  • I'm not even sure if it's a valid DLL! I can't test it anymore than getting a BadImageFormatException to tell me it wont work. I tried using the DLL with an x86 debug target, and it still didn't work. – Chris Watts Jun 12 '12 at 16:06
  • Related: http://stackoverflow.com/questions/3322276/is-there-a-transparent-way-to-force-64-bit-gcc-compilation-on-solaris – Prof. Falken Jun 13 '12 at 06:59
  • Related: http://stackoverflow.com/questions/4315606/precompiled-sqlite-binaries-for-windows-x64 – Prof. Falken Jun 13 '12 at 11:28

2 Answers2

8

You are compiling to an EXE. Calling it a DLL won't magically make it a DLL.

You need to pass special linker options to gcc to make it create DLLs. Quoted from Mingw site: (Sort of, I replaced g++ with gcc)

gcc -c -DBUILDING_EXAMPLE_DLL example_dll.cpp
gcc -shared -o example_dll.dll example_dll.o -Wl,--out-implib,libexample_dll.a

The page also explains that functions you want your DLL to export, must be declared with __declspec(dllexport). (Further down, there is an example on how to export all global functions to the DLL, like usually happens in Unix.)

The -Wl argument to gcc is what tells gcc to pass on the further arguments --out-implib,libexample_dll.a to the linker.

I would also make 100% sure that the built DLL is actually a 64 bit DLL and not a 32 bit DLL. Do you have any way to check that? On Linux you can run the "file" command.

You can also try adding the -m64 option to the gcc commandline, that should force gcc to target the amd64 target.

If that doesn't work, you may have the wrong compiler altogether. Make sure you have the x86_64/amd64 version of the Mingw toolchain. Installation is as simple as finding the right ZIP, unpacking it, and setting the path.

If all of that fails, or if you just want to verify against a supposedly correctly compiled setup, try precompiled 64-bit binaries here or from here.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
  • Hah, you are right. Renaming it to an exe produced a neat little console application. Does that mean it ignored the _USRDLL define? – Chris Watts Jun 11 '12 at 10:45
  • @CJxD, no but defines are a preprocessor/compiler thing. If it ends an EXE or DLL is a *linker* thing, so you need to pass linker options so gcc knows how to link. (DLLs and EXEs are similar but not the same.) Didn't this answer work for you btw? – Prof. Falken Jun 11 '12 at 12:12
  • It's basically the same thing as the other answer. If you check back and look at what I tried in the question update, you'll see what happened. I think someone's going to need to try it for themselves because I just can't figure it out by myself. – Chris Watts Jun 11 '12 at 15:37
4

What would work in your case is this single link-and-compile command:

g++ -shared
-DWIN64
-DNDEBUG
-D_WINDOWS
-D_USRDLL
-DNO_TCL
-D_CRT_SECURE_NO_DEPRECATE
-DTHREADSAFE=1
-DTEMP_STORE=1
-DSQLITE_MAX_EXPR_DEPTH=0
-I.
shell.c sqlite3.c
-o sqlite_x64.dll
-Wl,--out-implib,libsqllite_x64.dll.a

The compile and link stage will be performed at once. The defined can be added on the commandline. The headers need not be compiled, but you need to pass the current directory as a header search directory, and specify the names of the dll and import file.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • 1
    Tried this (replacing g++ for gcc), and it created the 'a' file and a 740KB DLL file; but I still get the same exception. – Chris Watts Jun 11 '12 at 10:42