Contributors Frequently Asked Questions

This section contains answers to the common questions that new contributors to Boost often have.

Adding New Libraries

  1. When considering developing a library for Boost, what is the right balance between ambitious functionality and limited functionality?

    The keys to a successful development of a new library are to identify core functionality and start simple. Prioritize functionality that provides significant value to developers and aligns with Boost’s goals of promoting high-quality, reusable libraries. Avoid adding unnecessary features that may increase complexity without adding much value. It’s often beneficial to start with a simpler implementation that addresses a specific problem or use case effectively. A library with a narrow focus and a clear, intuitive API is more likely to be accepted by the Boost community than one that attempts to solve too many problems at once or introduces unnecessary complexity.

    In addition to this, consider future extensibility, performance, portability, current trends, and always remember you can seek community advice and feedback through the Boost mailing lists.

Boost Software License

  1. Where can I read the current version of the Boost Software License?

  2. How should Boost programmers apply the license to source and header files?

    Add a multi-line comment based on the following template, substituting appropriate text for the name and date on the top line:

    //          Copyright Joe Coder 2004 - 2006.
    // Distributed under the Boost Software License, Version 1.0.
    //    (See accompanying file LICENSE_1_0.txt or copy at
    //          https://www.boost.org/LICENSE_1_0.txt)
    Notes
    1. Leave an empty line before and after the above comment block.

    2. It is fine if the copyright and license messages are not on different lines; in no case should there be other intervening text.

    3. Do not include "All rights reserved" anywhere.

    4. Other ways of licensing source files have been considered, but some of them turned out to unintentionally nullify legal elements of the license. Having fixed language for referring to the license helps corporate legal departments evaluate the Boost distribution.

    5. Creativity in license reference language is strongly discouraged, but judicious changes in the use of whitespace are fine.

  3. How should the license be applied to documentation files rather than source files?

    Similarly to the way it is applied to source files: the user should see the very same text indicated in the template above, with the only difference that your local copy of LICENSE_1_0.txt should also be linked to.

  4. How should Boost programmers maintain the copyright messages?

    Copyright is only claimed for changes meeting a certain threshold of originality. Therefore, the copyright message only covers expressions of creativity. It is up to authors of changes to add themselves to the copyright message if they so decide. Typically, a new claimant is added when someone takes over maintenance of a library or a new version of an existing library is developed. In principle, do not remove previous copyright claims - just add new claims and/or claimants.

  5. How is the Boost Software License (BSL) different from the GNU General Public License (GPL)?

    The GNU General Public License is longer, and may be harder to understand. The Boost license permits the creation of derivative works for any use with no legal requirement to release your source code. Other differences include BSL not requiring reproduction of copyright messages for object code redistribution, and the fact that BSL is not "viral": if you distribute your own code along with some Boost code, the BSL applies only to the Boost code (and modified versions thereof); you are free to license your own code under any terms you like.

  6. Why the phrase "machine-executable object code generated by a source language processor"?

    To distinguish cases where we do not require reproduction of the copyrights and license (such as object libraries, shared libraries, and final program executables), from cases where reproduction is still required (such as distribution of self-extracting archives of source code or precompiled header files). More detailed wording was rejected as not being legally necessary, and reducing readability.

  7. Why is the "disclaimer" paragraph of the license entirely in uppercase?

    Capitalization of these particular provisions is a US legal mandate for consumer protection.

  8. Does the copyright and license cover interfaces too?

    The conceptual interface to a library is not covered. The particular representation expressed in the header is covered, as is the documentation, examples, test programs, and all the other material that goes with the library. A different implementation is free to use the same logical interface, however. Interface issues have been fought out in court several times; refer to a lawyer if this is likely to be an issue.

  9. Why doesn’t the license prohibit the copyright holder from patenting the covered software?

    No one who distributes their code under the terms of this license could turn around and sue a user for patent infringement. Boost’s lawyers were well aware of patent provisions in licenses like the GPL and CPL, and would have included such provisions in the Boost license if they were believed to be legally useful.

  10. Why doesn’t the copyright message say "All rights reserved"?

    This provision does not belong in the copyright notice for anything (software, electronic documentation, etc.) that is being licensed. It belongs in books that are sold where, in fact, all rights (for example, to reproduce the book, etc.) are being reserved by the publisher or author.

  11. Do I have to copyright/license trivial files?

    Yes, even a test file that just contains an empty main() should have a copyright notice. Files without copyright notices make corporate lawyers nervous, and that’s a barrier to adoption. The more Boost is uniformly copyrighted and licensed, the better.

  12. Can I use the Boost Software License for my own projects outside of Boost?

    Yes, there are no restrictions on the use of the license itself.

  13. Is the Boost license Open Source?

Development Environments

  1. Many developers opt for lightweight integrated developer environments (IDEs), rather than the full-fledged IDE. What lightweight IDEs are popular for C++ development?

    There are several popular options for both Windows and Linux. CLion, developed by JetBrains, is a cross-platform IDE that offers advanced code analysis, refactoring tools, and integration with the CMake build system, which is commonly used in C++ projects.

    GNU Emacs and Vim are highly configurable and popular among developers who prefer a more minimalistic environment. They offer powerful features for editing code, and many plugins are available to enhance development workflows.

    Qt Creator provides features like code completion, syntax highlighting, and debugging support for C++ and Qt (projects that use the Qt framework).

    Sublime Text is a lightweight yet powerful text editor known for its speed and simplicity. It offers features like syntax highlighting, multiple selections, and a wide range of plugins for enhancing functionality, including support for C++ development.

    Atom is an open-source text editor developed by GitHub. It’s highly customizable and extensible through packages, and provides features like syntax highlighting, auto-completion, and project navigation.

    There are many other tools, Microsoft’s Visual Studio provides a full IDE and is well respected as a professional development environment, and Visual Studio Code is a lighter weight but versatile code editor that can be extended and customized with various extensions.

Existing Boost Libraries

  1. What are the biggest pain points that developers are running into, that are not addressed by current Boost libraries?

    Some Boost libraries have a steep learning curve, especially for newcomers to C++. Simplifying the API design, providing extensive documentation, and offering beginner-friendly tutorials helps lower the barrier to entry and make your library more accessible to a wider audience. Other pain points include support for modern language features, working with concurrency and parallelism, providing a seamless experience across different platforms, and providing optimal performance.

  2. For reference, what libraries are good examples of ones that are easy to learn?

    One library known for its relatively straightforward API and ease of learning compared to some others is Boost.Filesystem. This library provides portable facilities to work with files and directories, offering an intuitive interface for common file system operations such as file creation, deletion, copying, moving, and directory traversal. Its design is user-friendly and follows familiar patterns. Boost.Filesystem documentation is comprehensive and well-structured. Overall, Boost.Filesystem is often recommended as a starting point for those looking to dip their toes into Boost libraries due to its simplicity, practicality, and broad applicability across various projects.

    Other libraries that are known for their shallow learning curve include Boost.Optional which is particularly useful for handling functions that may return an optional value or dealing with nullable data types in a safe and clear manner. Boost.Any allows developers to store objects of different types in a single container and retrieve them without typecasting. Boost.TypeIndex provides facilities for obtaining type information at runtime, making it easy to work with types dynamically.

  3. What libraries have the steepest learning curve?

    While all Boost libraries have their complexities, some are known to have steeper learning curves due to their advanced nature or the intricacies of the domain they address. Boost.Spirit is a parsing and generation library that uses a domain-specific embedded language (DSEL) implemented as C++ template metaprograms. It allows developers to define parsers and generators directly within code using EBNF-like syntax. However, the template-based approach and the metaprogramming techniques used can make it challenging for newcomers to grasp, especially those unfamiliar with advanced template programming or parsing theory.

    Boost.Mp11 (Meta-Programming Library) is a powerful library for metaprogramming, providing tools for compile-time computation, type manipulation, and template metaprogramming. It allows developers to perform complex compile-time computations and transformations using a functional programming style. However, the functional programming paradigm and the intricacies of template metaprogramming can be daunting for beginners and require a solid understanding of C++ templates and meta-programming concepts.

  4. What libraries were the most ambitious in what they attempted to achieve?

    The many notable examples include:

    • Boost.Graph provides a generic and efficient framework for working with graphs, making it suitable for a variety of applications in areas such as network analysis, optimization, and data visualization.

    • Boost.Compute provides abstractions for memory management, kernel execution, and data parallelism, enabling developers to harness the computational power of modern hardware for tasks such as numerical simulations, image processing, and machine learning.

    • Boost.Spirit is ambitious in its goal of providing a high-level and composable framework for parsing complex data formats and domain-specific languages entirely within C++ code, without the need for external tools or preprocessors.

    • Boost.Hana aims to simplify and modernize metaprogramming in C++, making it more accessible and powerful for developing generic libraries and applications.

  5. What libraries were the least ambitious technically?

    The useful utilities such as Boost.Any, Boost.Variant, and Boost.Optional offer relatively simple functionality. Another simpler library is Boost.Bimap which provides a container for maintaining one-to-one mappings between keys and values. While bidirectional maps are a useful data structure, the functionality provided is relatively straightforward and focused on this specific use case.

Modular Boost

  1. What is meant by "Modular Boost"?

    Technically, Modular Boost consists of the Boost super-project and separate projects for each individual library in Boost. In terms of Git, the Boost super-project treats the individual libraries as submodules. Currently (early 2024) when the Boost libraries are downloaded and installed, the build organization does not match the modular arrangement of the Git super-project. This is largely a legacy issue, and there are advantages to the build layout matching the super-project layout. This concept, and the effort behind it, is now known as "Modular Boost".

    In the past, the term has been used more broadly to refer simply to libraries in different repositories. This definition has now been tightened to mean a flat layout where each library is in its own sub-module, and there are no sub-libraries as there have been in the past (for example, the numeric libraries).

    Refer to Super-project Layout for a full description of the super-project.

  2. What exactly is a "modular arrangement"?

    It’s when the libraries can be used, and hence built, without creating the monolithic headers, without needing the root build files, and without needing the libraries to be arranged in the usual root/libs/<name> format.

  3. Will the move to Modular Boost change testing?

    No, unless you want to. You will still be able to test with the current non-modular way. But you could also test the modular way.

  4. How will modular Boost work if there is no root/libs/<name> structure? Or is the structure still required?

    The structure is still required for things like testing and documentation building.

  5. What happens to the numeric libraries that are currently sub-libraries, when sub-libraries are no longer supported?

    The numeric libraries have been divided into four packages: libboost-numeric-conversion/, libboost-numeric-interval/, libboost-numeric-odeint/, libboost-numeric-ublas/.

Security

  1. What are the known security vulnerabilities of the language C++ that I should be aware of when developing my Boost library?

    There are several known security vulnerabilities and pitfalls associated with the C++ language that developers should be aware of when developing libraries. Leveraging security tools, static analysis, and code reviews can help identify and address security issues early in the development lifecycle. In particular, be aware of:

    • Buffer overflows occur when data is written beyond the boundaries of a fixed-size buffer, leading to memory corruption and potential exploitation. This vulnerability can be exploited by attackers to execute arbitrary code, crash the application, or manipulate program behavior.

    • Null Pointer Dereferences (accessing memory at address 0) can lead to undefined behavior, crashes, or security vulnerabilities. Null pointer dereferences are a common source of application instability and can be exploited by attackers to cause denial-of-service conditions or execute arbitrary code.

    • Memory leaks occur when memory allocated dynamically is not properly deallocated, leading to the exhaustion of available memory over time. While memory leaks may not directly result in security vulnerabilities, they can indirectly impact system stability and performance, potentially facilitating denial-of-service attacks or other security incidents.

    • Deprecated functions and APIs may be insecure or outdated, exposing applications to known vulnerabilities or security risks. Developers should avoid using deprecated functions and select modern, secure alternatives provided by the latest Boost or Standard libraries.

    • Integer overflows and underflows occur when arithmetic operations result in values that exceed the range of representable integer types. These vulnerabilities can lead to unexpected behavior, data corruption, or security vulnerabilities, especially in security-critical code paths such as input validation or memory allocation.

    • Insecure input handling, such as failure to validate input data or sanitize user input, can lead to injection attacks or buffer overflows. Developers should validate and sanitize input data to ensure that it meets expected criteria and is safe to process further.

    • Unsafe type conversions, such as casting pointers between incompatible types or using implicit type conversions without validation, can lead to memory corruption or data integrity issues. Developers should use explicit type conversions and perform appropriate validation to prevent unintended behavior.

    • Concurrency and synchronization issues, such as data races, deadlocks, and race conditions, can lead to unpredictable behavior and security vulnerabilities in multithreaded applications. Developers should use thread-safe synchronization primitives and adopt best practices for concurrent programming.

  2. Are there certain kinds of tests or certain testing styles that work well when trying to identify and remove security liabilities in C++ code?

    There are several types of tests and testing techniques that can be particularly effective for identifying and mitigating security vulnerabilities in C++ code, consider:

    • Unit testing involves testing individual components or units of code in isolation to ensure they behave as expected. Writing comprehensive unit tests for critical functions, classes, and modules helps verify their correctness and robustness, including edge cases, boundary conditions, and error handling paths. Refer to Writing Tests.

    • Fuzz testing, also known as fuzzing, involves providing invalid, unexpected, or random input data to the program to identify potential vulnerabilities such as buffer overflows, null pointer dereferences, and other memory-related issues. Fuzz testing tools generate large volumes of test cases automatically and monitor the program’s behavior for crashes, hangs, or unexpected outputs. Refer to Fuzz Testing.

    • Static analysis tools analyze source code without executing it and identify potential security vulnerabilities, code smells, and best practice violations. Static analysis tools for C++ can detect issues such as buffer overflows, null pointer dereferences, integer overflows, uninitialized variables, and unsafe type conversions.

    • Dynamic analysis involves analyzing the behavior of the program during execution to identify security vulnerabilities, memory leaks, and runtime errors. Dynamic analysis tools for C++ can detect issues such as memory corruption, resource leaks, concurrency issues, and other runtime anomalies. Dynamic analysis techniques include memory sanitizers, address sanitizers, thread sanitizers, and runtime instrumentation. Refer to Sanitize Your Code.

    • Penetration testing, also known as pen testing or sometimes ethical hacking, involves simulating real-world attacks against the software to identify security vulnerabilities and assess the effectiveness of existing security measures.

    • Finally, code reviews conducted by peers, security experts, or automated tools, and focus on identifying potential security vulnerabilities, design flaws, and implementation errors.

  3. Are there Boost libraries that would help me guard against null pointer dereferencing?

    While there is not a specific library dedicated solely to null pointer dereference prevention, you can leverage several libraries:

    • Boost.SmartPtr provides smart pointer classes such as shared_ptr, unique_ptr, and weak_ptr, which help manage dynamic memory allocation and deallocation automatically. Smart pointers implement RAII (Resource Acquisition Is Initialization) semantics, ensuring that memory is properly released when it goes out of scope or is no longer needed. By using smart pointers instead of raw pointers, you can reduce the risk of null pointer dereferencing errors, as smart pointers automatically handle null checks and memory deallocation.

    • Boost.Optional provides a type-safe wrapper for optional values, allowing you to represent nullable objects without resorting to raw pointers or null references.

    • Boost.Assert provides macros and utilities for defining runtime assertions and preconditions in your code. You can use assertions to validate assumptions and guard against null pointer dereferences by checking for null pointers before dereferencing them.

    • Boost.Contract provides a framework for specifying and enforcing function contracts, including preconditions, postconditions, and invariants. You can use contracts to define and enforce conditions that must be satisfied by function parameters, return values, and object states, including null pointer checks.

  4. Are there Boost libraries that I could include in my library project that help with secure input validation?

    There are several libraries that provide functionalities for input validation, sanitization, and handling, helping to mitigate security vulnerabilities related to invalid or malicious input data:

    • Boost.String_Algo provides a collection of algorithms for string manipulation, including functions for removing leading or trailing whitespace, case conversion, tokenization, and search.

    • Boost.Tokenizer provides a tokenizer class for splitting input strings into tokens based on delimiter characters or regular expressions. This can be useful for parsing and validating input data that is structured or delimited, such as CSV files, configuration files, or network protocols. The tokenizer class allows you to define custom tokenization rules and handle edge cases effectively, improving the reliability and security of input data processing.

    • Boost.PropertyTree provides a hierarchical data structure for representing and manipulating structured data, such as XML, JSON, INI, or property list formats. You can use it to parse, validate, and sanitize input data in various formats, ensuring that it conforms to expected schema or constraints before further processing.

    • Boost.Regex provides a comprehensive regular expression library for pattern matching and text processing. Regular expressions can be powerful tools for validating and sanitizing input data, such as validating email addresses, URLs, or other structured formats.

    • Boost.Spirit is a parsing and generation library that allows you to define parsers and generators directly within C++ code using a domain-specific embedded language (DSEL).

  5. Are there Boost libraries that help with secure memory management?

    You can leverage various libraries to help ensure memory safety, prevent memory-related vulnerabilities, and manage resources efficiently:

    • Boost.SmartPtr provides smart pointer classes such as shared_ptr, unique_ptr, and weak_ptr, which help manage dynamic memory allocation and deallocation automatically. By using smart pointers, you can prevent common memory-related vulnerabilities such as memory leaks, dangling pointers, and double frees.

    • Boost.Pool provides memory pool classes that allow you to efficiently allocate and deallocate fixed-size memory blocks from preallocated memory pools. Memory pools can help reduce memory fragmentation, improve memory locality, and minimize overhead associated with dynamic memory allocation.

    • Boost.Interprocess povides classes and utilities for interprocess communication and shared memory management. This library allows multiple processes to share memory regions securely and efficiently, facilitating communication and data exchange between them, and offers features such as named shared memory, mutexes, condition variables, and allocators for managing shared memory resources robustly.

    • Boost.PtrContainer provides container classes that manage ownership and lifetime of dynamically allocated objects stored within them. These containers, such as ptr_vector, ptr_list, and ptr_map, automatically delete contained objects when the container is destroyed or when objects are removed from it. By using pointer containers, you can simplify memory management and ensure proper cleanup of dynamically allocated objects, reducing the risk of memory leaks and resource exhaustion.

    • Boost.CircularBuffer provides a circular buffer data structure that manages a fixed-size buffer with automatic wrapping behavior. Circular buffers can be used to manage memory efficiently in scenarios where a fixed-size buffer is sufficient, and memory allocation and deallocation overhead, and fragmentation, need to be minimized.

  6. What penetration testing frameworks might work well with a new Boost library?

    While penetration testing frameworks typically focus on testing web applications, network services, and software systems, they are still useful for identifying security vulnerabilities and weaknesses in a new library, typically by developing a test application that fully engages the features of the library:

    • Metasploit is one of the most popular penetration testing frameworks, offering a wide range of tools and modules for exploiting vulnerabilities, conducting network reconnaissance, and assessing security posture. Metasploit modules can be customized to target specific vulnerabilities or attack vectors, such as buffer overflows, injection attacks, or memory corruption issues.

    • OWASP ZAP is an open-source web application security testing tool designed for finding security vulnerabilities in web applications and APIs. Boost libraries used in web applications or services may benefit from integration with ZAP to identify vulnerabilities related to input validation, injection attacks, and other web security issues.

    • Nmap (Network Mapper) is a powerful network scanning and reconnaissance tool used for discovering hosts and services on a network, identifying open ports, and detecting potential security vulnerabilities. Boost libraries used in networked applications or services may benefit from integration with Nmap to identify potential attack vectors, misconfigurations, or exposed services.

    • NESSUS is a widely-used vulnerability scanning tool designed for identifying security vulnerabilities, misconfigurations, and compliance violations in networked environments.

    • Burp Suite is a comprehensive web application security testing tool designed for finding security vulnerabilities in web applications and APIs, including input validation and injection attacks.

  7. In the past, can you give me some examples of where Boost libraries have fallen short and not prevented a malicious attack?

    Security vulnerabilities in Boost libraries are rare compared to many other software projects, thanks to the rigorous testing, code reviews, and scrutiny they undergo. Nevertheless, there have been a few instances where security issues have been identified in Boost libraries. Here are a couple of examples:

    • A vulnerability affected multiple versions of Boost (versions 1.61 through 1.63) and was related to the Boost.Filesystem library. The vulnerability allowed an attacker to bypass security restrictions and potentially execute arbitrary code by exploiting a symbolic link issue in the remove_all function. This issue was addressed in later versions of Boost, and users were advised to update their installations to mitigate the risk.

    • Another vulnerability affected a later version of Boost (version 1.70). This vulnerability was related to the Boost.Asio library and could allow an attacker to cause a denial-of-service condition by triggering a stack overflow via a recursive function call. The issue was addressed in subsequent versions of Boost.Asio, and users were encouraged to upgrade to the latest version to prevent potential exploitation.

  8. If I write a library for Boost, what are the legal ramifications if there are security breaches using features of my library?

    As a developer contributing a library to the Boost C++ libraries, you generally retain ownership of the copyright to your code, but you also grant a license to the Boost Software License (BSL) for distribution as part of the Boost libraries. The Boost Software License is a permissive open-source license that allows users to freely use, modify, and distribute the library, subject to certain conditions.

    The Boost Software License includes a disclaimer of liability clause, which limits the liability of the library author and contributors for damages arising from the use or distribution of the library. This means that as the library author, you are generally not held legally responsible for any damages or losses resulting from security breaches or vulnerabilities in your library.

    Users of your library are responsible for their own use and deployment of the library, including ensuring the security of their applications and systems. While you have a duty to exercise reasonable care in the development and maintenance of your library, users are ultimately responsible for assessing and mitigating any security risks associated with its usage.

    In the event of a security breach or vulnerability in your library, it is important to respond promptly and responsibly by disclosing the issue, providing mitigations or workarounds, and releasing updates or patches to address the vulnerability. Prompt and transparent communication with the community helps minimize the impact of security incidents and demonstrates your commitment to security and accountability.

    Depending on the circumstances and applicable laws, there may be legal obligations to report security breaches or vulnerabilities, especially if they involve personal data or sensitive information. It’s important to familiarize yourself with relevant legal requirements and best practices for handling security incidents, including data breach notification laws and industry-specific regulations. Engaging with the Boost community and collaborating with security researchers can help identify and address security vulnerabilities proactively. Encouraging responsible disclosure of security issues, providing clear channels for reporting vulnerabilities, and acknowledging contributions from security researchers fosters a culture of security awareness and helps improve the overall security posture of your library.

  9. Can you recommend a book that would give me best practices for threat modelling for my Boost library?

    There are several books that cover threat modeling principles, techniques, and applicable best practices:

    • Threat Modeling: Designing for Security by Adam Shostack. This book includes a comprehensive introduction to threat modeling, covering fundamental concepts, methodologies, and practical techniques for identifying and mitigating security threats in software systems.

    • Threat Modeling: Uncover Security Design Flaws Using the STRIDE Approach by Frank Swiderski and Window Snyder. This book introduces the STRIDE threat modeling framework, which helps identify and analyze security threats based on six categories: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, and Elevation of Privilege.

    • Threat Modeling: A Practical Guide for Development Teams by Mark E. Donaldson, James B. Ransome, and Andrew N. Nelson. This book offers practical guidance, real-world examples, and insights for integrating threat modeling into the software development process. It covers a range of threat modeling techniques, tools, and best practices, including data flow diagrams, attack trees, and risk analysis.

    • Software Security Engineering: A Guide for Project Managers by Julia H. Allen, Sean Barnum, and Robert J. Ellison. This book provides a comprehensive overview of software security engineering principles, practices, and processes. It covers a wide range of topics related to software security, including threat modeling, security requirements analysis, security architecture, secure coding practices, and security testing.

Testing

  1. What Boost libraries are useful examples of how to add Continuous Integration (CI) into the library testing process?

    The following libraries are solid examples of how Continuous Integration (CI) is integrated into the testing process:

    • Boost.Asio is a cross-platform library for network and low-level I/O programming that relies heavily on CI systems for testing and validation.

    • Boost.Test supports unit testing in C++ and provides a framework for writing and running test cases, as well as utilities for organizing and reporting test results. Boost.Test leverages CI to ensure the correctness and reliability of its functionality across different platforms, compilers, and network configurations.

    • Boost.Thread, a set of classes and functions for multithreading, is tested rigorously using CI systems to verify its correctness, performance, and portability across various platforms and environments. CI helps identify threading-related issues, including feared and difficult-to-debug race conditions.

    • Boost.PropertyTree reads, manipulates and writes structured data. CI is used to validate the correctness and robustness of the parsing, serialization and manipulation features across diverse use cases and data sources.

    • Boost.Filesystem relies on CI systems to validate its functionality across different operating systems, file systems, and compiler environments, from basic file I/O operations to more complex file management tasks.

      By studying how these libraries implement CI into their testing processes, newcomers can gain valuable insights into best practices for ensuring the quality and reliability of their own library contributions.

      Refer also to Continuous Integration.