Skip to content

Commit 1ae7ce4

Browse files
Merge pull request #120 from cxtuttle/use_staticlib
Use staticlib
2 parents 2b733c5 + fa0cb08 commit 1ae7ce4

File tree

3 files changed

+86
-59
lines changed

3 files changed

+86
-59
lines changed

README.md

+76-58
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,52 @@ go get github.com/marcboeker/go-duckdb
1313

1414
### Windows
1515

16-
On windows, the correct version of gcc and the necessary runtime libraries needs to be installed.
17-
One method to do this is using msys64. To begin, install msys64 using their installer. Once this is done, open a msys64 shell and run
16+
You must have the correct version of gcc and the necessary runtime libraries installed on Windows.
17+
One method to do this is using msys64.
18+
To begin, install msys64 using their installer.
19+
Once you installed msys64, open a msys64 shell and run:
1820

1921
```
2022
pacman -S mingw-w64-ucrt-x86_64-gcc
2123
```
2224

23-
select yes when necessary, its ok if the shell closes. Then add gcc to the path using whatever method you prefer. In powershell this is `$env:PATH = "C:\msys64\ucrt64\bin:$env:PATH"`. Once this is done, you can compile this package on windows.
25+
Select "yes" when necessary; it is okay if the shell closes.
26+
Then, add gcc to the path using whatever method you prefer.
27+
In powershell this is `$env:PATH = "C:\msys64\ucrt64\bin:$env:PATH"`.
28+
After, you can compile this package in Windows.
2429

2530
## Usage
2631

27-
`go-duckdb` hooks into the `database/sql` interface provided by the Go `stdlib`. To open a connection, simply specify the driver type as `duckdb`.
32+
_Note: For readability, we omit error handling in most examples._
33+
34+
`go-duckdb` hooks into the `database/sql` interface provided by the Go `stdlib`.
35+
To open a connection, specify the driver type as `duckdb`.
2836

2937
```go
3038
db, err := sql.Open("duckdb", "")
31-
check(err)
3239
defer db.Close()
3340
```
3441

35-
This creates an in-memory instance of DuckDB. To open a persistent database, you need to specify a filepath to the database file. If
36-
the file does not exist, then DuckDB creates it.
42+
The above lines create an in-memory instance of DuckDB.
43+
To open a persistent database, specify a file path to the database file.
44+
If the file does not exist, then DuckDB creates it.
3745

3846
```go
3947
db, err := sql.Open("duckdb", "/path/to/foo.db")
40-
check(err)
4148
defer db.Close()
4249
```
4350

44-
If you want to set specific [config options for DuckDB](https://duckdb.org/docs/sql/configuration), you can add them as query style parameters in the form of `name=value` pairs to the DSN.
51+
If you want to set specific [config options for DuckDB](https://duckdb.org/docs/sql/configuration),
52+
you can add them as query style parameters in the form of `name=value` pairs to the DSN.
4553

4654
```go
4755
db, err := sql.Open("duckdb", "/path/to/foo.db?access_mode=read_only&threads=4")
48-
check(err)
4956
defer db.Close()
5057
```
5158

5259
Alternatively, you can use [sql.OpenDB](https://cs.opensource.google/go/go/+/refs/tags/go1.23.0:src/database/sql/sql.go;l=824).
5360
That way, you can perform initialization steps in a callback function before opening the database.
54-
Here's an example that configures some database parameters when opening a database with `sql.OpenDB(connector)`.
61+
Here's an example that configures some parameters when opening a database with `sql.OpenDB(connector)`.
5562

5663
```go
5764
connector, err := duckdb.NewConnector("/path/to/foo.db?access_mode=read_only&threads=4", func(execer driver.ExecerContext) error {
@@ -68,43 +75,87 @@ connector, err := duckdb.NewConnector("/path/to/foo.db?access_mode=read_only&thr
6875
}
6976
return nil
7077
})
71-
check(err)
7278

7379
db := sql.OpenDB(connector)
7480
defer db.Close()
7581
```
7682

77-
Please refer to the [database/sql](https://godoc.org/database/sql) documentation for further usage instructions.
83+
Please refer to the [database/sql](https://godoc.org/database/sql) documentation for further instructions on usage.
84+
85+
## Linking DuckDB
86+
87+
By default, `go-duckdb` statically links pre-build DuckDB libraries into your binary.
88+
Statically linking DuckDB increases your binary size.
89+
90+
`go-duckdb` bundles the following pre-compiled static libraries.
91+
However, due to GitHub file size restrictions (100MB) and Go repository size limitations (500MB), these might change in the future.
92+
- MacOS: amd64, arm64.
93+
- Linux: amd64, arm64.
94+
- FreeBSD: amd64.
95+
- Windows: amd64.
96+
97+
### Linking a custom static library
98+
99+
If none of the pre-build libraries satisfy your needs, you can build a custom static library; see `deps.yaml`.
100+
101+
*Note: The DuckDB team is currently working on deploying pre-built static libraries as part of their releases and nightly builds.
102+
Once available, you can also download these libraries. They bundle the default extensions for duckdb releases.*
103+
104+
Once a static library (`libduckdb_bundle.a`) is available, you can build your project like this.
105+
```
106+
CGO_LDFLAGS="-lc++ -lduckdb_bundle -L/path/to/folder/with/lib" go build -tags=duckdb_use_static_lib
107+
```
108+
109+
### Dynamic linking
110+
111+
Alternatively, you can dynamically link DuckDB by passing `-tags=duckdb_use_lib` to `go build`.
112+
You must have a copy of `libduckdb` available on your system (`.so` on Linux or `.dylib` on macOS),
113+
which you can download from the DuckDB [releases page](https://github.com/duckdb/duckdb/releases).
114+
For example:
115+
116+
```sh
117+
# On Linux.
118+
CGO_ENABLED=1 CGO_LDFLAGS="-L/path/to/libs" go build -tags=duckdb_use_lib main.go
119+
LD_LIBRARY_PATH=/path/to/libs ./main
120+
121+
# On macOS.
122+
CGO_ENABLED=1 CGO_LDFLAGS="-L/path/to/libs" go build -tags=duckdb_use_lib main.go
123+
DYLD_LIBRARY_PATH=/path/to/libs ./main
124+
```
78125

79126
## Notes and FAQs
80127

81128
**`undefined: conn`**
82129

83-
When building this package, some people run into an `undefined: conn` error.
84-
This is due to the go compiler determining that CGO is not available. This can happen due to a few issues.
130+
Some people encounter an `undefined: conn` error when building this package.
131+
This error is due to the Go compiler determining that CGO is unavailable.
132+
This error can happen due to a few issues.
85133

86-
The first noted in the [comment here](https://github.com/marcboeker/go-duckdb/issues/275#issuecomment-2355712997) is that the buildtools are not installed.
134+
The first cause, as noted in the [comment here](https://github.com/marcboeker/go-duckdb/issues/275#issuecomment-2355712997),
135+
might be that the `buildtools` are not installed.
87136
To fix this for ubuntu, you can install them using:
88137
```
89138
sudo apt-get update && sudo apt-get install build-essential
90139
```
91140

92-
Another issue is when you are cross-compiling, since the go compiler automatically disables CGO when cross-compiling.
93-
To enable cgo when cross-compiling use `CC={C cross compiler} CGO_ENABLED=1 {command}` to force-enable CGO and set the right cross-compiler.
141+
Another cause can be cross-compilation since the Go compiler automatically disables CGO when cross-compiling.
142+
To enable CGO when cross-compiling, use `CC={C cross compiler} CGO_ENABLED=1 {command}` to force-enable CGO and set the right cross-compiler.
94143

95144
**`TIMESTAMP vs. TIMESTAMP_TZ`**
96145

97146
In the C API, DuckDB stores both `TIMESTAMP` and `TIMESTAMP_TZ` as `duckdb_timestamp`, which holds the number of
98-
microseconds elapsed since January 1, 1970 UTC (i.e., an instant without offset information).
147+
microseconds elapsed since January 1, 1970, UTC (i.e., an instant without offset information).
99148
When passing a `time.Time` to go-duckdb, go-duckdb transforms it to an instant with `UnixMicro()`,
100149
even when using `TIMESTAMP_TZ`. Later, scanning either type of value returns an instant, as SQL types do not model
101150
time zone information for individual values.
102151

103152
## Memory Allocation
104153

105-
DuckDB lives in-process. Therefore, all its memory lives in the driver. All allocations live in the host process, which
106-
is the Go application. Especially for long-running applications, it is crucial to call the corresponding `Close`-functions as specified
107-
in [database/sql](https://godoc.org/database/sql). The following is a list of examples.
154+
DuckDB lives in process.
155+
Therefore, all its memory lives in the driver.
156+
All allocations live in the host process, which is the Go application.
157+
Especially for long-running applications, it is crucial to call the corresponding `Close`-functions as specified in [database/sql](https://godoc.org/database/sql).
158+
The following is a list of examples.
108159

109160
```go
110161
db, err := sql.Open("duckdb", "")
@@ -132,21 +183,17 @@ See `examples/appender.go` for a complete example.
132183

133184
```go
134185
connector, err := duckdb.NewConnector("test.db", nil)
135-
check(err)
136186
defer connector.Close()
137187

138188
conn, err := connector.Connect(context.Background())
139-
check(err)
140189
defer conn.Close()
141190

142191
// Obtain an appender from the connection.
143192
// NOTE: The table 'test_tbl' must exist in test.db.
144193
appender, err := NewAppenderFromConn(conn, "", "test_tbl")
145-
check(err)
146194
defer appender.Close()
147195

148196
err = appender.AppendRow(...)
149-
check(err)
150197
```
151198

152199
## DuckDB Profiling API
@@ -163,7 +210,6 @@ Please refer to the [DuckDB documentation](https://duckdb.org/docs/dev/profiling
163210
- Next, you execute the query for which you want to obtain profiling information.
164211
- Finally, directly after executing the query, retrieve any available profiling information.
165212

166-
For readability, we omit error handling in this example.
167213
```Go
168214
db, err := sql.Open("duckdb", "")
169215
con, err := db.Conn(context.Background())
@@ -186,19 +232,15 @@ If you want to use the [DuckDB Arrow Interface](https://duckdb.org/docs/api/c/ap
186232

187233
```go
188234
connector, err := duckdb.NewConnector("", nil)
189-
check(err)
190235
defer connector.Close()
191236

192237
conn, err := connector.Connect(context.Background())
193-
check(err)
194238
defer conn.Close()
195239

196240
// Obtain the Arrow from the connection.
197241
arrow, err := duckdb.NewArrowFromConn(conn)
198-
check(err)
199242

200243
rdr, err := arrow.QueryContext(context.Background(), "SELECT * FROM generate_series(1, 10)")
201-
check(err)
202244
defer rdr.Release()
203245

204246
for rdr.Next() {
@@ -208,7 +250,8 @@ for rdr.Next() {
208250

209251
The Arrow interface is a heavy dependency.
210252
If you do not need it, you can disable it by passing `-tags=no_duckdb_arrow` to `go build`.
211-
This will be made opt-in in V2.
253+
254+
*Note: This will be made opt-in in V2.*
212255

213256
```sh
214257
go build -tags="no_duckdb_arrow"
@@ -223,32 +266,7 @@ See issue [#174](https://github.com/marcboeker/go-duckdb/issues/174#issuecomment
223266
2. `go mod vendor`
224267
3. `modvendor -copy="**/*.a **/*.h" -v`
225268

226-
Now you can build your module as usual.
227-
228-
## Linking DuckDB
229-
230-
By default, `go-duckdb` statically links DuckDB into your binary.
231-
Statically linking DuckDB increases your binary size.
232-
233-
`go-duckdb` bundles pre-compiled static libraries for some OS and architecture combinations.
234-
- MacOS: amd64, arm64.
235-
- Linux: amd64, arm64.
236-
- FreeBSD: amd64.
237-
- Windows: amd64.
238-
239-
Alternatively, you can dynamically link DuckDB by passing `-tags=duckdb_use_lib` to `go build`.
240-
You must have a copy of `libduckdb` available on your system (`.so` on Linux or `.dylib` on macOS), which you can download from the DuckDB [releases page](https://github.com/duckdb/duckdb/releases).
241-
For example:
242-
243-
```sh
244-
# On Linux.
245-
CGO_ENABLED=1 CGO_LDFLAGS="-L/path/to/libs" go build -tags=duckdb_use_lib main.go
246-
LD_LIBRARY_PATH=/path/to/libs ./main
247-
248-
# On macOS.
249-
CGO_ENABLED=1 CGO_LDFLAGS="-L/path/to/libs" go build -tags=duckdb_use_lib main.go
250-
DYLD_LIBRARY_PATH=/path/to/libs ./main
251-
```
269+
Now, you can build your module as usual.
252270

253271
## DuckDB Extensions
254272

cgo_static.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build !duckdb_use_lib && (darwin || (linux && (amd64 || arm64)) || (freebsd && amd64) || (windows && amd64))
1+
//go:build !duckdb_use_lib && !duckdb_use_static_lib && (darwin || (linux && (amd64 || arm64)) || (freebsd && amd64) || (windows && amd64))
22

33
package duckdb
44

cgo_static_lib.go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build duckdb_use_static_lib
2+
3+
package duckdb
4+
5+
/*
6+
#cgo CPPFLAGS: -DDUCKDB_STATIC_BUILD
7+
#include <duckdb.h>
8+
*/
9+
import "C"

0 commit comments

Comments
 (0)