Brian Silverman | 9d8fa39 | 2018-08-04 17:09:24 -0700 | [diff] [blame^] | 1 | [/ |
| 2 | Boost.Config |
| 3 | |
| 4 | Copyright (c) 2001 Beman Dawes |
| 5 | Copyright (c) 2001 Vesa Karvonen |
| 6 | Copyright (c) 2001 John Maddock |
| 7 | |
| 8 | Distributed under the Boost Software License, Version 1.0. |
| 9 | (See accompanying file LICENSE_1_0.txt or copy at |
| 10 | http://www.boost.org/LICENSE_1_0.txt) |
| 11 | ] |
| 12 | |
| 13 | [section Rationale] |
| 14 | |
| 15 | The problem with many traditional "textbook" implementations of configuration |
| 16 | headers (where all the configuration options are in a single "monolithic" |
| 17 | header) is that they violate certain fundamental software engineering |
| 18 | principles which would have the effect of making boost more fragile, more |
| 19 | difficult to maintain and more difficult to use safely. You can find a |
| 20 | description of the principles from the __PRINCIPLES_AND_PATTERNS_ARTICLE__. |
| 21 | |
| 22 | [section The problem] |
| 23 | |
| 24 | Consider a situation in which you are concurrently developing on multiple |
| 25 | platforms. Then consider adding a new platform or changing the platform |
| 26 | definitions of an existing platform. What happens? Everything, and this does |
| 27 | literally mean everything, recompiles. Isn't it quite absurd that adding a |
| 28 | new platform, which has absolutely nothing to do with previously existing |
| 29 | platforms, means that all code on all existing platforms needs to be |
| 30 | recompiled? |
| 31 | |
| 32 | Effectively, there is an imposed physical dependency between platforms that |
| 33 | have nothing to do with each other. Essentially, the traditional solution |
| 34 | employed by configuration headers does not conform to the Open-Closed |
| 35 | Principle: |
| 36 | |
| 37 | [: [*"A module should be open for extension but closed for modification."]] |
| 38 | |
| 39 | Extending a traditional configuration header implies modifying existing code. |
| 40 | |
| 41 | Furthermore, consider the complexity and fragility of the platform detection |
| 42 | code. What if a simple change breaks the detection on some minor platform? |
| 43 | What if someone accidentally or on purpose (as a workaround for some other |
| 44 | problem) defines some platform dependent macros that are used by the |
| 45 | detection code? A traditional configuration header is one of the most |
| 46 | volatile headers of the entire library, and more stable elements of |
| 47 | Boost would depend on it. This violates the Stable Dependencies Principle: |
| 48 | |
| 49 | [: [*"Depend in the direction of stability."]] |
| 50 | |
| 51 | After even a minor change to a traditional configuration header on one minor |
| 52 | platform, almost everything on every platform should be tested if we follow |
| 53 | sound software engineering practice. |
| 54 | |
| 55 | Another important issue is that it is not always possible to submit changes |
| 56 | to `<boost/config.hpp>`. Some boost users are currently working on platforms |
| 57 | using tools and libraries that are under strict Non-Disclosure Agreements. |
| 58 | In this situation it is impossible to submit changes to a traditional |
| 59 | monolithic configuration header, instead some method by which the user |
| 60 | can insert their own configuration code must be provided. |
| 61 | |
| 62 | [endsect] |
| 63 | |
| 64 | [section The solution] |
| 65 | |
| 66 | The approach taken by boost's configuration headers is to separate |
| 67 | configuration into three orthogonal parts: the compiler, the standard |
| 68 | library and the platform. Each compiler/standard library/platform gets |
| 69 | its own mini-configuration header, so that changes to one compiler's |
| 70 | configuration (for example) does not affect other compilers. In addition |
| 71 | there are measures that can be taken both to omit the compiler/standard |
| 72 | library/platform detection code (so that adding support to a new platform |
| 73 | does not break dependencies), or to freeze the configuration completely; |
| 74 | providing almost complete protection against dependency changes. |
| 75 | |
| 76 | [endsect] |
| 77 | |
| 78 | [endsect] |
| 79 | |
| 80 | |