For product development, the goal of effective collaboration is to fully engage all parties. Good product-oriented collaborators maintain a flow of information, ideas and commensurate action. Hesitation is minimized. Feedback is rapid. Reactions are prompt, yet measured through constant practice.
The following criteria are a guide to effective collaboration candidates for product development.
People with the following traits disqualify themselves from being a member of the core team because they are unable to consistently contribute effectively to the ever-evolving vision for the project.
ChatGPT gave me the following response when I asked, “Compare and contrast the processes of architecture and engineering for software”. I like the quality of this response, and provide it verbatim because it exactly matches my understanding of those terms.
When it comes to software development, there are parallels between the processes of architecture and engineering, but there are also significant differences due to the intangible and rapidly evolving nature of software. Let's compare and contrast the processes of software architecture and engineering:
Software Architecture: Similar to architectural design in physical structures, software architecture focuses on designing the overall structure and organization of a software system. It involves making high-level decisions about the system's components, their interactions, and the principles that guide their design.
Software Engineering: Software engineering encompasses the systematic approach to developing software solutions. It involves various disciplines such as requirements analysis, design, coding, testing, deployment, and maintenance. The focus is on creating reliable, efficient, and maintainable software systems.
Software Architecture: The architectural design process involves defining the system's key components, interfaces, and their interactions. Architectural patterns, such as layered architecture, microservices, or event-driven architecture, are often used to guide the design. Considerations include scalability, performance, security, and maintainability.
Software Engineering: Software engineering encompasses the entire software development lifecycle (SDLC). It begins with requirements gathering and analysis, followed by design, implementation (coding), testing, deployment, and maintenance. Various methodologies like Waterfall, Agile, and DevOps guide this process.
Software Architecture: Software architects must balance creative design decisions with technical constraints. They need to envision the overall structure of the system and choose appropriate technologies and patterns to achieve the desired functionality and quality attributes.
Software Engineering: Software engineers focus on implementing the design created by architects. While creativity is still important, engineers primarily deal with the technical aspects of coding, testing, and debugging. They translate the architectural design into working software components.
Software Architecture: Collaboration between architects, stakeholders, and development teams is crucial to ensure that architectural decisions align with business goals and technical requirements. Architects often communicate their designs through diagrams, documentation, and discussions.
Software Engineering: Software engineers collaborate closely with other team members, including architects, designers, testers, and project managers. They work together to implement features, resolve technical challenges, and deliver software increments according to project timelines.
Software Architecture: Architectural decisions may need to comply with regulatory standards, industry best practices, and security guidelines. Architects must consider factors like data privacy, compliance requirements (such as GDPR or HIPAA), and interoperability with other systems.
Software Engineering: Engineers implement features and functionalities while adhering to coding standards, security protocols, and testing practices. They ensure that the software meets quality standards, performance targets, and regulatory requirements specified by the architecture and project stakeholders.
In summary, while both software architecture and engineering involve designing and building software systems, they have distinct focuses and processes. Architecture concentrates on high-level design decisions and system structure, while engineering encompasses the entire software development lifecycle, from requirements to deployment. Collaboration and communication are essential in both disciplines to deliver successful software solutions.
ChatGPT defined collaboration as the following. Again, I very much like the response, so I provide it verbatim.
Collaboration refers to the process of individuals or groups working together to achieve a common goal or objective.
It involves the sharing of ideas, resources, responsibilities, and tasks in a coordinated manner to accomplish tasks
more effectively and efficiently than if done individually.
Collaboration often emphasizes communication, cooperation, and mutual respect among participants.
It can occur within various contexts, including businesses, organizations, teams, communities,
and even across different disciplines or sectors.
Successful collaboration typically results in synergy,
where the combined efforts of the participants produce outcomes that exceed what could be achieved by any individual or subgroup working alone.
Following is the response when I asked "what is required for effective collaboration in a new software project?"
I highlighted a passage that is important, and struck out portions that I disagree with.
Effective collaboration in a new software project requires several key elements:
By incorporating these elements into the collaborative process, teams can increase the likelihood of success in their new software projects.
I asked ChatGPT "how would someone document design decisions in a software project?" The highlighted portion is covered in more detail later in this article.
Documenting design decisions in a software project is essential for ensuring clarity, facilitating collaboration, and providing a reference for future development. Here's a structured approach to documenting design decisions:
By following these steps, you can effectively document design decisions in a software project, providing a comprehensive and structured reference for developers, stakeholders, and future contributors.
Comparative product matrices are useful for guiding and documenting design decisions. Search for them when you need to identify pre-existing solutions to a problem, and generate them when considering the implementation of various approaches.
Comparative product matrices take time to read and to prepare, but they help guide the team to the best technical decisions. Without them, you are just hoping to get lucky.
]]>I ran out of room on my WSL2 virtual hard drive. Microsoft’s instructions worked perfectly to increase the virtual drive size.
The following command work from WSL bash, and cmd, and PowerShell:
$ wsl.exe --shutdown
The virtual disk was in %LocalAppData%\
Open a cmd.exe
window with admininstrator privileges and run diskpart
.
DISKPART> Select vdisk file="%LocalAppData%\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\ext4.vhdx"
DISKPART> detail vdisk Device type ID: 0 (Unknown) Vendor ID: {00000000-0000-0000-0000-000000000000} (Unknown) State: Added Virtual size: 256 GB Physical size: 247 GB Filename: C:\Users\Mike Slinn\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\ext4.vhdx Is Child: No Parent Filename: Associated disk#: Not found.
The virtual disk was 256 GB (256,000 MB). I want it to be twice as big: 512,000 MB.
DISKPART> expand vdisk maximum=512000
100 percent completed
DiskPart successfully expanded the virtual disk file. DISKPART> exit
Leaving DiskPart...
Now I restarted WSL from a cmd
window.
The following command work from WSL bash, and cmd, and PowerShell:
$ wsl.exe
Now tell Linux to use all available space:
$ sudo resize2fs /dev/sdc 512000M resize2fs 1.47.0 (5-Feb-2023) Filesystem at /dev/sdc is mounted on /; on-line resizing required old_desc_blocks = 32, new_desc_blocks = 63 The filesystem on /dev/sdc is now 131072000 (4k) blocks long.
Done!
]]>The Java Development Kit (JDK) version 17 is compatible with v11 and v8. Installing the JDK also installs the JRE, as you can see from the highlighted dependency shown below:
$ apt show -a openjdk-17-jdk Package: openjdk-17-jdk Version: 17.0.8.1+1~us1-0ubuntu1~23.04 Priority: optional Section: java Source: openjdk-17 Origin: Ubuntu Maintainer: Ubuntu DevelopersOriginal-Maintainer: OpenJDK Team Bugs: https://bugs.launchpad.net/ubuntu/+filebug Installed-Size: 1544 kB Provides: java-compiler, java-sdk (= 17), java10-sdk, java11-sdk, java12-sdk, java13-sdk, java14-sdk, java15-sdk, java16-sdk, java17-sdk, java2-sdk, java5-sdk, java6-sdk, java7-sdk, java8-sdk, java9-sdk Depends: openjdk-17-jre (= 17.0.8.1+1~us1-0ubuntu1~23.04), openjdk-17-jdk-headless (= 17.0.8.1+1~us1-0ubuntu1~23.04), libc6 (>= 2.34), zlib1g (>= 1:1.1.4) Recommends: libxt-dev Suggests: openjdk-17-demo, openjdk-17-source, visualvm Homepage: https://openjdk.java.net/ Download-Size: 1486 kB APT-Sources: http://archive.ubuntu.com/ubuntu lunar-updates/main amd64 Packages Description: OpenJDK Development Kit (JDK) OpenJDK is a development environment for building applications, applets, and components using the Java programming language.
Package: openjdk-17-jdk Version: 17.0.6+10-1ubuntu2 Priority: optional Section: java Source: openjdk-17 Origin: Ubuntu Maintainer: Ubuntu DevelopersOriginal-Maintainer: OpenJDK Team Bugs: https://bugs.launchpad.net/ubuntu/+filebug Installed-Size: 4732 kB Provides: java-compiler, java-sdk, java10-sdk, java11-sdk, java12-sdk, java13-sdk, java14-sdk, java15-sdk, java16-sdk, java17-sdk, java2-sdk, java5-sdk, java6-sdk, java7-sdk, java8-sdk, java9-sdk Depends: openjdk-17-jre (= 17.0.6+10-1ubuntu2), openjdk-17-jdk-headless (= 17.0.6+10-1ubuntu2), libc6 (>= 2.34) Recommends: libxt-dev Suggests: openjdk-17-demo, openjdk-17-source, visualvm Homepage: https://openjdk.java.net/ Download-Size: 4585 kB APT-Sources: http://archive.ubuntu.com/ubuntu lunar/main amd64 Packages Description: OpenJDK Development Kit (JDK) OpenJDK is a development environment for building applications, applets, and components using the Java programming language.
Install OpenJDK 17 and its dependencies:
$ sudo apt install openjdk-17-jdk
The man page for update-java-alternatives
is:
$ man update-java-alternatives UPDATE-JAVA-ALTERNATIVESystem Manager's MUPDATE-JAVA-ALTERNATIVES(8)
NAME update-java-alternatives - update alternatives for jre/sdk installations
SYNOPSIS update-java-alternatives [--jre] [--plugin] [-v|--verbose] -l|--list [<jname>] -s|--set <jname> -a|--auto -h|-?|--help
DESCRIPTION update-java-alternatives updates all alternatives belonging to one runtime or development kit for the Java language. A package does provide these information of it's alternatives in /usr/lib/jvm/.<jname>.jinfo.
OPTIONS -l|--list [<jname>] List all installed packages (or just <jname>) provid‐ ing information to set a bunch of java alternatives. Verbose output shows each alternative provided by the packages.
-a|--auto Switch all alternatives of registered jre/sdk instal‐ lations to automatic mode.
-s|--set <jname> Set all alternatives of the registered jre/sdk instal‐ lation to the program path provided by the <jname> in‐ stallation.
--jre Limit the actions to alternatives belong to a runtime environment, not a development kit.
--jre-headless Limit the actions to alternatives belong to the head‐ less part of a runtime environment.
--plugin Limit the actions to alternatives providing browser plugins.
-h|--help Display a help message.
-v|--verbose Verbose output.
FILES /usr/lib/jvm/.*.jinfo A text file describing a jre/sdk installation. Con‐ sists of some variables of the form <var>=<value> and a list of alternatives of the form jre|jdk <name> <path>.
AUTHOR update-java-alternatives and this manual page was written by Matthias Klose <doko@ubuntu.com>.
May 2006 UPDATE-JAVA-ALTERNATIVES(8)
The above man page neglects to say that a package version’s priority is set from its version number. Thus a newer version would normally have a higher priority. To get a list of the installed Java versions, type:
$ sudo update-java-alternatives --list java-1.11.0-openjdk-amd64 1111 /usr/lib/jvm/java-1.11.0-openjdk-amd64 java-1.17.0-openjdk-amd64 1711 /usr/lib/jvm/java-1.17.0-openjdk-amd64
As you can see, my machine had Java 11 and 17 installed. To set the newest version to be the default, type:
$ sudo update-java-alternatives -a $ java -version openjdk version "17.0.8.1" 2023-08-24 OpenJDK Runtime Environment (build 17.0.8.1+1-Ubuntu-0ubuntu123.04) OpenJDK 64-Bit Server VM (build 17.0.8.1+1-Ubuntu-0ubuntu123.04, mixed mode, sharing)
Boost is a general-purpose open source library of utility functions for C++. The list of categories of fuctionality is formidable.
Boost is used in many commercial products, in-house projects, and open-source projects.
Ostensibly a C++ library for wide usage, it has become an techical underpinning for Python; that is why Boost documentation also contains information about Python.
I started by reading the online Getting Started guide.
For most Boost functionality, only headers are required, and libraries need not be built. The exceptions are described here.
The Boost C++ Libraries is a good free online book, and you can order non-free printed copies.
The latest version of Boost is shown on
https://www.boost.org/users/history/?ref=learnubuntu.com
:
Let’s scrape the lastest version number from the above web page:
$ sudo apt install libxml2-utils $ VER=$( wget -q -O - https://www.boost.org/users/history/?ref=learnubuntu.com | \ xmllint --html --xpath '//*[@id="intro"]/div/h2[1]/a[2]' - 2>/dev/null | \ grep -oEi 'Version ([0-9].)*' | \ cut -d' ' -f 2 ) $ echo $VER 1.83
Download and unpack the library source to a new directory within your home directory as follows:
$ cd $ V_R=`echo $VER | tr . _` $ echo $V_R 1_83 $ NAME=boost_${V_R}_0 $ echo $NAME boost_1_83_0 $ wget -O $NAME.tar.gz \ https://sourceforge.net/projects/boost/files/boost/$VER.0/$NAME.tar.gz/download $ tar xzvf $NAME.tar.gz $ cd $NAME/
You should now have the following files and directories:
$ ls -w72 INSTALL boost/ boostcpp.jam index.htm rst.css Jamroot boost-build.jam bootstrap.bat index.html status/ LICENSE_1_0.txt boost.css bootstrap.sh* libs/ tools/ README.md boost.png doc/ more/
Install the required dependencies for building Boost.
$ sudo apt-get update $ sudo apt install autotools-dev build-essential g++ \ libbz2-dev libicu-dev python3-dev
Two scripts for building the installation program Boost are provided:
bootstrap.sh
(for Bash) and bootstrap.bat
(for Windows/DOS).
By default the scripts build all possible static/shared debug/release Boost libraries.
Another default is that the script uses all the CPU cores your computer has for the build process.
Even using all the cores on a fast laptop, the build might take 10 minutes.
Here is the bootstrap.sh
help message:
$ ./bootstrap.sh -h `./bootstrap.sh\' builds the Boost build system B2 and prepares Boost for building. This includes setting defaults in the project-config.jam which you can adjust prior to invoking B2.
Usage: ./bootstrap.sh [OPTION]...
Defaults for the options are specified in brackets.
Configuration: -h, --help display this help and exit --with-bjam=BJAM use existing Boost.Jam executable (bjam) [automatically built] --with-toolset=TOOLSET use specific TOOLSET to build B2 and as default for building Boost [automatically detected] --show-libraries show the set of libraries that require build and installation steps (i.e., those libraries that can be used with --with-libraries or --without-libraries), then exit --with-libraries=list build only a particular set of libraries, describing using either a comma-separated list of library names or "all" [all] --without-libraries=list build all libraries except the ones listed [] --with-icu enable Unicode/ICU support in Regex [automatically detected] --without-icu disable Unicode/ICU support in Regex --with-icu=DIR specify the root of the ICU library installation and enable Unicode/ICU support in Regex [automatically detected] --with-python=PYTHON specify the Python executable [python] --with-python-root=DIR specify the root of the Python installation [automatically detected] --with-python-version=X.Y specify the Python version as X.Y [automatically detected]
Installation directories: --prefix=PREFIX install Boost into the given PREFIX [/usr/local] --exec-prefix=EPREFIX install Boost binaries into the given EPREFIX [PREFIX]
More precise control over installation directories: --libdir=DIR install libraries here [EPREFIX/lib] --includedir=DIR install headers here [PREFIX/include]
Bootstrap.sh
compiles and links a build program called b2
,
which by default installs all of Boost into /usr/
.
To be more specific, the default location for Boost include files to be installed into is /usr/
,
and Boost libraries are installed by default into /usr/
.
Create (and recreate) the b2
installation program for Boost
for each Python virtual environment.
By default, bootstrap.sh
uses the currently active Python virtual environment, like this:
$ ./bootstrap.sh
Following is how to build b2
for the virtual environment at ~/venv/blah/
.
$ ./bootstrap.sh --with-python-root=~/venv/blah Building B2 engine..
### ### ### Using 'gcc' toolset. ### ###
g++ (Ubuntu 12.3.0-1ubuntu1~23.04) 12.3.0 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
### ###
> g++ -x c++ -std=c++11 -O2 -s -DNDEBUG builtins.cpp class.cpp command.cpp compile.cpp constants.cpp cwd.cpp debug.cpp debugger.cpp execcmd.cpp execnt.cpp execunix.cpp filesys.cpp filent.cpp fileunix.cpp frames.cpp function.cpp glob.cpp hash.cpp hcache.cpp hdrmacro.cpp headers.cpp jam_strings.cpp jam.cpp jamgram.cpp lists.cpp make.cpp make1.cpp md5.cpp mem.cpp modules.cpp native.cpp object.cpp option.cpp output.cpp parse.cpp pathnt.cpp pathsys.cpp pathunix.cpp regexp.cpp rules.cpp scan.cpp search.cpp startup.cpp subst.cpp sysinfo.cpp timestamp.cpp variable.cpp w32_getreg.cpp modules/order.cpp modules/path.cpp modules/property-set.cpp modules/regex.cpp modules/sequence.cpp modules/set.cpp -o b2 tools/build/src/engine/b2 Detecting Python version... 3.11 Unicode/ICU support for Boost.Regex?... /usr Backing up existing B2 configuration in project-config.jam.2 Generating B2 configuration in project-config.jam for gcc...
Bootstrapping is done. To build, run:
./b2
To generate header files, run:
./b2 headers
The configuration generated uses gcc to build by default. If that is unintended either use the --with-toolset option or adjust configuration, by editing 'project-config.jam'.
Further information:
- Command line help: ./b2 --help
- Getting started guide: http://www.boost.org/more/getting_started/unix-variants.html
- B2 documentation: http://www.boost.org/build/
Following is the help message for the newly created b2
Boost installation program.
As you can see, the defaults specified when creating the b2
script can be overidden.
Note that not all of the available options are described in this help message;
for example, the -j
option is only described in the
online help for b2
.
$ ./b2 --help B2 4.10-git
Project-specific help:
Project has jamfile at Jamroot
Usage:
b2 [options] [properties] [install|stage]
Builds and installs Boost.
Targets and Related Options:
install Install headers and compiled library files to the ======= configured locations (below).
--prefix=<PREFIX> Install architecture independent files here. Default: C:\Boost on Windows Default: /usr/local on Unix, Linux, etc.
--exec-prefix=<EPREFIX> Install architecture dependent files here. Default: <PREFIX>
--libdir=<LIBDIR> Install library files here. Default: <EPREFIX>/lib
--includedir=<HDRDIR> Install header files here. Default: <PREFIX>/include
--cmakedir=<CMAKEDIR> Install CMake configuration files here. Default: <LIBDIR>/cmake
--no-cmake-config Do not install CMake configuration files.
stage Build and install only compiled library files to the ===== stage directory.
--stagedir=<STAGEDIR> Install library files here Default: ./stage
Other Options:
--build-type=<type> Build the specified pre-defined set of variations of the libraries. Note, that which variants get built depends on what each library supports.
-- minimal -- (default) Builds a minimal set of variants. On Windows, these are static multithreaded libraries in debug and release modes, using shared runtime. On Linux, these are static and shared multithreaded libraries in release mode.
-- complete -- Build all possible variations.
--build-dir=DIR Build in this location instead of building within the distribution tree. Recommended!
--show-libraries Display the list of Boost libraries that require build and installation steps, and then exit.
--layout=<layout> Determine whether to choose library names and header locations such that multiple versions of Boost or multiple compilers can be used on the same system.
-- versioned -- Names of boost binaries include the Boost version number, name and version of the compiler and encoded build properties. Boost headers are installed in a subdirectory of <HDRDIR> whose name contains the Boost version number.
-- tagged -- Names of boost binaries include the encoded build properties such as variant and threading, but do not including compiler name and version, or Boost version. This option is useful if you build several variants of Boost, using the same compiler.
-- system -- Binaries names do not include the Boost version number or the name and version number of the compiler. Boost headers are installed directly into <HDRDIR>. This option is intended for system integrators building distribution packages.
The default value is 'versioned' on Windows, and 'system' on Unix.
--buildid=ID Add the specified ID to the name of built libraries. The default is to not add anything.
--python-buildid=ID Add the specified ID to the name of built libraries that depend on Python. The default is to not add anything. This ID is added in addition to --buildid.
--help This message.
--with-<library> Build and install the specified <library>. If this option is used, only libraries specified using this option will be built.
--without-<library> Do not build, stage, or install the specified <library>. By default, all libraries are built.
Properties:
toolset=toolset Indicate the toolset to build with.
variant=debug|release Select the build variant
link=static|shared Whether to build static or shared libraries
threading=single|multi Whether to build single or multithreaded binaries
runtime-link=static|shared Whether to link to static or shared C and C++ runtime.
General command line usage:
b2 [options] [properties] [targets]
Options, properties and targets can be specified in any order.
Important Options:
* --clean Remove targets instead of building * -a Rebuild everything * -n Don't execute the commands, only print them * -d+2 Show commands as they are executed * -d0 Suppress all informational messages * -q Stop at first error * --reconfigure Rerun all configuration checks * --durations[=N] Report top N targets by execution time * --debug-configuration Diagnose configuration * --debug-building Report which targets are built with what properties * --debug-generator Diagnose generator search/execution
Further Help:
The following options can be used to obtain additional documentation.
* --help-options Print more obscure command line options. * --help-internal B2 implementation details. * --help-doc-options Implementation details doc formatting.
...found 1 target...
The following runs the newly created b2
program,
which builds and installs Boost using all CPU cores.
PVER
.
CPLUS_INCLUDE_PATH
environment variable is pointed at the location of the Python 3 include files.
PVER
was used to set the proper value for CPLUS_INCLUDE_PATH
.
B2
generates screen upon screen of compiler warnings.
The -d 1
option suppresses them.
$ PVER="$(python --version | cut -d' ' -f 2 | grep -oEi '(3.[0-9]*)')" $ echo $PVER 3.11 $ sudo CPLUS_INCLUDE_PATH=/usr/include/python$PVER ./b2 -d 1 install Performing configuration checks
- default address-model : 64-bit (cached) [1] - default architecture : x86 (cached) [1] - compiler supports SSE2 : yes (cached) [2] - compiler supports SSE4.1 : yes (cached) [2] - has std::atomic_ref : no (cached) [2] - has -Wl,--no-undefined : yes (cached) [2] - has statx : yes (cached) [2] - has init_priority attribute : yes (cached) [2] - has stat::st_blksize : yes (cached) [2] - has stat::st_mtim : yes (cached) [2] - has stat::st_mtimensec : no (cached) [2] - has stat::st_mtimespec : no (cached) [2] - has stat::st_birthtim : no (cached) [2] - has stat::st_birthtimensec : no (cached) [2] - has stat::st_birthtimespec : no (cached) [2] - has fdopendir(O_NOFOLLOW) : yes (cached) [2] - has dirent::d_type : yes (cached) [2] - has POSIX *at APIs : yes (cached) [2] - cxx11_auto_declarations : yes (cached) [2] - cxx11_constexpr : yes (cached) [2] - cxx11_defaulted_functions : yes (cached) [2] - cxx11_final : yes (cached) [2] - cxx11_hdr_mutex : yes (cached) [2] - cxx11_hdr_tuple : yes (cached) [2] - cxx11_lambdas : yes (cached) [2] - cxx11_noexcept : yes (cached) [2] - cxx11_nullptr : yes (cached) [2] - cxx11_rvalue_references : yes (cached) [2] - cxx11_template_aliases : yes (cached) [2] - cxx11_thread_local : yes (cached) [2] - cxx11_variadic_templates : yes (cached) [2] - has_icu builds : yes (cached) [2] warning: Graph library does not contain MPI-based parallel components. note: to enable them, add "using mpi ;" to your user-config.jam. note: to suppress this message, pass "--without-graph_parallel" to bjam. - zlib : yes (cached) - bzip2 : yes (cached) - lzma : yes (cached) - zstd : yes (cached) - has_lzma_cputhreads builds : yes (cached) [2] - cxx11_decltype : yes (cached) [2] - cxx11_basic_alignas : yes (cached) [2] - iconv (libc) : yes (cached) [2] - icu : yes (cached) [2] - cxx11_defaulted_moves : yes (cached) [2] - cxx11_hdr_functional : yes (cached) [2] - cxx11_hdr_type_traits : yes (cached) [2] - cxx11_override : yes (cached) [2] - cxx11_range_based_for : yes (cached) [2] - cxx11_scoped_enums : yes (cached) [2] - cxx11_smart_ptr : yes (cached) [2] - cxx11_static_assert : yes (cached) [2] - lockfree boost::atomic_flag : yes (cached) [2] - native atomic int32 supported : yes (cached) [2] - native syslog supported : yes (cached) [2] - pthread supports robust mutexes : yes (cached) [2] - compiler supports SSSE3 : yes (cached) [2] - compiler supports AVX2 : yes (cached) [2] - gcc visibility : yes (cached) [2] - sfinae_expr : yes (cached) [2] - cxx11_unified_initialization_syntax : yes (cached) [2] - cxx11_hdr_initializer_list : yes (cached) [2] - cxx11_hdr_chrono : yes (cached) [2] - cxx11_numeric_limits : yes (cached) [2] - cxx11_hdr_array : yes (cached) [2] - cxx11_hdr_atomic : yes (cached) [2] - cxx11_allocator : yes (cached) [2] - cxx11_explicit_conversion_operators : yes (cached) [2] - long double support : yes (cached) [2] warning: skipping optional Message Passing Interface (MPI) library. note: to enable MPI support, add "using mpi ;" to user-config.jam. note: to suppress this message, pass "--without-mpi" to bjam. note: otherwise, you can safely ignore this message. - cxx11_char16_t : yes (cached) [2] - cxx11_char32_t : yes (cached) [2] - Has Large File Support : yes (cached) [2] - Has attribute init_priority : yes (cached) [2] - libbacktrace builds : yes (cached) [2] - addr2line builds : yes (cached) [2] - WinDbg builds : no (cached) [2] - WinDbg builds : no (cached) [3] - WinDbgCached builds : no (cached) [2] - WinDbgCached builds : no (cached) [3] - BOOST_COMP_GNUC >= 4.3.0 : yes (cached) [2] - BOOST_COMP_GNUC >= 4.3.0 : yes (cached) [4] - cxx11_hdr_thread : yes (cached) [2] - cxx11_hdr_regex : yes (cached) [2] - compiler supports SSE2 : yes (cached) [4] - compiler supports SSE4.1 : yes (cached) [4] - has std::atomic_ref : no (cached) [4] - has statx : yes (cached) [4] - has init_priority attribute : yes (cached) [4] - has stat::st_blksize : yes (cached) [4] - has stat::st_mtim : yes (cached) [4] - has stat::st_mtimensec : no (cached) [4] - has stat::st_mtimespec : no (cached) [4] - has stat::st_birthtim : no (cached) [4] - has stat::st_birthtimensec : no (cached) [4] - has stat::st_birthtimespec : no (cached) [4] - has fdopendir(O_NOFOLLOW) : yes (cached) [4] - has dirent::d_type : yes (cached) [4] - has POSIX *at APIs : yes (cached) [4] - cxx11_auto_declarations : yes (cached) [4] - cxx11_constexpr : yes (cached) [4] - cxx11_defaulted_functions : yes (cached) [4] - cxx11_final : yes (cached) [4] - cxx11_hdr_mutex : yes (cached) [4] - cxx11_hdr_tuple : yes (cached) [4] - cxx11_lambdas : yes (cached) [4] - cxx11_noexcept : yes (cached) [4] - cxx11_nullptr : yes (cached) [4] - cxx11_rvalue_references : yes (cached) [4] - cxx11_template_aliases : yes (cached) [4] - cxx11_thread_local : yes (cached) [4] - cxx11_variadic_templates : yes (cached) [4] - has_icu builds : yes (cached) [4] - zlib : yes (cached) [5] - bzip2 : yes (cached) [5] - lzma : yes (cached) [5] - zstd : yes (cached) [5] - has_lzma_cputhreads builds : yes (cached) [4] - cxx11_decltype : yes (cached) [4] - cxx11_basic_alignas : yes (cached) [4] - iconv (libc) : yes (cached) [4] - icu : yes (cached) [4] - cxx11_defaulted_moves : yes (cached) [4] - cxx11_hdr_functional : yes (cached) [4] - cxx11_hdr_type_traits : yes (cached) [4] - cxx11_override : yes (cached) [4] - cxx11_range_based_for : yes (cached) [4] - cxx11_scoped_enums : yes (cached) [4] - cxx11_smart_ptr : yes (cached) [4] - cxx11_static_assert : yes (cached) [4] - lockfree boost::atomic_flag : yes (cached) [4] - native atomic int32 supported : yes (cached) [4] - native syslog supported : yes (cached) [4] - pthread supports robust mutexes : yes (cached) [4] - compiler supports SSSE3 : yes (cached) [4] - compiler supports AVX2 : yes (cached) [4] - gcc visibility : yes (cached) [4] - sfinae_expr : yes (cached) [4] - cxx11_unified_initialization_syntax : yes (cached) [4] - cxx11_hdr_initializer_list : yes (cached) [4] - cxx11_hdr_chrono : yes (cached) [4] - cxx11_numeric_limits : yes (cached) [4] - cxx11_hdr_array : yes (cached) [4] - cxx11_hdr_atomic : yes (cached) [4] - cxx11_allocator : yes (cached) [4] - cxx11_explicit_conversion_operators : yes (cached) [4] - long double support : yes (cached) [4] - cxx11_char16_t : yes (cached) [4] - cxx11_char32_t : yes (cached) [4] - Has Large File Support : yes (cached) [4] - Has attribute init_priority : yes (cached) [4] - libbacktrace builds : yes (cached) [4] - addr2line builds : yes (cached) [4] - WinDbg builds : no (cached) [4] - WinDbg builds : no (cached) [6] - WinDbgCached builds : no (cached) [4] - WinDbgCached builds : no (cached) [6] - cxx11_hdr_thread : yes (cached) [4] - cxx11_hdr_regex : yes (cached) [4]
[1] gcc-12 [2] gcc-12/release/python-3.11/threading-multi/visibility-hidden [3] gcc-12/release/build-no/python-3.11/threading-multi/visibility-hidden [4] gcc-12/release/link-static/python-3.11/threading-multi/visibility-hidden [5] link-static [6] gcc-12/release/build-no/link-static/python-3.11/threading-multi/visibility-hidden
Component configuration:
- atomic : building - chrono : building - container : building - context : building - contract : building - coroutine : building - date_time : building - exception : building - fiber : building - filesystem : building - graph : building - graph_parallel : building - headers : building - iostreams : building - json : building - locale : building - log : building - math : building - mpi : building - nowide : building - program_options : building - python : building - random : building - regex : building - serialization : building - stacktrace : building - system : building - test : building - thread : building - timer : building - type_erasure : building - url : building - wave : building
...patience... ...patience... ...patience... ...patience... ...patience... ...patience... ...patience... ...found 52031 targets...
The b2
installation program stored the following include files in
/usr/
$ ls -w72 /usr/local/include/boost/ accumulators/ make_unique.hpp algorithm/ math/ align/ math_fwd.hpp align.hpp mem_fn.hpp aligned_storage.hpp memory_order.hpp any/ metaparse/ any.hpp metaparse.hpp archive/ move/ array.hpp mp11/ asio/ mp11.hpp asio.hpp mpi/ assert/ mpi.hpp assert.hpp mpl/ assign/ msm/ assign.hpp multi_array/ atomic/ multi_array.hpp atomic.hpp multi_index/ beast/ multi_index_container.hpp beast.hpp multi_index_container_fwd.hpp bimap/ multiprecision/ bimap.hpp mysql/ bind/ mysql.hpp bind.hpp next_prior.hpp blank.hpp non_type.hpp blank_fwd.hpp noncopyable.hpp call_traits.hpp nondet_random.hpp callable_traits/ none.hpp callable_traits.hpp none_t.hpp cast.hpp nowide/ cerrno.hpp numeric/ checked_delete.hpp operators.hpp chrono/ operators_v1.hpp chrono.hpp optional/ circular_buffer/ optional.hpp circular_buffer.hpp outcome/ circular_buffer_fwd.hpp outcome.hpp compat/ parameter/ compatibility/ parameter.hpp compressed_pair.hpp pending/ compute/ pfr/ compute.hpp pfr.hpp concept/ phoenix/ concept_archetype.hpp phoenix.hpp concept_check/ pointee.hpp concept_check.hpp pointer_cast.hpp config/ pointer_to_other.hpp config.hpp poly_collection/ container/ polygon/ container_hash/ polymorphic_cast.hpp context/ polymorphic_pointer_cast.hpp contract/ pool/ contract.hpp predef/ contract_macro.hpp predef.h convert/ preprocessor/ convert.hpp preprocessor.hpp core/ process/ coroutine/ process.hpp coroutine2/ program_options/ crc.hpp program_options.hpp cregex.hpp progress.hpp cstdfloat.hpp property_map/ cstdint.hpp property_tree/ cstdlib.hpp proto/ current_function.hpp ptr_container/ cxx11_char_types.hpp python/ date_time/ python.hpp date_time.hpp qvm/ describe/ qvm.hpp describe.hpp qvm_lite.hpp detail/ random/ dll/ random.hpp dll.hpp range/ dynamic_bitset/ range.hpp dynamic_bitset.hpp ratio/ dynamic_bitset_fwd.hpp ratio.hpp enable_shared_from_this.hpp rational.hpp endian/ ref.hpp endian.hpp regex/ exception/ regex.h exception_ptr.hpp regex.hpp fiber/ regex_fwd.hpp filesystem/ safe_numerics/ filesystem.hpp scope_exit.hpp flyweight/ scoped_array.hpp flyweight.hpp scoped_ptr.hpp foreach.hpp serialization/ foreach_fwd.hpp shared_array.hpp format/ shared_container_iterator.hpp format.hpp shared_ptr.hpp function/ signals2/ function.hpp signals2.hpp function_equal.hpp smart_ptr/ function_output_iterator.hpp smart_ptr.hpp function_types/ sort/ functional/ spirit/ functional.hpp spirit.hpp fusion/ stacktrace/ generator_iterator.hpp stacktrace.hpp geometry/ statechart/ geometry.hpp static_assert.hpp get_pointer.hpp static_string/ gil/ static_string.hpp gil.hpp stl_interfaces/ graph/ swap.hpp hana/ system/ hana.hpp system.hpp heap/ test/ histogram/ thread/ histogram.hpp thread.hpp hof/ throw_exception.hpp hof.hpp timer/ icl/ timer.hpp implicit_cast.hpp token_functions.hpp indirect_reference.hpp token_iterator.hpp integer/ tokenizer.hpp integer.hpp tti/ integer_fwd.hpp tuple/ integer_traits.hpp type.hpp interprocess/ type_erasure/ intrusive/ type_index/ intrusive_ptr.hpp type_index.hpp io/ type_traits/ io_fwd.hpp type_traits.hpp iostreams/ typeof/ is_placeholder.hpp units/ iterator/ unordered/ iterator.hpp unordered_map.hpp iterator_adaptors.hpp unordered_set.hpp json/ url/ json.hpp url.hpp lambda/ utility/ lambda2/ utility.hpp lambda2.hpp uuid/ leaf/ variant/ leaf.hpp variant.hpp lexical_cast/ variant2/ lexical_cast.hpp variant2.hpp limits.hpp version.hpp local_function/ visit_each.hpp local_function.hpp vmd/ locale/ wave/ locale.hpp wave.hpp lockfree/ weak_ptr.hpp log/ winapi/ logic/ xpressive/ make_default.hpp yap/ make_shared.hpp
The b2
installation program stored the following libraries in /usr/
:
$ ls -w72 /usr/local/lib cmake/ libboost_atomic.a libboost_atomic.so@ libboost_atomic.so.1.83.0* libboost_chrono.a libboost_chrono.so@ libboost_chrono.so.1.83.0* libboost_container.a libboost_container.so@ libboost_container.so.1.83.0* libboost_context.a libboost_context.so@ libboost_context.so.1.83.0* libboost_contract.a libboost_contract.so@ libboost_contract.so.1.83.0* libboost_coroutine.a libboost_coroutine.so@ libboost_coroutine.so.1.83.0* libboost_date_time.a libboost_date_time.so@ libboost_date_time.so.1.83.0* libboost_exception.a libboost_fiber.a libboost_fiber.so@ libboost_fiber.so.1.83.0* libboost_filesystem.a libboost_filesystem.so@ libboost_filesystem.so.1.83.0* libboost_graph.a libboost_graph.so@ libboost_graph.so.1.83.0* libboost_iostreams.a libboost_iostreams.so@ libboost_iostreams.so.1.83.0* libboost_json.a libboost_json.so@ libboost_json.so.1.83.0* libboost_locale.a libboost_locale.so@ libboost_locale.so.1.83.0* libboost_log.a libboost_log.so@ libboost_log.so.1.83.0* libboost_log_setup.a libboost_log_setup.so@ libboost_log_setup.so.1.83.0* libboost_math_c99.a libboost_math_c99.so@ libboost_math_c99.so.1.83.0* libboost_math_c99f.a libboost_math_c99f.so@ libboost_math_c99f.so.1.83.0* libboost_math_c99l.a libboost_math_c99l.so@ libboost_math_c99l.so.1.83.0* libboost_math_tr1.a libboost_math_tr1.so@ libboost_math_tr1.so.1.83.0* libboost_math_tr1f.a libboost_math_tr1f.so@ libboost_math_tr1f.so.1.83.0* libboost_math_tr1l.a libboost_math_tr1l.so@ libboost_math_tr1l.so.1.83.0* libboost_nowide.a libboost_nowide.so@ libboost_nowide.so.1.83.0* libboost_prg_exec_monitor.a libboost_prg_exec_monitor.so@ libboost_prg_exec_monitor.so.1.83.0* libboost_program_options.a libboost_program_options.so@ libboost_program_options.so.1.83.0* libboost_random.a libboost_random.so@ libboost_random.so.1.83.0* libboost_regex.a libboost_regex.so@ libboost_regex.so.1.83.0* libboost_serialization.a libboost_serialization.so@ libboost_serialization.so.1.83.0* libboost_stacktrace_addr2line.a libboost_stacktrace_addr2line.so@ libboost_stacktrace_addr2line.so.1.83.0* libboost_stacktrace_backtrace.a libboost_stacktrace_backtrace.so@ libboost_stacktrace_backtrace.so.1.83.0* libboost_stacktrace_basic.a libboost_stacktrace_basic.so@ libboost_stacktrace_basic.so.1.83.0* libboost_stacktrace_noop.a libboost_stacktrace_noop.so@ libboost_stacktrace_noop.so.1.83.0* libboost_system.a libboost_system.so@ libboost_system.so.1.83.0* libboost_test_exec_monitor.a libboost_thread.a libboost_thread.so@ libboost_thread.so.1.83.0* libboost_timer.a libboost_timer.so@ libboost_timer.so.1.83.0* libboost_type_erasure.a libboost_type_erasure.so@ libboost_type_erasure.so.1.83.0* libboost_unit_test_framework.a libboost_unit_test_framework.so@ libboost_unit_test_framework.so.1.83.0* libboost_url.a libboost_url.so@ libboost_url.so.1.83.0* libboost_wave.a libboost_wave.so@ libboost_wave.so.1.83.0* libboost_wserialization.a libboost_wserialization.so@ libboost_wserialization.so.1.83.0* node_modules/ python3.11/
The ldconfig
command manages Linux system libraries.
Here is the help message:
$ man ldconfig ldconfig(8) System Manager's Manual ldconfig(8)
NAME ldconfig - configure dynamic linker run-time bindings
SYNOPSIS /sbin/ldconfig [-nNvVX] [-C cache] [-f conf] [-r root] directory ...
/sbin/ldconfig -l [-v] library ...
/sbin/ldconfig -p
DESCRIPTION ldconfig creates the necessary links and cache to the most re‐ cent shared libraries found in the directories specified on the command line, in the file /etc/ld.so.conf, and in the trusted directories, /lib and /usr/lib. On some 64-bit architectures such as x86-64, /lib and /usr/lib are the trusted directories for 32-bit libraries, while /lib64 and /usr/lib64 are used for 64-bit libraries.
The cache is used by the run-time linker, ld.so or ld-linux.so. ldconfig checks the header and filenames of the libraries it encounters when determining which versions should have their links updated. ldconfig should normally be run by the supe‐ ruser as it may require write permission on some root owned di‐ rectories and files.
ldconfig will look only at files that are named lib*.so* (for regular shared objects) or ld-*.so* (for the dynamic loader it‐ self). Other files will be ignored. Also, ldconfig expects a certain pattern to how the symbolic links are set up, like this example, where the middle file (libfoo.so.1 here) is the SONAME for the library:
libfoo.so -> libfoo.so.1 -> libfoo.so.1.12
Failure to follow this pattern may result in compatibility is‐ sues after an upgrade.
OPTIONS -c fmt --format=fmt (Since glibc 2.2) Use cache format fmt, which is one of old, new, or compat. Since glibc 2.32, the default is new. Before that, it was compat.
-C cache Use cache instead of /etc/ld.so.cache.
-f conf Use conf instead of /etc/ld.so.conf.
-i --ignore-aux-cache (Since glibc 2.7) Ignore auxiliary cache file.
-l (Since glibc 2.2) Interpret each operand as a libary name and configure its links. Intended for use only by experts.
-n Process only the directories specified on the command line; don't process the trusted directories, nor those specified in /etc/ld.so.conf. Implies -N.
-N Don't rebuild the cache. Unless -X is also specified, links are still updated.
-p --print-cache Print the lists of directories and candidate libraries stored in the current cache.
-r root Change to and use root as the root directory.
-v --verbose Verbose mode. Print current version number, the name of each directory as it is scanned, and any links that are created. Overrides quiet mode.
-V --version Print program version.
-X Don't update links. Unless -N is also specified, the cache is still rebuilt.
FILES /lib/ld.so is the run-time linker/loader. /etc/ld.so.conf contains a list of directories, one per line, in which to search for libraries. /etc/ld.so.cache contains an ordered list of libraries found in the di‐ rectories specified in /etc/ld.so.conf, as well as those found in the trusted directories.
SEE ALSO ldd(1), ld.so(8)
Linux man-pages 6.03 2023-01-07 ldconfig(8)
The Boost installation procedure automatically causes the newly built Boost libraries
to be added to the configured system libraries when
bootstrap.sh
is not invoked with a target path,
for example by specifying the --with-python-root
option.
To manually add the newly built Boost libraries to the system load path, use ldconfig
.
The following adds the newly compiled and installed Boost libraries in
/usr/local/lib/
(and any other libraries that might happen to be in that directory)
to the ld.so
cache.
$ sudo ldconfig -n /usr/local/lib
We can verify that the library cache now contains the newly built Boost libraries
by using ldconfig
:
$ ldconfig -p | grep boost libboost_wserialization.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_wserialization.so.1.83.0 libboost_wserialization.so (libc6,x86-64) => /usr/local/lib/libboost_wserialization.so libboost_wave.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_wave.so.1.83.0 libboost_wave.so (libc6,x86-64) => /usr/local/lib/libboost_wave.so libboost_url.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_url.so.1.83.0 libboost_url.so (libc6,x86-64) => /usr/local/lib/libboost_url.so libboost_unit_test_framework.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_unit_test_framework.so.1.83.0 libboost_unit_test_framework.so (libc6,x86-64) => /usr/local/lib/libboost_unit_test_framework.so libboost_type_erasure.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_type_erasure.so.1.83.0 libboost_type_erasure.so (libc6,x86-64) => /usr/local/lib/libboost_type_erasure.so libboost_timer.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_timer.so.1.83.0 libboost_timer.so (libc6,x86-64) => /usr/local/lib/libboost_timer.so libboost_thread.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_thread.so.1.83.0 libboost_thread.so (libc6,x86-64) => /usr/local/lib/libboost_thread.so libboost_system.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_system.so.1.83.0 libboost_system.so (libc6,x86-64) => /usr/local/lib/libboost_system.so libboost_stacktrace_noop.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_stacktrace_noop.so.1.83.0 libboost_stacktrace_noop.so (libc6,x86-64) => /usr/local/lib/libboost_stacktrace_noop.so libboost_stacktrace_basic.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_stacktrace_basic.so.1.83.0 libboost_stacktrace_basic.so (libc6,x86-64) => /usr/local/lib/libboost_stacktrace_basic.so libboost_stacktrace_backtrace.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_stacktrace_backtrace.so.1.83.0 libboost_stacktrace_backtrace.so (libc6,x86-64) => /usr/local/lib/libboost_stacktrace_backtrace.so libboost_stacktrace_addr2line.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_stacktrace_addr2line.so.1.83.0 libboost_stacktrace_addr2line.so (libc6,x86-64) => /usr/local/lib/libboost_stacktrace_addr2line.so libboost_serialization.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_serialization.so.1.83.0 libboost_serialization.so (libc6,x86-64) => /usr/local/lib/libboost_serialization.so libboost_regex.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_regex.so.1.83.0 libboost_regex.so.1.74.0 (libc6,x86-64) => /lib/x86_64-linux-gnu/libboost_regex.so.1.74.0 libboost_regex.so (libc6,x86-64) => /usr/local/lib/libboost_regex.so libboost_random.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_random.so.1.83.0 libboost_random.so (libc6,x86-64) => /usr/local/lib/libboost_random.so libboost_python311.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_python311.so.1.83.0 libboost_python311.so (libc6,x86-64) => /usr/local/lib/libboost_python311.so libboost_program_options.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_program_options.so.1.83.0 libboost_program_options.so (libc6,x86-64) => /usr/local/lib/libboost_program_options.so libboost_prg_exec_monitor.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_prg_exec_monitor.so.1.83.0 libboost_prg_exec_monitor.so (libc6,x86-64) => /usr/local/lib/libboost_prg_exec_monitor.so libboost_nowide.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_nowide.so.1.83.0 libboost_nowide.so (libc6,x86-64) => /usr/local/lib/libboost_nowide.so libboost_math_tr1l.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_math_tr1l.so.1.83.0 libboost_math_tr1l.so (libc6,x86-64) => /usr/local/lib/libboost_math_tr1l.so libboost_math_tr1f.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_math_tr1f.so.1.83.0 libboost_math_tr1f.so (libc6,x86-64) => /usr/local/lib/libboost_math_tr1f.so libboost_math_tr1.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_math_tr1.so.1.83.0 libboost_math_tr1.so (libc6,x86-64) => /usr/local/lib/libboost_math_tr1.so libboost_math_c99l.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_math_c99l.so.1.83.0 libboost_math_c99l.so (libc6,x86-64) => /usr/local/lib/libboost_math_c99l.so libboost_math_c99f.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_math_c99f.so.1.83.0 libboost_math_c99f.so (libc6,x86-64) => /usr/local/lib/libboost_math_c99f.so libboost_math_c99.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_math_c99.so.1.83.0 libboost_math_c99.so (libc6,x86-64) => /usr/local/lib/libboost_math_c99.so libboost_log_setup.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_log_setup.so.1.83.0 libboost_log_setup.so (libc6,x86-64) => /usr/local/lib/libboost_log_setup.so libboost_log.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_log.so.1.83.0 libboost_log.so (libc6,x86-64) => /usr/local/lib/libboost_log.so libboost_locale.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_locale.so.1.83.0 libboost_locale.so (libc6,x86-64) => /usr/local/lib/libboost_locale.so libboost_json.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_json.so.1.83.0 libboost_json.so (libc6,x86-64) => /usr/local/lib/libboost_json.so libboost_iostreams.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_iostreams.so.1.83.0 libboost_iostreams.so (libc6,x86-64) => /usr/local/lib/libboost_iostreams.so libboost_graph.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_graph.so.1.83.0 libboost_graph.so (libc6,x86-64) => /usr/local/lib/libboost_graph.so libboost_filesystem.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_filesystem.so.1.83.0 libboost_filesystem.so (libc6,x86-64) => /usr/local/lib/libboost_filesystem.so libboost_fiber.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_fiber.so.1.83.0 libboost_fiber.so (libc6,x86-64) => /usr/local/lib/libboost_fiber.so libboost_date_time.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_date_time.so.1.83.0 libboost_date_time.so (libc6,x86-64) => /usr/local/lib/libboost_date_time.so libboost_coroutine.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_coroutine.so.1.83.0 libboost_coroutine.so (libc6,x86-64) => /usr/local/lib/libboost_coroutine.so libboost_contract.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_contract.so.1.83.0 libboost_contract.so (libc6,x86-64) => /usr/local/lib/libboost_contract.so libboost_context.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_context.so.1.83.0 libboost_context.so (libc6,x86-64) => /usr/local/lib/libboost_context.so libboost_container.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_container.so.1.83.0 libboost_container.so (libc6,x86-64) => /usr/local/lib/libboost_container.so libboost_chrono.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_chrono.so.1.83.0 libboost_chrono.so (libc6,x86-64) => /usr/local/lib/libboost_chrono.so libboost_atomic.so.1.83.0 (libc6,x86-64) => /usr/local/lib/libboost_atomic.so.1.83.0 libboost_atomic.so (libc6,x86-64) => /usr/local/lib/libboost_atomic.so
As a further check, examine the full path of an arbitrary include file (src.hpp
) and list the Boost libraries:
$ locate src.hpp /usr/include/boost/asio/impl/src.hpp /usr/include/boost/asio/ssl/impl/src.hpp /usr/include/boost/beast/src.hpp $ find /usr/local/lib/ -iname *boost* /usr/local/lib/libboost_math_tr1f.a /usr/local/lib/libboost_log_setup.so /usr/local/lib/libboost_system.so.1.83.0 /usr/local/lib/libboost_system.so /usr/local/lib/libboost_serialization.a /usr/local/lib/libboost_context.a /usr/local/lib/libboost_nowide.so /usr/local/lib/libboost_contract.so.1.83.0 /usr/local/lib/libboost_prg_exec_monitor.a /usr/local/lib/libboost_stacktrace_backtrace.so /usr/local/lib/libboost_iostreams.so /usr/local/lib/libboost_math_c99.so.1.83.0 /usr/local/lib/libboost_stacktrace_addr2line.so /usr/local/lib/libboost_locale.so.1.83.0 /usr/local/lib/libboost_math_c99l.so.1.83.0 /usr/local/lib/libboost_timer.a /usr/local/lib/libboost_atomic.so.1.83.0 /usr/local/lib/libboost_url.so.1.83.0 /usr/local/lib/libboost_math_c99.a /usr/local/lib/libboost_date_time.so /usr/local/lib/libboost_fiber.a /usr/local/lib/libboost_filesystem.so.1.83.0 /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_log_setup.a /usr/local/lib/libboost_type_erasure.so /usr/local/lib/libboost_json.so.1.83.0 /usr/local/lib/libboost_wave.so.1.83.0 /usr/local/lib/libboost_unit_test_framework.so /usr/local/lib/libboost_type_erasure.so.1.83.0 /usr/local/lib/libboost_random.so.1.83.0 /usr/local/lib/libboost_filesystem.so /usr/local/lib/libboost_stacktrace_basic.a /usr/local/lib/libboost_math_c99.so /usr/local/lib/libboost_regex.a /usr/local/lib/libboost_coroutine.so.1.83.0 /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_date_time.so.1.83.0 /usr/local/lib/libboost_wave.a /usr/local/lib/libboost_regex.so /usr/local/lib/libboost_container.a /usr/local/lib/libboost_locale.a /usr/local/lib/libboost_graph.so /usr/local/lib/libboost_graph.so.1.83.0 /usr/local/lib/libboost_math_tr1f.so.1.83.0 /usr/local/lib/libboost_math_tr1.so.1.83.0 /usr/local/lib/libboost_program_options.so.1.83.0 /usr/local/lib/libboost_iostreams.so.1.83.0 /usr/local/lib/libboost_math_c99f.so.1.83.0 /usr/local/lib/libboost_nowide.so.1.83.0 /usr/local/lib/libboost_thread.so.1.83.0 /usr/local/lib/libboost_unit_test_framework.a /usr/local/lib/cmake/boost_math_c99f-1.83.0 /usr/local/lib/cmake/boost_math_c99f-1.83.0/libboost_math_c99f-variant-shared.cmake /usr/local/lib/cmake/boost_math_c99f-1.83.0/boost_math_c99f-config.cmake /usr/local/lib/cmake/boost_math_c99f-1.83.0/libboost_math_c99f-variant-static.cmake /usr/local/lib/cmake/boost_math_c99f-1.83.0/boost_math_c99f-config-version.cmake /usr/local/lib/cmake/boost_test_exec_monitor-1.83.0 /usr/local/lib/cmake/boost_test_exec_monitor-1.83.0/libboost_test_exec_monitor-variant-static.cmake /usr/local/lib/cmake/boost_test_exec_monitor-1.83.0/libboost_test_exec_monitor-variant-shared.cmake /usr/local/lib/cmake/boost_test_exec_monitor-1.83.0/boost_test_exec_monitor-config.cmake /usr/local/lib/cmake/boost_test_exec_monitor-1.83.0/boost_test_exec_monitor-config-version.cmake /usr/local/lib/cmake/boost_stacktrace_backtrace-1.83.0 /usr/local/lib/cmake/boost_stacktrace_backtrace-1.83.0/libboost_stacktrace_backtrace-variant-shared.cmake /usr/local/lib/cmake/boost_stacktrace_backtrace-1.83.0/boost_stacktrace_backtrace-config-version.cmake /usr/local/lib/cmake/boost_stacktrace_backtrace-1.83.0/libboost_stacktrace_backtrace-variant-static.cmake /usr/local/lib/cmake/boost_stacktrace_backtrace-1.83.0/boost_stacktrace_backtrace-config.cmake /usr/local/lib/cmake/boost_wave-1.83.0 /usr/local/lib/cmake/boost_wave-1.83.0/libboost_wave-variant-shared.cmake /usr/local/lib/cmake/boost_wave-1.83.0/boost_wave-config-version.cmake /usr/local/lib/cmake/boost_wave-1.83.0/libboost_wave-variant-static.cmake /usr/local/lib/cmake/boost_wave-1.83.0/boost_wave-config.cmake /usr/local/lib/cmake/boost_log-1.83.0 /usr/local/lib/cmake/boost_log-1.83.0/libboost_log-variant-shared.cmake /usr/local/lib/cmake/boost_log-1.83.0/boost_log-config.cmake /usr/local/lib/cmake/boost_log-1.83.0/libboost_log-variant-static.cmake /usr/local/lib/cmake/boost_log-1.83.0/boost_log-config-version.cmake /usr/local/lib/cmake/boost_stacktrace_basic-1.83.0 /usr/local/lib/cmake/boost_stacktrace_basic-1.83.0/boost_stacktrace_basic-config.cmake /usr/local/lib/cmake/boost_stacktrace_basic-1.83.0/boost_stacktrace_basic-config-version.cmake /usr/local/lib/cmake/boost_stacktrace_basic-1.83.0/libboost_stacktrace_basic-variant-static.cmake /usr/local/lib/cmake/boost_stacktrace_basic-1.83.0/libboost_stacktrace_basic-variant-shared.cmake /usr/local/lib/cmake/boost_coroutine-1.83.0 /usr/local/lib/cmake/boost_coroutine-1.83.0/boost_coroutine-config-version.cmake /usr/local/lib/cmake/boost_coroutine-1.83.0/boost_coroutine-config.cmake /usr/local/lib/cmake/boost_coroutine-1.83.0/libboost_coroutine-variant-shared.cmake /usr/local/lib/cmake/boost_coroutine-1.83.0/libboost_coroutine-variant-static.cmake /usr/local/lib/cmake/boost_timer-1.83.0 /usr/local/lib/cmake/boost_timer-1.83.0/boost_timer-config-version.cmake /usr/local/lib/cmake/boost_timer-1.83.0/boost_timer-config.cmake /usr/local/lib/cmake/boost_timer-1.83.0/libboost_timer-variant-shared.cmake /usr/local/lib/cmake/boost_timer-1.83.0/libboost_timer-variant-static.cmake /usr/local/lib/cmake/boost_program_options-1.83.0 /usr/local/lib/cmake/boost_program_options-1.83.0/boost_program_options-config.cmake /usr/local/lib/cmake/boost_program_options-1.83.0/libboost_program_options-variant-static.cmake /usr/local/lib/cmake/boost_program_options-1.83.0/libboost_program_options-variant-shared.cmake /usr/local/lib/cmake/boost_program_options-1.83.0/boost_program_options-config-version.cmake /usr/local/lib/cmake/boost_math_tr1f-1.83.0 /usr/local/lib/cmake/boost_math_tr1f-1.83.0/libboost_math_tr1f-variant-static.cmake /usr/local/lib/cmake/boost_math_tr1f-1.83.0/boost_math_tr1f-config.cmake /usr/local/lib/cmake/boost_math_tr1f-1.83.0/boost_math_tr1f-config-version.cmake /usr/local/lib/cmake/boost_math_tr1f-1.83.0/libboost_math_tr1f-variant-shared.cmake /usr/local/lib/cmake/boost_date_time-1.83.0 /usr/local/lib/cmake/boost_date_time-1.83.0/libboost_date_time-variant-static.cmake /usr/local/lib/cmake/boost_date_time-1.83.0/libboost_date_time-variant-shared.cmake /usr/local/lib/cmake/boost_date_time-1.83.0/boost_date_time-config.cmake /usr/local/lib/cmake/boost_date_time-1.83.0/boost_date_time-config-version.cmake /usr/local/lib/cmake/boost_math_c99l-1.83.0 /usr/local/lib/cmake/boost_math_c99l-1.83.0/libboost_math_c99l-variant-static.cmake /usr/local/lib/cmake/boost_math_c99l-1.83.0/libboost_math_c99l-variant-shared.cmake /usr/local/lib/cmake/boost_math_c99l-1.83.0/boost_math_c99l-config.cmake /usr/local/lib/cmake/boost_math_c99l-1.83.0/boost_math_c99l-config-version.cmake /usr/local/lib/cmake/boost_prg_exec_monitor-1.83.0 /usr/local/lib/cmake/boost_prg_exec_monitor-1.83.0/libboost_prg_exec_monitor-variant-shared.cmake /usr/local/lib/cmake/boost_prg_exec_monitor-1.83.0/libboost_prg_exec_monitor-variant-static.cmake /usr/local/lib/cmake/boost_prg_exec_monitor-1.83.0/boost_prg_exec_monitor-config.cmake /usr/local/lib/cmake/boost_prg_exec_monitor-1.83.0/boost_prg_exec_monitor-config-version.cmake /usr/local/lib/cmake/boost_wserialization-1.83.0 /usr/local/lib/cmake/boost_wserialization-1.83.0/libboost_wserialization-variant-shared.cmake /usr/local/lib/cmake/boost_wserialization-1.83.0/boost_wserialization-config-version.cmake /usr/local/lib/cmake/boost_wserialization-1.83.0/libboost_wserialization-variant-static.cmake /usr/local/lib/cmake/boost_wserialization-1.83.0/boost_wserialization-config.cmake /usr/local/lib/cmake/boost_serialization-1.83.0 /usr/local/lib/cmake/boost_serialization-1.83.0/boost_serialization-config.cmake /usr/local/lib/cmake/boost_serialization-1.83.0/libboost_serialization-variant-static.cmake /usr/local/lib/cmake/boost_serialization-1.83.0/boost_serialization-config-version.cmake /usr/local/lib/cmake/boost_serialization-1.83.0/libboost_serialization-variant-shared.cmake /usr/local/lib/cmake/boost_random-1.83.0 /usr/local/lib/cmake/boost_random-1.83.0/boost_random-config.cmake /usr/local/lib/cmake/boost_random-1.83.0/libboost_random-variant-static.cmake /usr/local/lib/cmake/boost_random-1.83.0/libboost_random-variant-shared.cmake /usr/local/lib/cmake/boost_random-1.83.0/boost_random-config-version.cmake /usr/local/lib/cmake/boost_log_setup-1.83.0 /usr/local/lib/cmake/boost_log_setup-1.83.0/boost_log_setup-config-version.cmake /usr/local/lib/cmake/boost_log_setup-1.83.0/libboost_log_setup-variant-shared.cmake /usr/local/lib/cmake/boost_log_setup-1.83.0/libboost_log_setup-variant-static.cmake /usr/local/lib/cmake/boost_log_setup-1.83.0/boost_log_setup-config.cmake /usr/local/lib/cmake/boost_exception-1.83.0 /usr/local/lib/cmake/boost_exception-1.83.0/boost_exception-config.cmake /usr/local/lib/cmake/boost_exception-1.83.0/boost_exception-config-version.cmake /usr/local/lib/cmake/boost_system-1.83.0 /usr/local/lib/cmake/boost_system-1.83.0/libboost_system-variant-shared.cmake /usr/local/lib/cmake/boost_system-1.83.0/boost_system-config-version.cmake /usr/local/lib/cmake/boost_system-1.83.0/libboost_system-variant-static.cmake /usr/local/lib/cmake/boost_system-1.83.0/boost_system-config.cmake /usr/local/lib/cmake/boost_python-1.83.0 /usr/local/lib/cmake/boost_python-1.83.0/boost_python-config.cmake /usr/local/lib/cmake/boost_python-1.83.0/boost_python-config-version.cmake /usr/local/lib/cmake/boost_thread-1.83.0 /usr/local/lib/cmake/boost_thread-1.83.0/libboost_thread-variant-shared.cmake /usr/local/lib/cmake/boost_thread-1.83.0/boost_thread-config.cmake /usr/local/lib/cmake/boost_thread-1.83.0/boost_thread-config-version.cmake /usr/local/lib/cmake/boost_thread-1.83.0/libboost_thread-variant-static.cmake /usr/local/lib/cmake/boost_json-1.83.0 /usr/local/lib/cmake/boost_json-1.83.0/libboost_json-variant-shared.cmake /usr/local/lib/cmake/boost_json-1.83.0/libboost_json-variant-static.cmake /usr/local/lib/cmake/boost_json-1.83.0/boost_json-config.cmake /usr/local/lib/cmake/boost_json-1.83.0/boost_json-config-version.cmake /usr/local/lib/cmake/boost_iostreams-1.83.0 /usr/local/lib/cmake/boost_iostreams-1.83.0/libboost_iostreams-variant-shared.cmake /usr/local/lib/cmake/boost_iostreams-1.83.0/boost_iostreams-config.cmake /usr/local/lib/cmake/boost_iostreams-1.83.0/libboost_iostreams-variant-static.cmake /usr/local/lib/cmake/boost_iostreams-1.83.0/boost_iostreams-config-version.cmake /usr/local/lib/cmake/boost_math_c99-1.83.0 /usr/local/lib/cmake/boost_math_c99-1.83.0/libboost_math_c99-variant-static.cmake /usr/local/lib/cmake/boost_math_c99-1.83.0/boost_math_c99-config-version.cmake /usr/local/lib/cmake/boost_math_c99-1.83.0/libboost_math_c99-variant-shared.cmake /usr/local/lib/cmake/boost_math_c99-1.83.0/boost_math_c99-config.cmake /usr/local/lib/cmake/boost_unit_test_framework-1.83.0 /usr/local/lib/cmake/boost_unit_test_framework-1.83.0/libboost_unit_test_framework-variant-static.cmake /usr/local/lib/cmake/boost_unit_test_framework-1.83.0/boost_unit_test_framework-config-version.cmake /usr/local/lib/cmake/boost_unit_test_framework-1.83.0/libboost_unit_test_framework-variant-shared.cmake /usr/local/lib/cmake/boost_unit_test_framework-1.83.0/boost_unit_test_framework-config.cmake /usr/local/lib/cmake/boost_filesystem-1.83.0 /usr/local/lib/cmake/boost_filesystem-1.83.0/libboost_filesystem-variant-static.cmake /usr/local/lib/cmake/boost_filesystem-1.83.0/boost_filesystem-config.cmake /usr/local/lib/cmake/boost_filesystem-1.83.0/boost_filesystem-config-version.cmake /usr/local/lib/cmake/boost_filesystem-1.83.0/libboost_filesystem-variant-shared.cmake /usr/local/lib/cmake/Boost-1.83.0 /usr/local/lib/cmake/Boost-1.83.0/BoostConfigVersion.cmake /usr/local/lib/cmake/Boost-1.83.0/BoostConfig.cmake /usr/local/lib/cmake/boost_headers-1.83.0 /usr/local/lib/cmake/boost_headers-1.83.0/boost_headers-config.cmake /usr/local/lib/cmake/boost_headers-1.83.0/boost_headers-config-version.cmake /usr/local/lib/cmake/boost_nowide-1.83.0 /usr/local/lib/cmake/boost_nowide-1.83.0/libboost_nowide-variant-static.cmake /usr/local/lib/cmake/boost_nowide-1.83.0/libboost_nowide-variant-shared.cmake /usr/local/lib/cmake/boost_nowide-1.83.0/boost_nowide-config.cmake /usr/local/lib/cmake/boost_nowide-1.83.0/boost_nowide-config-version.cmake /usr/local/lib/cmake/boost_atomic-1.83.0 /usr/local/lib/cmake/boost_atomic-1.83.0/boost_atomic-config-version.cmake /usr/local/lib/cmake/boost_atomic-1.83.0/boost_atomic-config.cmake /usr/local/lib/cmake/boost_atomic-1.83.0/libboost_atomic-variant-shared.cmake /usr/local/lib/cmake/boost_atomic-1.83.0/libboost_atomic-variant-static.cmake /usr/local/lib/cmake/boost_graph-1.83.0 /usr/local/lib/cmake/boost_graph-1.83.0/boost_graph-config-version.cmake /usr/local/lib/cmake/boost_graph-1.83.0/libboost_graph-variant-static.cmake /usr/local/lib/cmake/boost_graph-1.83.0/libboost_graph-variant-shared.cmake /usr/local/lib/cmake/boost_graph-1.83.0/boost_graph-config.cmake /usr/local/lib/cmake/boost_math_tr1-1.83.0 /usr/local/lib/cmake/boost_math_tr1-1.83.0/boost_math_tr1-config-version.cmake /usr/local/lib/cmake/boost_math_tr1-1.83.0/libboost_math_tr1-variant-static.cmake /usr/local/lib/cmake/boost_math_tr1-1.83.0/libboost_math_tr1-variant-shared.cmake /usr/local/lib/cmake/boost_math_tr1-1.83.0/boost_math_tr1-config.cmake /usr/local/lib/cmake/boost_graph_parallel-1.83.0 /usr/local/lib/cmake/boost_graph_parallel-1.83.0/boost_graph_parallel-config-version.cmake /usr/local/lib/cmake/boost_graph_parallel-1.83.0/boost_graph_parallel-config.cmake /usr/local/lib/cmake/boost_stacktrace_noop-1.83.0 /usr/local/lib/cmake/boost_stacktrace_noop-1.83.0/libboost_stacktrace_noop-variant-static.cmake /usr/local/lib/cmake/boost_stacktrace_noop-1.83.0/boost_stacktrace_noop-config-version.cmake /usr/local/lib/cmake/boost_stacktrace_noop-1.83.0/boost_stacktrace_noop-config.cmake /usr/local/lib/cmake/boost_stacktrace_noop-1.83.0/libboost_stacktrace_noop-variant-shared.cmake /usr/local/lib/cmake/boost_mpi-1.83.0 /usr/local/lib/cmake/boost_mpi-1.83.0/boost_mpi-config-version.cmake /usr/local/lib/cmake/boost_mpi-1.83.0/boost_mpi-config.cmake /usr/local/lib/cmake/boost_type_erasure-1.83.0 /usr/local/lib/cmake/boost_type_erasure-1.83.0/libboost_type_erasure-variant-shared.cmake /usr/local/lib/cmake/boost_type_erasure-1.83.0/libboost_type_erasure-variant-static.cmake /usr/local/lib/cmake/boost_type_erasure-1.83.0/boost_type_erasure-config-version.cmake /usr/local/lib/cmake/boost_type_erasure-1.83.0/boost_type_erasure-config.cmake /usr/local/lib/cmake/boost_chrono-1.83.0 /usr/local/lib/cmake/boost_chrono-1.83.0/boost_chrono-config-version.cmake /usr/local/lib/cmake/boost_chrono-1.83.0/libboost_chrono-variant-static.cmake /usr/local/lib/cmake/boost_chrono-1.83.0/libboost_chrono-variant-shared.cmake /usr/local/lib/cmake/boost_chrono-1.83.0/boost_chrono-config.cmake /usr/local/lib/cmake/boost_math_tr1l-1.83.0 /usr/local/lib/cmake/boost_math_tr1l-1.83.0/libboost_math_tr1l-variant-shared.cmake /usr/local/lib/cmake/boost_math_tr1l-1.83.0/boost_math_tr1l-config.cmake /usr/local/lib/cmake/boost_math_tr1l-1.83.0/boost_math_tr1l-config-version.cmake /usr/local/lib/cmake/boost_math_tr1l-1.83.0/libboost_math_tr1l-variant-static.cmake /usr/local/lib/cmake/boost_contract-1.83.0 /usr/local/lib/cmake/boost_contract-1.83.0/libboost_contract-variant-shared.cmake /usr/local/lib/cmake/boost_contract-1.83.0/boost_contract-config-version.cmake /usr/local/lib/cmake/boost_contract-1.83.0/boost_contract-config.cmake /usr/local/lib/cmake/boost_contract-1.83.0/libboost_contract-variant-static.cmake /usr/local/lib/cmake/boost_fiber-1.83.0 /usr/local/lib/cmake/boost_fiber-1.83.0/libboost_fiber-variant-static.cmake /usr/local/lib/cmake/boost_fiber-1.83.0/boost_fiber-config-version.cmake /usr/local/lib/cmake/boost_fiber-1.83.0/libboost_fiber-variant-shared.cmake /usr/local/lib/cmake/boost_fiber-1.83.0/boost_fiber-config.cmake /usr/local/lib/cmake/BoostDetectToolset-1.83.0.cmake /usr/local/lib/cmake/boost_context-1.83.0 /usr/local/lib/cmake/boost_context-1.83.0/boost_context-config.cmake /usr/local/lib/cmake/boost_context-1.83.0/libboost_context-variant-shared.cmake /usr/local/lib/cmake/boost_context-1.83.0/libboost_context-variant-static.cmake /usr/local/lib/cmake/boost_context-1.83.0/boost_context-config-version.cmake /usr/local/lib/cmake/boost_container-1.83.0 /usr/local/lib/cmake/boost_container-1.83.0/libboost_container-variant-shared.cmake /usr/local/lib/cmake/boost_container-1.83.0/boost_container-config-version.cmake /usr/local/lib/cmake/boost_container-1.83.0/boost_container-config.cmake /usr/local/lib/cmake/boost_container-1.83.0/libboost_container-variant-static.cmake /usr/local/lib/cmake/boost_regex-1.83.0 /usr/local/lib/cmake/boost_regex-1.83.0/libboost_regex-variant-shared.cmake /usr/local/lib/cmake/boost_regex-1.83.0/boost_regex-config.cmake /usr/local/lib/cmake/boost_regex-1.83.0/libboost_regex-variant-static.cmake /usr/local/lib/cmake/boost_regex-1.83.0/boost_regex-config-version.cmake /usr/local/lib/cmake/boost_url-1.83.0 /usr/local/lib/cmake/boost_url-1.83.0/boost_url-config-version.cmake /usr/local/lib/cmake/boost_url-1.83.0/libboost_url-variant-static.cmake /usr/local/lib/cmake/boost_url-1.83.0/libboost_url-variant-shared.cmake /usr/local/lib/cmake/boost_url-1.83.0/boost_url-config.cmake /usr/local/lib/cmake/boost_locale-1.83.0 /usr/local/lib/cmake/boost_locale-1.83.0/libboost_locale-variant-static.cmake /usr/local/lib/cmake/boost_locale-1.83.0/boost_locale-config.cmake /usr/local/lib/cmake/boost_locale-1.83.0/libboost_locale-variant-shared.cmake /usr/local/lib/cmake/boost_locale-1.83.0/boost_locale-config-version.cmake /usr/local/lib/cmake/boost_stacktrace_addr2line-1.83.0 /usr/local/lib/cmake/boost_stacktrace_addr2line-1.83.0/libboost_stacktrace_addr2line-variant-static.cmake /usr/local/lib/cmake/boost_stacktrace_addr2line-1.83.0/libboost_stacktrace_addr2line-variant-shared.cmake /usr/local/lib/cmake/boost_stacktrace_addr2line-1.83.0/boost_stacktrace_addr2line-config-version.cmake /usr/local/lib/cmake/boost_stacktrace_addr2line-1.83.0/boost_stacktrace_addr2line-config.cmake /usr/local/lib/libboost_fiber.so.1.83.0 /usr/local/lib/libboost_chrono.a /usr/local/lib/libboost_serialization.so /usr/local/lib/libboost_fiber.so /usr/local/lib/libboost_wserialization.a /usr/local/lib/libboost_unit_test_framework.so.1.83.0 /usr/local/lib/libboost_stacktrace_noop.a /usr/local/lib/libboost_iostreams.a /usr/local/lib/libboost_math_c99f.a /usr/local/lib/libboost_exception.a /usr/local/lib/libboost_type_erasure.a /usr/local/lib/libboost_thread.a /usr/local/lib/libboost_chrono.so.1.83.0 /usr/local/lib/libboost_math_c99l.so /usr/local/lib/libboost_log_setup.so.1.83.0 /usr/local/lib/libboost_stacktrace_addr2line.a /usr/local/lib/libboost_container.so.1.83.0 /usr/local/lib/libboost_context.so /usr/local/lib/libboost_program_options.so /usr/local/lib/libboost_stacktrace_basic.so /usr/local/lib/libboost_graph.a /usr/local/lib/libboost_prg_exec_monitor.so.1.83.0 /usr/local/lib/libboost_atomic.a /usr/local/lib/libboost_math_tr1l.a /usr/local/lib/libboost_log.so.1.83.0 /usr/local/lib/libboost_random.a /usr/local/lib/libboost_math_tr1f.so /usr/local/lib/libboost_contract.a /usr/local/lib/libboost_atomic.so /usr/local/lib/libboost_serialization.so.1.83.0 /usr/local/lib/libboost_thread.so /usr/local/lib/libboost_wave.so /usr/local/lib/libboost_program_options.a /usr/local/lib/libboost_context.so.1.83.0 /usr/local/lib/libboost_coroutine.a /usr/local/lib/libboost_json.a /usr/local/lib/libboost_stacktrace_noop.so.1.83.0 /usr/local/lib/libboost_wserialization.so.1.83.0 /usr/local/lib/libboost_math_tr1.a /usr/local/lib/libboost_chrono.so /usr/local/lib/libboost_stacktrace_backtrace.a /usr/local/lib/libboost_stacktrace_addr2line.so.1.83.0 /usr/local/lib/libboost_stacktrace_basic.so.1.83.0 /usr/local/lib/libboost_math_c99l.a /usr/local/lib/libboost_log.so /usr/local/lib/libboost_log.a /usr/local/lib/libboost_math_tr1l.so /usr/local/lib/libboost_container.so /usr/local/lib/libboost_coroutine.so /usr/local/lib/libboost_prg_exec_monitor.so /usr/local/lib/libboost_nowide.a /usr/local/lib/libboost_url.so /usr/local/lib/libboost_url.a /usr/local/lib/libboost_math_c99f.so /usr/local/lib/libboost_stacktrace_backtrace.so.1.83.0 /usr/local/lib/libboost_test_exec_monitor.a /usr/local/lib/libboost_json.so /usr/local/lib/libboost_wserialization.so /usr/local/lib/libboost_system.a /usr/local/lib/libboost_regex.so.1.83.0 /usr/local/lib/libboost_contract.so /usr/local/lib/libboost_stacktrace_noop.so /usr/local/lib/libboost_locale.so /usr/local/lib/libboost_math_tr1.so /usr/local/lib/libboost_timer.so.1.83.0 /usr/local/lib/libboost_random.so /usr/local/lib/libboost_math_tr1l.so.1.83.0 /usr/local/lib/libboost_timer.so
Many Ubuntu/Debian packages are left behind by the Boost installation program. You can view them as follows:
$ apt --dry-run autoremove | grep -Po '^Remv \K[^ ]+' libboost-mpi-python-dev libboost-mpi-python1.74-dev libboost-mpi-python1.74.0 mpi-default-bin libboost-mpi-dev libboost-mpi1.74-dev mpi-default-dev libopenmpi-dev openmpi-bin libcoarrays-openmpi-dev libopenmpi3 libucx0 libfabric1 ibverbs-providers libboost-atomic-dev libboost-coroutine-dev libboost-coroutine1.74-dev libboost-fiber-dev libboost-fiber1.74-dev libboost-context1.74-dev libboost-type-erasure-dev libboost-type-erasure1.74-dev libboost-thread1.74-dev libboost-log-dev libboost-log1.74-dev libboost-atomic1.74-dev libboost-atomic1.74.0 libboost-chrono-dev libboost-timer-dev libboost-timer1.74-dev libboost-chrono1.74-dev libboost-timer1.74.0 libboost-chrono1.74.0 libboost-container-dev libboost-container1.74-dev libboost-container1.74.0 libboost-context-dev libboost-fiber1.74.0 libboost-coroutine1.74.0 libboost-context1.74.0 libboost-date-time-dev libboost-date-time1.74-dev libboost-date-time1.74.0 libboost-dev libboost-exception-dev libboost-exception1.74-dev libboost-filesystem-dev libboost-wave-dev libboost-wave1.74-dev libboost-filesystem1.74-dev libboost-graph-dev libboost-graph-parallel-dev libboost-graph-parallel1.74-dev libboost-graph-parallel1.74.0 libboost-graph1.74-dev libboost-graph1.74.0 libboost-iostreams-dev libboost-iostreams1.74-dev libboost-locale-dev libboost-locale1.74-dev libboost-log1.74.0 libboost-math-dev libboost-math1.74-dev libboost-math1.74.0 libboost-mpi1.74.0 libboost-nowide-dev libboost-nowide1.74-dev libboost-nowide1.74.0 libboost-numpy-dev libboost-numpy1.74-dev libboost-numpy1.74.0 libboost-program-options-dev libboost-program-options1.74-dev libboost-program-options1.74.0 libboost-python-dev libboost-python1.74-dev libboost-python1.74.0 libboost-random-dev libboost-random1.74-dev libboost-random1.74.0 libboost-regex-dev libboost-regex1.74-dev libboost-serialization-dev libboost-serialization1.74-dev libboost-serialization1.74.0 libboost-stacktrace-dev libboost-stacktrace1.74-dev libboost-stacktrace1.74.0 libboost-system-dev libboost-system1.74-dev libboost-system1.74.0 libboost-test-dev libboost-test1.74-dev libboost-test1.74.0 libboost-thread-dev libboost-tools-dev libboost-type-erasure1.74.0 libboost-wave1.74.0 libboost1.74-dev libboost1.74-tools-dev libcaf-openmpi-3 libpmix-dev libevent-dev libevent-extra-2.1-7 libevent-openssl-2.1-7 libpmix2 libevent-pthreads-2.1-7 libhwloc-dev libhwloc-plugins libhwloc15 libibverbs-dev librdmacm1 libibverbs1 libjs-jquery-ui libmunge2 libnl-route-3-dev libnl-3-dev libnuma-dev libpsm-infinipath1 libpsm2-2 openmpi-common
Remove the packages as follows:
$ yes | sudo apt autoremove Reading package lists... Done Building dependency tree... Done Reading state information... Done The following packages will be REMOVED: ibverbs-providers libboost-atomic-dev libboost-atomic1.74-dev libboost-atomic1.74.0 libboost-chrono-dev libboost-chrono1.74-dev libboost-chrono1.74.0 libboost-container-dev libboost-container1.74-dev libboost-container1.74.0 libboost-context-dev libboost-context1.74-dev libboost-context1.74.0 libboost-coroutine-dev libboost-coroutine1.74-dev libboost-coroutine1.74.0 libboost-date-time-dev libboost-date-time1.74-dev libboost-date-time1.74.0 libboost-dev libboost-exception-dev libboost-exception1.74-dev libboost-fiber-dev libboost-fiber1.74-dev libboost-fiber1.74.0 libboost-filesystem-dev libboost-filesystem1.74-dev libboost-graph-dev libboost-graph-parallel-dev libboost-graph-parallel1.74-dev libboost-graph-parallel1.74.0 libboost-graph1.74-dev libboost-graph1.74.0 libboost-iostreams-dev libboost-iostreams1.74-dev libboost-locale-dev libboost-locale1.74-dev libboost-log-dev libboost-log1.74-dev libboost-log1.74.0 libboost-math-dev libboost-math1.74-dev libboost-math1.74.0 libboost-mpi-dev libboost-mpi-python-dev libboost-mpi-python1.74-dev libboost-mpi-python1.74.0 libboost-mpi1.74-dev libboost-mpi1.74.0 libboost-nowide-dev libboost-nowide1.74-dev libboost-nowide1.74.0 libboost-numpy-dev libboost-numpy1.74-dev libboost-numpy1.74.0 libboost-program-options-dev libboost-program-options1.74-dev libboost-program-options1.74.0 libboost-python-dev libboost-python1.74-dev libboost-python1.74.0 libboost-random-dev libboost-random1.74-dev libboost-random1.74.0 libboost-regex-dev libboost-regex1.74-dev libboost-serialization-dev libboost-serialization1.74-dev libboost-serialization1.74.0 libboost-stacktrace-dev libboost-stacktrace1.74-dev libboost-stacktrace1.74.0 libboost-system-dev libboost-system1.74-dev libboost-system1.74.0 libboost-test-dev libboost-test1.74-dev libboost-test1.74.0 libboost-thread-dev libboost-thread1.74-dev libboost-timer-dev libboost-timer1.74-dev libboost-timer1.74.0 libboost-tools-dev libboost-type-erasure-dev libboost-type-erasure1.74-dev libboost-type-erasure1.74.0 libboost-wave-dev libboost-wave1.74-dev libboost-wave1.74.0 libboost1.74-dev libboost1.74-tools-dev libcaf-openmpi-3 libcoarrays-openmpi-dev libevent-dev libevent-extra-2.1-7 libevent-openssl-2.1-7 libevent-pthreads-2.1-7 libfabric1 libhwloc-dev libhwloc-plugins libhwloc15 libibverbs-dev libibverbs1 libjs-jquery-ui libmunge2 libnl-3-dev libnl-route-3-dev libnuma-dev libopenmpi-dev libopenmpi3 libpmix-dev libpmix2 libpsm-infinipath1 libpsm2-2 librdmacm1 libucx0 mpi-default-bin mpi-default-dev openmpi-bin openmpi-common 0 upgraded, 0 newly installed, 121 to remove and 4 not upgraded. After this operation, 413 MB disk space will be freed. (Reading database ... 399799 files and directories currently installed.) Removing libboost-mpi-python-dev (1.74.0.3ubuntu7) ... Removing libboost-mpi-python1.74-dev (1.74.0-18.1ubuntu3) ... Removing libboost-mpi-python1.74.0 (1.74.0-18.1ubuntu3) ... Removing mpi-default-bin (1.14) ... Removing libboost-mpi-dev (1.74.0.3ubuntu7) ... Removing libboost-mpi1.74-dev (1.74.0-18.1ubuntu3) ... Removing mpi-default-dev (1.14) ... Removing libopenmpi-dev:amd64 (4.1.4-3ubuntu2) ... Removing libcoarrays-openmpi-dev:amd64 (2.10.1-1) ... update-alternatives: warning: alternative /usr/bin/caf.openmpi (part of link group caf) doesn't exist; removing from list of alternatives update-alternatives: warning: /etc/alternatives/caf is dangling; it will be updated with best choice Removing libboost-atomic-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-coroutine-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-coroutine1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-fiber-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-fiber1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-type-erasure-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-type-erasure1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-log-dev (1.74.0.3ubuntu7) ... Removing libboost-log1.74-dev (1.74.0-18.1ubuntu3) ... Removing libboost-chrono-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-timer-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-timer1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-timer1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-container-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-container1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-container1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-context-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-fiber1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-coroutine1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-date-time-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-exception-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-exception1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-filesystem-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-wave-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-wave1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-filesystem1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-graph-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-graph-parallel-dev (1.74.0.3ubuntu7) ... Removing libboost-graph-parallel1.74-dev (1.74.0-18.1ubuntu3) ... Removing libboost-graph-parallel1.74.0 (1.74.0-18.1ubuntu3) ... Removing libboost-graph1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-graph1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-iostreams-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-iostreams1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-locale-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-locale1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-log1.74.0 (1.74.0-18.1ubuntu3) ... Removing libboost-math-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-math1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-math1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-mpi1.74.0 (1.74.0-18.1ubuntu3) ... Removing libboost-nowide-dev (1.74.0.3ubuntu7) ... Removing libboost-nowide1.74-dev (1.74.0-18.1ubuntu3) ... Removing libboost-nowide1.74.0 (1.74.0-18.1ubuntu3) ... Removing libboost-numpy-dev (1.74.0.3ubuntu7) ... Removing libboost-numpy1.74-dev (1.74.0-18.1ubuntu3) ... Removing libboost-numpy1.74.0 (1.74.0-18.1ubuntu3) ... Removing libboost-program-options-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-program-options1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-program-options1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-python-dev (1.74.0.3ubuntu7) ... Removing libboost-python1.74-dev (1.74.0-18.1ubuntu3) ... Removing libboost-python1.74.0 (1.74.0-18.1ubuntu3) ... Removing libboost-random-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-random1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-random1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-regex-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-regex1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-serialization-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-stacktrace-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-stacktrace1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-stacktrace1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-system-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-test-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-test1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-test1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-thread-dev:amd64 (1.74.0.3ubuntu7) ... Removing libboost-tools-dev (1.74.0.3ubuntu7) ... Removing libboost-type-erasure1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-wave1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost1.74-tools-dev (1.74.0-18.1ubuntu3) ... Removing libcaf-openmpi-3:amd64 (2.10.1-1) ... Removing libpmix-dev:amd64 (4.2.2-1) ... Removing libevent-dev (2.1.12-stable-8ubuntu3) ... Removing libevent-extra-2.1-7:amd64 (2.1.12-stable-8ubuntu3) ... Removing libevent-openssl-2.1-7:amd64 (2.1.12-stable-8ubuntu3) ... Removing libhwloc-dev:amd64 (2.9.0-1) ... Removing libibverbs-dev:amd64 (44.0-2) ... Removing libjs-jquery-ui (1.13.2+dfsg-1) ... Removing libnl-route-3-dev:amd64 (3.7.0-0.2) ... Removing libnl-3-dev:amd64 (3.7.0-0.2) ... Removing libnuma-dev:amd64 (2.0.16-1) ... Removing openmpi-bin (4.1.4-3ubuntu2) ... Removing libopenmpi3:amd64 (4.1.4-3ubuntu2) ... Removing libucx0:amd64 (1.13.1-1) ... Removing libfabric1:amd64 (1.17.0-3) ... Removing ibverbs-providers:amd64 (44.0-2) ... Removing libboost-context1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-thread1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-atomic1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-atomic1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-chrono1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-chrono1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-context1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-date-time1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-date-time1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-serialization1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-serialization1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-system1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost-system1.74.0:amd64 (1.74.0-18.1ubuntu3) ... Removing libboost1.74-dev:amd64 (1.74.0-18.1ubuntu3) ... Removing libpmix2:amd64 (4.2.2-1) ... Removing libevent-pthreads-2.1-7:amd64 (2.1.12-stable-8ubuntu3) ... Removing libhwloc-plugins:amd64 (2.9.0-1) ... Removing libhwloc15:amd64 (2.9.0-1) ... Removing librdmacm1:amd64 (44.0-2) ... Removing libibverbs1:amd64 (44.0-2) ... Removing libmunge2 (0.5.15-2) ... Removing libpsm-infinipath1 (3.3+20.604758e7-6.2) ... update-alternatives: warning: alternative /usr/lib/libpsm1/libpsm_infinipath.so.1.16 (part of link group libpsm_infinipath.so.1) doesn't exist; removing from list of alternatives update-alternatives: warning: /etc/alternatives/libpsm_infinipath.so.1 is dangling; it will be updated with best choice Removing libpsm2-2 (11.2.185-2) ... Removing openmpi-common (4.1.4-3ubuntu2) ... Processing triggers for man-db (2.11.2-1) ... Processing triggers for libc-bin (2.37-0ubuntu2) ... /sbin/ldconfig.real: /usr/lib/wsl/lib/libcuda.so.1 is not a symbolic link
Boost usage as a C++ general-pupose library is widespread throughout a diverse range of industries and requirements.
]]>
The pdftk
website
discusses pdktk
(a F/OSS command-line program), a Windows GUI, and mentions
the book PDF Hacks.
An alternative free GUI is PDFTK Builder.
Other command-line utilties for manipulating PDF documents are:
Install the command-line pdftk
program on Ubuntu:
$ sudo apt install pdftk
This is the pdftk
help text:
$ man pdftk pdftk.pdftk-java(1) General Commands Manual pdftk.pdftk-java(1)
NAME pdftk - A handy tool for manipulating PDF
SYNOPSIS pdftk <input PDF files | - | PROMPT> [ input_pw <input PDF owner passwords | PROMPT> ] [ <operation> <operation arguments> ] [ output <output filename | - | PROMPT> ] [ encrypt_40bit | encrypt_128bit | encrypt_aes128 ] [ allow <permissions> ] [ owner_pw <owner password | PROMPT> ] [ user_pw <user password | PROMPT> ] [ flatten ] [ need_appearances ] [ compress | uncompress ] [ keep_first_id | keep_final_id ] [ drop_xfa ] [ drop_xmp ] [ replacement_font <font name> ] [ verbose ] [ dont_ask | do_ask ] Where: <operation> may be empty, or: [ cat | shuffle | burst | rotate | generate_fdf | fill_form | background | multibackground | stamp | multistamp | dump_data | dump_data_utf8 | dump_data_fields | dump_data_fields_utf8 | dump_data_annots | update_info | update_info_utf8 | attach_files | unpack_files ]
For Complete Help: pdftk --help
DESCRIPTION If PDF is electronic paper, then pdftk is an electronic staple- remover, hole-punch, binder, secret-decoder-ring, and X-Ray- glasses. Pdftk is a simple tool for doing everyday things with PDF documents. Use it to:
* Merge PDF Documents or Collate PDF Page Scans * Split PDF Pages into a New Document * Rotate PDF Documents or Pages * Decrypt Input as Necessary (Password Required) * Encrypt Output as Desired * Fill PDF Forms with X/FDF Data and/or Flatten Forms * Generate FDF Data Stencils from PDF Forms * Apply a Background Watermark or a Foreground Stamp * Report PDF Metrics, Bookmarks and Metadata * Add/Update PDF Metrics, Bookmarks or Metadata * Attach Files to PDF Pages or the PDF Document * Unpack PDF Attachments * Burst a PDF Document into Single Pages * Uncompress and Re-Compress Page Streams * Repair Corrupted PDF (Where Possible)
OPTIONS A summary of options is included below.
--help, -h Show this summary of options.
<input PDF files | - | PROMPT> A list of the input PDF files. If you plan to combine these PDFs (without using handles) then list files in the order you want them combined. Use - to pass a sin‐ gle PDF into pdftk via stdin. Input files can be asso‐ ciated with handles, where a handle is one or more up‐ per-case letters:
<input PDF handle>=<input PDF filename>
Handles are often omitted. They are useful when speci‐ fying PDF passwords or page ranges, later.
For example: A=input1.pdf QT=input2.pdf M=input3.pdf
[input_pw <input PDF owner passwords | PROMPT>] Input PDF owner passwords, if necessary, are associated with files by using their handles:
<input PDF handle>=<input PDF file owner password>
If handles are not given, then passwords are associated with input files by order.
Most pdftk features require that encrypted input PDF are accompanied by the ~owner~ password. If the input PDF has no owner password, then the user password must be given, instead. If the input PDF has no passwords, then no password should be given.
When running in do_ask mode, pdftk will prompt you for a password if the supplied password is incorrect or none was given.
[<operation> <operation arguments>] Available operations are: cat, shuffle, burst, rotate, generate_fdf, fill_form, background, multibackground, stamp, multistamp, dump_data, dump_data_utf8, dump_data_fields, dump_data_fields_utf8, dump_data_an‐ nots, update_info, update_info_utf8, attach_files, un‐ pack_files. Some operations takes additional arguments, described below.
If this optional argument is omitted, then pdftk runs in 'filter' mode. Filter mode takes only one PDF input and creates a new PDF after applying all of the output op‐ tions, like encryption and compression.
cat [<page ranges>] Assembles (catenates) pages from input PDFs to create a new PDF. Use cat to merge PDF pages or to split PDF pages from documents. You can also use it to rotate PDF pages. Page order in the new PDF is specified by the order of the given page ranges. Page ranges are described like this:
<input PDF handle>[<begin page number>[-<end page number>[<qualifier>]]][<page rotation>]
Where the handle identifies one of the input PDF files, and the beginning and ending page numbers are one-based references to pages in the PDF file. The qualifier can be even, odd, or ~, and the page rota‐ tion can be north, south, east, west, left, right, or down.
If a PDF handle is given but no pages are specified, then the entire PDF is used. If no pages are speci‐ fied for any of the input PDFs, then the input PDFs' bookmarks are also merged and included in the output.
If the handle is omitted from the page range, then the pages are taken from the first input PDF.
The even qualifier causes pdftk to use only the even- numbered PDF pages, so 1-6even yields pages 2, 4 and 6 in that order. 6-1even yields pages 6, 4 and 2 in that order.
The odd qualifier works similarly to the even.
Pages can be subtracted from a page range using the ~ qualifier followed by a page range. For instance, 1-20~5-6 and 1-20~5~6 are equivalent to 1-4 7-20, and ~5 yields all pages except page 5. Depending on your shell, you may need to quote this argument because of the ~ at the beginning.
The page rotation setting can cause pdftk to rotate pages and documents. Each option sets the page rota‐ tion as follows (in degrees): north: 0, east: 90, south: 180, west: 270, left: -90, right: +90, down: +180. left, right, and down make relative adjustments to a page's rotation.
If no arguments are passed to cat, then pdftk com‐ bines all input PDFs in the order they were given to create the output.
NOTES: * <end page number> may be less than <begin page num‐ ber>. * The keyword end may be used to reference the final page of a document instead of a page number. * Reference a single page by omitting the ending page number. * The handle may be used alone to represent the en‐ tire PDF document, e.g., B1-end is the same as B. * You can reference page numbers in reverse order by prefixing them with the letter r. For example, page r1 is the last page of the document, r2 is the next- to-last page of the document, and rend is the first page of the document. You can use this prefix in ranges, too, for example r3-r1 is the last three pages of a PDF.
Page Range Examples without Handles: 1\-endeast – rotate entire document 90 degrees 5 11 20 – take single pages from input PDF 5-25oddwest – take odd pages in range, rotate 90 de‐ grees 6-1 – reverse pages in range from input PDF
Page Range Examples Using Handles: Say A=in1.pdf B=in2.pdf, then: A1-21 – take range from in1.pdf Bend-1odd – take all odd pages from in2.pdf in re‐ verse order A72 – take a single page from in1.pdf A1-21 Beven A72 – assemble pages from both in1.pdf and in2.pdf Awest – rotate entire in1.pdf document 90 degrees B – use all of in2.pdf A2-30evenleft – take the even pages from the range, remove 90 degrees from each page's rotation A A – catenate in1.pdf with in1.pdf Aevenwest Aoddeast – apply rotations to even pages, odd pages from in1.pdf Awest Bwest Bdown – catenate rotated documents
shuffle [<page ranges>] Collates pages from input PDFs to create a new PDF. Works like the cat operation except that it takes one page at a time from each page range to assemble the output PDF. If one range runs out of pages, it con‐ tinues with the remaining ranges. Ranges can use all of the features described above for cat, like reverse page ranges, multiple ranges from a single PDF, and page rotation. This feature was designed to help collate PDF pages after scanning paper documents.
burst Splits a single input PDF document into individual pages. Also creates a report named doc_data.txt which is the same as the output from dump_data. The output section can contain a printf-styled format string to name these pages. For example, if you want pages named page_01.pdf, page_02.pdf, etc., pass output page_%02d.pdf to pdftk. If the pattern is omitted, then a default pattern g_%04d.pdf is appended and produces pages named pg_0001.pdf, pg_0002.pdf, etc. Encryption can be applied to the output by appending output options such as owner_pw, e.g.:
pdftk in.pdf burst owner_pw foopass
rotate [<page ranges>] Takes a single input PDF and rotates just the speci‐ fied pages. All other pages remain unchanged. The page order remains unchanged. Specify the pages to rotate using the same notation as you would with cat, except you omit the pages that you aren't rotating:
[<begin page number>[-<end page number>[<quali‐ fier>]]][<page rotation>]
The qualifier can be even or odd, and the page rota‐ tion can be north, south, east, west, left, right, or down.
Each option sets the page rotation as follows (in de‐ grees): north: 0, east: 90, south: 180, west: 270, left: -90, right: +90, down: +180. left, right, and down make relative adjustments to a page's rotation.
The given order of the pages doesn't change the page order in the output.
generate_fdf Reads a single input PDF file and generates an FDF file suitable for fill_form out of it to the given output filename or (if no output is given) to stdout. Does not create a new PDF.
fill_form <FDF data filename | XFDF data filename | - | PROMPT> Fills the single input PDF's form fields with the data from an FDF file, XFDF file or stdin. Enter the data filename after fill_form, or use - to pass the data via stdin, like so:
pdftk form.pdf fill_form data.fdf output form.filled.pdf
If the input FDF file includes Rich Text formatted data in addition to plain text, then the Rich Text data is packed into the form fields as well as the plain text. Pdftk also sets a flag that cues Reader/Acrobat to generate new field appearances based on the Rich Text data. So when the user opens the PDF, the viewer will create the Rich Text appear‐ ance on the spot. If the user's PDF viewer does not support Rich Text, then the user will see the plain text data instead. If you flatten this form before Acrobat has a chance to create (and save) new field appearances, then the plain text field data is what you'll see.
Also see the flatten, need_appearances, and replace‐ ment_font options.
background <background PDF filename | - | PROMPT> Applies a PDF watermark to the background of a single input PDF. Pass the background PDF's filename after background like so:
pdftk in.pdf background back.pdf output out.pdf
Pdftk uses only the first page from the background PDF and applies it to every page of the input PDF. This page is scaled and rotated as needed to fit the input page. You can use - to pass a background PDF into pdftk via stdin.
If the input PDF does not have a transparent back‐ ground (such as a PDF created from page scans) then the resulting background won't be visible – use the stamp operation instead.
multibackground <background PDF filename | - | PROMPT> Same as the background operation, but applies each page of the background PDF to the corresponding page of the input PDF. If the input PDF has more pages than the stamp PDF, then the final stamp page is re‐ peated across these remaining pages in the input PDF.
stamp <stamp PDF filename | - | PROMPT> This behaves just like the background operation ex‐ cept it overlays the stamp PDF page on top of the in‐ put PDF document's pages. This works best if the stamp PDF page has a transparent background.
multistamp <stamp PDF filename | - | PROMPT> Same as the stamp operation, but applies each page of the background PDF to the corresponding page of the input PDF. If the input PDF has more pages than the stamp PDF, then the final stamp page is repeated across these remaining pages in the input PDF.
dump_data Reads a single input PDF file and reports its meta‐ data, bookmarks (a/k/a outlines), page metrics (me‐ dia, rotation and labels), data embedded by STAMPtk (see STAMPtk's embed option) and other data to the given output filename or (if no output is given) to stdout. Non-ASCII characters are encoded as XML nu‐ merical entities. Does not create a new PDF.
dump_data_utf8 Same as dump_data except that the output is encoded as UTF-8.
dump_data_fields Reads a single input PDF file and reports form field statistics to the given output filename or (if no output is given) to stdout. Non-ASCII characters are encoded as XML numerical entities. Does not create a new PDF.
dump_data_fields_utf8 Same as dump_data_fields except that the output is encoded as UTF-8.
dump_data_annots This operation currently reports only link annota‐ tions. Reads a single input PDF file and reports an‐ notation information to the given output filename or (if no output is given) to stdout. Non-ASCII charac‐ ters are encoded as XML numerical entities. Does not create a new PDF.
update_info <info data filename | - | PROMPT> Changes the bookmarks, page labels, page sizes, page rotations, and metadata in a single PDF's Info dic‐ tionary to match the input data file. The input data file uses the same syntax as the output from dump_data. Non-ASCII characters should be encoded as XML numerical entities.
This operation does not change the metadata stored in the PDF's XMP stream, if it has one. (For this reason you should include a ModDate entry in your updated info with a current date/timestamp, format: D:YYYYM‐ MDDHHmmSS, e.g. D:201307241346 – omitted data after YYYY revert to default values.)
For example:
pdftk in.pdf update_info in.info output out.pdf
update_info_utf8 <info data filename | - | PROMPT> Same as update_info except that the input is encoded as UTF-8.
attach_files <attachment filenames | PROMPT> [to_page <page number | PROMPT> | relation <relationship>] Packs arbitrary files into a PDF using PDF's file at‐ tachment features. More than one attachment may be listed after attach_files. Attachments are added at the document level unless the optional to_page option is given, in which case the files are attached to the given page number (the first page is 1, the final page is end). Attachments at the document level may be tagged with a relationship among Source, Data, Al‐ ternative, Supplement, and Unspecified (default).
For example:
pdftk in.pdf attach_files table1.html table2.html to_page 6 output out.pdf
pdftk in.pdf attach_files in.tex relation Source out‐ put out.pdf
unpack_files Copies all of the attachments from the input PDF into the current folder or to an output directory given after output. For example:
pdftk report.pdf unpack_files output ~/atts/
or, interactively:
pdftk report.pdf unpack_files output PROMPT
[output <output filename | - | PROMPT>] The output PDF filename may not be set to the name of an input filename. Use - to output to stdout. When using the dump_data operation, use output to set the name of the output data file. When using the unpack_files opera‐ tion, use output to set the name of an output directory. When using the burst operation, you can use output to control the resulting PDF page filenames (described above).
[encrypt_40bit | encrypt_128bit | encrypt_aes128] If an output PDF user or owner password is given, the output PDF encryption algorithm defaults to AES-128. The weaker RC4 40-bit and RC4 128-bit algorithms can be cho‐ sen by specifying encrypt_40bit or encrypt_128bit (dis‐ couraged).
[allow <permissions>] Permissions are applied to the output PDF only if an en‐ cryption strength is specified or an owner or user pass‐ word is given. If permissions are not specified, they default to 'none,' which means all of the following fea‐ tures are disabled.
The permissions section may include one or more of the following features:
Printing Top Quality Printing
DegradedPrinting Lower Quality Printing
ModifyContents Also allows Assembly
Assembly
CopyContents Also allows ScreenReaders
ScreenReaders
ModifyAnnotations Also allows FillIn
FillIn
AllFeatures Allows the user to perform all of the above, and top quality printing.
[owner_pw <owner password | PROMPT>]
[user_pw <user password | PROMPT>] If an encryption strength is given but no passwords are supplied, then the owner and user passwords remain empty, which means that the resulting PDF may be opened and its security parameters altered by anybody.
[compress | uncompress] These are only useful when you want to edit PDF code in a text editor like vim or emacs. Remove PDF page stream compression by applying the uncompress filter. Use the compress filter to restore compression.
[flatten] Use this option to merge an input PDF's interactive form fields (and their data) with the PDF's pages. Only one input PDF may be given. Sometimes used with the fill_form operation.
[need_appearances] Sets a flag that cues Reader/Acrobat to generate new field appearances based on the form field values. Use this when filling a form with non-ASCII text to ensure the best presentation in Adobe Reader or Acrobat. It won't work when combined with the flatten option.
[replacement_font <font name>] Use the specified font to display text in form fields. This option is useful when filling a form with non-ASCII text that is not supported by the fonts included in the input PDF. font name may be either the file name or the family name of a font, but using a file name is more re‐ liable. Currently only TrueType fonts with Unicode text are supported.
[keep_first_id | keep_final_id] When combining pages from multiple PDFs, use one of these options to copy the document ID from either the first or final input document into the new output PDF. Otherwise pdftk creates a new document ID for the output PDF. When no operation is given, pdftk always uses the ID from the (single) input PDF.
[drop_xfa] If your input PDF is a form created using Acrobat 7 or Adobe Designer, then it probably has XFA data. Filling such a form using pdftk yields a PDF with data that fails to display in Acrobat 7 (and 6?). The workaround solution is to remove the form's XFA data, either before you fill the form using pdftk or at the time you fill the form. Using this option causes pdftk to omit the XFA data from the output PDF form.
This option is only useful when running pdftk on a sin‐ gle input PDF. When assembling a PDF from multiple in‐ puts using pdftk, any XFA data in the input is automati‐ cally omitted.
[drop_xmp] Many PDFs store document metadata using both an Info dictionary (old school) and an XMP stream (new school). Pdftk's update_info operation can update the Info dic‐ tionary, but not the XMP stream. The proper remedy for this is to include a ModDate entry in your updated info with a current date/timestamp. The date/timestamp format is: D:YYYYMMDDHHmmSS, e.g. D:201307241346 – omitted data after YYYY revert to default values. This newer ModDate should cue PDF viewers that the Info metadata is more current than the XMP data.
Alternatively, you might prefer to remove the XMP stream from the PDF altogether – that's what this option does. Note that objects inside the PDF might have their own, separate XMP metadata streams, and that drop_xmp does not remove those. It only removes the PDF's document- level XMP stream.
[verbose] By default, pdftk runs quietly. Append verbose to the end and it will speak up.
[dont_ask | do_ask] Depending on the compile-time settings (see ASK_ABOUT_WARNINGS), pdftk might prompt you for further input when it encounters a problem, such as a bad pass‐ word. Override this default behavior by adding dont_ask (so pdftk won't ask you what to do) or do_ask (so pdftk will ask you what to do).
When running in dont_ask mode, pdftk will over-write files with its output without notice.
EXAMPLES Collate scanned pages pdftk A=even.pdf B=odd.pdf shuffle A B output collated.pdf or if odd.pdf is in reverse order: pdftk A=even.pdf B=odd.pdf shuffle A Bend-1 output col‐ lated.pdf
The following examples use actual passwords as command line pa‐ rameters, which is discouraged (see the SECURITY CONSIDERATIONS section).
Decrypt a PDF pdftk secured.pdf input_pw foopass output unsecured.pdf
Encrypt a PDF using AES-128 (the default), withhold all permis‐ sions (the default) pdftk 1.pdf output 1.128.pdf owner_pw foopass
Same as above, except password 'baz' must also be used to open output PDF pdftk 1.pdf output 1.128.pdf owner_pw foo user_pw baz
Same as above, except printing is allowed (once the PDF is open) pdftk 1.pdf output 1.128.pdf owner_pw foo user_pw baz allow printing
Apply RCA 40-bit encryption to output, revoking all permissions (the default). Set the owner PW to 'foopass'. pdftk 1.pdf 2.pdf cat output 3.pdf encrypt_40bit owner_pw foopass
Join two files, one of which requires the password 'foopass'. The output is not encrypted. pdftk A=secured.pdf 2.pdf input_pw A=foopass cat output 3.pdf
Join in1.pdf and in2.pdf into a new PDF, out1.pdf pdftk in1.pdf in2.pdf cat output out1.pdf or (using handles): pdftk A=in1.pdf B=in2.pdf cat A B output out1.pdf or (using wildcards): pdftk *.pdf cat output combined.pdf
Remove page 13 from in1.pdf to create out1.pdf pdftk in.pdf cat 1-12 14-end output out1.pdf or: pdftk A=in1.pdf cat A1-12 A14-end output out1.pdf
Uncompress PDF page streams for editing the PDF in a text edi‐ tor (e.g., vim, emacs) pdftk doc.pdf output doc.unc.pdf uncompress
Repair a PDF's corrupted XREF table and stream lengths, if pos‐ sible pdftk broken.pdf output fixed.pdf
Burst a single PDF document into pages and dump its data to doc_data.txt pdftk in.pdf burst
Burst a single PDF document into encrypted pages. Allow low- quality printing pdftk in.pdf burst owner_pw foopass allow DegradedPrinting
Write a report on PDF document metadata and bookmarks to re‐ port.txt pdftk in.pdf dump_data output report.txt
Rotate the first PDF page to 90 degrees clockwise pdftk in.pdf cat 1east 2-end output out.pdf
Rotate an entire PDF document to 180 degrees pdftk in.pdf cat 1-endsouth output out.pdf
NOTES This is a port of pdftk to java. See https://gitlab.com/pdftk-java/pdftk The original program can be found at www.pdftk.com
AUTHOR Original author of pdftk is Sid Steward (sid.steward at pdflabs dot com).
SECURITY CONSIDERATIONS Passing a password as a command line parameter is insecure be‐ cause it can get saved into the shell's history and be accessi‐ ble by other users via /proc. Use the keyword PROMPT and input any passwords via standard input instead.
December 7, 2020 pdftk.pdftk-java(1)
https://tools.pdf24.org/en/ocr-pdf
provides fast, free OCR, without ads.
This website works well, and offers a total of 30 PDF operations.
The other operations of https://tools.pdf24.org/
include merging, splitting,
compressing, editing, signing, redacting, watermarking, locking, unlocking, etc.
Given my_file.pdf
, a 2-page document:
my_file_fixed.pdf
$ pdftk my_file.pdf cat 1 2south output my_file_fixed.pdf
Concatenate file_a.pdf
, file_b.pdf
and file_c.pdf
, then save as big_file.pdf
:
$ pdftk file_a.pdf file_b.pdf file_c.pdf cat output big_file.pdf
If you need to create multiple excerpts of a book, one way to proceed is to:
book_wrapper.pdf
.
book_excerpt_raw_1.pdf
, book_excerpt_raw_2.pdf
, etc.
book_wrapper.pdf
, book_excerpt_raw_N.pdf
and the last page of book_wrapper.pdf
, then save as book_excerpt_N.pdf
.
Following is an example of how to do that for 3 excerpts:
$ pdftk book_wrapper.pdf 1-2 \ book_excerpt_raw_1.pdf \ book_wrapper.pdf 3 \ cat output book_excerpt_1.pdf $ pdftk book_wrapper.pdf 1-2 \ book_excerpt_raw_2.pdf \ book_wrapper.pdf 3 \ cat output book_excerpt_2.pdf $ pdftk book_wrapper.pdf 1-2 \ book_excerpt_raw_3.pdf \ book_wrapper.pdf 3 \ cat output book_excerpt_3.pdf
Cut bigfile.pdf
into two parts:
bigfile_part1.pdf
(containing pages 1-150)bigfile_part2.pdf
(containing pages 151-350)$ pdftk A=bigfile.pdf cat 1-150 output bigfile_part1.pdf $ pdftk A=bigfile.pdf cat 151-end output bigfile_part2.pdf
If you scan a double-sided document, you might end up with the odd-numbered pages in one PDF document, and the even-numbered pages in another.
A problem that you will encouter is that when you turn over the document to scan the even-numbered pages, they will be in reverse order because the pages will be scanned from the back to the front of the document. The following examples show two ways of combining the odd- and even-numbered pages in the proper order.
This example shows how to interleave the pages in both documents to create complete.pdf
.
odd.pdf
.even.pdf
.$ pdftk A=odd.pdf B=even.pdf shuffle A B output complete.pdf
$ rm even.pdf odd.pdf
This example does not require you to manually re-order the pages,
because pdftk
can perform that task.
odd.pdf
.even_reversed.pdf
.$ pdftk even_reversed.pdf cat end-1 output even.pdf
$ pdftk A=odd.pdf B=even.pdf shuffle A B output complete.pdf
$ rm even.pdf even_reversed.pdf odd.pdf
Delete page 69 from bigfile.pdf
and save as smaller.pdf
:
$ pdftk A=bigfile.pdf cat ~69 output smaller.pdf
Delete pages 69-96 from bigfile.pdf
and save as smaller.pdf
:
$ pdftk A=bigfile.pdf cat ~69-96 output smaller.pdf
Assuming protected.pdf
is encrypted with password myPwd
, make an unencrypted copy and save as output.pdf
:
$ pdftk protected.pdf input_pw myPwd output output.pdf
You might need to enclose the password within single quotes.
]]>
Python has several well-known testing frameworks.
Popular choices for functional and unit testing include
pytest
,
the Robot framework,
and unittest
.
Lettuce
and Behave
are popular for behavior-driven testing.
I decided to use pytest
for a recent Python project.
I found that pytest
’s test discovery mechanism was finicky,
and demanded that Python packages and modules be set up before tests could be run.
This is in sharp contrast to writing unit tests for Ruby, for example, using
rspec
,
because Ruby modules are so much more flexible, forgiving and malleable.
However, getting pytest
to work in Visual Studio Code was nearly impossible.
Microsoft's documentation leaves a lot unsaid.
I share what I learned, and how I made things work in this article.
You can run pytest
from the command line 3 ways.
The most common way to run pytest
is to type the pytest
command,
like the following, which runs all tests:
$ pytest
The second way to run pytest
is to invoke the pytest
Python module, as follows:
$ python -m pytest
Running pytest
as a Python module is nearly the same as running the pytest
command,
except that running it as a module adds the current directory to sys.path
,
which is standard python behavior, and can be helpful.
I had best results running pytest
tests from Visual Studio Code when pytest
was invoked as a module.
Your code can
call pytest
.
Lots of interesting and advanced development setups could be crafted using this approach.
Baby steps.
The help message for pytest
is:
$ pytest -h usage: pytest [options] [file_or_dir] [file_or_dir] [...]
positional arguments: file_or_dir
general: -k EXPRESSION Only run tests which match the given substring expression. An expression is a Python evaluatable expression where all names are substring-matched against test names and their parent classes. Example: -k 'test_method or test_other' matches all test functions and classes whose name contains 'test_method' or 'test_other', while -k 'not test_method' matches those that don't contain 'test_method' in their names. -k 'not test_method and not test_other' will eliminate the matches. Additionally keywords are matched to classes and functions containing extra names in their 'extra_keyword_matches' set, as well as functions which have names assigned directly to them. The matching is case-insensitive. -m MARKEXPR Only run tests matching given mark expression. For example: -m 'mark1 and not mark2'. --markers show markers (builtin, plugin and per-project ones). -x, --exitfirst Exit instantly on first error or failed test --fixtures, --funcargs Show available fixtures, sorted by plugin appearance (fixtures with leading '_' are only shown with '-v') --fixtures-per-test Show fixtures per test --pdb Start the interactive Python debugger on errors or KeyboardInterrupt --pdbcls=modulename:classname Specify a custom interactive Python debugger for use with --pdb.For example: --pdbcls=IPython.terminal.debugger:TerminalPdb --trace Immediately break when running each test --capture=method Per-test capturing method: one of fd|sys|no|tee-sys -s Shortcut for --capture=no --runxfail Report the results of xfail tests as if they were not marked --lf, --last-failed Rerun only the tests that failed at the last run (or all if none failed) --ff, --failed-first Run all tests, but run the last failures first. This may re-order tests and thus lead to repeated fixture setup/teardown. --nf, --new-first Run tests from new files first, then the rest of the tests sorted by file mtime --cache-show=[CACHESHOW] Show cache contents, don't perform collection or tests. Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run --lfnf={all,none}, --last-failed-no-failures={all,none} Which tests to run with no previously (known) failures --sw, --stepwise Exit on test failure and continue from last failing test next time --sw-skip, --stepwise-skip Ignore the first failing test but stop on the next failing test. Implicitly enables --stepwise.
Reporting: --durations=N Show N slowest setup/test durations (N=0 for all) --durations-min=N Minimal duration in seconds for inclusion in slowest list. Default: 0.005. -v, --verbose Increase verbosity --no-header Disable header --no-summary Disable summary -q, --quiet Decrease verbosity --verbosity=VERBOSE Set verbosity. Default: 0. -r chars Show extra test summary info as specified by chars: (f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed, (P)assed with output, (a)ll except passed (p/P), or (A)ll. (w)arnings are enabled by default (see --disable-warnings), 'N' can be used to reset the list. (default: 'fE'). --disable-warnings, --disable-pytest-warnings Disable warnings summary -l, --showlocals Show locals in tracebacks (disabled by default) --no-showlocals Hide locals in tracebacks (negate --showlocals passed through addopts) --tb=style Traceback print mode (auto/long/short/line/native/no) --show-capture={no,stdout,stderr,log,all} Controls how captured stdout/stderr/log is shown on failed tests. Default: all. --full-trace Don't cut any tracebacks (default is to cut) --color=color Color terminal output (yes/no/auto) --code-highlight={yes,no} Whether code should be highlighted (only if --color is also enabled). Default: yes. --pastebin=mode Send failed|all info to bpaste.net pastebin service --junit-xml=path Create junit-xml style report file at given path --junit-prefix=str Prepend prefix to classnames in junit-xml output
pytest-warnings: -W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGS Set which warnings to report, see -W option of Python itself --maxfail=num Exit after first num failures or errors --strict-config Any warnings encountered while parsing the `pytest` section of the configuration file raise errors --strict-markers Markers not registered in the `markers` section of the configuration file raise errors --strict (Deprecated) alias to --strict-markers -c FILE, --config-file=FILE Load configuration from `FILE` instead of trying to locate one of the implicit configuration files. --continue-on-collection-errors Force test execution even if collection errors occur --rootdir=ROOTDIR Define root directory for tests. Can be relative path: 'root_dir', './root_dir', 'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with variables: '$HOME/root_dir'.
collection: --collect-only, --co Only collect tests, don't execute them --pyargs Try to interpret all arguments as Python packages --ignore=path Ignore path during collection (multi-allowed) --ignore-glob=path Ignore path pattern during collection (multi-allowed) --deselect=nodeid_prefix Deselect item (via node id prefix) during collection (multi-allowed) --confcutdir=dir Only load conftest.py's relative to specified dir --noconftest Don't load any conftest.py files --keep-duplicates Keep duplicate tests --collect-in-virtualenv Don't ignore tests in a local virtualenv directory --import-mode={prepend,append,importlib} Prepend/append to sys.path when importing test modules and conftest files. Default: prepend. --doctest-modules Run doctests in all .py modules --doctest-report={none,cdiff,ndiff,udiff,only_first_failure} Choose another output format for diffs on doctest failure --doctest-glob=pat Doctests file matching pattern, default: test*.txt --doctest-ignore-import-errors Ignore doctest ImportErrors --doctest-continue-on-failure For a given doctest, continue to run after the first failure
test session debugging and configuration: --basetemp=dir Base temporary directory for this test run. (Warning: this directory is removed if it exists.) -V, --version Display pytest version and information about plugins. When given twice, also display information about plugins. -h, --help Show help message and configuration info -p name Early-load given plugin module name or entry point (multi-allowed). To avoid loading of plugins, use the `no:` prefix, e.g. `no:doctest`. --trace-config Trace considerations of conftest.py files --debug=[DEBUG_FILE_NAME] Store internal tracing debug information in this log file. This file is opened with 'w' and truncated as a result, care advised. Default: pytestdebug.log. -o OVERRIDE_INI, --override-ini=OVERRIDE_INI Override ini option with "option=value" style, e.g. `-o xfail_strict=True -o cache_dir=cache`. --assert=MODE Control assertion debugging tools. 'plain' performs no assertion debugging. 'rewrite' (the default) rewrites assert statements in test modules on import to provide assert expression information. --setup-only Only setup fixtures, do not execute tests --setup-show Show setup of fixtures while executing tests --setup-plan Show what fixtures and tests would be executed but don't execute anything
logging: --log-level=LEVEL Level of messages to catch/display. Not set by default, so it depends on the root/parent log handler's effective level, where it is "WARNING" by default. --log-format=LOG_FORMAT Log format used by the logging module --log-date-format=LOG_DATE_FORMAT Log date format used by the logging module --log-cli-level=LOG_CLI_LEVEL CLI logging level --log-cli-format=LOG_CLI_FORMAT Log format used by the logging module --log-cli-date-format=LOG_CLI_DATE_FORMAT Log date format used by the logging module --log-file=LOG_FILE Path to a file when logging will be written to --log-file-level=LOG_FILE_LEVEL Log file logging level --log-file-format=LOG_FILE_FORMAT Log format used by the logging module --log-file-date-format=LOG_FILE_DATE_FORMAT Log date format used by the logging module --log-auto-indent=LOG_AUTO_INDENT Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer. --log-disable=LOGGER_DISABLE Disable a logger by name. Can be passed multiple times.
[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg|pyproject.toml file found:
markers (linelist): Markers for test functions empty_parameter_set_mark (string): Default marker for empty parametersets norecursedirs (args): Directory patterns to avoid for recursion testpaths (args): Directories to search for tests when no files or directories are given on the command line filterwarnings (linelist): Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings. usefixtures (args): List of default fixtures to be used with this project python_files (args): Glob-style file patterns for Python test module discovery python_classes (args): Prefixes or glob names for Python test class discovery python_functions (args): Prefixes or glob names for Python test function and method discovery disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool): Disable string escape non-ASCII characters, might cause unwanted side effects(use at your own risk) console_output_style (string): Console output: "classic", or with additional progress information ("progress" (percentage) | "count" | "progress-even-when-capture-no" (forces progress even when capture=no) xfail_strict (bool): Default for the strict parameter of xfail markers when not given explicitly (default: False) tmp_path_retention_count (string): How many sessions should we keep the `tmp_path` directories, according to `tmp_path_retention_policy`. tmp_path_retention_policy (string): Controls which directories created by the `tmp_path` fixture are kept around, based on test outcome. (all/failed/none) enable_assertion_pass_hook (bool): Enables the pytest_assertion_pass hook. Make sure to delete any previously generated pyc cache files. junit_suite_name (string): Test suite name for JUnit report junit_logging (string): Write captured log messages to JUnit report: one of no|log|system-out|system-err|out-err|all junit_log_passing_tests (bool): Capture log information for passing tests to JUnit report: junit_duration_report (string): Duration time to report: one of total|call junit_family (string): Emit XML for schema: one of legacy|xunit1|xunit2 doctest_optionflags (args): Option flags for doctests doctest_encoding (string): Encoding used for doctest files cache_dir (string): Cache directory path log_level (string): Default value for --log-level log_format (string): Default value for --log-format log_date_format (string): Default value for --log-date-format log_cli (bool): Enable log display during test run (also known as "live logging") log_cli_level (string): Default value for --log-cli-level log_cli_format (string): Default value for --log-cli-format log_cli_date_format (string): Default value for --log-cli-date-format log_file (string): Default value for --log-file log_file_level (string): Default value for --log-file-level log_file_format (string): Default value for --log-file-format log_file_date_format (string): Default value for --log-file-date-format log_auto_indent (string): Default value for --log-auto-indent pythonpath (paths): Add paths to sys.path faulthandler_timeout (string): Dump the traceback of all threads if a test takes more than TIMEOUT seconds to finish addopts (args): Extra command line options minversion (string): Minimally required pytest version required_plugins (args): Plugins that must be present for pytest to run
Environment variables: PYTEST_ADDOPTS Extra command line options PYTEST_PLUGINS Comma-separated plugins to load during startup PYTEST_DISABLE_PLUGIN_AUTOLOAD Set to disable plugin auto-loading PYTEST_DEBUG Set to enable debug tracing of pytest's internals
to see available markers type: pytest --markers to see available fixtures type: pytest --fixtures (shown according to specified file_or_dir or current dir if not specified; fixtures with leading '_' are only shown with the '-v' option
It is handy to run new and failing tests, but to skip previously passing tests.
The ‑‑nf
and ‑‑lf
options,
respectively, invoke that mode of behavior:
$ pytest --nf --lf
Pytest
needed to know that
the source code for my Python project is stored in the src
directory.
I created pyproject.toml
as follows, which configured pytest
:
[tool.pytest.ini_options] addopts = [ "--import-mode=importlib", ] pythonpath = "src"
The way in which pytest
discovers tests is
complex.
TL;DR:
specify the newest and best mechanism for test discovery by using the
‑‑import-mode=importlib
option as shown above.
To always run pytest
with the ‑‑nf
and ‑‑lf
options,
add those options to pyproject.toml
:
[tool.pytest.ini_options] addopts = [ "--import-mode=importlib", "--lf", "--nf", ] pythonpath = "src"
Flexibility generally adds complexity.
Pytest
allows for a lot of flexibility regarding the location of where tests can reside.
Unfortunately, Python’s package and module mechanism in combination with the pytest
discovery
mechanism for tests can lead to a frustrating experience when setting up a new project.
You can read about
good practices for pytest
.
Those recommendations are intimidating for first-time pytest
programmers.
I did not follow all of them.
I found the simplest approach was to create a subdirectory for the bulk of the Python project code.
If a file called __init__.py
is created in that directory
(use touch
for this)
then the subdirectory becomes a submodule of your Python program.
For this type of pytest
setup,
each submodule needs a tests
directory.
Here is how you could use touch
to define an imaginary subdirectory/submodule
called my_submodule
:
$ mkdir -p src/my_submodule/
$ touch src/my_submodule/__init__.py
My project structure was as follows.
Tree
docs are here.
$ tree -I .git -I __pycache__ . ├── README.md ├── dl ├── dl.config ├── pyproject.toml ├── requirements.txt └── src ├── __main__.py └── dl ├── __init__.py ├── argument_parse.py ├── dl_config.py ├── media_file.py ├── remote.py ├── tests │  ├── __init__.py │  ├── test_dl_config.py │  └── test_uti.py └── util.py 3 directories, 15 files
src/dl/tests/__init__.py
was an empty marker file,
but the ___init__.py
file in the
parent module
defined import
s for the submodule:
from dl.argument_parse import ArgParse from dl.dl_config import DLConfig from dl.media_file import MediaFile from dl.remote import Remote from dl.util import *
Here is a sample pytest
file, containing 2 unit tests.
It is simple and clear.
import pytest from pathlib import Path from dl import samba_mount, samba_parse class TestUtil: def test_samba_parse(self): remote_drive, local_path = samba_parse('e:/media/renders') assert remote_drive=='e' assert local_path=='/media/renders' def test_samba_mount(self): samba_root = samba_mount('bear', 'e', False) assert samba_root==Path('/mnt/bear/e') assert samba_root.is_mount()
If you have been paying attention, you should realize that one option for running new and failing tests is to type the following from the command line. We will use this method of invocation in the next section to integrate with Visual Studio Code.
$ python -m pytest --nf --lf
Visual Studio Code has a Testing explorer and a Run and Debug explorer. I find the existance of two very similar explorers annoying, because you often want to debug a test. Yes, you can do that by pushing the right button in the Testing Explorer ... if it works. This did not work for me.
Shopify Ruby, the latest and greatest Ruby extension for Visual Studio Code, uses the Run and Debug explorer to run and debug tests as well as entire programs. This makes sense to me.
Microsoft Pylance (for Python) follows a different convention, and uses the Run and Debug explorer to run and debug Python programs. You must use the Testing explorer for running or debugging Python unit tests. Annoying.
In the Testing explorer, I was able to see my dl
module,
but no tests were discovered.
This was really annoying, and this is where more documentation from Microsoft would have been helpful.
After wasting lots of time trying to solve this problem, I discovered a solution.
Run and Debug configurations that invoke the pytest
module work perfectly.
Here is an example .vscode/launch.json
that demonstrates this:
{ "version": "0.2.0", "configurations": [ { "name": "PyTest All", "type": "python", "request": "launch", "module": "pytest", "justMyCode": true }, { "args": ["--nf", "--lf"], "name": "PyTest New and Failing", "type": "python", "request": "launch", "module": "pytest", "justMyCode": true }, ] }
You can set breakpoints in your code and debug your tests this way.
]]>Recently I decided to brush up on my C programming.
I first discovered C during a visit in 1978 to the Computer Science department of University of California, Berkeley, where I also encounted UNIX for the first time.
From about 1983 to 1985 I was the unofficial Canadian distributor of the Lattice C compiler. I used that compiler for most of the programming work I was doing on PCs at the time. FedEx Express Canada did not come into being until 1987, UPS was even worse with the Canadian border than it is now, and Canada Post took forever to bring packages across the border. I bought in bulk at a discount, and sold at list price. Distribution is all about time and place.
I also sold the first edition of the K&R book (“The C Programming Language”) via mail order, and I provided technical support, which brought in interesting consulting work.
The Borland Turbo C compiler, released in 1990, was the original IDE. It was eventually replaced by Borland C++ compiler, which also compiled C. In 2005 I became the product marketing manager for most of Borland’s compilers. One of my responsibilities was to give free copies to book authors and members of the trade press. Borland C++ shipped in a massive box that was responsible for a lot of dead trees.
The C language has evolved since K&R days.
The current and previous iterations are well summarized on
cppreference.com
,
which also provides an online C/C++ IDE for sample code.
1978: K&R book first published.
1989: C89, also known as ANSI X3. 159-1989, or ANSI C.
1995: NA1 (aka C94 and C95) added support for wide-characters, wide-strings, and international keyboard layouts.
1999:
C99 added restricted pointers, variable-length arrays, flexible array members,
complex numbers support, type-generic math, long long int
, extended identifiers,
hexadecimal floating-point constants, compound literals, designated initializers,
single line comments, extended integer type, the ability to mix declarations and code,
variadic macros, new math functions, inline functions, boolean types,
_Pragma
and standard pragmas, and VA_COPY
.
C99 removed implicit function declaration.
2011: C11 added concurrency support, type-generic expressions, alignment-related facilities, static assertion, Unicode support, floating-point characteristic macros, no-return functions, anonymous structures and unions, bound-checking, and reentrancy functions.
2018: C18 addressed defects in C11 without introducing new language features.
2023:
The most recent publicly available draft of the next release,
C23,
was released on April 1, 2023.
Unfortunately, that document was written for insiders, and is very difficult to read.
Happily, JeanHeyd Meneide, the Project Editor for ISO/IEC JTC1 SC22 WG14 - Programming Languages, C, wrote an
easy-to-read
It has been reported that Linux was originally written in C89, but Linux moved to C11 in 2022. I am curious as to why C18 is not used, since C18 just contains bug fixes for C11. Most of the Linux kernel code is written using the GNU extensions of GCC.
I pioneered online programming with SMX Explorer in 1994, JSP Explorer in 2000, and supported most available languages in 2002 with Zamples.com.
Now it seems that every day another online programming option becomes available. Many are free:
cppreference.com
;
GitHub project
Online programming is fine for learning, but I prefer to be independent and self-reliant whenever practical for doing actual work.
To program in C or C++ on Ubuntu using the traditional Linux command-line toolchain,
install the build-essential
Debian meta-package on Ubuntu.
It includes the GNU Compiler Collection (GCC),
which is a collection of compilers and libraries for
C, C++, Objective-C, Fortran, Ada, Go, and D programming languages.
It also includes make
and
libc6.1-dev
,
the GNU C development libraries and header files.
You probably should also install
gdb
, the GNU Project Debugger,
and the manual pages
about using GNU/Linux for development.
$ sudo apt install build-essential gdb manpages-dev
Now you are able to compile and run C programs at the command line:
$ mkdir test && cd test $ cat >test.c <<EOF #include <stdio.h> int main(void) { printf("Hello, World!\n"); } EOF $ gcc test.c -o test && ./test Hello, World!
Visual Studio Code is a high-quality (and free) IDE. To work with C and C++ in Visual Studio Code, install the Microsoft C/C++ extension.
]]>The name of this project is problematic, and you publicly dismissed the issue when it was brought to your attention. While ignorance of the law is no defense; demonstrably flaunting another party’s rights never has positive consequences.
The LEGO Group has not taken legal action yet, but the laws of most countries (including the US) are that if a trademark is not defended, then the trademark is at risk of being lost.
You should expect to receive a legal notice at some point. Not because the trademark owners are evil, but because they have a duty to their company, and the well-being of their employees, and a duty to their shareholders.
Your disregard for the LEGO Group's rights constituted a real and present danger to them, their employees and shareholders. They are compelled to address threats against their well-being.
Not only must a trademark holder defend their trademark, they must be seen to defend it. That means taking action that is publicly visible. For example, they might include GitHub and maybe even Microsoft in the legal action against you.
The LEGO Group would likely include GitHub/Microsoft in the case, even though they know that Section 230 would probably be found to apply (in due course), and GitHub/Microsoft would not be found to be liable – after they spent several million dollars in a successful legal defense.
It is easy to understand the motivation for the LEGO Group deliberately ‘losing’ at the attempt to ensnare GitHub/Microsoft in this court case. You would have caused GitHub/Microsoft an unnecessary and pointless waste of time and resources, and it would be shown that you knew better. Remember, you have already been publicly been warned that there would likely be consequences – yet you chose to ignore the warning.
This would likely motivate GitHub/Microsoft to protect themselves against similar misguided behavior of other GitHub users. Restrictive policies and procedures would likely get implemented, and the entire world would know that the resulting degraded GitHub experience was your fault. You would be vilified by every other GitHub user. Not a great thing for your resume.
... And GitHub/Microsoft might ask you to pay their legal expenses.
Please understand that because you are acting as an informal collection of individuals, everyone who ever contributed to this project is exposed to signficant financial risk. The LEGO Group would probably not attempt to narrow down the guilty individuals – identifying the guilty and assigning punishment would be the outcomes of the court case. Instead, they would likely include every contributor in the litigation; that means every committer.
You are risking the financial well-being of your families ... just because you like a cute play on words?
Rational people would not expose themselves to significant risk without any prospect of signficant benefit, and when not faced with dire necessity.
If you presently balk at paying a lawyer to advise you on this matter, that cost will be as nothing compared to the world of hurt you are likely to find yourselves in if you do not change the name of your project.
From a technical aspect, you have done excellent work on your project, and you are freely providing the world a valuable benefit. Unfortunately, you trampled the rights of another in doing so... and for no reason. Please act on this before the inevitable negative consequences arise. Do not poke the bear because you are curious to see what it will do.
The wheels of corporate law grind slowly, and huge amounts of money are spent.
According to the path you are now on,
the committers of this project may be subjected to immense financial and mental burdens.
Broken families and suicides may result.
Please heed this warning.
If nothing bad has ever happened to you yet in life,
rest assured that
Lachesis, Atropos and Clotho
will inevitably make themselves known.
Do not let arrogance and pride ruin you.
I have no relationship with the LEGO Group, or any individuals associated with them. Please consider this as a notice freely offered for public service.
Although I have experience working as an expert witness in the US Federal legal system as a software expert, I am not a lawyer and I have no legal training. However, I have seen corporate legal machinery at work many times, up close. I have spent thousands of hours working with corporate attorneys in the US and Europe. My clients have included Adobe, Amazon/AWS, Apple, and SAP.
]]>Letsencrypt certificates are only valid for 90 days. It is common practice to renew them every 60 days, a task that one should automate when the website is first published.
I wrote about setting up wildcard SSL certificates with Nginx 9 months ago. That article included a demonstration of how to create an SSL certificate manually, but did not discuss how to maintain it.
This article discusses how to automatically generate and maintain the SSL certificate using
lego
,
a Letsencrypt/ACME client and library written in Go
that has become popular since I last wrote about this topic.
Lego
handles many moving parts transparently.
It is much simpler than using DNS delegates with
acme-dns
.
We’ll start by briefly discussing some background information.
You must prove to Letsencrypt that you control the DNS for a domain before
it issues a wildcard SSL certificate for that domain.
Letsencrypt’s certbot
currently uses the
DNS-01
challenge
for this purpose.
The DNS-01 challenge requires that DNS TXT
records for the domain be
created with specific values as part of the authentication mechanism.
Several of these TXT
records can co-exist among the DNS records for a domain.
The name of the TXT
records is always _acme-challenge
.
When certbot
requests that a new wildcard SSL certificate be created by Letsencrypt,
it sends DNS-01 TXT
queries to the primary DNS.
The Letsencrypt service verifies that the required _acme-challenge
TXT
records are available with the correct values.
A Technical Deep Dive: Securing the Automation of ACME DNS Challenge Validation, published by the Electronic Frontier Foundation, explains how this works in detail.
Certbot
plugins have been created for various DNS providers to make this process easier.
Lego
is a higher-level program that makes the entire process even easier.
The high-level outline of the remainder of this blog is:
go
language support.lego
.crontab
to automate the SSL certificate generation.
Lego
is written in Go.
Ensure that Go language support is installed.
For Ubuntu Linux (and the default WSL distro), type:
$ yes | sudo apt install golang-go The following NEW packages will be installed: golang-1.18-go golang-1.18-src golang-go golang-src 0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded. Need to get 82.2 MB of archives. After this operation, 436 MB of additional disk space will be used. Do you want to continue? [Y/n] Get:1 http://archive.ubuntu.com/ubuntu jammy/main amd64 golang-1.18-src all 1.18.1-1ubuntu1 [16.2 MB] Get:2 http://archive.ubuntu.com/ubuntu jammy/main amd64 golang-1.18-go amd64 1.18.1-1ubuntu1 [66.0 MB] Get:3 http://archive.ubuntu.com/ubuntu jammy/main amd64 golang-src all 2:1.18~0ubuntu2 [4438 B] Get:4 http://archive.ubuntu.com/ubuntu jammy/main amd64 golang-go amd64 2:1.18~0ubuntu2 [41.8 kB] Fetched 82.2 MB in 2s (33.6 MB/s) Selecting previously unselected package golang-1.18-src. (Reading database ... 173763 files and directories currently installed.) Preparing to unpack .../golang-1.18-src_1.18.1-1ubuntu1_all.deb ... Unpacking golang-1.18-src (1.18.1-1ubuntu1) ... Selecting previously unselected package golang-1.18-go. Preparing to unpack .../golang-1.18-go_1.18.1-1ubuntu1_amd64.deb ... Unpacking golang-1.18-go (1.18.1-1ubuntu1) ... Selecting previously unselected package golang-src. Preparing to unpack .../golang-src_2%3a1.18~0ubuntu2_all.deb ... Unpacking golang-src (2:1.18~0ubuntu2) ... Selecting previously unselected package golang-go:amd64. Preparing to unpack .../golang-go_2%3a1.18~0ubuntu2_amd64.deb ... Unpacking golang-go:amd64 (2:1.18~0ubuntu2) ... Setting up golang-1.18-src (1.18.1-1ubuntu1) ... Setting up golang-src (2:1.18~0ubuntu2) ... Setting up golang-1.18-go (1.18.1-1ubuntu1) ... Setting up golang-go:amd64 (2:1.18~0ubuntu2) ... Processing triggers for man-db (2.10.2-1) ... Scanning processes... Scanning processor microcode... Scanning linux images... Failed to retrieve available kernel versions. Failed to check for processor microcode upgrades. No services need to be restarted. No containers need to be restarted. No user sessions are running outdated binaries. No VM guests are running outdated hypervisor (qemu) binaries on this host.
View the version of go
that was installed:
$ go version go version go1.19.2 linux/amd64
The official lego
installation instructions are
here.
They do not mention Ubuntu instructions, but the
lego
package for Ubuntu
can be installed in the usual way:
$ yes | sudo apt install lego Reading package lists... Done Building dependency tree... Done Reading state information... Done The following NEW packages will be installed: lego 0 upgraded, 1 newly installed, 0 to remove and 7 not upgraded. Need to get 5322 kB of archives. After this operation, 19.7 MB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 lego amd64 4.1.3-3ubuntu1.22.04.1 [5322 kB] Fetched 5322 kB in 1s (10.2 MB/s) Selecting previously unselected package lego. (Reading database ... 86044 files and directories currently installed.) Preparing to unpack .../lego_4.1.3-3ubuntu1.22.04.1_amd64.deb ... Unpacking lego (4.1.3-3ubuntu1.22.04.1) ... Setting up lego (4.1.3-3ubuntu1.22.04.1) ...
Here is the lego
help message:
$ lego -h NAME: lego - Let's Encrypt client written in Go
USAGE: lego [global options] command [command options] [arguments...]
VERSION: dev
COMMANDS: run Register an account, then create and install a certificate revoke Revoke a certificate renew Renew a certificate dnshelp Shows additional help for the '--dns' global option list Display certificates and accounts information. help, h Shows a list of commands or help for one command
GLOBAL OPTIONS: --domains value, -d value Add a domain to the process. Can be specified multiple times. --server value, -s value CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "https://acme-v02.api.letsencrypt.org/directory") --accept-tos, -a By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service. --email value, -m value Email used for registration and recovery contact. --csr value, -c value Certificate signing request filename, if an external CSR is to be used. --eab Use External Account Binding for account registration. Requires --kid and --hmac. --kid value Key identifier from External CA. Used for External Account Binding. --hmac value MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding. --key-type value, -k value Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384. (default: "ec256") --filename value (deprecated) Filename of the generated certificate. --path value Directory to use for storing the data. (default: "/mnt/_/work/lego/.lego") [$LEGO_PATH] --http Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges. --http.port value Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port. (default: ":80") --http.proxy-header value Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy. (default: "Host") --http.webroot value Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge --http.memcached-host value Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts. --tls Use the TLS challenge to solve challenges. Can be mixed with other types of challenges. --tls.port value Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port. (default: ":443") --dns value Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage. --dns.disable-cp By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers. --dns.resolvers value Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined. --http-timeout value Set the HTTP timeout value to a specific value in seconds. (default: 0) --dns-timeout value Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries. (default: 10) --pem Generate a .pem file by concatenating the .key and .crt files together. --cert.timeout value Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates. (default: 30) --help, -h show help --version, -v print the version
My projects are defined in a directory tree,
which is pointed to by an environment variable called work
.
This is helpful when working across many machines,
each of which has a different directory layout.
I define the work
environment variable in the
system-wide /etc/environment
file,
where it affects all users, all scripts, and crontab entries:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" work=/mnt/_/work sites=/mnt/_/www
$work
is used in the script shown below,
and that script will be launched via crontab
,
which is why /etc/environment
is used instead of $HOME/.bashrc
.
WSL does not run systemd
services, and WSL2 only runs them if they are enabled.
You can easily convert WSL instances into WSL2 instances.
Unless systemd
starts automatically at boot time,
/etc/environment
will not be processed.
Read Microsoft’s announcement to learn more:
Systemd
support is now available in WSL!
When working with the lego
CLI with DNS authentication,
a directory is needed to hold all the files that are required.
I created a directory for this purpose at $work/lego
:
$ mkdir $work/lego
$ cd $work/lego
The lego --dns namecheap
option connects to Namecheap, which is my DNS provider,
and uses the Namecheap DNS for the DNS-01
challenge.
Lego supports many other DNS providers.
The Namecheap API documentation is here. For some reason, that page reloads to a different page, which is annoying. Press the Esc key right after the page opens, so you can read it.
Please also read the
FAQ.
Enable the Namecheap API
here.
You could enable the Namecheap sandbox API
here.
Here is a short script that displays your current public IP address:
#!/bin/bash dig +short myip.opendns.com @resolver1.opendns.com
If your modem goes offline, Namecheap’s DNS will assign a new IP address the next time the modem reconnects. That will cause the scripts shown below to stop working until you manually provide the new address to the Namecheap API. Annoying! Be sure to plug your modem into a UPS to maintain the IP address even during short outages, power brownouts and voltage dropouts. A sine-wave UPS is strongly preferred, since modems are sensitive to low-quality power.
The Namecheap API needs 2 environment variables for authentication
(NAMECHEAP_API_USER
and NAMECHEAP_API_KEY
).
Here is how I defined those environment variables so they were available for the
lego
process launched by sudo
:
$ export NAMECHEAP_API_USER=asdf
$ export NAMECHEAP_API_KEY=asdfasdf
To generate a wildcard certificate, you must specify the --domains
option twice:
once with the domain name, and once for all subdomains, like this:
$ lego \ --accept-tos \ --dns namecheap \ --domains="scalacourses.com" \ --domains="*.scalacourses.com" \ --email="mslinn@scalacourses.com" \ run 2023/03/01 13:40:03 [INFO] [*.scalacourses.com] acme: Obtaining bundled SAN certificate 2023/03/01 13:40:03 [INFO] [*.scalacourses.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/207409481036 2023/03/01 13:40:03 [INFO] [*.scalacourses.com] acme: use dns-01 solver 2023/03/01 13:40:03 [INFO] [*.scalacourses.com] acme: Preparing to solve DNS-01 2023/03/01 13:40:04 [INFO] [*.scalacourses.com] acme: Trying to solve DNS-01 2023/03/01 13:40:04 [INFO] [*.scalacourses.com] acme: Checking DNS record propagation using [172.19.176.1:53] 2023/03/01 13:40:19 [INFO] Wait for propagation [timeout: 1h0m0s, interval: 15s] 2023/03/01 13:40:20 [INFO] [*.scalacourses.com] acme: Waiting for DNS record propagation. 2023/03/01 13:40:35 [INFO] [*.scalacourses.com] acme: Waiting for DNS record propagation. 2023/03/01 13:40:56 [INFO] [*.scalacourses.com] The server validated our request 2023/03/01 13:40:56 [INFO] [*.scalacourses.com] acme: Cleaning DNS-01 challenge 2023/03/01 13:40:56 [INFO] [*.scalacourses.com] acme: Validations succeeded; requesting certificates 2023/03/01 13:40:57 [INFO] [*.scalacourses.com] Server responded with a certificate.
The wildcard SSL certificate and associated files are generated into the .lego/certificates
directory.
$ ls -alF .lego/certificates total 12 drwx------ 1 mslinn mslinn 4096 Mar 1 13:40 ./ drwx------ 1 mslinn mslinn 4096 Mar 1 13:15 ../ -rw------- 1 mslinn mslinn 5325 Mar 1 13:40 scalacourses.com.crt -rw------- 1 mslinn mslinn 3751 Mar 1 13:40 scalacourses.com.issuer.crt -rw------- 1 mslinn mslinn 239 Mar 1 13:40 scalacourses.com.json -rw------- 1 mslinn mslinn 227 Mar 1 13:40 scalacourses.com.key
scalacourses.com.crt
is the server certificate that nginx needs,
already combined with the CA certificate.
scalacourses.com.key
is the private key for the server certificate.scalacourses.com.issuer.crt
is the issuing Certificate Authority's certificate.scalacourses.com.json
contains JSON encoded meta information.
It looked like this:
{ "domain": "*.scalacourses.com", "certUrl": "https://acme-v02.api.letsencrypt.org/acme/cert/3939493849340275024024", "certStableUrl": "https://acme-v02.api.letsencrypt.org/acme/cert/738378373923492384932874932" }
Using the value for certStableUrl
in the above JSON file,
we can view the generated (and combined) certificate that was saved on letsencrypt.org
.
$ wget -O aw.crt \
https://acme-v02.api.letsencrypt.org/acme/cert/03b099f52b4841db17e035c5c2b390f0219b
60 days from now, when the certificate should be renewed,
the last parameter passed to lego
in the above command line should be changed from
run
to renew
.
Here is a bash script that you can edit for this purpose;
at the end of this article this script is incorporated into a new crontab
entry:
#!/bin/bash export NAMECHEAP_API_USER=asdf export NAMECHEAP_API_KEY=asdfasdf ACTION=run if [ -f .lego/certificates/scalacourses.com.crt ]; then ACTION=renew fi cd $work/lego lego \ --accept-tos \ --dns namecheap \ --domains="scalacourses.com" \ --domains="*.scalacourses.com" \ --email="mslinn@scalacourses.com" \ "$ACTION" sudo systemctl reload nginx
For Ubuntu 22.10, the filetype associations are defined in a hierarchy of files called mimeapps.list
:
$ locate mimeapps.list ~/.config/mimeapps.list ~/.local/share/applications/mimeapps.list /snap/core/14447/usr/share/applications/mimeapps.list /snap/core/14784/usr/share/applications/mimeapps.list /snap/core18/2679/usr/share/applications/mimeapps.list /snap/core18/2697/usr/share/applications/mimeapps.list /snap/core20/1778/usr/share/applications/mimeapps.list /snap/core20/1822/usr/share/applications/mimeapps.list /snap/core22/509/usr/share/applications/mimeapps.list /snap/core22/522/usr/share/applications/mimeapps.list /usr/share/gdm/greeter/applications/mimeapps.list
/snap/
contains the default association for *.crt
files:
[Default Applications] x-scheme-handler/http=xdg-open.desktop x-scheme-handler/https=xdg-open.desktop x-scheme-handler/mailto=xdg-open.desktop x-scheme-handler/help=xdg-open.desktop
The above associates a program called
xdg-open
with CRT files.
Double-clicking on a crt
file displayed by an Ubuntu file manager such as Nautilus causes
xdg-open
to open the file.
You can also use the command line to open the file in xdg-open
.
For example, typing the following causes aw.crt
to open:
$ xdg-open aw.crt
This is what xdg-open
displays:
As you can see, this is a combined certificate, containing not just one certificate, but an entire certificate chain. Clicking on any of the red > Details buttons causes more information to be displayed about the corresponding certificate in the chain.
If you forget to include the domain, and just specify the wildcard for subdomains,
the certificate will not be valid for the domain.
For example, if above I had only specified one --domains
option, like this:
--domains="scalacourses.com"
--domains="scalacourses.com" \
--domains="*.scalacourses.com"
_
),
for example _.scalacourses.com.crt
,
instead of being named scalacourses.com.crt
.
*
).DNS: *.scalacourses.com
DNS: scalacourses.com
DNS: *.scalacourses.com
DNS: scalacourses.com
Previously,
before working with lego
, I used raw certbot
to generate the SSL wildcard certificates.
That process generated files in ~/.certbot/
:
fullchain.pem
(the
ssl_certificate
)
privkey.pem
(the
ssl_certificate_key
)
ssl_certificate /home/mslinn/.certbot/scalacourses.com/config/live/scalacourses.com/fullchain.pem; ssl_certificate_key /home/mslinn/.certbot/scalacourses.com/config/live/scalacourses.com/privkey.pem;
Now I need to modify /etc/
to reference the files generated by lego
:
scalacourses.com.crt
(the
ssl_certificate
)
scalacourses.com.key
(the
ssl_certificate_key
)
If the webserver had access to the directory containing the new wildcard certificate, it would be simplest to provide the full path to the certificate and its key, like this:
ssl_certificate /mnt/_/work/lego/.lego/certificates/scalacourses.com.crt; ssl_certificate_key /mnt/_/work/lego/.lego/certificates/scalacourses.com.key;
I tested the nginx
configuration:
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Then I reloaded nginx:
$ sudo systemctl reload nginx
The new SSL certificate needs to be checked to make sure it was installed properly. I just visually examine the start and expire dates:
$ curl -Lvs https://www.scalacourses.com \ 2>&1 1>/dev/null | \ grep '\(start\|expire\) date:' * start date: Mar 1 17:40:56 2023 GMT * expire date: May 30 17:40:55 2023 GMT
Automating the regeneration of the SSL wildcard certificate is easy.
Edit your crontab
:
$ crontab -e
Add the following reference to the
certGenScalaCourses
script
that I gave you earlier to crontab
:
# Runs every 2 months / 60 days (more or less) 30 0 1 */2 * $work/lego/certGenScalaCourses
The above only works because
we defined the work
environment variable
in /etc/
.
Microsoft Windows caches SSL certificates, which can prevent your web browser from detecting newly updated SSL certificates. To clear the Windows SSL cache:
Internet Options
, and press Enter.Web browsers now have built-in automatic hyphenation support, but it is turned off by default for compatibity with older browsers. You can enable hyphenation with two words of CSS, like this:
body {
hyphens: auto;
}
hyphens
property.
CSS Text Level 3 does not define the exact rules for hyphenation;
however, UAs are strongly encouraged to optimize their choice of break points and to chose
language-appropriate hyphenation points.
Possible hyphens values: none | manual | auto Initial value: manual
However, the W3 CSS3 hyphenation standard also says:
lang
attribute or XML xml:lang
attribute)
in order to obtain correct automatic hyphenation.
Let’s put this into practice now.
You may not want certain passages to be hyphenated.
Defining a CSS style that disables automatic hyphenation for portions of a document is easy;
you can still use &shy;
in those portions of the document
to manually define optional hyphenation points.
Here is a suggestion for your stylesheet, so it has the hyphenation support you need. Note that hypenation for kbd tags is completely disabled.
body, .hyphen { hyphens: auto; } .nohyphen { hyphens: manual; } kbd { hyphens: none; }
The following example enables automatic hyphenation of the entire HTML body
,
according to US English rules.
The HTML document contains nested tags,
some of which disable or enable automatic hyphenation.
One line demonstrates manual hyphenation, through the use of
­
entities:
<html lang="en-US"> <head> <style> body, .hyphen { hyphens: auto; } .nohyphen { hyphens: manual; } </style> </head> <body> <p>This element is automatically hyphenated.</p> <p class="nohyphen">This element is not hyphenated.</p> <ol class="nohyphen"> <li>This elem­ent is manual­ly hyphen­ated.</li> <li class="hyphen">This element is automatically hyphenated.</li> </ol> </body> </html>
Easy!
Invisible hypenation is sometimes desirable.
For example, if I have a long directory path, like
$HOME/.rbenv/versions/$RUBY_VERSION/lib/ruby/gems/$RUBY_VERSION/$GEM_NAME-$GEM_VERSION
I might want to tell the web browser where the string could be broken.
You have two options — they are actually different syntaxes for the same zero-width space.
​
is the HTML entity for a unicode character called the zero-width space
(ZWSP
).
For example,
$HOME/.rbenv/​versions/​$RUBY_VERSION/​lib/​ruby/​gems/​$RUBY_VERSION/​$GEM_NAME-​$GEM_VERSION
renders as:
$HOME/.rbenv/versions/$RUBY_VERSION/lib/ruby/gems/$RUBY_VERSION/$GEM_NAME-$GEM_VERSION
You could also use the
line break opportunity tag,
<wbr>
.
For example,
$HOME/.rbenv/<wbr>versions/<wbr>$RUBY_VERSION/<wbr>lib/<wbr>ruby/<wbr>gems/<wbr>$RUBY_VERSION/<wbr>$GEM_NAME-<wbr>$GEM_VERSION
renders as:
$HOME/.rbenv/versions/$RUBY_VERSION/
I prefer to use <wbr>. YMMV.
The non-breaking hyphen HTML entity (‑
) displays a hyphen character that does not break.
For CSS, use content: "\2011"
to produce a non-breaking hyphen.