SQLite Forum

Compiling FILEIO.C
Login

Compiling FILEIO.C

(1) By anonymous on 2021-09-19 20:30:49

Following the [hints provided here](https://sqlite.org/src/file?name=ext/misc/fileio.c&ci=trunk):

- I obtained the [source](https://sqlite.org/src/file?name=ext/misc/fileio.c&ci=trunk)
- Trying <i>To compile on Windows using MSVC, a command similar to the following will usually work:</i>

>cl YourCode.c -link -dll -out:YourCode.dll

I am running this from the command prompt:

> "D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\SDK\\ScopeCppSDK\\vc15\\VC\\bin\\cl.exe" FILEIO.c -link -dll -out:FILEIO.dll

My Command prompt is at the directory where FILEIO.C is saved; the location contains just the file FILEIO.C

I am getting this error:

> fatal error C1034: ?.h: no include path set

Where ? = one file name or another.

I have made NO changes to FILEIO.C. t seems to fulfil the requirements [4. Programming Loadable Extensions](https://sqlite.org/loadext.html#build).

I'd appreciate some help in overcoming fatal error C1034; thank you.

(2) By Larry Brasfield (larrybr) on 2021-09-19 20:56:51 in reply to 1 [link]

You need to first run one of the batch files installed along with Visual Studio in recent years, shortcuts to which are labeled something like "Open Visual Studio 20xx Tools Command Prompt for targeting ..." and appear in the "Start" menu under "Visual Studio 20xx". These shortcuts run something like "...\VC\Auxiliary\Build\vcvars??.bat" in a cmd.exe session. This leaves a number of environment variable set, such as INCLUDE, LIB, LIBPATH and PATH which makes the Microsoft Visual C/C++ command line tools (CL.exe, LINK.exe, LIB.exe, NMAKE.exe) conveniently usable. (SQLite project makefiles for that toolset are designed with this setup presumed.)

You will need to have "sqlite3ext.h" reachable by the compiler, either in the current directory or findable among the paths named by the INCLUDE environment variable. This header is included with the amalgamation.

The environment variable setup done per above will also cause various link libraries to be findable by the compiler/linker that is run as CL.exe ; these should permit the link phase, which happens when the simple, one-line build procedure is used, to succeed.

The above-described arrangement, where "CL" just works (usually), is not unique to SQLite. A great many software builds can be effected the same way, by naming the files to be compiled and linked to the CL.exe driver.

(3) By Keith Medcalf (kmedcalf) on 2021-09-19 20:57:03 in reply to 1 [link]

Include the directory containing the needed .h files on the command line.  For example, if the "sexyturd.h" file is required and it can be found in directory "D:/Toilet" then add that include directory to your command:

`-ID:/Toilet`

Lather rinse and repeat adding each directory which contains an include file that the compiler needs to locate.

(4) By anonymous on 2021-09-19 21:17:22 in reply to 2 [link]

I copied sqlite3ext.h & sqlite3.h to the location where fileio.c is.

Now, I'm getting this error:

> fatal error C1083: Cannot open include file: 'test_windirent.h': No such file or directory


Compiling is not as [straight forward as made out here](https://sqlite.org/loadext.html#build).

(5) By Warren Young (wyoung) on 2021-09-20 01:42:22 in reply to 4 [link]

That file is in `src/`, the same place you got the previous two files from.

Alternately, from an unpacked copy of the SQLite source tree, this might work:

     C:\PATH\TO\SQLITE\SOURCE> cl ext/misc/fileio.c -Isrc -link -dll -out:fileio.dll

(6) By Larry Brasfield (larrybr) on 2021-09-20 02:02:37 in reply to 4 [link]

> Compiling is not as straight forward as made out here.

True. I am about to add an expando-tip to that "usually works" claim. It's author and I are not accustomed to using computers which do not have a compiler, linker, library manipulator, debugger, symbol table dumper, and other tools available with a few keystrokes at a command line shell. So read "usually" as "usually for the supposed target audience."

Given that tool setup [described in post #2](https://sqlite.org/forum/forumpost/188a920d07823b65?t=h), fileio.c is still not going to build as easily as described in [Compiling A Loadable Extension](https://sqlite.org/loadext.html#build). This is unusual because fileio.c, when built for WIN32, has (apparently) been designed to link against a semi-public API of the SQLite library. (See sqlite3_win32_utf8_to_unicode if curious.)

To build a standalone DLL for WIN32, this code can be used:

<code>
/\* utf8_to_wide.c
.
 Fixup for SQLite project's ext/misc/fileio.c extension which appears to
 require static linking with the SQLite library to get one function that
 is unavailable otherwise and reuse several of that library's functions
 which are available from the C runtime. This wrapper provides the said
 unavailable function and #define's the others to use C runtime versions.
 This allows the extension to be built and used as a DLL.
.
 Build thusly on Windows using the MSVC development tool set:
  CL -Os utf8_to_wide.c -link -dll -out:fileio.dll
.
 In addition to this file, these 3 project sources are required:
 https://www.sqlite.org/src/file?name=ext/misc/fileio.c&ci=trunk
 https://www.sqlite.org/src/file?name=src/test_windirent.c&ci=trunk
 https://www.sqlite.org/src/file?name=src/test_windirent.h&ci=trunk 
\*/
\#undef sqlite3_win32_utf8_to_unicode
\#define sqlite3_win32_utf8_to_unicode utf8_to_utf16
\#include "fileio.c"
/* Replacement for SQLite library API: */
LPWSTR utf8_to_utf16(const char *z){
  int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
  LPWSTR rv = malloc(nAllot * sizeof(WCHAR));
  if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
    return rv;
  free(rv);
  return 0;
}
\#undef sqlite3_malloc
\#define sqlite3_malloc malloc
\#undef sqlite3_free
\#define sqlite3_free free
\#undef sqlite3_stricmp
\#define sqlite3_stricmp stricmp
\#include "test_windirent.c"
</code>

After saving the above as utf8_to_wide.c in some directory, and placing sqlite3.h, sqlite3ext.h and the 3 above-referenced sources in that same directory, see its heading comment for the one-liner build invocation.

(7) By anonymous on 2021-09-20 07:04:29 in reply to 6 [link]

Thank you for re-visiting this; sharing your insight is much appreciated.

<b>Attempt 1: </b>

>CL -Os utf8_to_wide.c -link -dll -out:fileio.dll

And that takes me straight to the 

>  fatal error C1034: ??.h: no include path set

Finding each *.h file and copying to the location where I have FILEIO.C & other files will take a long time.

<b> Attempt 2:</b>

I created a DLL project in VS2019. I feel that I am nearer to compiling FILEIO.C successfully but not quite there yet. Here's the output:

```

Rebuild started...
------ Rebuild All started: Project: FILEIO, Configuration: Release x64 ------
FILEIO.C
test_windirent.c
utf8_to_wide.c
Generating Code...
utf8_to_wide.obj : error LNK2005: closedir already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: opendir already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: readdir already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: readdir_r already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: sqlite3_fileio_init already defined in FILEIO.obj
utf8_to_wide.obj : error LNK2005: windirent_getenv already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: sqlite3_api already defined in FILEIO.obj
   Creating library E:\SQLite_The Hospital\FILEIO\x64\Release\FILEIO.lib and object E:\SQLite_The Hospital\FILEIO\x64\Release\FILEIO.exp
LINK : fatal error LNK1561: entry point must be defined
Done building project "FILEIO.vcxproj" -- FAILED.
------ Rebuild All started: Project: FILEIO, Configuration: Debug x64 ------
FILEIO.C
test_windirent.c
utf8_to_wide.c
Generating Code...
utf8_to_wide.obj : error LNK2005: closedir already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: opendir already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: readdir already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: readdir_r already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: sqlite3_fileio_init already defined in FILEIO.obj
utf8_to_wide.obj : error LNK2005: windirent_getenv already defined in test_windirent.obj
utf8_to_wide.obj : error LNK2005: sqlite3_api already defined in FILEIO.obj
   Creating library E:\SQLite_The Hospital\FILEIO\x64\Debug\FILEIO.lib and object E:\SQLite_The Hospital\FILEIO\x64\Debug\FILEIO.exp
FILEIO.obj : error LNK2019: unresolved external symbol sqlite3_win32_utf8_to_unicode referenced in function statTimesToUtc
test_windirent.obj : error LNK2019: unresolved external symbol sqlite3_malloc referenced in function opendir
test_windirent.obj : error LNK2019: unresolved external symbol sqlite3_free referenced in function closedir
test_windirent.obj : error LNK2019: unresolved external symbol sqlite3_stricmp referenced in function opendir
E:\SQLite_The Hospital\FILEIO\x64\Debug\FILEIO.dll : fatal error LNK1120: 4 unresolved externals
Done building project "FILEIO.vcxproj" -- FAILED.
========== Rebuild All: 0 succeeded, 2 failed, 0 skipped ==========

```

(8) By Larry Brasfield (larrybr) on 2021-09-20 12:58:29 in reply to 7 [link]

> Attempt 1: ...<br>
fatal error C1034: ??.h: no include path set

The single-line, compile/link invocation works if my [advice in post 2](https://sqlite.org/forum/forumpost/188a920d07823b65?t=h) is followed. Without that environment variable setup, the CL.exe compile/link driver does not know where to find system include files and libraries unless they are (tediously and laboriously) specified at each tool invocation. (Avoidance of the tedium and labor, and the study needed to perform it, is why the batch files and shortcuts to them exist.)

> Attempt 2: ...<br>
... error LNK2005: ... already defined in ...

The post in which I embedded utf8_to_wide.c advised this build method:<code>
  Build thusly on Windows using the MSVC development tool set:
    CL -Os utf8_to_wide.c -link -dll -out:fileio.dll
</code>. Note that a single translation unit is compiled. A glance at that code shows that it \#include's a couple of other sources directly. If you additionally compile those and attempt to link the resulting object files, you are bound to get multiple-definition errors.

If you really want to use your IDE to individually compile the C sources and link the results, you will need to do at least this to utf8_to_wide.c: (1) Remove the \#include lines which incorporate fileio.c and test_windirent.c into the same compilation; and (2) Add one or more \#include lines to bring in headers that fileio.c had itself \#include'd. Then you will need to set preprocessor symbols for each of the 3 translation units equivalently to what utf8_to_wide.c had arranged as it caused them all to be compiled. (There may be a single set of values that works for all 3, or they may have to differ; I don't know.)

Now I must say something that might seem unkind (but is not:) If you are intent on being a software developer, you **must** learn to read and understand error messages that come from the tools you use. Bringing each little tool complaint to a forum where other participants are willing and able to do that is not a workable approach. A web search for the portions of error messages not specific to your project(s) may be illuminating as you initially learn what they mean. But the errors that have appeared in your threads here are very fundamental -- so much so that you should be making your own effort to discover what they mean. That is how you will progress up the learning curve.

(9) By anonymous on 2021-09-20 14:28:00 in reply to 8 [link]

I kept the faith knowing that [the detailed instructions](https://sqlite.org/forum/forumpost/e89f92050564a2d8?t=h) would have been tested successfully and persevered. Several hours later I have created FILEIO.DLL

<code>
20/09/2021  14:43           148,992 fileio.dll
</code>

<i>Larry, I'd be interested to know how the size compares with the size of your FILEIO.DLL.</i>

I have tested this extension and no longer get the [aberration I reported](https://sqlite.org/forum/forumpost/8314c494ec1ec7fa?t=h) The steps I followed are:
 
<b>Step 1</b>
Start Command Prompt as Administrator

<b>Step 2</b>
Find the location of CL.EXE; the location should have the dependencies mspd*.DLL. In my case, this location is: <i>cd "D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\VC\\Tools\\MSVC\14.29.30133\\bin\\Hostx86\\x86"</i> That is, I have to be in this directory.

<b>Step 3</b>
Find the batch file that creates the environment wherein CL.EXE can find the *.h dependencies. In my case this batch file is: <i>"D:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat"                    </i>  I ran this batch file which provided this response:

<code>
[vcvarsall.bat] Environment initialized for: 'x86'
</code>

<b>Step 4</b>

> cl -Os "E:\SQLite_The Hospital\FILEIO\utf8_to_wide.c" -link -dll -out:fileio.dll

This provided this feedback:

<code>
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

utf8_to_wide.c
Microsoft (R) Incremental Linker Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:utf8_to_wide.exe
-dll
-out:fileio.dll
utf8_to_wide.obj
   Creating library fileio.lib and object fileio.exp
</code>

<b>Step 5</b>
Since <i>"D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\Enterprise\\VC\\Tools\\MSVC\\14.29.30133\\bin\\Hostx86\\x86"</i> is a system location (<i>the reason for running as Administrator</i>) , I need to tidy up.

- Deleted utf8_to_wide.obj
- Copied FILEIO.DLL to another (preferred) location
- Deleted FILEIO.*

<b>Step 6</b>
Tested FILEIO.DLL from my preferred location with success.

Hopefully, this experience will save me (& others) time when compiling other extensions.

<span style="color:red"><b>Larry, thank you very much.</b></span>.

(10) By Larry Brasfield (larrybr) on 2021-09-20 15:16:37 in reply to 9 [link]

I'm just responding to a few minor issues, quoted.

> \[reporting file size\] 148,992 fileio.dll<br>
Larry, I'd be interested to know how the size compares with the size of your FILEIO.DLL.

I get your size with latest VS2019 compiler targeting x86 and 178688 bytes targeting amd64.

> <b>Step 1</b> Start Command Prompt as Administrator

That is not necessary. Ordinary privilege is all that is needed.

> <b>Step 2</b> ... <b>Step 3</b> ...

There is a VS2019 (and earlier) installation option to provide Start menu shortcuts that accomplish all that with two clicks and some mouse motion.

> ... need to tidy up ... Deleted FILEIO.*

It is odd to delete fileio.c and no other sources.

> ... Tested FILEIO.DLL from my preferred location with success.

I was unable to discover how that fileio.dll you found was built when I perused the site where you were told to find it. This makes me wonder what it really was.

> Hopefully, this experience will save me (& others) time when compiling other extensions.

Most (or maybe all) other extensions are as easy to build as is suggested at [Compiling a Loadable Extension](https://sqlite.org/loadext.html#build).

I will ponder how to warn about the extra considerations for fileio.c when built for WIN32.

> thank you

You're welcome. We intend that this is somewhat easier than you experienced.

(11) By anonymous on 2021-09-20 15:26:21 in reply to 10 [link]

>It is odd to delete fileio.c and no other sources.

I have kept ALL the source files ... which are in a location (E:\\SQLite_The Hospital\\FILEIO\\) other than where fileio.dll is created (D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\VC\\Tools\\MSVC\\14.29.30133\\bin\\Hostx86\\x86)

(12) By Larry Brasfield (larrybr) on 2021-09-20 20:37:56 in reply to 11 [link]

I have checked in a <u>[revised fileio.c](https://www.sqlite.org/src/file?name=ext/misc/fileio.c&ci=trunk)</u> which better accomplishes the effect of the separate source I posted earlier in this thread. 

The fileio.dll extension can now be built thusly:<code>
    CL -Os -DFILEIO_WIN32_DLL fileio.c -link -dll -out:fileio.dll
</code>, (assuming that a suitable vc_vars??.bat is run first as discussed earlier.) It is still necessary to have test_windirent.c, test_windirent.h, sqlite3ext.h and sqlite3.h in the same directory as fileio.c (or made #include'able via CL.exe's -I option.)

I would appreciate it if you could use that source to build and verify satisfactory operation of the fileio extension.<sup>a</sup> Please post results, positive or otherwise. (And consider it payback for the technical help.)


----

a. The resulting image has a slight improvement: The extension code which traffics in heap allocated objects with the SQLite library will use the same allocator that has been used by default or designated for the library's use via [sqlite3_config](https://sqlite.org/c3ref/config.htmlhttps://sqlite.org/c3ref/config.html). This defaults to malloc() and its cohorts, so this improvement will usually have no effect.

(13) By anonymous on 2021-09-21 05:55:05 in reply to 12 [link]

- Repeated the compilation with the new FILEIO.C. Passed. DLL is the same size as with the [previous method of compilation](https://sqlite.org/forum/forumpost/23b67c3846f5a875?t=h).
- Repeated my tests with the new FILEIO.DLL. Passed.

I noticed that the new FILEIO.C has the same date, namely, 2014-06-13. Should this change?

(14) By anonymous on 2021-09-21 06:40:30 in reply to 13 [link]

> Repeated the compilation with the new FILEIO.C. Passed. DLL is the same size as with the previous method of compilation.

For clarity, I used the CL syntax given i.e. 

> CL -Os -DFILEIO_WIN32_DLL fileio.c -link -dll -out:fileio.dll

(15) By Larry Brasfield (larrybr) on 2021-09-21 11:53:11 in reply to 13 [link]

> Repeated the compilation with the new FILEIO.C. Passed. DLL is the same size as with the previous method of compilation.

Without FILEIO_WIN32_DLL defined, the preprocessed code is unchanged substantively. (Only whitespace and #line directives will differ.) So only debug builds could differ in size.

> Repeated my tests with the new FILEIO.DLL. \[(using -DFILEIO_WIN32_DLL)\] Passed.

Thanks for verifying (and for the CL options carification.)

> I noticed that the new FILEIO.C has the same date, namely, 2014-06-13. Should this change?

The headings of files in the repository are left alone as the source evolves.

(16) By anonymous on 2021-09-21 21:11:06 in reply to 15 [link]

There are 3 NEW blocks of code in the new version, namely, lines [75] - [79], [232] - [247], [1002] - [1030] ... made the difference between compiling success and failure.

Thanks for sorting it out.

I'm curious: <i>why aren't compiled extensions not included in the downloads? </i>Especially FILEIO.DLL as it is built-in SQLite3.EXE but omitted in SQLite3.DLL.

(17) By Larry Brasfield (larrybr) on 2021-09-21 21:35:14 in reply to 16 [link]

> Thanks for sorting it out.

It either needed fixing or an apologetic/caution against using it like the other extensions in just one context. Fixing won.

> I'm curious: why aren't compiled extensions ... included in the downloads? Especially FILEIO.DLL as it is built-in SQLite3.EXE but omitted in SQLite3.DLL.

The SQLite library is the main, supported product here. That is what is made conveniently available at the download page.

SQLite.exe and SQLite.dll differ more than how they are (normally) loaded. The former is the CLI shell, an application which uses and is linked against the library. The latter is just the library. There is much in the shell, including other extensions, that is not compiled into the dropped library images.

The extensions tend to be much more stable than the library and the shell. And they have less usage (I surmise.) So it is not evident that publishing binaries for the extension set across the supported platforms is worth the extra clutter on the download page and extra work required to create them. This could change some day, but nobody should hold their breath until then.