build.py 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309
  1. # Copyright 2012-2014 The Meson development team
  2. # Licensed under the Apache License, Version 2.0 (the "License");
  3. # you may not use this file except in compliance with the License.
  4. # You may obtain a copy of the License at
  5. # http://www.apache.org/licenses/LICENSE-2.0
  6. # Unless required by applicable law or agreed to in writing, software
  7. # distributed under the License is distributed on an "AS IS" BASIS,
  8. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. # See the License for the specific language governing permissions and
  10. # limitations under the License.
  11. from . import coredata
  12. from . import environment
  13. from . import dependencies
  14. from . import mlog
  15. import copy, os, re
  16. from .mesonlib import File, flatten, MesonException, stringlistify
  17. from .environment import for_windows, for_darwin
  18. known_basic_kwargs = {'install' : True,
  19. 'c_pch' : True,
  20. 'cpp_pch' : True,
  21. 'c_args' : True,
  22. 'cpp_args' : True,
  23. 'cs_args' : True,
  24. 'vala_args' : True,
  25. 'd_args' : True,
  26. 'link_args' : True,
  27. 'link_depends': True,
  28. 'link_with' : True,
  29. 'include_directories': True,
  30. 'dependencies' : True,
  31. 'install_dir' : True,
  32. 'main_class' : True,
  33. 'gui_app' : True,
  34. 'extra_files' : True,
  35. 'install_rpath' : True,
  36. 'resources' : True,
  37. 'sources' : True,
  38. 'objects' : True,
  39. 'native' : True,
  40. }
  41. known_shlib_kwargs = known_basic_kwargs.copy()
  42. known_shlib_kwargs.update({'version' : True,
  43. 'soversion' : True,
  44. 'name_prefix' : True,
  45. 'name_suffix' : True,
  46. 'vs_module_defs' : True})
  47. def compilers_are_msvc(compilers):
  48. """
  49. Check if all the listed compilers are MSVC. Used by Executable,
  50. StaticLibrary, and SharedLibrary for deciding when to use MSVC-specific
  51. file naming.
  52. """
  53. for compiler in compilers.values():
  54. if compiler.get_id() != 'msvc':
  55. return False
  56. return True
  57. class InvalidArguments(MesonException):
  58. pass
  59. class Build:
  60. """A class that holds the status of one build including
  61. all dependencies and so on.
  62. """
  63. def __init__(self, environment):
  64. self.project_name = 'name of master project'
  65. self.project_version = None
  66. self.environment = environment
  67. self.projects = {}
  68. self.targets = {}
  69. self.compilers = []
  70. self.cross_compilers = []
  71. self.global_args = {}
  72. self.global_link_args = {}
  73. self.tests = []
  74. self.benchmarks = []
  75. self.headers = []
  76. self.man = []
  77. self.data = []
  78. self.static_linker = None
  79. self.static_cross_linker = None
  80. self.subprojects = {}
  81. self.install_scripts = []
  82. self.postconf_scripts = []
  83. self.install_dirs = []
  84. self.dep_manifest_name = None
  85. self.dep_manifest = {}
  86. self.cross_stdlibs = {}
  87. def has_language(self, language):
  88. for i in self.compilers:
  89. if i.get_language() == language:
  90. return True
  91. return False
  92. def add_compiler(self, compiler):
  93. if self.static_linker is None and compiler.needs_static_linker():
  94. self.static_linker = self.environment.detect_static_linker(compiler)
  95. if self.has_language(compiler.get_language()):
  96. return
  97. self.compilers.append(compiler)
  98. def add_cross_compiler(self, compiler):
  99. if len(self.cross_compilers) == 0:
  100. self.static_cross_linker = self.environment.detect_static_linker(compiler)
  101. for i in self.cross_compilers:
  102. if i.get_language() == compiler.get_language():
  103. return
  104. self.cross_compilers.append(compiler)
  105. def get_project(self):
  106. return self.projects['']
  107. def get_targets(self):
  108. return self.targets
  109. def get_tests(self):
  110. return self.tests
  111. def get_benchmarks(self):
  112. return self.benchmarks
  113. def get_headers(self):
  114. return self.headers
  115. def get_man(self):
  116. return self.man
  117. def get_data(self):
  118. return self.data
  119. def get_install_subdirs(self):
  120. return self.install_dirs
  121. def get_global_args(self, compiler):
  122. return self.global_args.get(compiler.get_language(), [])
  123. def get_global_link_args(self, compiler):
  124. return self.global_link_args.get(compiler.get_language(), [])
  125. class IncludeDirs():
  126. def __init__(self, curdir, dirs, is_system, extra_build_dirs=None):
  127. self.curdir = curdir
  128. self.incdirs = dirs
  129. self.is_system = is_system
  130. # Interpreter has validated that all given directories
  131. # actually exist.
  132. if extra_build_dirs is None:
  133. self.extra_build_dirs = []
  134. else:
  135. self.extra_build_dirs = extra_build_dirs
  136. def get_curdir(self):
  137. return self.curdir
  138. def get_incdirs(self):
  139. return self.incdirs
  140. def get_extra_build_dirs(self):
  141. return self.extra_build_dirs
  142. class ExtractedObjects():
  143. def __init__(self, target, srclist):
  144. self.target = target
  145. self.srclist = srclist
  146. class EnvironmentVariables():
  147. def __init__(self):
  148. self.envvars = []
  149. def get_value(self, name, values, kwargs):
  150. separator = kwargs.get('separator', os.pathsep)
  151. value = ''
  152. for var in values:
  153. value += separator + var
  154. return separator, value.strip(separator)
  155. def set(self, env, name, values, kwargs):
  156. return self.get_value(name, values, kwargs)[1]
  157. def append(self, env, name, values, kwargs):
  158. sep, value = self.get_value(name, values, kwargs)
  159. if name in env:
  160. return env[name] + sep + value
  161. return value
  162. def prepend(self, env, name, values, kwargs):
  163. sep, value = self.get_value(name, values, kwargs)
  164. if name in env:
  165. return value + sep + env[name]
  166. return value
  167. def get_env(self, full_env):
  168. env = {}
  169. for method, name, values, kwargs in self.envvars:
  170. env[name] = method(full_env, name, values, kwargs)
  171. return env
  172. class BuildTarget():
  173. def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
  174. self.name = name
  175. self.subdir = subdir
  176. self.subproject = subproject # Can not be calculated from subdir as subproject dirname can be changed per project.
  177. self.is_cross = is_cross
  178. self.environment = environment
  179. self.sources = []
  180. self.compilers = {}
  181. self.objects = []
  182. self.external_deps = []
  183. self.include_dirs = []
  184. self.link_targets = []
  185. self.link_depends = []
  186. self.filename = 'no_name'
  187. # The file with debugging symbols
  188. self.debug_filename = None
  189. self.need_install = False
  190. self.pch = {}
  191. self.extra_args = {}
  192. self.generated = []
  193. self.extra_files = []
  194. self.process_sourcelist(sources)
  195. self.process_objectlist(objects)
  196. self.process_kwargs(kwargs, environment)
  197. self.check_unknown_kwargs(kwargs)
  198. if len(self.sources) == 0 and \
  199. len(self.generated) == 0 and \
  200. len(self.objects) == 0:
  201. raise InvalidArguments('Build target %s has no sources.' % name)
  202. self.process_compilers()
  203. self.validate_sources()
  204. def __repr__(self):
  205. repr_str = "<{0} {1}: {2}>"
  206. return repr_str.format(self.__class__.__name__, self.get_id(), self.filename)
  207. def get_id(self):
  208. # This ID must also be a valid file name on all OSs.
  209. # It should also avoid shell metacharacters for obvious
  210. # reasons.
  211. base = self.name + self.type_suffix()
  212. if self.subproject == '':
  213. return base
  214. return self.subproject + '@@' + base
  215. def check_unknown_kwargs(self, kwargs):
  216. # Override this method in derived classes that have more
  217. # keywords.
  218. self.check_unknown_kwargs_int(kwargs, known_basic_kwargs)
  219. def check_unknown_kwargs_int(self, kwargs, known_kwargs):
  220. unknowns = []
  221. for k in kwargs:
  222. if not k in known_kwargs:
  223. unknowns.append(k)
  224. if len(unknowns) > 0:
  225. mlog.log(mlog.bold('Warning:'), 'Unknown keyword argument(s) in target %s: %s.' %
  226. (self.name, ', '.join(unknowns)))
  227. def process_objectlist(self, objects):
  228. assert(isinstance(objects, list))
  229. for s in objects:
  230. if hasattr(s, 'held_object'):
  231. s = s.held_object
  232. if isinstance(s, (str, ExtractedObjects)):
  233. self.objects.append(s)
  234. elif isinstance(s, (GeneratedList, CustomTarget)):
  235. msg = 'Generated files are not allowed in the \'objects\' kwarg ' + \
  236. 'for target {!r}.\nIt is meant only for '.format(self.name) + \
  237. 'pre-built object files that are shipped with the\nsource ' + \
  238. 'tree. Try adding it in the list of sources.'
  239. raise InvalidArguments(msg)
  240. else:
  241. msg = 'Bad object of type {!r} in target {!r}.'.format(type(s).__name__, self.name)
  242. raise InvalidArguments(msg)
  243. def process_sourcelist(self, sources):
  244. if not isinstance(sources, list):
  245. sources = [sources]
  246. added_sources = {} # If the same source is defined multiple times, use it only once.
  247. for s in sources:
  248. # Holder unpacking. Ugly.
  249. if hasattr(s, 'held_object'):
  250. s = s.held_object
  251. if isinstance(s, File):
  252. if not s in added_sources:
  253. self.sources.append(s)
  254. added_sources[s] = True
  255. elif isinstance(s, (GeneratedList, CustomTarget)):
  256. self.generated.append(s)
  257. else:
  258. msg = 'Bad source of type {!r} in target {!r}.'.format(type(s).__name__, self.name)
  259. raise InvalidArguments(msg)
  260. @staticmethod
  261. def can_compile_remove_sources(compiler, sources):
  262. removed = False
  263. for s in sources[:]:
  264. if compiler.can_compile(s):
  265. sources.remove(s)
  266. removed = True
  267. return removed
  268. def process_compilers(self):
  269. if len(self.sources) == 0:
  270. return
  271. sources = list(self.sources)
  272. if self.is_cross:
  273. compilers = self.environment.coredata.cross_compilers
  274. else:
  275. compilers = self.environment.coredata.compilers
  276. for lang, compiler in compilers.items():
  277. if self.can_compile_remove_sources(compiler, sources):
  278. self.compilers[lang] = compiler
  279. def validate_sources(self):
  280. if len(self.sources) == 0:
  281. return
  282. for lang in ('cs', 'java'):
  283. if lang in self.compilers:
  284. check_sources = list(self.sources)
  285. compiler = self.compilers[lang]
  286. if not self.can_compile_remove_sources(compiler, check_sources):
  287. m = 'No {} sources found in target {!r}'.format(lang, self.name)
  288. raise InvalidArguments(m)
  289. if check_sources:
  290. m = '{0} targets can only contain {0} files:\n'.format(lang.capitalize())
  291. m += '\n'.join([repr(c) for c in check_sources])
  292. raise InvalidArguments(m)
  293. # CSharp and Java targets can't contain any other file types
  294. assert(len(self.compilers) == 1)
  295. return
  296. if 'rust' in self.compilers:
  297. firstname = self.sources[0]
  298. if isinstance(firstname, File):
  299. firstname = firstname.fname
  300. first = os.path.split(firstname)[1]
  301. (base, suffix) = os.path.splitext(first)
  302. if suffix != '.rs' or self.name != base:
  303. raise InvalidArguments('In Rust targets, the first source file must be named projectname.rs.')
  304. def get_original_kwargs(self):
  305. return self.kwargs
  306. def unpack_holder(self, d):
  307. if not isinstance(d, list):
  308. d = [d]
  309. newd = []
  310. for i in d:
  311. if hasattr(i, 'held_object'):
  312. newd.append(i.held_object)
  313. else:
  314. newd.append(i)
  315. return newd
  316. def copy_kwargs(self, kwargs):
  317. self.kwargs = copy.copy(kwargs)
  318. # This sucks quite badly. Arguments
  319. # are holders but they can't be pickled
  320. # so unpack those known.
  321. if 'dependencies' in self.kwargs:
  322. self.kwargs['dependencies'] = self.unpack_holder(self.kwargs['dependencies'])
  323. if 'link_with' in self.kwargs:
  324. self.kwargs['link_with'] = self.unpack_holder(self.kwargs['link_with'])
  325. def extract_objects(self, srcargs):
  326. obj_src = []
  327. for srclist in srcargs:
  328. if not isinstance(srclist, list):
  329. srclist = [srclist]
  330. for src in srclist:
  331. if not isinstance(src, str):
  332. raise MesonException('Extraction arguments must be strings.')
  333. src = File(False, self.subdir, src)
  334. if src not in self.sources:
  335. raise MesonException('Tried to extract unknown source %s.' % src)
  336. obj_src.append(src)
  337. return ExtractedObjects(self, obj_src)
  338. def extract_all_objects(self):
  339. return ExtractedObjects(self, self.sources)
  340. def get_all_link_deps(self):
  341. return self.get_transitive_link_deps()
  342. def get_transitive_link_deps(self):
  343. result = []
  344. for i in self.link_targets:
  345. result += i.get_all_link_deps()
  346. return result
  347. def get_custom_install_dir(self):
  348. return self.custom_install_dir
  349. def process_kwargs(self, kwargs, environment):
  350. self.copy_kwargs(kwargs)
  351. kwargs.get('modules', [])
  352. self.need_install = kwargs.get('install', self.need_install)
  353. llist = kwargs.get('link_with', [])
  354. if not isinstance(llist, list):
  355. llist = [llist]
  356. for linktarget in llist:
  357. # Sorry for this hack. Keyword targets are kept in holders
  358. # in kwargs. Unpack here without looking at the exact type.
  359. if hasattr(linktarget, "held_object"):
  360. linktarget = linktarget.held_object
  361. self.link(linktarget)
  362. c_pchlist = kwargs.get('c_pch', [])
  363. if not isinstance(c_pchlist, list):
  364. c_pchlist = [c_pchlist]
  365. self.add_pch('c', c_pchlist)
  366. cpp_pchlist = kwargs.get('cpp_pch', [])
  367. if not isinstance(cpp_pchlist, list):
  368. cpp_pchlist = [cpp_pchlist]
  369. self.add_pch('cpp', cpp_pchlist)
  370. clist = kwargs.get('c_args', [])
  371. if not isinstance(clist, list):
  372. clist = [clist]
  373. self.add_compiler_args('c', clist)
  374. cpplist = kwargs.get('cpp_args', [])
  375. if not isinstance(cpplist, list):
  376. cpplist = [cpplist]
  377. self.add_compiler_args('cpp', cpplist)
  378. cslist = kwargs.get('cs_args', [])
  379. if not isinstance(cslist, list):
  380. cslist = [cslist]
  381. self.add_compiler_args('cs', cslist)
  382. valalist = kwargs.get('vala_args', [])
  383. if not isinstance(valalist, list):
  384. valalist = [valalist]
  385. self.add_compiler_args('vala', valalist)
  386. dlist = stringlistify(kwargs.get('d_args', []))
  387. self.add_compiler_args('d', dlist)
  388. self.link_args = kwargs.get('link_args', [])
  389. if not isinstance(self.link_args, list):
  390. self.link_args = [self.link_args]
  391. for i in self.link_args:
  392. if not isinstance(i, str):
  393. raise InvalidArguments('Link_args arguments must be strings.')
  394. self.link_depends = kwargs.get('link_depends', [])
  395. if not isinstance(self.link_depends, list):
  396. self.link_depends = [self.link_depends]
  397. for i in self.link_depends:
  398. if not isinstance(i, str):
  399. raise InvalidArguments('Link_depends arguments must be strings.')
  400. inclist = kwargs.get('include_directories', [])
  401. if not isinstance(inclist, list):
  402. inclist = [inclist]
  403. self.add_include_dirs(inclist)
  404. deplist = kwargs.get('dependencies', [])
  405. if not isinstance(deplist, list):
  406. deplist = [deplist]
  407. self.add_external_deps(deplist)
  408. self.custom_install_dir = kwargs.get('install_dir', None)
  409. if self.custom_install_dir is not None:
  410. if not isinstance(self.custom_install_dir, str):
  411. raise InvalidArguments('Custom_install_dir must be a string')
  412. main_class = kwargs.get('main_class', '')
  413. if not isinstance(main_class, str):
  414. raise InvalidArguments('Main class must be a string')
  415. self.main_class = main_class
  416. if isinstance(self, Executable):
  417. self.gui_app = kwargs.get('gui_app', False)
  418. if not isinstance(self.gui_app, bool):
  419. raise InvalidArguments('Argument gui_app must be boolean.')
  420. elif 'gui_app' in kwargs:
  421. raise InvalidArguments('Argument gui_app can only be used on executables.')
  422. extra_files = kwargs.get('extra_files', [])
  423. if isinstance(extra_files, str):
  424. extra_files = [extra_files]
  425. for i in extra_files:
  426. if not isinstance(i, str):
  427. raise InvalidArguments('Arguments to extra_files must be strings.')
  428. trial = os.path.join(environment.get_source_dir(), self.subdir, i)
  429. if not(os.path.isfile(trial)):
  430. raise InvalidArguments('Tried to add non-existing extra file %s.' % i)
  431. self.extra_files = extra_files
  432. self.install_rpath = kwargs.get('install_rpath', '')
  433. if not isinstance(self.install_rpath, str):
  434. raise InvalidArguments('Install_rpath is not a string.')
  435. resources = kwargs.get('resources', [])
  436. if not isinstance(resources, list):
  437. resources = [resources]
  438. for r in resources:
  439. if not isinstance(r, str):
  440. raise InvalidArguments('Resource argument is not a string.')
  441. trial = os.path.join(environment.get_source_dir(), self.subdir, r)
  442. if not os.path.isfile(trial):
  443. raise InvalidArguments('Tried to add non-existing resource %s.' % r)
  444. self.resources = resources
  445. if 'name_prefix' in kwargs:
  446. name_prefix = kwargs['name_prefix']
  447. if isinstance(name_prefix, list):
  448. if len(name_prefix) != 0:
  449. raise InvalidArguments('Array must be empty to signify null.')
  450. elif not isinstance(name_prefix, str):
  451. raise InvalidArguments('Name prefix must be a string.')
  452. self.prefix = name_prefix
  453. if 'name_suffix' in kwargs:
  454. name_suffix = kwargs['name_suffix']
  455. if isinstance(name_suffix, list):
  456. if len(name_suffix) != 0:
  457. raise InvalidArguments('Array must be empty to signify null.')
  458. else:
  459. if not isinstance(name_suffix, str):
  460. raise InvalidArguments('Name suffix must be a string.')
  461. self.suffix = name_suffix
  462. def get_subdir(self):
  463. return self.subdir
  464. def get_filename(self):
  465. return self.filename
  466. def get_debug_filename(self):
  467. """
  468. The name of the file that contains debugging symbols for this target
  469. Returns None if there are no debugging symbols or if they are embedded
  470. in the filename itself
  471. """
  472. return self.debug_filename
  473. def get_extra_args(self, language):
  474. return self.extra_args.get(language, [])
  475. def get_dependencies(self):
  476. transitive_deps = []
  477. for t in self.link_targets:
  478. transitive_deps.append(t)
  479. if isinstance(t, StaticLibrary):
  480. transitive_deps += t.get_dependencies()
  481. return transitive_deps
  482. def get_basename(self):
  483. return self.name
  484. def get_source_subdir(self):
  485. return self.subdir
  486. def get_sources(self):
  487. return self.sources
  488. def get_objects(self):
  489. return self.objects
  490. def get_generated_sources(self):
  491. return self.generated
  492. def should_install(self):
  493. return self.need_install
  494. def has_pch(self):
  495. return len(self.pch) > 0
  496. def get_pch(self, language):
  497. try:
  498. return self.pch[language]
  499. except KeyError:
  500. return[]
  501. def get_include_dirs(self):
  502. return self.include_dirs
  503. def add_external_deps(self, deps):
  504. if not isinstance(deps, list):
  505. deps = [deps]
  506. for dep in deps:
  507. if hasattr(dep, 'held_object'):
  508. dep = dep.held_object
  509. if isinstance(dep, dependencies.InternalDependency):
  510. # Those parts that are internal.
  511. self.process_sourcelist(dep.sources)
  512. self.add_include_dirs(dep.include_directories)
  513. for l in dep.libraries:
  514. self.link(l)
  515. # Those parts that are external.
  516. extpart = dependencies.InternalDependency('undefined',
  517. [],
  518. dep.compile_args,
  519. dep.link_args,
  520. [], [], [])
  521. self.external_deps.append(extpart)
  522. # Deps of deps.
  523. self.add_external_deps(dep.ext_deps)
  524. elif isinstance(dep, dependencies.Dependency):
  525. self.external_deps.append(dep)
  526. self.process_sourcelist(dep.get_sources())
  527. else:
  528. # This is a bit of a hack. We do not want Build to know anything
  529. # about the interpreter so we can't import it and use isinstance.
  530. # This should be reliable enough.
  531. if hasattr(dep, 'subproject'):
  532. raise InvalidArguments('''Tried to use subproject object as a dependency.
  533. You probably wanted to use a dependency declared in it instead. Access it
  534. by calling get_variable() on the subproject object.''')
  535. raise InvalidArguments('Argument is not an external dependency.')
  536. def get_external_deps(self):
  537. return self.external_deps
  538. def link(self, target):
  539. if not isinstance(target, list):
  540. target = [target]
  541. for t in target:
  542. if hasattr(t, 'held_object'):
  543. t = t.held_object
  544. if not isinstance(t, (StaticLibrary, SharedLibrary)):
  545. raise InvalidArguments('Link target is not library.')
  546. if self.is_cross != t.is_cross:
  547. raise InvalidArguments('Tried to mix cross built and native libraries in target %s.' % self.name)
  548. self.link_targets.append(t)
  549. def set_generated(self, genlist):
  550. for g in genlist:
  551. if not(isinstance(g, GeneratedList)):
  552. raise InvalidArguments('Generated source argument is not the output of a generator.')
  553. self.generated.append(g)
  554. def add_pch(self, language, pchlist):
  555. if len(pchlist) == 0:
  556. return
  557. elif len(pchlist) == 1:
  558. if not environment.is_header(pchlist[0]):
  559. raise InvalidArguments('Pch argument %s is not a header.' % pchlist[0])
  560. elif len(pchlist) == 2:
  561. if environment.is_header(pchlist[0]):
  562. if not environment.is_source(pchlist[1]):
  563. raise InvalidArguments('PCH definition must contain one header and at most one source.')
  564. elif environment.is_source(pchlist[0]):
  565. if not environment.is_header(pchlist[1]):
  566. raise InvalidArguments('PCH definition must contain one header and at most one source.')
  567. pchlist = [pchlist[1], pchlist[0]]
  568. else:
  569. raise InvalidArguments('PCH argument %s is of unknown type.' % pchlist[0])
  570. elif len(pchlist) > 2:
  571. raise InvalidArguments('PCH definition may have a maximum of 2 files.')
  572. self.pch[language] = pchlist
  573. def add_include_dirs(self, args):
  574. ids = []
  575. for a in args:
  576. # FIXME same hack, forcibly unpack from holder.
  577. if hasattr(a, 'held_object'):
  578. a = a.held_object
  579. if not isinstance(a, IncludeDirs):
  580. raise InvalidArguments('Include directory to be added is not an include directory object.')
  581. ids.append(a)
  582. self.include_dirs += ids
  583. def add_compiler_args(self, language, args):
  584. args = flatten(args)
  585. for a in args:
  586. if not isinstance(a, (str, File)):
  587. raise InvalidArguments('A non-string passed to compiler args.')
  588. if language in self.extra_args:
  589. self.extra_args[language] += args
  590. else:
  591. self.extra_args[language] = args
  592. def get_aliaslist(self):
  593. return []
  594. class Generator():
  595. def __init__(self, args, kwargs):
  596. if len(args) != 1:
  597. raise InvalidArguments('Generator requires one and only one positional argument')
  598. exe = args[0]
  599. if hasattr(exe, 'held_object'):
  600. exe = exe.held_object
  601. if not isinstance(exe, (Executable, dependencies.ExternalProgram)):
  602. raise InvalidArguments('First generator argument must be an executable.')
  603. self.exe = exe
  604. self.depfile = None
  605. self.process_kwargs(kwargs)
  606. def __repr__(self):
  607. repr_str = "<{0}: {1}>"
  608. return repr_str.format(self.__class__.__name__, self.exe)
  609. def get_exe(self):
  610. return self.exe
  611. def process_kwargs(self, kwargs):
  612. if 'arguments' not in kwargs:
  613. raise InvalidArguments('Generator must have "arguments" keyword argument.')
  614. args = kwargs['arguments']
  615. if isinstance(args, str):
  616. args = [args]
  617. if not isinstance(args, list):
  618. raise InvalidArguments('"Arguments" keyword argument must be a string or a list of strings.')
  619. for a in args:
  620. if not isinstance(a, str):
  621. raise InvalidArguments('A non-string object in "arguments" keyword argument.')
  622. self.arglist = args
  623. if 'output' not in kwargs:
  624. raise InvalidArguments('Generator must have "output" keyword argument.')
  625. outputs = kwargs['output']
  626. if not isinstance(outputs, list):
  627. outputs = [outputs]
  628. for rule in outputs:
  629. if not isinstance(rule, str):
  630. raise InvalidArguments('"output" may only contain strings.')
  631. if not '@BASENAME@' in rule and not '@PLAINNAME@' in rule:
  632. raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.')
  633. if '/' in rule or '\\' in rule:
  634. raise InvalidArguments('"outputs" must not contain a directory separator.')
  635. if len(outputs) > 1:
  636. for o in outputs:
  637. if '@OUTPUT@' in o:
  638. raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.')
  639. self.outputs = outputs
  640. if 'depfile' in kwargs:
  641. depfile = kwargs['depfile']
  642. if not isinstance(depfile, str):
  643. raise InvalidArguments('Depfile must be a string.')
  644. if os.path.split(depfile)[1] != depfile:
  645. raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
  646. self.depfile = depfile
  647. def get_base_outnames(self, inname):
  648. plainname = os.path.split(inname)[1]
  649. basename = os.path.splitext(plainname)[0]
  650. return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs]
  651. def get_dep_outname(self, inname):
  652. if self.depfile is None:
  653. raise InvalidArguments('Tried to get dep name for rule that does not have dependency file defined.')
  654. plainname = os.path.split(inname)[1]
  655. basename = os.path.splitext(plainname)[0]
  656. return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)
  657. def get_arglist(self):
  658. return self.arglist
  659. class GeneratedList():
  660. def __init__(self, generator, extra_args=[]):
  661. if hasattr(generator, 'held_object'):
  662. generator = generator.held_object
  663. self.generator = generator
  664. self.infilelist = []
  665. self.outfilelist = []
  666. self.outmap = {}
  667. self.extra_depends = []
  668. self.extra_args = extra_args
  669. def add_file(self, newfile):
  670. self.infilelist.append(newfile)
  671. outfiles = self.generator.get_base_outnames(newfile)
  672. self.outfilelist += outfiles
  673. self.outmap[newfile] = outfiles
  674. def get_infilelist(self):
  675. return self.infilelist
  676. def get_outfilelist(self):
  677. return self.outfilelist
  678. def get_outputs_for(self, filename):
  679. return self.outmap[filename]
  680. def get_generator(self):
  681. return self.generator
  682. def get_extra_args(self):
  683. return self.extra_args
  684. class Executable(BuildTarget):
  685. def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
  686. super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
  687. # Unless overriden, executables have no suffix or prefix. Except on
  688. # Windows and with C#/Mono executables where the suffix is 'exe'
  689. if not hasattr(self, 'prefix'):
  690. self.prefix = ''
  691. if not hasattr(self, 'suffix'):
  692. # Executable for Windows or C#/Mono
  693. if for_windows(is_cross, environment) or 'cs' in self.compilers:
  694. self.suffix = 'exe'
  695. else:
  696. self.suffix = ''
  697. self.filename = self.name
  698. if self.suffix:
  699. self.filename += '.' + self.suffix
  700. # See determine_debug_filenames() in build.SharedLibrary
  701. buildtype = environment.coredata.get_builtin_option('buildtype')
  702. if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'):
  703. self.debug_filename = self.prefix + self.name + '.pdb'
  704. def type_suffix(self):
  705. return "@exe"
  706. class StaticLibrary(BuildTarget):
  707. def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
  708. super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
  709. if 'cs' in self.compilers:
  710. raise InvalidArguments('Static libraries not supported for C#.')
  711. # By default a static library is named libfoo.a even on Windows because
  712. # MSVC does not have a consistent convention for what static libraries
  713. # are called. The MSVC CRT uses libfoo.lib syntax but nothing else uses
  714. # it and GCC only looks for static libraries called foo.lib and
  715. # libfoo.a. However, we cannot use foo.lib because that's the same as
  716. # the import library. Using libfoo.a is ok because people using MSVC
  717. # always pass the library filename while linking anyway.
  718. if not hasattr(self, 'prefix'):
  719. self.prefix = 'lib'
  720. if not hasattr(self, 'suffix'):
  721. # Rust static library crates have .rlib suffix
  722. if 'rust' in self.compilers:
  723. self.suffix = 'rlib'
  724. else:
  725. self.suffix = 'a'
  726. self.filename = self.prefix + self.name + '.' + self.suffix
  727. # See determine_debug_filenames() in build.SharedLibrary
  728. buildtype = environment.coredata.get_builtin_option('buildtype')
  729. if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'):
  730. self.debug_filename = self.prefix + self.name + '.pdb'
  731. def type_suffix(self):
  732. return "@sta"
  733. class SharedLibrary(BuildTarget):
  734. def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
  735. self.soversion = None
  736. self.ltversion = None
  737. self.vs_module_defs = None
  738. # The import library this target will generate
  739. self.import_filename = None
  740. # The import library that Visual Studio would generate (and accept)
  741. self.vs_import_filename = None
  742. # The import library that GCC would generate (and prefer)
  743. self.gcc_import_filename = None
  744. super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
  745. if not hasattr(self, 'prefix'):
  746. self.prefix = None
  747. if not hasattr(self, 'suffix'):
  748. self.suffix = None
  749. self.basic_filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
  750. self.determine_filenames(is_cross, environment)
  751. self.determine_debug_filenames(is_cross, environment)
  752. def determine_filenames(self, is_cross, env):
  753. """
  754. See https://github.com/mesonbuild/meson/pull/417 for details.
  755. First we determine the filename template (self.filename_tpl), then we
  756. set the output filename (self.filename).
  757. The template is needed while creating aliases (self.get_aliaslist),
  758. which are needed while generating .so shared libraries for Linux.
  759. Besides this, there's also the import library name, which is only used
  760. on Windows since on that platform the linker uses a separate library
  761. called the "import library" during linking instead of the shared
  762. library (DLL). The toolchain will output an import library in one of
  763. two formats: GCC or Visual Studio.
  764. When we're building with Visual Studio, the import library that will be
  765. generated by the toolchain is self.vs_import_filename, and with
  766. MinGW/GCC, it's self.gcc_import_filename. self.import_filename will
  767. always contain the import library name this target will generate.
  768. """
  769. prefix = ''
  770. suffix = ''
  771. self.filename_tpl = self.basic_filename_tpl
  772. # If the user already provided the prefix and suffix to us, we don't
  773. # need to do any filename suffix/prefix detection.
  774. # NOTE: manual prefix/suffix override is currently only tested for C/C++
  775. if self.prefix != None and self.suffix != None:
  776. pass
  777. # C# and Mono
  778. elif 'cs' in self.compilers:
  779. prefix = ''
  780. suffix = 'dll'
  781. self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
  782. # Rust
  783. elif 'rust' in self.compilers:
  784. # Currently, we always build --crate-type=rlib
  785. prefix = 'lib'
  786. suffix = 'rlib'
  787. self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
  788. # C, C++, Swift, Vala
  789. # Only Windows uses a separate import library for linking
  790. # For all other targets/platforms import_filename stays None
  791. elif for_windows(is_cross, env):
  792. suffix = 'dll'
  793. self.vs_import_filename = '{0}.lib'.format(self.name)
  794. self.gcc_import_filename = 'lib{0}.dll.a'.format(self.name)
  795. if compilers_are_msvc(self.compilers):
  796. # Shared library is of the form foo.dll
  797. prefix = ''
  798. # Import library is called foo.lib
  799. self.import_filename = self.vs_import_filename
  800. # Assume GCC-compatible naming
  801. else:
  802. # Shared library is of the form libfoo.dll
  803. prefix = 'lib'
  804. # Import library is called libfoo.dll.a
  805. self.import_filename = self.gcc_import_filename
  806. # Shared library has the soversion if it is defined
  807. if self.soversion:
  808. self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}'
  809. else:
  810. self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
  811. elif for_darwin(is_cross, env):
  812. prefix = 'lib'
  813. suffix = 'dylib'
  814. # libfoo.dylib
  815. self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
  816. # On OS X, the filename should never have the soversion
  817. # See: https://github.com/mesonbuild/meson/pull/680
  818. else:
  819. prefix = 'lib'
  820. suffix = 'so'
  821. if self.ltversion:
  822. # libfoo.so.X[.Y[.Z]] (.Y and .Z are optional)
  823. self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}.{0.ltversion}'
  824. elif self.soversion:
  825. # libfoo.so.X
  826. self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}.{0.soversion}'
  827. else:
  828. # No versioning, libfoo.so
  829. self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
  830. if self.prefix == None:
  831. self.prefix = prefix
  832. if self.suffix == None:
  833. self.suffix = suffix
  834. self.filename = self.filename_tpl.format(self)
  835. def determine_debug_filenames(self, is_cross, env):
  836. """
  837. Determine the debug filename(s) using the prefix/name/etc detected in
  838. determine_filenames() above.
  839. """
  840. buildtype = env.coredata.get_builtin_option('buildtype')
  841. if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'):
  842. # Currently we only implement separate debug symbol files for MSVC
  843. # since the toolchain does it for us. Other toolchains embed the
  844. # debugging symbols in the file itself by default.
  845. if self.soversion:
  846. self.debug_filename = '{0.prefix}{0.name}-{0.soversion}.pdb'.format(self)
  847. else:
  848. self.debug_filename = '{0.prefix}{0.name}.pdb'.format(self)
  849. def process_kwargs(self, kwargs, environment):
  850. super().process_kwargs(kwargs, environment)
  851. # Shared library version
  852. if 'version' in kwargs:
  853. self.ltversion = kwargs['version']
  854. if not isinstance(self.ltversion, str):
  855. raise InvalidArguments('Shared library version needs to be a string, not ' + type(self.ltversion).__name__)
  856. if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', self.ltversion):
  857. raise InvalidArguments('Invalid Shared library version "{0}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.'.format(self.ltversion))
  858. # Try to extract/deduce the soversion
  859. if 'soversion' in kwargs:
  860. self.soversion = kwargs['soversion']
  861. if isinstance(self.soversion, int):
  862. self.soversion = str(self.soversion)
  863. if not isinstance(self.soversion, str):
  864. raise InvalidArguments('Shared library soversion is not a string or integer.')
  865. try:
  866. int(self.soversion)
  867. except ValueError:
  868. raise InvalidArguments('Shared library soversion must be a valid integer')
  869. elif self.ltversion:
  870. # library version is defined, get the soversion from that
  871. self.soversion = self.ltversion.split('.')[0]
  872. # Visual Studio module-definitions file
  873. if 'vs_module_defs' in kwargs:
  874. path = kwargs['vs_module_defs']
  875. if (os.path.isabs(path)):
  876. self.vs_module_defs = File.from_absolute_file(path)
  877. else:
  878. self.vs_module_defs = File.from_source_file(environment.source_dir, self.subdir, path)
  879. # link_depends can be an absolute path or relative to self.subdir
  880. self.link_depends.append(path)
  881. def check_unknown_kwargs(self, kwargs):
  882. self.check_unknown_kwargs_int(kwargs, known_shlib_kwargs)
  883. def get_import_filename(self):
  884. """
  885. The name of the import library that will be outputted by the compiler
  886. Returns None if there is no import library required for this platform
  887. """
  888. return self.import_filename
  889. def get_import_filenameslist(self):
  890. if self.import_filename:
  891. return [self.vs_import_filename, self.gcc_import_filename]
  892. return []
  893. def get_all_link_deps(self):
  894. return [self] + self.get_transitive_link_deps()
  895. def get_aliaslist(self):
  896. """
  897. If the versioned library name is libfoo.so.0.100.0, aliases are:
  898. * libfoo.so.0 (soversion)
  899. * libfoo.so (unversioned; for linking)
  900. """
  901. # Aliases are only useful with .so libraries. Also if the .so library
  902. # ends with .so (no versioning), we don't need aliases.
  903. if self.suffix != 'so' or self.filename.endswith('.so'):
  904. return []
  905. # Unversioned alias: libfoo.so
  906. aliases = [self.basic_filename_tpl.format(self)]
  907. # If ltversion != soversion we create an soversion alias: libfoo.so.X
  908. if self.ltversion and self.ltversion != self.soversion:
  909. if not self.soversion:
  910. # This is done in self.process_kwargs()
  911. raise AssertionError('BUG: If library version is defined, soversion must have been defined')
  912. alias_tpl = self.filename_tpl.replace('ltversion', 'soversion')
  913. aliases.append(alias_tpl.format(self))
  914. return aliases
  915. def type_suffix(self):
  916. return "@sha"
  917. class CustomTarget:
  918. known_kwargs = {'input' : True,
  919. 'output' : True,
  920. 'command' : True,
  921. 'capture' : False,
  922. 'install' : True,
  923. 'install_dir' : True,
  924. 'build_always' : True,
  925. 'depends' : True,
  926. 'depend_files' : True,
  927. 'depfile' : True,
  928. }
  929. def __init__(self, name, subdir, kwargs):
  930. self.name = name
  931. self.subdir = subdir
  932. self.dependencies = []
  933. self.extra_depends = []
  934. self.depend_files = [] # Files that this target depends on but are not on the command line.
  935. self.depfile = None
  936. self.process_kwargs(kwargs)
  937. self.extra_files = []
  938. self.install_rpath = ''
  939. unknowns = []
  940. for k in kwargs:
  941. if k not in CustomTarget.known_kwargs:
  942. unknowns.append(k)
  943. if len(unknowns) > 0:
  944. mlog.log(mlog.bold('Warning:'), 'Unknown keyword arguments in target %s: %s' %
  945. (self.name, ', '.join(unknowns)))
  946. def __repr__(self):
  947. repr_str = "<{0} {1}: {2}>"
  948. return repr_str.format(self.__class__.__name__, self.get_id(), self.command)
  949. def get_id(self):
  950. return self.name + self.type_suffix()
  951. def get_target_dependencies(self):
  952. deps = self.dependencies[:]
  953. deps += self.extra_depends
  954. for c in self.sources:
  955. if hasattr(c, 'held_object'):
  956. c = c.held_object
  957. if isinstance(c, (BuildTarget, CustomTarget, GeneratedList)):
  958. deps.append(c)
  959. return deps
  960. def process_kwargs(self, kwargs):
  961. self.sources = kwargs.get('input', [])
  962. if not isinstance(self.sources, list):
  963. self.sources = [self.sources]
  964. if 'output' not in kwargs:
  965. raise InvalidArguments('Missing keyword argument "output".')
  966. self.output = kwargs['output']
  967. if not isinstance(self.output, list):
  968. self.output = [self.output]
  969. for i in self.output:
  970. if not(isinstance(i, str)):
  971. raise InvalidArguments('Output argument not a string.')
  972. if '/' in i:
  973. raise InvalidArguments('Output must not contain a path segment.')
  974. self.capture = kwargs.get('capture', False)
  975. if self.capture and len(self.output) != 1:
  976. raise InvalidArguments(
  977. 'Capturing can only output to a single file.')
  978. if 'command' not in kwargs:
  979. raise InvalidArguments('Missing keyword argument "command".')
  980. if 'depfile' in kwargs:
  981. depfile = kwargs['depfile']
  982. if not isinstance(depfile, str):
  983. raise InvalidArguments('Depfile must be a string.')
  984. if os.path.split(depfile)[1] != depfile:
  985. raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
  986. self.depfile = depfile
  987. cmd = kwargs['command']
  988. if not(isinstance(cmd, list)):
  989. cmd = [cmd]
  990. final_cmd = []
  991. for i, c in enumerate(cmd):
  992. if hasattr(c, 'held_object'):
  993. c = c.held_object
  994. if isinstance(c, (str, File)):
  995. final_cmd.append(c)
  996. elif isinstance(c, dependencies.ExternalProgram):
  997. if not c.found():
  998. raise InvalidArguments('Tried to use not found external program in a build rule.')
  999. final_cmd += c.get_command()
  1000. elif isinstance(c, (BuildTarget, CustomTarget)):
  1001. self.dependencies.append(c)
  1002. final_cmd.append(c)
  1003. elif isinstance(c, list):
  1004. # Hackety hack, only supports one level of flattening. Should really
  1005. # work to arbtrary depth.
  1006. for s in c:
  1007. if not isinstance(s, str):
  1008. raise InvalidArguments('Array as argument %d contains a non-string.' % i)
  1009. final_cmd.append(s)
  1010. else:
  1011. raise InvalidArguments('Argument %s in "command" is invalid.' % i)
  1012. self.command = final_cmd
  1013. if self.capture:
  1014. for c in self.command:
  1015. if isinstance(c, str) and '@OUTPUT@' in c:
  1016. raise InvalidArguments('@OUTPUT@ is not allowed when capturing output.')
  1017. if 'install' in kwargs:
  1018. self.install = kwargs['install']
  1019. if not isinstance(self.install, bool):
  1020. raise InvalidArguments('"install" must be boolean.')
  1021. if self.install:
  1022. if 'install_dir' not in kwargs:
  1023. raise InvalidArguments('"install_dir" not specified.')
  1024. self.install_dir = kwargs['install_dir']
  1025. if not(isinstance(self.install_dir, str)):
  1026. raise InvalidArguments('"install_dir" must be a string.')
  1027. else:
  1028. self.install = False
  1029. self.build_always = kwargs.get('build_always', False)
  1030. if not isinstance(self.build_always, bool):
  1031. raise InvalidArguments('Argument build_always must be a boolean.')
  1032. extra_deps = kwargs.get('depends', [])
  1033. if not isinstance(extra_deps, list):
  1034. extra_deps = [extra_deps]
  1035. for ed in extra_deps:
  1036. while hasattr(ed, 'held_object'):
  1037. ed = ed.held_object
  1038. if not isinstance(ed, (CustomTarget, BuildTarget)):
  1039. raise InvalidArguments('Can only depend on toplevel targets.')
  1040. self.extra_depends.append(ed)
  1041. depend_files = kwargs.get('depend_files', [])
  1042. if not isinstance(depend_files, list):
  1043. depend_files = [depend_files]
  1044. for i in depend_files:
  1045. if isinstance(i, (File, str)):
  1046. self.depend_files.append(i)
  1047. else:
  1048. mlog.debug(i)
  1049. raise InvalidArguments('Unknown type in depend_files.')
  1050. def get_basename(self):
  1051. return self.name
  1052. def get_dependencies(self):
  1053. return self.dependencies
  1054. def should_install(self):
  1055. return self.install
  1056. def get_custom_install_dir(self):
  1057. return self.install_dir
  1058. def get_subdir(self):
  1059. return self.subdir
  1060. def get_filename(self):
  1061. return self.output
  1062. def get_aliaslist(self):
  1063. return []
  1064. def get_sources(self):
  1065. return self.sources
  1066. def get_generated_sources(self):
  1067. return []
  1068. def type_suffix(self):
  1069. return "@cus"
  1070. class RunTarget:
  1071. def __init__(self, name, command, args, dependencies, subdir):
  1072. self.name = name
  1073. self.command = command
  1074. self.args = args
  1075. self.dependencies = dependencies
  1076. self.subdir = subdir
  1077. def __repr__(self):
  1078. repr_str = "<{0} {1}: {2}>"
  1079. return repr_str.format(self.__class__.__name__, self.get_id(), self.command)
  1080. def get_id(self):
  1081. return self.name + self.type_suffix()
  1082. def get_basename(self):
  1083. return self.name
  1084. def get_dependencies(self):
  1085. return self.dependencies
  1086. def get_generated_sources(self):
  1087. return []
  1088. def get_sources(self):
  1089. return []
  1090. def get_subdir(self):
  1091. return self.subdir
  1092. def should_install(self):
  1093. return False
  1094. def get_filename(self):
  1095. return self.name
  1096. def type_suffix(self):
  1097. return "@run"
  1098. class Jar(BuildTarget):
  1099. def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
  1100. super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs);
  1101. for s in self.sources:
  1102. if not s.endswith('.java'):
  1103. raise InvalidArguments('Jar source %s is not a java file.' % s)
  1104. self.filename = self.name + '.jar'
  1105. incdirs = kwargs.get('include_directories', [])
  1106. def get_main_class(self):
  1107. return self.main_class
  1108. def type_suffix(self):
  1109. return "@jar"
  1110. class ConfigureFile():
  1111. def __init__(self, subdir, sourcename, targetname, configuration_data):
  1112. self.subdir = subdir
  1113. self.sourcename = sourcename
  1114. self.targetname = targetname
  1115. self.configuration_data = configuration_data
  1116. def __repr__(self):
  1117. repr_str = "<{0}: {1} -> {2}>"
  1118. src = os.path.join(self.subdir, self.sourcename)
  1119. dst = os.path.join(self.subdir, self.targetname)
  1120. return repr_str.format(self.__class__.__name__, src, dst)
  1121. def get_configuration_data(self):
  1122. return self.configuration_data
  1123. def get_subdir(self):
  1124. return self.subdir
  1125. def get_source_name(self):
  1126. return self.sourcename
  1127. def get_target_name(self):
  1128. return self.targetname
  1129. class ConfigurationData():
  1130. def __init__(self):
  1131. super().__init__()
  1132. self.values = {}
  1133. def __repr__(self):
  1134. return repr(self.values)
  1135. def get(self, name):
  1136. return self.values[name] # (val, desc)
  1137. def keys(self):
  1138. return self.values.keys()
  1139. # A bit poorly named, but this represents plain data files to copy
  1140. # during install.
  1141. class Data():
  1142. def __init__(self, in_sourcetree, source_subdir, sources, install_dir):
  1143. self.in_sourcetree = in_sourcetree
  1144. self.source_subdir = source_subdir
  1145. self.sources = sources
  1146. self.install_dir = install_dir
  1147. class InstallScript:
  1148. def __init__(self, cmd_arr):
  1149. assert(isinstance(cmd_arr, list))
  1150. self.cmd_arr = cmd_arr