HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
export.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_ARCH_EXPORT_H
8 #define PXR_BASE_ARCH_EXPORT_H
9 
10 /// \file arch/export.h
11 /// \ingroup group_arch_SymbolVisibility
12 ///
13 /// Defines symbol visibility macros.
14 ///
15 /// Defines \c ARCH_EXPORT to indicate a symbol should be exported from
16 /// a library, \c ARCH_IMPORT to indicate an exported symbol should be
17 /// imported (which only matters on Windows), and \c ARCH_HIDDEN to
18 /// indicate that a symbol which would be exported should not be.
19 ///
20 /// The correct way to use these macros is for each library to make a
21 /// header that looks like this (for some hypothetical library named foo):
22 ///
23 /// \code
24 /// #ifndef FOO_API_H
25 /// #define FOO_API_H
26 ///
27 /// #include "pxr/base/arch/export.h"
28 ///
29 /// #if defined(FOO_STATIC)
30 /// # define FOO_API
31 /// # define FOO_API_TEMPLATE_CLASS(...)
32 /// # define FOO_API_TEMPLATE_STRUCT(...)
33 /// # define FOO_LOCAL
34 /// #else
35 /// # if defined(FOO_EXPORTS)
36 /// # define FOO_API ARCH_EXPORT
37 /// # define FOO_API_TEMPLATE_CLASS(...) ARCH_EXPORT_TEMPLATE(class, __VA_ARGS__)
38 /// # define FOO_API_TEMPLATE_STRUCT(...) ARCH_EXPORT_TEMPLATE(struct, __VA_ARGS__)
39 /// # else
40 /// # define FOO_API ARCH_IMPORT
41 /// # define FOO_API_TEMPLATE_CLASS(...) ARCH_IMPORT_TEMPLATE(class, __VA_ARGS__)
42 /// # define FOO_API_TEMPLATE_STRUCT(...) ARCH_IMPORT_TEMPLATE(struct, __VA_ARGS__)
43 /// # endif
44 /// # define FOO_LOCAL ARCH_HIDDEN
45 /// #endif
46 ///
47 /// #endif
48 /// \endcode
49 ///
50 /// Note that every library has its own unique _API and _LOCAL macros and
51 /// the expansion of these macros depends on whether the library is being
52 /// built or used (indicated by the externally set macro FOO_EXPORTS).
53 ///
54 /// Library headers then include this header and mark classes, methods,
55 /// functions and variables as part of the API or local. Each case is
56 /// described below.
57 ///
58 /// A class is added to the API like this:
59 ///
60 /// \code
61 /// class FOO_API FooClass ...
62 /// \endcode
63 ///
64 /// This will add every member to the API, including implicitly created
65 /// members like a default constructor, default assignment, the vtable
66 /// and the type_info. The type_info is especially important. If you
67 /// will dynamic_cast to the type or catch an exception using the type
68 /// outside of the library, you \b must put its type_info into the API.
69 /// To export the vtable & type_info specifically, use \c ARCH_EXPORT_TYPE.
70 /// However, due to compiler limitations, ARCH_EXPORT_TYPE may put the
71 /// whole class into the API as if ARCH_EXPORT were used.
72 ///
73 /// Note that template classes do not get added to the API that way.
74 /// Instead they are added when explicitly instantiated like so:
75 ///
76 /// \code
77 /// template class FOO_API FooTemplateClass<FooArgType>;
78 /// \endcode
79 ///
80 /// It's also sometimes necessary to indicate that an instantiation exists
81 /// in the API and that a client should not do any of its own instantiation.
82 /// This is necessary, for example, when the template has static data members
83 /// and is done by using extern template in the header file that provides the
84 /// type. Two of the macros above will do that:
85 ///
86 /// \code
87 /// FOO_API_TEMPLATE_CLASS(FooTemplateClass<FooArgType>);
88 /// FOO_API_TEMPLATE_STRUCT(FooTemplateClass<FooArgType>);
89 /// \endcode
90 ///
91 /// Which you use depends on if FooTemplateClass is a class or struct. The
92 /// macro is used because we don't want to always use extern template, but
93 /// only when we're importing a dynamic library.
94 ///
95 /// A template that is completely inlined does not need to be added to the
96 /// API since it's simply instantiated where needed.
97 ///
98 /// Functions, methods and variables can also be put into the API:
99 ///
100 /// \code
101 /// struct FooLocalClass {
102 /// ~FooLocalClass();
103 /// FOO_API void MoveTheThing();
104 /// };
105 /// FOO_API FooLocalClass* FooNewThing();
106 /// FOO_API extern int doNotUseGlobalVariables;
107 /// \endcode
108 ///
109 /// Just because FooLocalClass is not in the API doesn't mean clients can't
110 /// have pointers and references to instances. What they can't do is call
111 /// member functions not in the API (or, as indicated above, use RTTI for
112 /// it). So, for example:
113 ///
114 /// \code
115 /// FooLocalClass* thing = FooNewThing();
116 /// thing->MoveTheThing();
117 /// (void)dynamic_cast<FooLocalClass*>(thing); // Link error!
118 /// delete thing; // Link error!
119 /// \endcode
120 ///
121 /// Deleting the FooLocalClass instance attempts to use the (non-API) d'tor
122 /// and fails to link. If we had an implicitly defined d'tor then the
123 /// deletion would have worked, presuming FooLocalClass didn't have any
124 /// data members with non-API d'tors.
125 ///
126 /// A method of a class added to the API is itself in the API but on some
127 /// platforms (i.e. not Windows) you can remove it from the API using
128 /// FOO_LOCAL:
129 ///
130 /// \code
131 /// struct FOO_API FooSemiAPI {
132 /// void DoSomethingPublic();
133 /// FOO_LOCAL void _DoSomethingPrivate();
134 /// };
135 /// \endcode
136 ///
137 /// Clients of the library will fail to link if they use _DoSomethingPrivate()
138 /// if FOO_LOCAL is supported. If not then the symbol will remain in the API.
139 
140 #include "pxr/base/arch/defines.h"
141 
142 #if defined(ARCH_OS_WINDOWS)
143 # if defined(ARCH_COMPILER_GCC) && ARCH_COMPILER_GCC_MAJOR >= 4 || defined(ARCH_COMPILER_CLANG)
144 # define ARCH_EXPORT __attribute__((dllexport))
145 # define ARCH_IMPORT __attribute__((dllimport))
146 # define ARCH_HIDDEN
147 # define ARCH_EXPORT_TYPE
148 # else
149 # define ARCH_EXPORT __declspec(dllexport)
150 # define ARCH_IMPORT __declspec(dllimport)
151 # define ARCH_HIDDEN
152 # define ARCH_EXPORT_TYPE
153 # endif
154 #elif defined(ARCH_COMPILER_GCC) && ARCH_COMPILER_GCC_MAJOR >= 4 || defined(ARCH_COMPILER_CLANG)
155 # define ARCH_EXPORT __attribute__((visibility("default")))
156 # define ARCH_IMPORT
157 # define ARCH_HIDDEN __attribute__((visibility("hidden")))
158 # if defined(ARCH_COMPILER_CLANG)
159 # define ARCH_EXPORT_TYPE __attribute__((type_visibility("default")))
160 # else
161 # define ARCH_EXPORT_TYPE __attribute__((visibility("default")))
162 # endif
163 #else
164 # define ARCH_EXPORT
165 # define ARCH_IMPORT
166 # define ARCH_HIDDEN
167 # define ARCH_EXPORT_TYPE
168 #endif
169 #define ARCH_EXPORT_TEMPLATE(type, ...)
170 #define ARCH_IMPORT_TEMPLATE(type, ...) extern template type ARCH_IMPORT __VA_ARGS__
171 
172 #endif // PXR_BASE_ARCH_EXPORT_H