Compiling SQLite for UWP ARM64: Missing Entry Points and Version Issues

Issue Overview: Missing SQLite API Entry Points and DLL Version Information

When compiling SQLite for UWP ARM64, a common issue arises where the resulting DLL fails to export the necessary API entry points, leading to runtime errors such as EntryPointNotFoundException. This issue is particularly prevalent when targeting platforms like HoloLens 2, where the compilation process involves cross-compilation from an x64 host to an ARM64 target. The core problem lies in the failure to properly export the SQLite API functions from the DLL, which is essential for the dynamic linking process to work correctly.

Additionally, another related issue is the absence of version information in the generated DLL. This is crucial for ensuring that the correct version of the SQLite library is being used, especially in environments where multiple versions of the library might be present. The version information is typically embedded in the DLL using a resource file, and its absence can lead to confusion and potential compatibility issues.

Possible Causes: Incomplete Compilation Flags and Missing Resource Compilation

The primary cause of the missing entry points is the absence of the -DSQLITE_API=__declspec(dllexport) flag during the compilation process. This flag is necessary to instruct the compiler to export the SQLite API functions from the DLL. Without this flag, the functions are not marked for export, and as a result, they are not available for linking at runtime.

The absence of version information in the DLL is typically due to the omission of the resource compilation step. The resource compiler (rc.exe) is used to embed version information and other resources into the DLL. This step is often overlooked when manually invoking the compiler and linker, leading to a DLL that lacks the necessary metadata.

Troubleshooting Steps, Solutions & Fixes: Ensuring Proper API Export and Version Embedding

To resolve the issue of missing entry points, the first step is to ensure that the -DSQLITE_API=__declspec(dllexport) flag is included in the compilation command. This flag should be added before the source file name in the command line. For example, the modified command would look like this:

cl -DSQLITE_API=__declspec(dllexport) sqlite3.c -link -dll -out:sqlite3.dll

This ensures that all SQLite API functions are marked for export, making them available for linking at runtime.

To address the issue of missing version information, the resource compilation step must be included in the build process. This involves using the resource compiler (rc.exe) to generate a resource file (sqlite3res.lo) that contains the version information. This file is then linked with the compiled code to produce the final DLL.

The resource file (sqlite3.rc) is typically included in the SQLite amalgamation download. If it is not present, it can be generated by running the following command:

echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
echo #define SQLITE_RESOURCE_VERSION 3,32,2 >> sqlite3rc.h
echo #endif >> sqlite3rc.h
rc -DSQLITE_OS_WIN=1 -I. -I. -DNDEBUG -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -DSQLITE_THREADSAFE=1 -DSQLITE_THREAD_OVERRIDE_LOCK=-1 -DSQLITE_TEMP_STORE=2 -DSQLITE_MAX_TRIGGER_DEPTH=100 -DSQLITE_DQS=0 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_DEFAULT_FOREIGN_KEYS=1 -DSQLITE_ENABLE_GEOPOLY -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_BYTECODE_VTAB -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION -DSQLITE_USE_URI -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_USE_ALLOCA -DSQLITE_DEFAULT_SYNCHRONOUS=3 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT -DSQLITE_REPLACE_INVALID_UTF -DSQLITE_DEFAULT_WORKER_THREADS=3 -r -fo sqlite3res.lo .\sqlite3.rc

Once the resource file is generated, it should be linked with the compiled code to produce the final DLL. The complete command would look like this:

cl -DSQLITE_API=__declspec(dllexport) sqlite3.c -link -dll -out:sqlite3.dll sqlite3res.lo

This ensures that the version information is embedded in the DLL, making it easier to identify the correct version of the SQLite library.

For those who prefer a more automated approach, using the provided Makefile.msc is highly recommended. This makefile includes all the necessary steps for compiling SQLite, including the resource compilation step. To use the makefile, simply run the following command:

nmake -f Makefile.msc USE_RC=1 sqlite3.dll

This will generate a DLL with all the necessary API entry points and version information, ready for use in UWP ARM64 applications.

In summary, the key to successfully compiling SQLite for UWP ARM64 lies in ensuring that the API functions are properly exported and that the version information is embedded in the DLL. By following the steps outlined above, you can avoid common pitfalls and produce a fully functional SQLite DLL for your UWP ARM64 applications.

Related Guides

Leave a Reply

Your email address will not be published. Required fields are marked *