/ lib / product.py
product.py
  1  # This source file is part of the Swift.org open source project
  2  #
  3  # Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
  4  # Licensed under Apache License v2.0 with Runtime Library Exception
  5  #
  6  # See http://swift.org/LICENSE.txt for license information
  7  # See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  8  #
  9  
 10  from .config import Configuration
 11  from .phases import CompileC
 12  from .phases import CompileCxx
 13  from .phases import Assemble
 14  from .phases import BuildAction
 15  from .phases import MergeSwiftModule
 16  from .target import OSType
 17  from .path import Path
 18  
 19  import os
 20  
 21  class Product(BuildAction):
 22      name = None
 23      product_name = None
 24      phases = []
 25      installed_headers = []
 26      CFLAGS = None
 27      CXXFLAGS = None
 28      LDFLAGS = None
 29      ASFLAGS = None
 30      SWIFTCFLAGS = ""
 31      needs_stdcxx = False
 32      needs_objc = False
 33      GCC_PREFIX_HEADER = None
 34      PUBLIC_HEADERS_FOLDER_PATH = os.path.join("usr", "include")
 35      PUBLIC_MODULE_FOLDER_PATH = os.path.join("usr", "include")
 36      PRIVATE_HEADERS_FOLDER_PATH = os.path.join("usr", "local", "include")
 37  
 38      def __init__(self, name):
 39          self.name = name
 40  
 41      def generate(self):
 42          generated = "\n\n"
 43          for phase in self.phases:
 44              generated += phase.generate()
 45          return generated
 46  
 47      def add_phase(self, phase):
 48          phase.set_product(self)
 49          if len(self.phases) > 0:
 50              phase.previous = self.phases[-1]
 51          self.phases.append(phase)
 52  
 53      @property
 54      def product(self):
 55          return Configuration.current.build_directory.path_by_appending(self.name).path_by_appending(self.product_name)
 56  
 57      @property
 58      def public_module_path(self):
 59          return Path.path(Configuration.current.build_directory.path_by_appending(self.name).absolute() + "/" + self.PUBLIC_MODULE_FOLDER_PATH)
 60  
 61      @property
 62      def public_headers_path(self):
 63          return Path.path(Configuration.current.build_directory.path_by_appending(self.name).absolute() + "/" + self.PUBLIC_HEADERS_FOLDER_PATH)
 64  
 65      @property
 66      def private_headers_path(self):
 67          return Path.path(Configuration.current.build_directory.path_by_appending(self.name).absolute() + "/" + self.PRIVATE_HEADERS_FOLDER_PATH)
 68  
 69      @property
 70      def project_headers_path(self):
 71          return Path.path(Configuration.current.build_directory.path_by_appending(self.name).absolute() + "/" + self.PROJECT_HEADERS_FOLDER_PATH)
 72  
 73  class Library(Product):
 74      runtime_object = ''
 75      rule = None
 76      def __init__(self, name):
 77          Product.__init__(self, name)
 78  
 79      def generate(self, flags, objects = []):
 80          generated = ""
 81          if len(objects) == 0:
 82              generated = Product.generate(self)
 83              for phase in self.phases:
 84                  objects += phase.objects
 85  
 86          product_flags = " ".join(flags)
 87          if self.LDFLAGS is not None:
 88              product_flags += " " + self.LDFLAGS
 89          if self.needs_stdcxx:
 90              product_flags += " -lstdc++"
 91  
 92          generated += """
 93  build """ + self.product.relative() + """: """ + self.rule + """ """ + self.runtime_object + """ """ + " ".join(objects) + """ """ + self.generate_dependencies() + """
 94      flags = """ + product_flags
 95          if self.needs_objc:
 96              generated += """
 97      start = ${TARGET_BOOTSTRAP_DIR}/usr/lib/objc-begin.o 
 98      end = ${TARGET_BOOTSTRAP_DIR}/usr/lib/objc-end.o
 99  """
100  
101          generated += """
102  
103  build """ + self.product_name + """: phony | """ + self.product.relative() + """
104  
105  default """ + self.product_name + """
106  
107  """
108  
109          return objects, generated
110  
111  
112  class DynamicLibrary(Library):
113      def __init__(self, name, uses_swift_runtime_object = True):
114          Library.__init__(self, name)
115          self.name = name
116          self.uses_swift_runtime_object = uses_swift_runtime_object
117  
118      def generate(self, objects = []):
119          self.rule = "Link"
120          self.product_name = Configuration.current.target.dynamic_library_prefix + self.name + Configuration.current.target.dynamic_library_suffix
121          if (Configuration.current.target.sdk == OSType.Linux or Configuration.current.target.sdk == OSType.FreeBSD) and self.uses_swift_runtime_object:
122              self.runtime_object = '${SDKROOT}/lib/swift/${OS}/${ARCH}/swiftrt.o'
123              return Library.generate(self, ["-shared", "-Wl,-soname," + self.product_name, "-Wl,--no-undefined"], objects)
124          else:
125              return Library.generate(self, ["-shared"], objects)
126  
127  
128  class Framework(Product):
129      def __init__(self, name):
130          Product.__init__(self, name)
131          self.product_name = name + ".framework"
132  
133      @property
134      def public_module_path(self):
135          return Configuration.current.build_directory.path_by_appending(self.name).path_by_appending(self.product_name).path_by_appending("Modules")
136  
137      @property
138      def public_headers_path(self):
139          return Configuration.current.build_directory.path_by_appending(self.name).path_by_appending(self.product_name).path_by_appending("Headers")
140  
141      @property
142      def private_headers_path(self):
143          return Configuration.current.build_directory.path_by_appending(self.name).path_by_appending(self.product_name).path_by_appending("PrivateHeaders")
144  
145      def generate(self):
146          generated = Product.generate(self)
147          objects = []
148          for phase in self.phases:
149              objects += phase.objects
150          product_flags = "-shared -Wl,-soname," + Configuration.current.target.dynamic_library_prefix + self.name + Configuration.current.target.dynamic_library_suffix + " -Wl,--no-undefined"
151          if self.LDFLAGS is not None:
152              product_flags += " " + self.LDFLAGS
153          if self.needs_stdcxx:
154              product_flags += " -lstdc++"
155  
156          generated += """
157  
158  build """ + self.product.path_by_appending(self.name).relative() + """: Link """ + " ".join(objects) + self.generate_dependencies() + """
159      flags = """ + product_flags
160          if self.needs_objc:
161              generated += """
162      start = ${TARGET_BOOTSTRAP_DIR}/usr/lib/objc-begin.o 
163      end = ${TARGET_BOOTSTRAP_DIR}/usr/lib/objc-end.o
164  """
165  
166          generated += """
167  build """ + self.product_name + """: phony | """ + self.product.relative() + """
168  
169  default """ + self.product_name + """
170  
171  build ${TARGET_BOOTSTRAP_DIR}/usr/lib/""" + Configuration.current.target.dynamic_library_prefix + self.name + Configuration.current.target.dynamic_library_suffix + """: Cp """ + self.product.path_by_appending(self.name).relative() + """
172  """
173  
174          return generated
175  
176  class StaticLibrary(Library):
177      def __init__(self, name):
178          Library.__init__(self, name)
179          self.name = name
180  
181      def generate(self, objects = []):
182          self.rule = "Archive"
183          self.product_name = Configuration.current.target.static_library_prefix + self.name + Configuration.current.target.static_library_suffix
184          self.runtime_object = ''
185          return Library.generate(self, [], objects)
186  
187  class StaticAndDynamicLibrary(StaticLibrary, DynamicLibrary):
188      def __init__(self, name):
189          StaticLibrary.__init__(self, name)
190          DynamicLibrary.__init__(self, name)
191  
192      def generate(self):
193          objects, generatedForDynamic = DynamicLibrary.generate(self)
194          _, generatedForStatic = StaticLibrary.generate(self, objects)
195          return generatedForDynamic + generatedForStatic
196  
197  class Executable(Product):
198      def __init__(self, name):
199          Product.__init__(self, name)
200          self.product_name = name + Configuration.current.target.executable_suffix
201  
202      def generate(self):
203          generated = Product.generate(self)
204  
205          return generated
206  
207  class Application(Product):
208      executable = None
209      def __init__(self, name):
210          Product.__init__(self, name)
211          self.product_name = name + ".app"
212  
213      def generate(self):
214          generated = Product.generate(self)
215          objects = []
216          for phase in self.phases:
217              objects += phase.objects
218          product_flags = ""
219  
220          if self.LDFLAGS is not None:
221              product_flags += " " + self.LDFLAGS
222          if self.needs_stdcxx:
223              product_flags += " -lstdc++"
224  
225  
226          generated += """
227  build """ + self.product.path_by_appending(self.name).relative() + ": Link " + " ".join(objects) + self.generate_dependencies() + """
228     flags = """ + product_flags
229          if self.needs_objc:
230              generated += """
231      start = ${TARGET_BOOTSTRAP_DIR}/usr/lib/objc-begin.o 
232      end = ${TARGET_BOOTSTRAP_DIR}/usr/lib/objc-end.o
233  """
234  
235          return generated
236