diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-09-04 17:19:27 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-09-04 17:19:27 +0200 |
commit | 2aa72e2e0e2551d986baeae7d57d628e58a61c39 (patch) | |
tree | 3ce764f17205e708d49399366743265a2b3f8650 /doc | |
parent | 11ea86d820e8a9600078e8b8f181d1a6c25dac94 (diff) |
Update introduction
Diffstat (limited to 'doc')
-rwxr-xr-x | doc/cli.sh | 4 | ||||
-rw-r--r-- | doc/intro.cli | 663 |
2 files changed, 403 insertions, 264 deletions
@@ -32,8 +32,8 @@ function gen () # <name> --generate-html --html-suffix .xhtml \ --html-prologue-file doc-prologue.xhtml \ --html-epilogue-file doc-epilogue.xhtml \ ---link-regex '%b([-.].+)%../../build2/doc/b$n%' \ ---link-regex '%bpkg([-.].+)%../../bpkg/doc/bpkg$n%' \ +--link-regex '%b([-.].+)%../../build2/doc/b$1%' \ +--link-regex '%bpkg([-.].+)%../../bpkg/doc/bpkg$1%' \ --output-prefix build2-toolchain- "${@}" $n.cli html2ps -f doc.html2ps:a4.html2ps -o build2-toolchain-$n-a4.ps build2-toolchain-$n.xhtml diff --git a/doc/intro.cli b/doc/intro.cli index 791394c..d0719c4 100644 --- a/doc/intro.cli +++ b/doc/intro.cli @@ -31,7 +31,7 @@ \h#tldr|TL;DR| \ -$ bpkg create -d hello cxx +$ bpkg create -d hello cc created new configuration in hello/ $ cd hello/ @@ -40,51 +40,47 @@ added repository build2.org/hello/stable $ bpkg fetch fetching build2.org/hello/stable -3 package(s) in 1 repository(s) +2 package(s) in 1 repository(s) $ bpkg build hello -build libhello 1.0.1 (required by hello) -build hello 1.0.0 +build libhello/1.0.0 (required by hello) +build hello/1.0.0 continue? [Y/n] y -libhello-1.0.1.tar.gz 100% of 1489 B 983 kBps 00m01s -fetched libhello 1.0.1 -unpacked libhello 1.0.1 -hello-1.0.0.tar.gz 100% of 1030 B 6882 kBps 00m01s -fetched hello 1.0.0 -unpacked hello 1.0.0 -configured libhello 1.0.1 -configured hello 1.0.0 +libhello-1.0.0.tar.gz 100% of 2428 B 983 kBps 00m01s +fetched libhello/1.0.0 +unpacked libhello/1.0.0 +hello-1.0.0.tar.gz 100% of 1057 B 6882 kBps 00m01s +fetched hello/1.0.0 +unpacked hello/1.0.0 +configured libhello/1.0.0 +configured hello/1.0.0 c++ hello-1.0.0/cxx{hello} -c++ libhello-1.0.1/hello/cxx{hello} -ld libhello-1.0.1/hello/libso{hello} +c++ libhello-1.0.0/hello/cxx{hello} +ld libhello-1.0.0/hello/libs{hello} ld hello-1.0.0/exe{hello} -updated hello 1.0.0 +updated hello/1.0.0 \ " " \h#warning|Warning| -The \c{build2} toolchain \c{0.x.y} series are alpha releases. Interfaces +The \c{build2} toolchain \c{0.X.Y} series are alpha releases. Interfaces \i{will} change in backwards-incompatible ways, guaranteed. Currently, it is more of a technology preview rather than anything final. But if you want to start playing with it, welcome and join the \l{https://lists.build2.org mailing list}! Our approach to developing \c{build2} is to first get the hard parts right -before focusing on completeness. So while we might still be extracting header -dependencies on every run (no caching yet) they do play well with -auto-generated source code. In other words, we go depth rather than -breadth-first. As a result, there are plenty of limitations and missing pieces, -especially in the build system. The most notable ones are: +before focusing on completeness. So while we might still only be building +serially, we do handle auto-generated source code (and, in particular, +headers) properly. In other words, we go depth rather than breadth-first. As a +result, there are plenty of limitations and missing pieces, especially in the +build system. The most notable ones are: \ul| -\li|Limited documentation.| - -\li|No C compiler rules.| - -\li|No support for Windows/VC++.| +\li|Very limited documentation.| \li|No support for parallel builds.| @@ -97,7 +93,7 @@ especially in the build system. The most notable ones are: \h#intro|Introduction| The \c{build2} toolchain is a set of tools designed for building and packaging -C++ code (though, if it can handle C++ it can handle anything, right?). The +C++ code (though, if it can handle C++, it can handle anything, right?). The toolchain currently includes the \i{build system} (\c{build2}), the \i{package manager} (\c{bpkg}), and the \i{repository web interface} (\c{brep}). More tools, such as the \i{build robot} (\c{bbot}), are in the works. Then there is @@ -109,22 +105,24 @@ toolchain can do so that you can decide if you are interested and want to learn more. Further documentation is referenced at the end of this introduction. The \c{build2} toolchain is self-hosted and self-packaged (and, yes, it is on -\l{https://cppget.org/ cppget.org}). It could then serve as its own example. -However, before the toolchain can unpack and build itself, we have to bootstrap -it (that chicken and egg problem again) and this step wouldn't serve our goal -of quickly learning what \c{build2} is about. So, instead, we will start with a -customary \i{\"Hello, World!\"} example which you won't yet be able to try -yourself (but don't worry, complete terminal output will be shown). If at the -end you find \c{build2} appealing, the following section jumps right into -bootstrapping and installation (and, yes, you get to run that coveted \c{bpkg -build bpkg}). Once the \c{build2} installation is complete, you can come back -to the \i{\"Hello, World!\"} example and try all of the steps for yourself. +\l{https://cppget.org/ cppget.org}). It could have then served as its own +example. However, before the toolchain can unpack and build itself, we have +to bootstrap it (that chicken and egg problem again) and this step wouldn't +serve our goal of quickly learning what \c{build2} is about. So, instead, we +will start with a customary \i{\"Hello, World!\"} example which you won't yet +be able to try yourself (but don't worry, complete terminal output will be +shown). If at the end you find \c{build2} appealing, you can jump right to the +\l{build2-toolchain-install.xhtml The \c{build2} Toolchain Installation and +Upgrade} (and, yes, there you get to run that coveted \c{bpkg build bpkg}). +Once the \c{build2} installation is complete, you can come back to the +\i{\"Hello, World!\"} example and try all of the steps for yourself. This introduction explores the \i{consumer} side of \i{\"Hello, World!\"}. That is, we assume that someone was kind enough to create and package the \c{libhello} library and the \c{hello} program and we will learn how to obtain -and build them as well as keep up with their updates. And so, without further -ado, let's begin. +and build them as well as keep up with their updates. At the end we will +also see how to write our own, \c{hello2}, program that depends on \c{libhello}. +And so, without further ado, let's begin. The first step in using \c{bpkg} is to create a \i{configuration}. A configuration is a directory where packages that require similar compile @@ -140,6 +138,23 @@ $ bpkg create cxx config.cxx=g++-5 config.cxx.coptions=-O3 created new configuration in /tmp/hello-gcc5-release/ \ +Or perhaps you are on Windows and prefer Visual Studio (running from the +Visual Studio Tools Command Prompt): + +\ +> mkdir hello-vc14-release +> cd hello-vc14-release +> bpkg create cxx config.cxx=cl config.cxx.coptions=/O2 +created new configuration in C:\projects\hello-vc14-release\ +\ + +One of the primary goals of the \c{build2} toolchain is to provide a uniform +build interface across all the platforms and compilers. While the following +examples use the \c{hello-gcc5-release} configuration and assume a UNIX-like +operation system, everything will work if you use \c{hello-vc14-release} (or +\c{hello-mingw-release}) on Windows. Just use appropriate paths, compilers, +and options. + Let's discuss that last command line: \l{bpkg-cfg-create(1) \c{bpkg create}} is the command for creating a new configuration. As a side note, if you ever want to get help for any \c{bpkg} command, run \c{bpkg help <command>}. To see the @@ -161,6 +176,31 @@ module with \c{coptions} standing for \i{compile options} (there are also \c{poptions} for \i{preprocess options}, \c{loptions} for \i{link options}, and \c{libs} for extra libraries to link). +There is also the \c{c} module for the C compilation. So if we were planning +to build both C and C++ projects, then we could have ran: + +\ +$ bpkg create c cxx ... +\ + +The problem, of course, is that you may not know what mix of languages those +projects (or their dependencies) might use. For example the use of C might be +an implementation detail of a C++ library. To solve this, \c{build2} provides +another module called \c{cc} which stands for \i{C-common}. So, in this +context, instead of using the \c{c} and \c{cxx} modules directly, it's a good +idea to get into the habit of using \c{cc}: + +\ +$ bpkg create cc config.cxx=g++-5 config.cc.coptions=-O3 +\ + +Notice two things about this command line: we don't need to specify the C +compiler with \c{config.c} \- \c{build2} is smart enough to figure it out +from \c{config.cxx} (or vice versa). We also used \c{config.cc.coptions} +instead of \c{config.cxx.coptions} so that the options apply to all the +C-common languages (we can still use \c{config.{c,cxx\}.*} for the +language-specific options). + Ok, configuration in hand, where can we get some packages? \c{bpkg} packages come from \i{repositories}. A repository can be a local filesystem directory or a remote URL. Our example packages come from their own remote \i{\"Hello, @@ -172,13 +212,37 @@ we can ask \c{bpkg} to interrogate a repository location for us: \ $ bpkg rep-info https://build2.org/pkg/1/hello/stable +warning: authenticity of the certificate for repository build2.org/hello/stable cannot be established +certificate is for build2.org, \"Code Synthesis\" <admin@build2.org> +certificate SHA256 fingerprint: +FF:DF:7D:38:67:4E:C3:82:65:7E:[...]:29:9A:30:56:B9:77:B9:F2:01:94 +trust this certificate? [y/N] +\ + +The \c{bpkg} repositories are normally signed to prevent tampering with +packages. If the repository certificate is seen (in this configuration) for +the first time, \c{bpkg} will ask you to authenticate it. A good way to +authenticate a certificate is to compare the displayed fingerprint to the one +you have received earlier, for example, in an email announcement. The +repository's about page also lists the fingerprint (see the +\l{https://build2.org/pkg/hello/?about about page} for our repository). For +more details on repository signing see \l{bpkg-repository-signing(1)} help +topic. + +If we answer \i{yes}, we will see the basic repository information (its +canonical name, location, certificate subject and fingerprint) followed +by the list of available packages: + +\ build2.org/hello/stable https://build2.org/pkg/1/hello/stable -hello 1.0.0 -libhello 1.0.0+1 -libhello 1.0.1 +CN=build2.org/O=Code Synthesis/admin@build2.org +FF:DF:7D:38:67:4E:C3:82:65:7E:[...]:29:9A:30:56:B9:77:B9:F2:01:94 + +hello/1.0.0 +libhello/1.0.0 \ -Or we could use the repository's web interface (implemented by \c{brep}). Our +We can also use the repository's web interface (implemented by \c{brep}). Our repository has one, check it out: \c{\l{https://build2.org/pkg/hello/}}. Ok, back to the command line. If we want to use a repository as a source of @@ -196,20 +260,20 @@ available packages for all the added repositories: \ $ bpkg fetch fetching build2.org/hello/stable -3 package(s) in 1 repository(s) +2 package(s) in 1 repository(s) \ -You would normally re-run the \l{bpkg-rep-fetch(1) \c{bpkg fetch}} command -after you've added another repository or to refresh the list of available -packages. +Note that you would normally re-run the \l{bpkg-rep-fetch(1) \c{bpkg fetch}} +command after you've added another repository or to refresh the list of +available packages. Now that \c{bpkg} knows where to get packages, we can finally get down to business: \ $ bpkg build hello -build libhello 1.0.1 (required by hello) -build hello 1.0.0 +build libhello/1.0.0 (required by hello) +build hello/1.0.0 continue? [Y/n] \ @@ -221,21 +285,19 @@ confirm that's what we want to do (you can add \c{--yes|-y} to skip the confirmation). Let's answer \i{yes} and see what happens: \ -... -continue? [Y/n] y -libhello-1.0.1.tar.gz 100% of 1489 B 1364 kBps 00m01s -fetched libhello 1.0.1 -unpacked libhello 1.0.1 -hello-1.0.0.tar.gz 100% of 1030 B 20 MBps 00m01s -fetched hello 1.0.0 -unpacked hello 1.0.0 -configured libhello 1.0.1 -configured hello 1.0.0 +libhello-1.0.0.tar.gz 100% of 2428 B 1364 kBps 00m01s +fetched libhello/1.0.0 +unpacked libhello/1.0.0 +hello-1.0.0.tar.gz 100% of 1057 B 20 MBps 00m01s +fetched hello/1.0.0 +unpacked hello/1.0.0 +configured libhello/1.0.0 +configured hello/1.0.0 c++ hello-1.0.0/cxx{hello} -c++ libhello-1.0.1/hello/cxx{hello} -ld libhello-1.0.1/hello/libso{hello} +c++ libhello-1.0.0/hello/cxx{hello} +ld libhello-1.0.0/hello/libs{hello} ld hello-1.0.0/exe{hello} -updated hello 1.0.0 +updated hello/1.0.0 \ While the output is mostly self-explanatory, in short, \c{bpkg} downloaded, @@ -266,48 +328,48 @@ if not interested. \ $ bpkg build -v -y hello -fetching libhello-1.0.1.tar.gz from build2.org/hello/stable -curl ... https://build2.org/pkg/1/hello/stable/libhello-1.0.1.tar.gz +fetching libhello-1.0.0.tar.gz from build2.org/hello/stable +curl ... https://build2.org/pkg/1/hello/stable/libhello-1.0.0.tar.gz % Total % Received Average Speed Time Time Time Current Dload Upload Total Spent Left Speed -100 1489 100 1489 1121 0 0:00:01 0:00:01 --:--:-- 1122 -fetched libhello 1.0.1 -tar -xf libhello-1.0.1.tar.gz -unpacked libhello 1.0.1 +100 2428 100 2428 1121 0 0:00:01 0:00:01 --:--:-- 1122 +fetched libhello/1.0.0 +tar -xf libhello-1.0.0.tar.gz +unpacked libhello/1.0.0 fetching hello-1.0.0.tar.gz from build2.org/hello/stable curl ... https://build2.org/pkg/1/hello/stable/hello-1.0.0.tar.gz % Total % Received Average Speed Time Time Time Current Dload Upload Total Spent Left Speed -100 1030 100 1030 773 0 0:00:01 0:00:01 --:--:-- 772 -fetched hello 1.0.0 +100 1057 100 1057 773 0 0:00:01 0:00:01 --:--:-- 772 +fetched hello/1.0.0 tar -xf hello-1.0.0.tar.gz -unpacked hello 1.0.0 -b -v configure(./libhello-1.0.1/) -config::save libhello-1.0.1/build/config.build -configured libhello 1.0.1 +unpacked hello/1.0.0 +b -v configure(./libhello-1.0.0/) +cat >libhello-1.0.0/build/config.build +configured libhello/1.0.0 b -v configure(./hello-1.0.0/) -config::save hello-1.0.0/build/config.build -configured hello 1.0.0 +cat >hello-1.0.0/build/config.build +configured hello/1.0.0 hold package hello b -v update(./hello-1.0.0/) -g++-5 -Ilibhello-1.0.1 -O3 -std=c++11 -o hello-1.0.0/hello.o -c hello-1.0.0/hello.cxx -g++-5 -Ilibhello-1.0.1 -O3 -std=c++11 -fPIC -o libhello-1.0.1/hello/hello-so.o -c libhello-1.0.1/hello/hello.cxx -g++-5 -O3 -std=c++11 -shared -o libhello-1.0.1/hello/libhello.so -g++-5 -O3 -std=c++11 -o hello-1.0.0/hello hello-1.0.0/hello.o libhello-1.0.1/hello/libhello.so -updated hello 1.0.0 +g++-5 -I libhello-1.0.0 -O3 -std=c++11 -o hello-1.0.0/hello.o -c hello-1.0.0/hello.cxx +g++-5 -I libhello-1.0.0 -O3 -std=c++11 -fPIC -o libhello-1.0.0/hello/hello.so.o -c libhello-1.0.0/hello/hello.cxx +g++-5 -O3 -std=c++11 -shared -o libhello-1.0.0/hello/libhello-1.0.so libhello-1.0.0/hello/hello.so.o +g++-5 -O3 -std=c++11 -o hello-1.0.0/hello hello-1.0.0/hello.o libhello-1.0.0/hello/libhello-1.0.so +updated hello/1.0.0 \ -Another handy command is \l{bpkg-pkg-status(1) \c{bpkg status}}. It can be used -to examine the state of a package in the configuration. Here are a few examples -(if you absolutely must know what \c{hold_package} means, check the -command's documentation): +Another handy command is \l{bpkg-pkg-status(1) \c{bpkg status}}. It can be +used to examine the state of a package in the configuration. Here are a few +examples (if you absolutely must know what \c{hold_package} and \c{sys:?} +mean, check \l{bpkg-pkg-status(1)}): \ $ bpkg status libhello -configured 1.0.1 +configured 1.0.0; available sys:? $ bpkg status hello -configured 1.0.0 hold_package +configured 1.0.0 hold_package; available sys:? $ bpkg drop -y hello disfigured hello @@ -316,7 +378,7 @@ purged hello purged libhello $ bpkg status hello -available 1.0.0 +available 1.0.0 sys:? $ bpkg status libfoobar unknown @@ -349,19 +411,28 @@ added repository build2.org/hello/testing $ bpkg fetch fetching build2.org/hello/stable fetching build2.org/hello/testing -7 package(s) in 2 repository(s) +5 package(s) in 2 repository(s) +\ +Notice that this time we don't see any authentication-related messages or +prompts since \c{bpkg} remembered (in this configuration) that we trust +this certificate (the \c{testing} repository naturally uses the same one +as \c{stable}). + +Let's see what's new: + +\ $ bpkg status libhello -configured 1.0.1; available 1.1.1 1.1.0 +configured 1.0.0; available 1.1.0 sys:? \ -Ok, \c{libhello 1.1.x} is now available. How do we upgrade? We can try to +Ok, \c{libhello/1.1.0} is now available. How do we upgrade? We can try to build \c{hello} again: \ $ bpkg build -y hello info: dir{hello-1.0.0/} is up to date -updated hello 1.0.0 +updated hello/1.0.0 \ Nothing happens. That's because \c{bpkg} will only upgrade (or downgrade) to a @@ -371,9 +442,9 @@ new version if we explicitly ask it to. As it is now, all dependencies for \ $ bpkg build libhello -build libformat 1.0.0 (required by libhello) -build libprint 1.0.0 (required by libhello) -upgrade libhello 1.1.1 +build libformat/1.0.0 (required by libhello) +build libprint/1.0.0 (required by libhello) +upgrade libhello/1.1.0 reconfigure hello (dependent of libhello) continue? [Y/n] \ @@ -390,14 +461,12 @@ so it might need a chance to make some adjustments to its configuration. Let's answer \i{yes} if only to see what happens: \ -... -continue? [Y/n] y update dependent packages? [Y/n] \ Another question. This one has to do with that \c{reconfigure hello} line we just talked about. If you were wondering why we were only offered to -reconfigure and not actually update the dependent package, you should realize +reconfigure and not actually update the dependent package, you should know that \c{bpkg} is a very lazy package manager, it only does what it must do. It must reconfigure but it doesn't really have to update. And this could be a good thing if, for example, you have a hundred dependents in your configuration @@ -409,39 +478,39 @@ answer \i{yes} again: \ ... update dependent packages? [Y/n] y -disfigured hello 1.0.0 -disfigured libhello 1.0.1 +disfigured hello/1.0.0 +disfigured libhello/1.0.0 libformat-1.0.0.tar.gz 100% of 1064 B 11 MBps 00m01s -fetched libformat 1.0.0 -unpacked libformat 1.0.0 +fetched libformat/1.0.0 +unpacked libformat/1.0.0 libprint-1.0.0.tar.gz 100% of 1040 B 9 MBps 00m01s -fetched libprint 1.0.0 -unpacked libprint 1.0.0 -libhello-1.1.1.tar.gz 100% of 1564 B 4672 kBps 00m01s -fetched libhello 1.1.1 -unpacked libhello 1.1.1 -configured libformat 1.0.0 -configured libprint 1.0.0 -configured libhello 1.1.1 -configured hello 1.0.0 -c++ libhello-1.1.1/hello/cxx{hello} +fetched libprint/1.0.0 +unpacked libprint/1.0.0 +libhello-1.1.0.tar.gz 100% of 1564 B 4672 kBps 00m01s +fetched libhello/1.1.0 +unpacked libhello/1.1.0 +configured libformat/1.0.0 +configured libprint/1.0.0 +configured libhello/1.1.0 +configured hello/1.0.0 +c++ libhello-1.1.0/hello/cxx{hello} c++ libformat-1.0.0/format/cxx{format} ld libformat-1.0.0/format/liba{format} c++ libprint-1.0.0/print/cxx{print} ld libprint-1.0.0/print/liba{print} -ld libhello-1.1.1/hello/liba{hello} -c++ libhello-1.1.1/hello/cxx{hello} +ld libhello-1.1.0/hello/liba{hello} +c++ libhello-1.1.0/hello/cxx{hello} c++ libformat-1.0.0/format/cxx{format} -ld libformat-1.0.0/format/libso{format} +ld libformat-1.0.0/format/libs{format} c++ libprint-1.0.0/print/cxx{print} -ld libprint-1.0.0/print/libso{print} -ld libhello-1.1.1/hello/libso{hello} -c++ libhello-1.1.1/tests/test/cxx{driver} -ld libhello-1.1.1/tests/test/exe{driver} +ld libprint-1.0.0/print/libs{print} +ld libhello-1.1.0/hello/libs{hello} +c++ libhello-1.1.0/tests/test/cxx{driver} +ld libhello-1.1.0/tests/test/exe{driver} c++ hello-1.0.0/cxx{hello} ld hello-1.0.0/exe{hello} -updated libhello 1.1.1 -updated hello 1.0.0 +updated libhello/1.1.0 +updated hello/1.0.0 \ If you were to answer \i{no} to the \"update dependent packages?\" question @@ -452,33 +521,33 @@ the \l{bpkg-pkg-update(1) \c{bpkg update}} command (there is also \ $ bpkg clean hello rm hello-1.0.0/exe{hello} -rm hello-1.0.0/obja{hello} -cleaned hello 1.0.0 +rm hello-1.0.0/obje{hello} +cleaned hello/1.0.0 $ bpkg update hello c++ hello-1.0.0/cxx{hello.cxx} ld hello-1.0.0/exe{hello} -updated hello 1.0.0 +updated hello/1.0.0 \ Let's say we really don't like the direction \c{libhello} is going and would -rather stick to version \c{1.0.0}. Just like upgrades, downgrades are -explicit plus, in this case, we need to specify the version (you -can also specify desired version for upgrades, in case you are wondering). +rather stick to version \c{1.0.0}. Just like upgrades, downgrades are explicit +plus, in this case, we need to specify the version (you can also specify +desired version for upgrades). \ -$ bpkg build libhello/1.0.1 -downgrade libhello 1.0.1 +$ bpkg build libhello/1.0.0 +downgrade libhello/1.0.0 reconfigure hello (dependent of libhello) continue? [Y/n] y update dependent packages? [Y/n] y -disfigured hello 1.0.0 -disfigured libhello 1.1.1 -libhello-1.0.1.tar.gz 100% of 1489 B 983 kBps 00m01s -fetched libhello 1.0.1 -unpacked libhello 1.0.1 -configured libhello 1.0.1 -configured hello 1.0.0 +disfigured hello/1.0.0 +disfigured libhello/1.1.0 +libhello-1.0.0.tar.gz 100% of 2428 B 983 kBps 00m01s +fetched libhello/1.0.0 +unpacked libhello/1.0.0 +configured libhello/1.0.0 +configured hello/1.0.0 following prerequisite packages were automatically built and will no longer be necessary: libprint libformat @@ -487,16 +556,16 @@ disfigured libprint disfigured libformat purged libprint purged libformat -c++ libhello-1.0.1/hello/cxx{hello} -ld libhello-1.0.1/hello/liba{hello} -c++ libhello-1.0.1/hello/cxx{hello} -ld libhello-1.0.1/hello/libso{hello} -c++ libhello-1.0.1/tests/test/cxx{driver} -ld libhello-1.0.1/tests/test/exe{driver} +c++ libhello-1.0.0/hello/cxx{hello} +ld libhello-1.0.0/hello/liba{hello} +c++ libhello-1.0.0/hello/cxx{hello} +ld libhello-1.0.0/hello/libs{hello} +c++ libhello-1.0.0/tests/test/cxx{driver} +ld libhello-1.0.0/tests/test/exe{driver} c++ hello-1.0.0/cxx{hello} ld hello-1.0.0/exe{hello} -updated libhello 1.0.1 -updated hello 1.0.0 +updated libhello/1.0.0 +updated hello/1.0.0 \ Notice how \c{bpkg} helpfully offered to get rid of \c{libprint} and @@ -507,7 +576,7 @@ also more granular options. For example, this is how we can instruct dependents just reconfigured (\c{--leave-dependent|-L}): \ -$ bpkg build -D -L libhello/1.0.1 +$ bpkg build -D -L libhello/1.0.0 \ Ok, so all this might look nice and all, but we haven't actually seen anything @@ -520,10 +589,10 @@ test}} command: \ $ bpkg test libhello hello -test libhello-1.0.1/tests/test/exe{driver} +test libhello-1.0.0/tests/test/exe{driver} test hello-1.0.0/exe{hello} -tested libhello 1.0.1 -tested hello 1.0.0 +tested libhello/1.0.0 +tested hello/1.0.0 \ But that doesn't quite count for seeing libraries and running programs. Well, @@ -537,11 +606,10 @@ packages that we've built: $ ls -1F build/ hello-1.0.0/ -libhello-1.0.1/ -bpkg.sqlite3 +libhello-1.0.0/ buildfile hello-1.0.0.tar.gz -libhello-1.0.1.tar.gz +libhello-1.0.0.tar.gz \ And if we look inside \c{hello-1.0.0/} we will see what looks like the @@ -568,27 +636,34 @@ Hello, World! \ The important point here is this: the \c{bpkg} configuration is not some black -box that you should never look inside. On the contrary, it is a normal building -block of the build system and if you understand what you are doing, feel free -to muck around. Now, confess, did you run \c{sqlite3 bpkg.sqlite3 .dump}? +box that you should never look inside. On the contrary, it is a normal and +predictable concept of the build system and if you understand what you are +doing, feel free to muck around. Another way to get hold of a package's goodies is to install it with \l{bpkg-pkg-install(1) \c{bpkg install}}. Let's try that: \ -$ bpkg install config.install.root=/opt/hello \ -config.install.root.sudo=sudo hello +$ bpkg install \ + config.install.root=/opt/hello \ + config.install.sudo=sudo \ + hello install /opt/hello/ +install /opt/hello/include/ install /opt/hello/include/hello/ -install libhello-1.0.1/hello/hxx{hello} +install libhello-1.0.0/hello/hxx{hello} +install libhello-1.0.0/hello/hxx{export} install /opt/hello/lib/ -install libhello-1.0.1/hello/libso{hello} +install libhello-1.0.0/hello/libs{hello} install /opt/hello/bin/ install hello-1.0.0/exe{hello} +install /opt/hello/share/ +install /opt/hello/share/doc/ install /opt/hello/share/doc/hello/ install hello-1.0.0/doc{version} -installed hello 1.0.0 + +installed hello/1.0.0 $ tree -F /opt/hello/ /opt/hello/ @@ -596,16 +671,18 @@ $ tree -F /opt/hello/ │ └── hello* ├── include/ │ └── hello/ +│ ├── export │ └── hello ├── lib/ -│ └── libhello.so* +│ ├── libhello-1.0.so* +│ └── libhello.so -> libhello-1.0.so* └── share/ └── doc/ └── hello/ └── version \ -The \c{config.install.root.sudo} value is the optional \i{sudo}-like program +The \c{config.install.sudo} value is the optional \i{sudo}-like program that should be used to run the \c{install} program. For those feeling queasy running \c{sudo make install}, here is your answer. If you are wondering whether you could have specified those \c{config.install.*} values during the @@ -614,32 +691,43 @@ installed program: \ $ /opt/hello/bin/hello World -/opt/hello/bin/hello: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory +/opt/hello/bin/hello: error while loading shared libraries: libhello-1.0.so: cannot open shared object file: No such file or directory \ -Not what we hoped to see. The problem is with our installation location: the -runtime linker won't look for \c{libhello.so} in \c{/opt/hello/lib} unless we -somehow tell it to, for example, using \c{LD_LIBRARY_PATH} or equivalent. -There are several way we can resolve this. We could give up on shared -libraries and link our prerequisite libraries statically -(\c{config.bin.exe.lib=static}). Or we could use the \i{rpath} mechanism: +Not what we hoped to see. Note to the Windows users: this will actually work +since \c{hello-1.0.dll} will be installed into \c{bin\\}, next to the +executable; for once things are working better on Windows. + +The problem is with our installation location: the runtime linker won't look +for \c{libhello-1.0.so} in \c{/opt/hello/lib} unless we somehow tell it to, for +example, using \c{LD_LIBRARY_PATH} or equivalent. There are several way we +can resolve this. We could give up on shared libraries and link our +prerequisite libraries statically (\c{config.bin.exe.lib=static}). Or we could +use the \i{rpath} mechanism: \ -$ bpkg install config.install.root=/opt/hello \ -config.install.root.sudo=sudo \ -config.bin.rpath=/opt/hello/lib hello +$ bpkg install \ + config.install.root=/opt/hello \ + config.install.sudo=sudo \ + config.bin.rpath=/opt/hello/lib \ + hello ld hello-1.0.0/exe{hello} install /opt/hello/ +install /opt/hello/include/ install /opt/hello/include/hello/ -install libhello-1.0.1/hello/hxx{hello} +install libhello-1.0.0/hello/hxx{hello} +install libhello-1.0.0/hello/hxx{export} install /opt/hello/lib/ -install libhello-1.0.1/hello/libso{hello} +install libhello-1.0.0/hello/libs{hello} install /opt/hello/bin/ install hello-1.0.0/exe{hello} +install /opt/hello/share/ +install /opt/hello/share/doc/ install /opt/hello/share/doc/hello/ install hello-1.0.0/doc{version} -installed hello 1.0.0 + +installed hello/1.0.0 $ /opt/hello/bin/hello World Hello, World! @@ -648,12 +736,41 @@ Hello, World! Notice that \c{ld} line above \- this is where our executable is re-linked with the \c{-rpath} option. +We can also uninstall what we have installed with \l{bpkg-pkg-uninstall(1) +\c{bpkg uninstall}}: + +\ +$ bpkg uninstall \ + config.install.root=/opt/hello \ + config.install.sudo=sudo + hello + +uninstall hello-1.0.0/doc{version} +uninstall /opt/hello/share/doc/hello/ +uninstall /opt/hello/share/doc/ +uninstall /opt/hello/share/ +uninstall hello-1.0.0/exe{hello} +uninstall /opt/hello/bin/ +uninstall libhello-1.0.0/hello/libs{hello} +uninstall /opt/hello/lib/ +uninstall libhello-1.0.0/hello/hxx{export} +uninstall libhello-1.0.0/hello/hxx{hello} +uninstall /opt/hello/include/hello/ +uninstall /opt/hello/include/ +uninstall /opt/hello/ + +uninstalled hello/1.0.0 + +$ ls /opt/hello +ls: cannot access /opt/hello: No such file or directory +\ + What if we wanted to use \c{libhello} in our own project? While the installed version is always an option, it may not be convenient when we develop our code. We may have multiple builds per project, for example, with GCC and Clang to catch all the warnings. We may also want to make sure our application works well with various versions of \c{libhello} (and maybe even with that heinous -\c{1.1.x}). While we can install different configurations into different +\c{1.1.X}). While we can install different configurations into different directories, it's hard to deny things are getting a bit hairy: multiple configurations, multiple installations... I guess we will have to get our hands into that cookie jar, I mean, configuration, again. @@ -689,15 +806,14 @@ using config # config module (those config.*) $ cat >build/root.build -using cxx # c++ module -cxx{*}: extension = cpp # c++ source file extension -cxx.std = 11 # c++ standard +cxx.std = 11 # C++ standard +using cxx # C++ module +cxx{*}: extension = cpp # C++ source file extension $ cat >buildfile import libs = libhello%lib{hello} exe{hello}: cxx{hello} $libs - \ While some of this might not be crystal clear (like why do we have @@ -713,8 +829,8 @@ To recap, these are the contents of our project so far: $ tree -F . ├── build/ -│ ├── bootstrap.build -│ └── root.build +│ ├── bootstrap.build +│ └── root.build ├── buildfile └── hello.cpp \ @@ -726,7 +842,7 @@ Let's try to build it and see what happens \- maybe it will magically work $ b config.cxx=g++-5 error: unable to import target libhello%lib{hello} info: consider explicitly specifying its project out_root via the config.import.libhello command line variable -info: while applying rule cxx.compile to update obja{hello} +info: while applying rule cxx.compile to update obje{hello} info: while applying rule cxx.link to update exe{hello} info: while applying rule alias to update dir{./} \ @@ -749,8 +865,8 @@ Almost magic. Let's see what we've got: $ tree -F . ├── build/ -│ ├── bootstrap.build -│ └── root.build +│ ├── bootstrap.build +│ └── root.build ├── buildfile ├── hello* ├── hello.d @@ -770,7 +886,7 @@ $ touch hello.cpp $ b error: unable to import target libhello%lib{hello} info: consider explicitly specifying its project out_root via the config.import.libhello command line variable -info: while applying rule cxx.compile to update obja{hello} +info: while applying rule cxx.compile to update obje{hello} info: while applying rule cxx.link to update exe{hello} info: while applying rule alias to update dir{./} \ @@ -788,9 +904,10 @@ $ ls -1F hello2/ hello2-gcc5-release/ -$ b config.cxx=g++-5 config.cxx.coptions=-O3 \ -config.import.libhello=/tmp/hello-gcc5-release \ -'configure(hello2/@hello2-gcc5-release/)' +$ b config.cxx=g++-5 \ + config.cc.coptions=-O3 \ + config.import.libhello=/tmp/hello-gcc5-release \ + 'configure(hello2/@hello2-gcc5-release/)' mkdir hello2-gcc5-release/build/ mkdir hello2-gcc5-release/build/bootstrap/ @@ -819,11 +936,11 @@ info: dir{./} is up to date $ b clean rm exe{hello} -rm obja{hello} +rm obje{hello} $ b -v -g++-5 -I/tmp/hello-gcc5-release/libhello-1.0.1 -O3 -std=c++11 -o hello.o -c ../hello2/hello.cpp -g++-5 -O3 -std=c++11 -o hello hello.o /tmp/hello-gcc5-release/libhello-1.0.1/hello/libhello.so +g++-5 -I/tmp/hello-gcc5-release/libhello-1.0.0 -O3 -std=c++11 -o hello.o -c ../hello2/hello.cpp +g++-5 -O3 -std=c++11 -o hello hello.o /tmp/hello-gcc5-release/libhello-1.0.0/hello/libhello-1.0.so \ Some of you might have noticed that \c{hello2-gcc5-release/} and @@ -845,12 +962,12 @@ save /tmp/hello-gcc5-release/hello2/build/bootstrap/src-root.build save /tmp/hello-gcc5-release/hello2/build/config.build $ b /tmp/hello-gcc5-release/hello2/ -c++ hello2/cxx{hello} +c++ hello2/cxx{hello}@/tmp/hello-gcc5-release/hello2/ ld /tmp/hello-gcc5-release/hello2/exe{hello} \ Now that might seem like magic, but it's actually pretty logical. Why don't we -need to specify any of the \c{config.cxx} values this time? Because they are +need to specify any of the \c{config.c*} values this time? Because they are inherited from those specified for \c{/tmp/hello-gcc5-release} when we created the configuration with \c{bpkg create}. What about \c{config.import.libhello}, don't we need at least that? Not really \- \c{libhello} will be found @@ -897,7 +1014,7 @@ inside \c{/tmp/hello-gcc5-release/}: \ $ b '{clean disfigure}(/tmp/hello-gcc5-release/hello2/)' rm /tmp/hello-gcc5-release/hello2/exe{hello} -rm /tmp/hello-gcc5-release/hello2/obja{hello} +rm /tmp/hello-gcc5-release/hello2/obje{hello} rm /tmp/hello-gcc5-release/hello2/build/config.build rm /tmp/hello-gcc5-release/hello2/build/bootstrap/src-root.build rmdir /tmp/hello-gcc5-release/hello2/build/bootstrap/ @@ -911,43 +1028,56 @@ package directory: \ $ bpkg build -d /tmp/hello-gcc5-release/ ./hello2/ -build hello2 1.0.0 +build hello2/1.0.0 continue? [Y/n] y -unpacked hello2 1.0.0 -configured hello2 1.0.0 -c++ hello2/cxx{hello} +unpacked hello2/1.0.0 +configured hello2/1.0.0 +c++ hello2/cxx{hello}@/tmp/hello-gcc5-release/hello2-1.0.0/ ld /tmp/hello-gcc5-release/hello2-1.0.0/exe{hello} -updated hello2 1.0.0 +updated hello2/1.0.0 \ Let's upgrade \c{libhello} and see what happens: \ $ bpkg build -d /tmp/hello-gcc5-release/ -L libhello -upgrade libhello 1.1.1 +build libformat/1.0.0 (required by libhello) +build libprint/1.0.0 (required by libhello) +upgrade libhello/1.1.0 reconfigure hello2 (dependent of libhello) continue? [Y/n] y -disfigured hello2 1.0.0 -disfigured libhello 1.0.1 -unpacked libhello 1.1.1 -configured libhello 1.1.1 -configured hello2 1.0.0 -mkdir fsdir{/tmp/hello-gcc5-release/libhello-1.1.1/hello/} -c++ libhello/hello/cxx{hello} -ld /tmp/hello-gcc5-release/libhello-1.1.1/hello/liba{hello} -c++ libhello/hello/cxx{hello} -ld /tmp/hello-gcc5-release/libhello-1.1.1/hello/libso{hello} -updated libhello 1.1.1 -\ - -As promised, \c{hello2} got reconfigured (it didn't get update because of the +disfigured hello2/1.0.0 +disfigured libhello/1.0.0 +[ ... fetching & unpacking ... ] +configured libformat/1.0.0 +configured libprint/1.0.0 +configured libhello/1.1.0 +configured hello2/1.0.0 +c++ libhello-1.1.0/hello/cxx{hello} +c++ libprint-1.0.0/print/cxx{print} +ld libprint-1.0.0/print/liba{print} +c++ libformat-1.0.0/format/cxx{format} +ld libformat-1.0.0/format/liba{format} +ld libhello-1.1.0/hello/liba{hello} +c++ libhello-1.1.0/hello/cxx{hello} +c++ libprint-1.0.0/print/cxx{print} +ld libprint-1.0.0/print/libs{print} +c++ libformat-1.0.0/format/cxx{format} +ld libformat-1.0.0/format/libs{format} +ld libhello-1.1.0/hello/libs{hello} +c++ libhello-1.1.0/tests/test/cxx{driver} +ld libhello-1.1.0/tests/test/exe{driver} +updated libhello/1.1.0 +\ + +As promised, \c{hello2} got reconfigured (it didn't get updated because of the \c{-L} option). We can now update it and give it a try: \ $ bpkg update -d /tmp/hello-gcc5-release/ hello2 -c++ hello2/cxx{hello} +c++ hello2/cxx{hello}@/tmp/hello-gcc5-release/hello2-1.0.0/ ld /tmp/hello-gcc5-release/hello2-1.0.0/exe{hello} -updated hello2 1.0.0 +updated hello2/1.0.0 $ /tmp/hello-gcc5-release/hello2-1.0.0/hello Hello, World! @@ -960,7 +1090,7 @@ $ cd /tmp $ mkdir hello-clang36-release $ cd hello-clang36-release -$ bpkg create cxx config.cxx=clang++-3.6 config.cxx.coptions=-O3 +$ bpkg create c config.cxx=clang++-3.6 config.cc.coptions=-O3 created new configuration in /tmp/hello-clang36-release/ $ bpkg add https://build2.org/pkg/1/hello/testing @@ -968,74 +1098,83 @@ added repository build2.org/hello/testing $ bpkg fetch fetching build2.org/hello/testing +warning: authenticity of the certificate for repository build2.org/hello/testing cannot be established +certificate is for build2.org, \"Code Synthesis\" <admin@build2.org> +certificate SHA256 fingerprint: +FF:DF:7D:38:67:4E:C3:82:65:7E:[...]:29:9A:30:56:B9:77:B9:F2:01:94 +trust this certificate? [y/N] y fetching build2.org/hello/stable (complements build2.org/hello/testing) 5 package(s) in 2 repository(s) -$ bpkg build libhello/1.0.0 .../hello2/ -build libhello 1.0.1 -build hello2 1.0.0 +$ bpkg build libhello/1.0.0 path/to/hello2/ +build libhello/1.0.0 +build hello2/1.0.0 continue? [Y/n] y -libhello-1.0.1.tar.gz 100% of 1489 B 983 kBps 00m01s -fetched libhello 1.0.1 -unpacked libhello 1.0.1 -unpacked hello2 1.0.0 -configured libhello 1.0.1 -configured hello2 1.0.0 -c++ libhello-1.0.1/hello/cxx{hello} -ld libhello-1.0.1/hello/liba{hello} -c++ libhello-1.0.1/hello/cxx{hello} -ld libhello-1.0.1/hello/libso{hello} -c++ libhello-1.0.1/tests/test/cxx{driver} -ld libhello-1.0.1/tests/test/exe{driver} -c++ ~/work/build2/hello/hello2/cxx{hello} +libhello-1.0.0.tar.gz 100% of 2428 B 983 kBps 00m01s +fetched libhello/1.0.0 +unpacked libhello/1.0.0 +unpacked hello2/1.0.0 +configured libhello/1.0.0 +configured hello2/1.0.0 +c++ libhello-1.0.0/hello/cxx{hello} +ld libhello-1.0.0/hello/liba{hello} +c++ libhello-1.0.0/hello/cxx{hello} +ld libhello-1.0.0/hello/libs{hello} +c++ libhello-1.0.0/tests/test/cxx{driver} +ld libhello-1.0.0/tests/test/exe{driver} +c++ path/to/hello2/cxx{hello}@hello2-1.0.0/ ld hello2-1.0.0/exe{hello} -updated libhello 1.0.1 -updated hello2 1.0.0 +updated libhello/1.0.0 +updated hello2/1.0.0 \ -Are you still here? Ok, one last example. This one is for \i{STL} (for those -missing the connection, Stephan T. Lavavej, said, and I am paraphrasing, that -he will never build a shared library and will never use a build system/package -manager more complex than a single makefile; got to respect the man's -convictions). - -The Warning section above said there is no Windows support yet. But nobody -said anything about cross-compilers: +Are you still here? Ok, one last example. Let's see how hard it is to +cross-compile. \ -$ mkdir hello-mingw32 -$ cd hello-mingw32 +$ mkdir hello-mingw64 +$ cd hello-mingw64 -$ bpkg create cxx \ -config.cxx=x86_64-w64-mingw32-g++ \ -config.bin.lib=static config.cxx.loptions=-static - -created new configuration in /tmp/hello-mingw32/ +$ bpkg create cc config.cxx=x86_64-w64-mingw32-g++ +created new configuration in /tmp/hello-mingw64/ $ bpkg add https://build2.org/pkg/1/hello/stable added repository build2.org/hello/stable $ bpkg fetch fetching build2.org/hello/stable +[... certificate authentication ...] 2 package(s) in 1 repository(s) $ bpkg build -y hello -bpkg build -y hello -libhello-1.0.1.tar.gz 100% of 1489 B 983 kBps 00m01s -fetched libhello 1.0.1 -unpacked libhello 1.0.1 -hello-1.0.0.tar.gz 100% of 1030 B 6882 kBps 00m01s -fetched hello 1.0.0 -unpacked hello 1.0.0 -configured libhello 1.0.1 -configured hello 1.0.0 +libhello-1.0.0.tar.gz 100% of 2428 B 983 kBps 00m01s +fetched libhello/1.0.0 +unpacked libhello/1.0.0 +hello-1.0.0.tar.gz 100% of 1057 B 6882 kBps 00m01s +fetched hello/1.0.0 +unpacked hello/1.0.0 +configured libhello/1.0.0 +configured hello/1.0.0 c++ hello-1.0.0/cxx{hello} -c++ libhello-1.0.1/hello/cxx{hello} -ld libhello-1.0.1/hello/libso{hello} +c++ libhello-1.0.0/hello/cxx{hello} +ld libhello-1.0.0/hello/libs{hello} ld hello-1.0.0/exe{hello} -updated hello 1.0.0 +updated hello/1.0.0 $ wine hello-1.0.0/hello.exe Windows Hello, Windows! \ + +In fact, on a properly setup GNU/Linux machine (that automatically uses +\c{wine} as a \c{.exe} interpreter) we can even run tests: + +\ +$ bpkg test libhello hello +c++ libhello-1.0.0/tests/test/cxx{driver} +ld libhello-1.0.0/tests/test/exe{driver} +test libhello-1.0.0/tests/test/exe{driver} +test hello-1.0.0/exe{hello} +tested libhello/1.0.0 +tested hello/1.0.0 +\ " |