1# 2# CDDL HEADER START 3# 4# The contents of this file are subject to the terms of the 5# Common Development and Distribution License (the "License"). 6# You may not use this file except in compliance with the License. 7# 8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9# or http://www.opensolaris.org/os/licensing. 10# See the License for the specific language governing permissions 11# and limitations under the License. 12# 13# When distributing Covered Code, include this CDDL HEADER in each 14# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15# If applicable, add the following below this CDDL HEADER, with the 16# fields enclosed by brackets "[]" replaced with your own identifying 17# information: Portions Copyright [yyyy] [name of copyright owner] 18# 19# CDDL HEADER END 20# 21# 22# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23# Use is subject to license terms. 24# 25 26Mapfiles and versioning in ON 27============================= 28 291.0 Objective of this README 30 31This README describes the engineering practices of creating and updating 32visible library interfaces. It describes various kinds of actions that 33typically occur as libraries are evolved, and shows how interface 34specifications are affected or updated in accordance. It tells you what 35you must do as a shared library developer if you: 36 37 1. Make interface additions to an existing library 38 - add a Public interface 39 - add a Private interface 40 2. Update an interface in an existing library 41 - remove an existing interface 42 - promote a Private interface to Public 43 - scope a Private interface to local 44 - move an interface from one library to another 45 - copy interfaces which are part of the standard to a new or 46 existing library 47 3. Introduce a new library 48 - source directory hierarchy 49 - creation of the "mapfile-vers" file 50 - Makefiles 51 4. Make an entire library obsolete before end-of-life 52 - introduce SUNWobsolete to the "mapfile-vers" file 53 54------------------------------------------------------------------------------- 55 562.0 What's a mapfile? 57 58Mapfiles are used to tell the link editor ("ld") all sorts of things about 59how to generate an executable file or a shared object from a collection of 60relocatable objects, such as generated by a compiler. For all the gory 61details, see the Solaris Linker and Libraries Guide, which can be found 62under http://docs.sun.com. 63 64Here, we are only concerned with specifying externally-visible interfaces 65for shared libraries (shared objects) and with specifying their versions 66for ABI (Application Binary Interface) purposes. For these purposes, we 67only need to deal with a subset of the mapfile interfaces. 68 69There should be a "mapfile-vers" file associated with every shared library 70and it should reside in the common source directory for that library, most 71often in a "common" directory. This is the usual layout of a library's 72top-level directory (usr/src/lib/libwombat): 73 Makefile amd64/ i386/ sparcv9/ 74 Makefile.com common/ sparc/ 75 76The "common" directory contains the source files and other common files 77for the library: 78 bat.c libwombat_impl.h mapfile-vers wom.c 79 libwombat.h llib-lwombat util.c wombat.c 80 81The mapfile's name is, by convention, "mapfile-vers" because it is used 82for only two purposes: to specify externally-visible interface names while 83suppressing visibility of all other names, and to specify their respective 84unique version names. 85 86------------------------------------------------------------------------------- 87 883.0 Contents of mapfile-vers 89 90The structure of mapfile-vers is best explained by an example 91(the license notification and copyright notice is omitted here 92for brevity): 93 94SUNW_1.2 { # update to libwombat, Solaris 10 95 global: 96 wb_readv; 97 wb_stat; 98 wb_writev; 99} SUNW_1.1; 100 101SUNW_1.1 { # first release of libwombat, Solaris 9 102 global: 103 wb_read; 104 wb_write; 105}; 106 107SUNWprivate { # private libwombat symbols 108 global: 109 wb_add; 110 wb_delete; 111 wb_search; 112 local: 113 *; 114}; 115 116The SUNW_1.* names are the Public version names for the library. 117There should be at most one version name for each release of Solaris, 118with the minor number incremented by one over the previous version. 119 120If no update to the Public-visible names in the library is made 121in a given Solaris release, no new version name should be generated 122for that release. If multiple updates are made to the library at 123different points in the development of a given release of Solaris, 124only one version should be used for the entire release. 125 126So, for example, if an update to libwombat is made in Solaris 11, 127you would add "SUNW_1.3" at the start of the mapfile: 128 129SUNW_1.3 { # update to libwombat, Solaris 11 130 global: 131 wb_lseek; 132} SUNW_1.2; 133 134Each version must inherit all symbols from its preceding version, 135specified at the ending "}" for each version. SUNW_1.1 does not 136inherit any symbols. SUNWprivate, if present, stands alone. 137 138The two lines in SUNWprivate: 139 local: 140 *; 141ensure that no symbols other than those listed in the mapfile are 142visible to clients of the library. If there is no SUNWprivate, 143these two lines should appear in SUNW_1.1. 144 145For maintainability, the list of names in each version block should 146be sorted in dictionary order (sort -d). Please comply. 147 148In addition to the common mapfile: 149 common/mapfile-vers 150some libraries require ISA-specific supplemental mapfiles, one in each 151of the ISA directories: 152 amd64/mapfile-vers 153 i386/mapfile-vers 154 sparc/mapfile-vers 155 sparcv9/mapfile-vers 156This is necessary only if there are ISA-specific library interfaces not 157common to all instances of the library. For example, see libproc, or, 158if you are masochistic, libc or libnsl. 159 160The ISA-specific mapfiles look like the common mapfile, except that only 161the ISA-specific names appear. The version names are the same as those 162in the common mapfile, but only non-empty version instances are present 163and no inheritance specification is present. The link-editor reads the 164information from the common and ISA-specific mapfiles and merges them 165in memory into a single description used to create the resulting object. 166 167------------------------------------------------------------------------------- 168 1694.0 Making interface additions to an existing library 170 1714.1 Adding a Public interface 172 173The first engineer to update the existing mapfile-vers file in a release needs 174to identify the current highest version name and properly increment the minor 175version number by 1 to be the new version name. If this is the first Public 176interface in the shared object, a new SUNW_1.1 version name must be introduced. 177 178The major revision number is incremented whenever an incompatible change is 179made to an interface. This could be the case if an API changes so dramatically 180as to invalidate dependencies. This rarely occurs in practice. It also 181requires changing the suffix of the shared object from, say, .so.1 to .so.2 182and introducing code to continue to ship the .so.1 version of the library. 183 184The minor revision number is incremented whenever one or more new interfaces 185is added to a library. Note that the minor number is not incremented on every 186putback that makes an interface addition to the library. Rather, it is 187incremented at most once per (external to Sun) release of the library. 188 1894.2 Adding a Private interface 190 191Private interfaces are the non-ABI interfaces of the library. Unlike 192introducing a Public interface, a new entry is simply added to the 193SUNWprivate version. No minor number increment is necessary. 194 195If this interface happens to be the first Private interface introduced 196into the library, the SUNWprivate version must be created (no major.minor 197version numbers). It inherits nothing and nothing inherits from it. 198 199If the library already has Private interfaces, they may have numbered version 200names like SUNWprivate_m.n (due to errors of the past). If so, just use the 201highest numbered private version name to version the new interface. There 202is no need to introduce a new private version name. Be careful not to use 203a lower numbered private version name; doing so can cause runtime errors 204(as opposed to load time errors) when running an application with older 205versions of the library. 206 207There are libraries in the OSnet consolidation that contain only private 208interfaces. In such libraries, the SUNWprivate_m.n may be incremented 209to ensure that the programs that depend on them are built and delivered as a 210integrated unit. A notable example of this is libld.so (usr/src/cmd/sgs/libld), 211which contains the implementation of the link-editor, the public interface to 212which is provided by the ld command. When making a modification to the interface 213of such a library, you should follow the convention already in place. 214 2154.3 Adding new public interfaces in an update release 216 217Adding new public interfaces in an update release requires careful 218coordination with the next marketing release currently under development. 219Multiple updates ship during the period before the next marketing release 220ships, and since it is generally impossible to know the full set of new 221interfaces in the next marketing release until late in its development 222(after multiple updates have shipped) it must be assumed that not all 223interfaces added to the next marketing release will be added to an update. 224 225Consequently, the new version number for an update cannot be a minor 226increment, but must be a micro increment. For example, if Release N 227has version number SUNW_1.3 and Release N+1 will have SUNW_1.4, then 228interfaces added to an update of Release N must have micro numbers such 229as SUNW_1.3.1, SUNW_1.3.2, etc. (note that the micro number is not 230directly tied to the update number: SUNW_1.3.1 may appear in Update 2). 231The micro versions form an inheritance chain that is inserted between 232two successive minor versions. For example, the mapfile-vers file for 233minor release "N+1" to reflect its inclusion of micro releases will 234look like the following: 235 236SUNW_1.4 { # release N+1 237 global: 238 ... 239} SUNW_1.3.2; 240 241SUNW_1.3.2 { # micro release 2 (e.g., release NU3) 242 global: 243 ... 244} SUNW_1.3.1; 245 246SUNW_1.3.1 { # micro release 1 (e.g., release NU2) 247 global: 248 ... 249} SUNW_1.3; 250 251SUNW_1.3 { # release N 252 global: 253 ... 254} SUNW_1.2; 255 256SUNW_1.2 { # release N-1 257 global: 258 ... 259} SUNW_1.1; 260 261SUNW_1.1 { # first release 262 global: 263 ... 264}; 265 266SUNW_private { # same in all releases 267 global: 268 ... 269 local: 270 *; 271}; 272 273The corresponding update/patch mapfile-vers file will be identical 274except for the exclusion of SUNW_1.4. 275 276Those interfaces which are only present in Release N+1 are always put 277into the next minor version set, SUNW_1.4. 278 279Thus when adding a new public interface to an update, both the mapfiles 280of the update release and next marketing release must be modified to be 281consistent. The update versions should not be added to the marketing 282release until the putback to the update release has occurred, to avoid 283timing problems with the update releases (it's all too easy for projects 284to slip out of updates, or to change ordering). 285 286------------------------------------------------------------------------------- 287 2885.0 How to update an interface in an existing library 289 2905.1 Removing an existing interface 291 2925.1.1 Moving a Public interface 293 294No Public interfaces should ever be removed from any mapfile. 295 296To move an interface from one library to (say) libc, the code has to be 297deleted from the library and added to libc, then the mapfile for the 298library has to have the interface's entry changed from: 299 getfoobar; 300to: 301 getfoobar = FUNCTION FILTER libc.so.1; 302See, for example, libnsl's common/mapfile-vers file. 303 304Follow the rules for adding a new interface for the necessary changes 305to libc's mapfile to accommodate the moved interface. In particular, 306the new interface must be added to the current highest libc version. 307 308To move an entire library into libc, look at what has already been done 309for libthread, libaio, and librt. 310 3115.1.2 Removing a Private interface 312 313Deletion of Private interfaces is allowed, but caution should be taken; 314it should first be established that the interface is not being used. 315To remove a Private interface, simply delete the corresponding entry 316for that symbol from the mapfile's SUNWprivate section. 317 318Do not forget to delete these Public or Private interfaces from the library's 319header files as well as from the code that implements the interfaces. 320 3215.2 Promoting a Private interface to Public 322 323This is similar to what's done when adding a Public interface. Promoting an 324existing Private interface to a Public one only requires a change to the 325existing interface definition. Private interfaces have the symbol version name 326"SUNWprivate" associated with them. To make the interface a Public one, the 327interface must be put into a set associated with the current Public release 328level of the library. 329 330As an example, if we were modifying libwombat.so.1 and its version in the 331last release of Solaris was SUNW_1.23, any new ABI introduced in the next 332release would be put into a version called SUNW_1.24. Therefore, whether 333you wish to promote an existing Private interface to Public, or to introduce 334a new Public interface, this (next successive minor numbered version level) 335would be the version that it would be associated with. 336 3375.3 Scoping a Private interface local 338 339Any interfaces not present in the mapfile-vers file will be scoped local 340due to the presence of the 341 local: 342 *; 343lines discussed earlier. This ensures that such interfaces will not be visible 344outside the library. To move an interface from Private to local scope, simply 345remove the Private interface from the mapfile-vers file and the header file 346to prevent it from being exported. This may require moving the Private 347interface into a library-private header file. Scope reduction of Public 348interfaces is not allowed without specific ARC review and approval. 349 350For the interface to be used in more than one file within the library, it 351should be in a header file that can be included by each file in the library 352that uses the interface. For example: 353 354 #include "libprivate.h" 355 3565.4 How to copy interfaces which are part of a standard to a new or existing 357 library 358 359SYSVABI and SISCD are reserved version names for interfaces listed in the 360System V Interface Definition and the Sparc Compliance Definition. Avoid using 361these version names when copying the implementation of standard interfaces to 362another library. Instead, use SUNW_1.1 for a new library, and SUNW_m.n for 363an existing library (where m.n is the next release version; i.e., if the 364last version was SUNW_1.18, then you should version the interfaces with 365SUNW_1.19). 366 367------------------------------------------------------------------------------- 368 3696.0 Introducing a new library 370 3716.1 Directories 372 373The normal discipline for introducing a new library in OS/Net is to create a 374new subdirectory of /usr/src/lib. The interface definition discipline is to 375create a common/mapfile-vers file for the new library. If we were introducing 376a new foo library, libfoo, we'd create /usr/src/lib/libfoo containing: 377 Makefile amd64/ i386/ sparcv9/ 378 Makefile.com common/ sparc/ 379The common subdirectory would contain the normal source files plus the 380mapfile-vers file. See usr/src/lib/README.Makefiles for directions on 381how to organize the Makefiles. 382 3836.2 The mapfile 384 385The new common/mapfile-vers file would contain: 386 387SUNW_1.1 { # first release of libfoo 388 global: 389 ... 390}; 391 392SUNWprivate { 393 global: 394 ... 395 local: 396 *; 397}; 398 399If there are no Public interfaces, the SUNW_1.1 section would be omitted. 400If there are no Private interfaces, the SUNWprivate section would be 401omitted and the two lines: 402 local: 403 *; 404would be moved into SUNW_1.1 405 406To decide which interfaces are Public (part of the ABI) and which are Private 407(unstable interfaces not intended to be used by third party applications or 408unbundled products), the heuristic which works to a first approximation is 409that if it has a man page then it's Public. Also, it is really the ARC case 410for the new interfaces that prescribes which interfaces are Public and 411which are not (hence, which interfaces have man pages and which do not). 412 413For maintainability, the list of names in each version block should 414be sorted in dictionary order (sort -d). Please comply. 415 416------------------------------------------------------------------------------- 417 4187.0 Make an entire library obsolete 419 4207.1 Introduce SUNWobsolete version 421 422Use this version name not for specific interfaces but for marking an entire 423library as obsolete. The existing public/private version names are left 424unchanged, but a new SUNWobsolete version is created with no symbols in it. 425This becomes a tag by which the obsolescence of the library can be recognized. 426There is no numbering of this version name. 427 428SUNWobsolete { 429 global: 430 SUNWobsolete; # This is the only way to do it. 431} SUNW_1.2; 432 433SUNW_1.2 { 434... 435 436------------------------------------------------------------------------------- 437 4388.0 Documentation 439 440For further information, please refer to the following documents: 441 442 "Solaris Linker and Libraries Guide", http://docs.sun.com 443 /shared/ON/general_docs/scoping-rules.fm.ps 444 445For information on the now-obsolete spec files, used in Solaris releases 4467 through 10, see: 447 /shared/ON/general_docs/README.spec 448 /shared/ON/general_docs/libspec-rules.ps 449 /shared/ON/general_docs/spectrans/* 450