@@ -407,6 +407,50 @@ performing this in a platform-agnostic fashion, and the purpose of a build
407
407
script is again to farm out as much of this as possible to make this as easy as
408
408
possible for consumers.
409
409
410
+ As an example to follow, let's take a look at one of [ Cargo's own
411
+ dependencies] [ git2-rs ] , [ libgit2] [ libgit2 ] . This library has a number of
412
+ constraints:
413
+
414
+ [ git2-rs ] : https://github.com/alexcrichton/git2-rs/tree/master/libgit2-sys
415
+ [ libgit2 ] : https://github.com/libgit2/libgit2
416
+
417
+ * It has an optional dependency on OpenSSL on Unix to implement the https
418
+ transport.
419
+ * It has an optional dependency on libssh2 on all platforms to implement the ssh
420
+ transport.
421
+ * It is often not installed on all systems by default.
422
+ * It can be built from source using ` cmake ` .
423
+
424
+ To visualize what's going on here, let's take a look at the manifest for the
425
+ relevant Cargo package.
426
+
427
+ ``` toml
428
+ [package ]
429
+ name = " libgit2-sys"
430
+ version = " 0.0.1"
431
+ authors = [" ..." ]
432
+ links = " git2"
433
+ build = " build.rs"
434
+
435
+ [dependencies .libssh2-sys ]
436
+ git = " https://github.com/alexcrichton/ssh2-rs"
437
+
438
+ [target .x86_64-unknown-linux-gnu .dependencies .openssl-sys ]
439
+ git = " https://github.com/alexcrichton/openssl-sys"
440
+
441
+ # ...
442
+ ```
443
+
444
+ As the above manifests show, we've got a ` build ` script specified, but it's
445
+ worth noting that this example has a ` links ` entry which indicates that the
446
+ crate (` libgit2-sys ` ) links to the ` git2 ` native library.
447
+
448
+ Here we also see the unconditional dependency on ` libssh2 ` via the
449
+ ` libssh2-sys ` crate, as well as a platform-specific dependency on ` openssl-sys `
450
+ for unix (other variants elided for now). It may seem a little counterintuitive
451
+ to express * C dependencies* in the * Cargo manifest* , but this is actually using
452
+ one of Cargo's conventions in this space.
453
+
410
454
## ` *-sys ` Packages
411
455
412
456
To alleviate linking to system libraries, Cargo has a * convention* of package
@@ -428,3 +472,43 @@ convention of native-library-related packages:
428
472
* A common dependency allows centralizing logic on discovering ` libfoo ` itself
429
473
(or building it from source).
430
474
* These dependencies are easily overridable.
475
+
476
+ ## Building libgit2
477
+
478
+ Now that we've got libgit2's dependencies sorted out, we need to actually write
479
+ the build script. We're not going to look at specific snippets of code here and
480
+ instead only take a look at the high-level details of the build script of
481
+ ` libgit2-sys ` . This is not recommending all packages follow this strategy, but
482
+ rather just outlining one specific strategy.
483
+
484
+ The first step of the build script should do is to query whether libgit2 is
485
+ already installed on the host system. To do this we'll leverage the preexisting
486
+ tool ` pkg-config ` (when its available). We'll also use a ` build-dependencies `
487
+ section to refactor out all the ` pkg-config ` related code (or someone's already
488
+ done that!).
489
+
490
+ If ` pkg-config ` failed to find libgit2, or if ` pkg-config ` just wasn't
491
+ installed, the next step is to build libgit2 from bundled source code
492
+ (distributed as part of ` libgit2-sys ` itself). There are a few nuances when
493
+ doing so that we need to take into account, however:
494
+
495
+ * The build system of libgit2, ` cmake ` , needs to be able to find libgit2's
496
+ optional dependency of libssh2. We're sure we've already built it (it's a
497
+ Cargo dependency), we just need to communicate this information. To do this
498
+ we leverage the metadata format to communicate information between build
499
+ scripts. In this example the libssh2 package printed out ` cargo:root=... ` to
500
+ tell us where libssh2 is installed at, and we can then pass this along to
501
+ cmake with the ` CMAKE_PREFIX_PATH ` environment variable.
502
+
503
+ * We'll need to handle some ` CFLAGS ` values when compiling C code (and tell
504
+ ` cmake ` about this). Some flags we may want to pass are ` -m64 ` for 64-bit
505
+ code, ` -m32 ` for 32-bit code, or ` -fPIC ` for 64-bit code as well.
506
+
507
+ * Finally, we'll invoke ` cmake ` to place all output into the ` OUT_DIR `
508
+ environment variable, and then we'll print the necessary metadata to instruct
509
+ rustc how to link to libgit2.
510
+
511
+ Most of the functionality of this build script is easily refactorable into
512
+ common dependencies, so our build script isn't quite as intimidating as this
513
+ descriptions! In reality it's expected that build scripts are quite succinct by
514
+ farming logic such as above to build dependencies.
0 commit comments