diff --git a/docs/import_library.md b/docs/import_library.md new file mode 100644 index 00000000000..124b8f3016c --- /dev/null +++ b/docs/import_library.md @@ -0,0 +1,52 @@ + + + +# Filenames + +Mode | Import Library | DLL (VS) | DLL (GitHub) | +--------|----------------|-----------------|---------------------| +Release | `msvcprt.lib` | `msvcp140.dll` | `msvcp140_oss.dll` | +Debug | `msvcprtd.lib` | `msvcp140d.dll` | `msvcp140d_oss.dll` | + +# Import Libraries + +An import library is a `.lib` file that defines its symbols as imported from a DLL. + +Usually there is one `.lib` file for one `.dll` file, with the same name. +The names are different for MSVC because it started encoding its ABI version into the DLL's filename, +but there was no reason to change the import library's filename. + +Also, an import library usually only contains references to DLL symbols and doesn't define anything on its own. +However, this is purely a convention - nothing technically stops an import library +from containing object files that are effectively statically linked. + +## Advantages of Injecting Additional Code + +This is what the STL's import library does - it defines some functions and variables on its own. +This allows us to: + +* Extend the STL implementation without altering the DLL export surface. + + This has been critical in allowing us to implement C++17 `` and much more. +* Separately compile functions and constant data for improved throughput. + + ``'s lookup tables are a notable example. + +## Limitations + +The caveats of this technique are: + +* It effectively defeats the purpose of the `/MD` and `/MDd` options by embedding part of + the STL implementation into the resulting user binaries, rather than staying in the STL's DLL. +* Due to the duplication in each user binary that links to the import library, + variables in the import library **cannot represent shared global state**. + + This limitation is subtle (not readily apparent from the source code) and critical. + If shared global state is necessary, our only option while preserving bincompat is adding a satellite DLL. +* Due to having just two flavors of the import library (debug and release), + we cannot use anything that depends on `_CONTAINER_DEBUG_LEVEL` or `_ITERATOR_DEBUG_LEVEL`. + +For these reasons, especially the last one, we need to strictly control what is used by the import library. +In particular, `basic_string` must not be used there. + +## Core Headers + +Restricting the import library to including core headers only is an effective way to avoid problems. +`locale0.cpp`'s inclusion of `` is currently a special case and should be treated with extreme caution. diff --git a/stl/inc/xcharconv_tables.h b/stl/inc/xcharconv_tables.h index 7e43ab8b83c..1ffb2ae7624 100644 --- a/stl/inc/xcharconv_tables.h +++ b/stl/inc/xcharconv_tables.h @@ -1,4 +1,4 @@ -// xcharconv_tables.h internal header +// xcharconv_tables.h internal header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception diff --git a/stl/inc/xfacet b/stl/inc/xfacet index ee4663bbae9..6a0807d4abf 100644 --- a/stl/inc/xfacet +++ b/stl/inc/xfacet @@ -3,6 +3,10 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// This header is used to compile the import library (via locale0_implib.cpp => locale0.cpp => xfacet). +// MAJOR LIMITATIONS apply to what can be included here! +// Before editing this file, read: /docs/import_library.md + #pragma once #ifndef _XFACET_ #define _XFACET_ @@ -16,11 +20,6 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - _STD_BEGIN extern "C++" class _CRTIMP2_PURE_IMPORT _Facet_base { // code for reference counting a facet public: diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 4f9cf55d90d..59107cf8135 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -3,6 +3,10 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// This header is used to compile the import library (via locale0_implib.cpp => locale0.cpp => xfacet => yvals.h). +// MAJOR LIMITATIONS apply to what can be included here! +// Before editing this file, read: /docs/import_library.md + #pragma once #ifndef _YVALS #define _YVALS diff --git a/stl/src/charconv.cpp b/stl/src/charconv.cpp index f400a440854..cae8561b4ba 100644 --- a/stl/src/charconv.cpp +++ b/stl/src/charconv.cpp @@ -1,11 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include // Generated by /tools/scripts/charconv_generate.cpp diff --git a/stl/src/filesystem.cpp b/stl/src/filesystem.cpp index ce0819b010b..959f40be8fd 100644 --- a/stl/src/filesystem.cpp +++ b/stl/src/filesystem.cpp @@ -4,11 +4,6 @@ // filesystem.cpp -- C++17 implementation // (see filesys.cpp for implementation) -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include #include #include diff --git a/stl/src/format.cpp b/stl/src/format.cpp index 66a999bda33..67a91356a9d 100644 --- a/stl/src/format.cpp +++ b/stl/src/format.cpp @@ -3,11 +3,6 @@ // Implements a win32 API wrapper for -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include <__msvc_xlocinfo_types.hpp> #include diff --git a/stl/src/locale0.cpp b/stl/src/locale0.cpp index cc3e7be9bf9..62d0fc647fb 100644 --- a/stl/src/locale0.cpp +++ b/stl/src/locale0.cpp @@ -3,16 +3,15 @@ // class locale basic member functions +// This file is compiled into the import library (via locale0_implib.cpp => locale0.cpp). +// MAJOR LIMITATIONS apply to what can be included here! +// Before editing this file, read: /docs/import_library.md + #include #include #include #include -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - // This should probably go to a compiler section just after the locks - unfortunately we have per-appdomain // and per-process variables to initialize #pragma warning(disable : 4073) diff --git a/stl/src/print.cpp b/stl/src/print.cpp index 02ae5d6fa41..74819b8f3b5 100644 --- a/stl/src/print.cpp +++ b/stl/src/print.cpp @@ -3,11 +3,6 @@ // print.cpp -- C++23 implementation -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include <__msvc_print.hpp> #include #include diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index d506db98edd..b678cf8c724 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -3,11 +3,6 @@ #include -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - // these declarations must be in sync with those in xthreads.h using _Smtx_t = void*; diff --git a/stl/src/stacktrace.cpp b/stl/src/stacktrace.cpp index 6d77f1084c7..7dfae0d0b5d 100644 --- a/stl/src/stacktrace.cpp +++ b/stl/src/stacktrace.cpp @@ -1,11 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include #include diff --git a/stl/src/syserror_import_lib.cpp b/stl/src/syserror_import_lib.cpp index 31fdb7573db..7ffc78d7288 100644 --- a/stl/src/syserror_import_lib.cpp +++ b/stl/src/syserror_import_lib.cpp @@ -1,11 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include <__msvc_system_error_abi.hpp> #include diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index a38d93c281f..71313054d46 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -1,11 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #ifdef _M_CEE_PURE #error _M_CEE_PURE should not be defined when compiling vector_algorithms.cpp. #endif diff --git a/stl/src/xcharconv_ryu_tables.cpp b/stl/src/xcharconv_ryu_tables.cpp index f116ddbe111..e8a7dd260d5 100644 --- a/stl/src/xcharconv_ryu_tables.cpp +++ b/stl/src/xcharconv_ryu_tables.cpp @@ -30,11 +30,6 @@ // DEALINGS IN THE SOFTWARE. -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include namespace std { diff --git a/stl/src/xcharconv_tables_double.cpp b/stl/src/xcharconv_tables_double.cpp index 00f53c5bc8a..a9f348ab5ab 100644 --- a/stl/src/xcharconv_tables_double.cpp +++ b/stl/src/xcharconv_tables_double.cpp @@ -1,11 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include namespace std { diff --git a/stl/src/xcharconv_tables_float.cpp b/stl/src/xcharconv_tables_float.cpp index abe60e416c1..c68de40447d 100644 --- a/stl/src/xcharconv_tables_float.cpp +++ b/stl/src/xcharconv_tables_float.cpp @@ -1,11 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - #include namespace std { diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 17c9a3c3a76..e90c6236025 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -6,11 +6,6 @@ #include #include -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - // Provides forwarders for InitOnceBeginInitialize and InitOnceComplete for // environments that can't use /ALTERNATENAME. // They were originally specific to /clr but are now used in other scenarios. diff --git a/tests/std/tests/GH_001411_core_headers/test.cpp b/tests/std/tests/GH_001411_core_headers/test.cpp index f2004ac7b63..0d5907989c5 100644 --- a/tests/std/tests/GH_001411_core_headers/test.cpp +++ b/tests/std/tests/GH_001411_core_headers/test.cpp @@ -15,6 +15,7 @@ #include #if _HAS_CXX17 +#include #include #endif // _HAS_CXX17