SQLite Forum

Compile for Apple Silicon
Login

Compile for Apple Silicon

(1) By Will Iverson (wiverson) on 2021-11-30 17:38:08 [link] [source]

Looking at building a universal binary for macOS Intel & Apple Silicon.

Downloaded the sqlite-amalgamation-3370000 and used:

clang++ -arch arm64 -arch x86_64 -o sqlite_build sqlite3.c

...to try build. Managed to get as far as the output below. Seems very close, like I'm just missing the right compiler flags...? Any thoughts?

clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
sqlite3.c:21601:20: error: redefinition of 'sqlite3WhereTrace'
SQLITE_PRIVATE u32 sqlite3WhereTrace = 0;
                   ^
sqlite3.c:14130:20: note: previous definition is here
SQLITE_PRIVATE u32 sqlite3WhereTrace;
                   ^
sqlite3.c:23315:11: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
  { 0, 6, "second", 464269060800.0, 1000.0         },
          ^
sqlite3.c:23316:11: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
  { 0, 6, "minute", 7737817680.0,   60000.0        },
          ^
sqlite3.c:23317:11: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
  { 0, 4, "hour",   128963628.0,    3600000.0      },
          ^
sqlite3.c:23318:11: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
  { 0, 3, "day",    5373485.0,      86400000.0     },
          ^
sqlite3.c:23319:11: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
  { 1, 5, "month",  176546.0,       2592000000.0   },
          ^
sqlite3.c:23320:11: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
  { 2, 4, "year",   14713.0,        31536000000.0  },
          ^
sqlite3.c:27359:11: error: assigning to 'sqlite3_mutex *' from incompatible type 'void *'
      p = sqlite3MallocZero( sizeof(*p) );
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

(omitted, can post full output if helpful)

sqlite3.c:33835:10: note: forward declaration of '_ht'
  struct _ht *pEntry,    /* The entry into which pNew is inserted */
         ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
8 warnings and 20 errors generated.


(2) By Larry Brasfield (larrybr) on 2021-11-30 17:44:39 in reply to 1 [link] [source]

Why not use clang instead of clang++?

(6) By Will Iverson (wiverson) on 2021-12-01 01:33:26 in reply to 2 [link] [source]

I get the following with both clang and gcc. Found a post somewhere on The Internet(tm) that suggested trying clang++, which gave me the errors above.

sqlite-amalgamation-3370000 % clang -arch arm64 -arch x86_64 -o sqlite_build sqlite3.c 
Undefined symbols for architecture arm64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

(8) By Stephan Beal (stephan) on 2021-12-01 02:43:11 in reply to 6 [source]

Undefined symbols for architecture arm64:

Because you're trying to compile the amalgamation as a standalone executable, which it is not. It's intended to be built as an object file or a library. Though i don't know exactly what the conventions are on your OS, that generally looks something like:

clang -arch arm64 -arch x86_64 -c -o sqlite3.o sqlite3.c

The -c flag tells it to compile but not link. The -o flag tells it the output file name. You end up with an object file (the whole sqlite3 library) which you can then link together with your application's other object files.

If you're trying to build the shell, you'll have further steps to take, but someone familiar with the oddities of your platform will need to suggest what they are.

On my OS that looks something like:

[stephan@nuc:~/Downloads/sqlite-amalgamation-3370000]$ ls -la
total 9516
drwxrwxr-x 2 stephan stephan    4096 Nov 27 16:05 .
drwxr-xr-x 8 stephan stephan   12288 Dec  1 03:40 ..
-rw-rw-r-- 1 stephan stephan  704219 Nov 27 16:05 shell.c
-rw-rw-r-- 1 stephan stephan 8385624 Nov 27 16:05 sqlite3.c
-rw-rw-r-- 1 stephan stephan   35995 Nov 27 16:05 sqlite3ext.h
-rw-rw-r-- 1 stephan stephan  595850 Nov 27 16:05 sqlite3.h

[stephan@nuc:~/Downloads/sqlite-amalgamation-3370000]$ clang -c sqlite3.c
[stephan@nuc:~/Downloads/sqlite-amalgamation-3370000]$ clang -c shell.c
[stephan@nuc:~/Downloads/sqlite-amalgamation-3370000]$ clang -o sqlite3 sqlite3.o shell.o

/usr/bin/ld: sqlite3.o: in function `unixDlOpen':
sqlite3.c:(.text+0x662a): undefined reference to `dlopen'
/usr/bin/ld: sqlite3.o: in function `unixDlError':
sqlite3.c:(.text+0x6659): undefined reference to `dlerror'
/usr/bin/ld: sqlite3.o: in function `unixDlSym':
sqlite3.c:(.text+0x66aa): undefined reference to `dlsym'
/usr/bin/ld: sqlite3.o: in function `unixDlClose':
sqlite3.c:(.text+0x66f5): undefined reference to `dlclose'
/usr/bin/ld: sqlite3.o: in function `pthreadMutexAlloc':
sqlite3.c:(.text+0x1ba8d): undefined reference to `pthread_mutexattr_init'
/usr/bin/ld: sqlite3.c:(.text+0x1ba9e): undefined reference to `pthread_mutexattr_settype'
/usr/bin/ld: sqlite3.c:(.text+0x1baba): undefined reference to `pthread_mutexattr_destroy'
/usr/bin/ld: sqlite3.o: in function `pthreadMutexTry':
sqlite3.c:(.text+0x1bb81): undefined reference to `pthread_mutex_trylock'
/usr/bin/ld: sqlite3.o: in function `sqlite3ThreadJoin':
sqlite3.c:(.text+0x37a0c): undefined reference to `pthread_join'
/usr/bin/ld: sqlite3.o: in function `sqlite3ThreadCreate':
sqlite3.c:(.text+0x5859f): undefined reference to `pthread_create'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

(Oooops - we need to link in some external dependencies)

[stephan@nuc:~/Downloads/sqlite-amalgamation-3370000]$ clang -o sqlite3 sqlite3.o shell.o -ldl -lpthread

[stephan@nuc:~/Downloads/sqlite-amalgamation-3370000]$ ./sqlite3 
SQLite version 3.37.0 2021-11-27 14:13:22
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> ^D

On your OS it will be something very close to that, if not identical.

(3) By RandomCoder on 2021-11-30 17:46:40 in reply to 1 [link] [source]

clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]

That's the crux of your failure. You're compiling C code as C++, which isn't going to work. You should use clang instead of clang++

Also, you probably want to bring in shell.c if you want to build an executable.

(7) By Will Iverson (wiverson) on 2021-12-01 01:41:27 in reply to 3 [link] [source]

I'm (perhaps foolishly) trying to build a lib I can use in Unity that's native for Apple Silicon. Right now I'm using a version of the lib in Unity that works fine on Intel but dies with an error for the Apple Silicon build.

My only supported platforms are Intel 64, macOS Intel and Apple Silicon.

Might all just be yak shaving but tbh kind of fun to poke at C/C++ stuff. Seems very close. I've found good baselines to riff off for the C# bindings.

(4) By Stephan Beal (stephan) on 2021-11-30 17:48:11 in reply to 1 [link] [source]

clang++ -arch arm64 -arch x86_64 -o sqlite_build sqlite3.c

Use clang instead of clang++. sqlite3 is C and not all C constructs are legal in C++.

Related: all of the extern "C" blocks in sqlite3.c seem to be no-ops:

#if 0
extern "C" {
#endif

That's a strange (and seemingly useless?) way to do that. The more common convention is:

#ifdef __cplusplus
extern "C" {
#endif

(5) By Larry Brasfield (larrybr) on 2021-11-30 17:57:29 in reply to 4 [link] [source]

On useless extern "C" blocks:

If the code was written to use a C++ compiler as "a better C compiler"a, then those modifying wrappers would be useful (without the #if 0, of course.) But there is nothing but confusion (and forum posts) to be gained by allowing sqlite3.c to be passed thru a C++ compiler.


a. This has been claimed, and I largely agree. But the code has been written for older C compilers and contains numerous violations of the C-like subset of C++, so it is futile at present to enable those extern "C" wrappers.

(9) By Adrian Ho (lexfiend) on 2021-12-01 04:58:27 in reply to 1 [link] [source]

Others have already pointed out where you went wrong, but I think you should probably use the autoconf tarball instead, then:

CC=clang CFLAGS="-arch x86_64 -arch arm64" ./configure
make
gets you the universal CLI binary and libs in a single step.

(10) By Will Iverson (wiverson) on 2021-12-01 17:51:37 in reply to 9 [link] [source]

So, in the "feel very silly" stage, it's failing because it was trying to build an executable not a lib. Should have figured that out from the error about main.

clang -arch arm64 -arch x86_64 -dynamiclib -o sqlite3 sqlite3.c

Works, at least insofar as it builds cleanly and generates a lib. Crazy fast as well, cool.

I just tried the autoconf tarball and that also worked. Generated the following, so now I get to research exactly which file/lib is which. :)

Thanks to everyone for the help, much appreciated.

sqlite-autoconf-3370000 % diff start.txt end.txt
1a2
> Makefile
10a12,13
> config.log
> config.status
14a18
> end.txt
15a20,21
> libsqlite3.la
> libtool
18a25,27
> sqlite3
> sqlite3-shell.o
> sqlite3-sqlite3.o
21a31,33
> sqlite3.lo
> sqlite3.o
> sqlite3.pc

(11) By Will Iverson (wiverson) on 2021-12-07 18:13:18 in reply to 9 [link] [source]

I wound up switching to autoconf for macOS with the following build command:

CC=clang CFLAGS="-arch x86_64 -arch arm64 -Os -DDSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE -DSQLITE_DQS=0 -DSQLITE_ENABLE_COLUMN_METADATA" ./configure; make

Which I think will effectively match the amalgamation build for Windows run via x64 Native Tools Command Prompt for VS 2022:

cl -O2 -DSQLITE_API=__declspec(dllexport) -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE -DSQLITE_DQS=0 -DSQLITE_ENABLE_COLUMN_METADATA sqlite3.c -link -dll -out:sqlite3.dll

Next up, tweaking sqlite-net to add bindings to the session extensions.

Thanks to everyone for all the help. Hoping to write up all of my notes as an article for future reference.