PyXMake Developer Guide 1.0
PyXMake
Loading...
Searching...
No Matches
stm_make.py
1# -*- coding: utf-8 -*-
2# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3# % PyXMake - Build environment for PyXMake %
4# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5"""
6Jenkins Test Server script.
7
8@note: Start build jobs on the Jenkins Test Server using PyXMake.
9
10@version: 1.0
11----------------------------------------------------------------------------------------------
12@requires:
13 - PyXMake, PyCODAC
14
15@change:
16 -
17
18@author:
19 - hein_fa [DLR-FA,STM Braunschweig]
20 - garb_ma [DLR-FA,STM Braunschweig]
21----------------------------------------------------------------------------------------------
22"""
23# See the file "LICENSE.txt" for the full license governing this code.
24
25## @package PyXMake.VTL.stm_make
26# Start build jobs on the Jenkins Test Server using PyXMake.
27## @author
28# Falk Heinecke, Marc Garbade
29## @date
30# 20.03.2018
31## @par Notes/Changes
32# - Added documentation // mg 28.06.2018
33
34"""
35Setup script.
36from main import release creator_Abhi
37"""
38import shutil
39import os
40import subprocess
41import sys
42import setuptools
43import inspect
44import warnings
45
46from packaging.version import parse
47from distutils.command import clean as _clean
48from distutils import core
49
50## Add PyXMake source folder to system path (if not already present). Allows usage as a plugin.
51if os.path.abspath(inspect.getfile(inspect.currentframe())).split("PyXMake")[0] not in sys.path:
52 sys.path.append(os.path.abspath(inspect.getfile(inspect.currentframe())).split("PyXMake")[0])
53
54class Clean(_clean.clean): # pragma: no cover
55 """
56 Little clean extension: Cleans up a non-empty build directory.
57 """
58 def run(self):
59 """
60 Delete all redundant folders and directories. Ignore read-only GIT repositories
61
62 @author: garb_ma
63 """
64 from PyXMake.Tools.Utility import DeleteRedundantFolders
65 for path in ["build", "dist", ".coverage"]:
66 if os.path.isdir(path):
67 try: DeleteRedundantFolders(path, ignore_readonly=True)
68 except: shutil.rmtree(path)
69 elif os.path.isfile(path):
70 os.remove(path)
71
72
73class _BaseCommandRunner(core.Command): # pragma: no cover
74 """
75 Base class for encapsulating command line commands.
76 """
77 def run(self):
79 command = self._create_command()
80 self._run_command(command)
82
83 @staticmethod
84 def _create_build_dir():
85 if not os.path.exists("build"):
86 os.mkdir("build")
87
88 def _create_command(self):
89 pass
90
91 def _run_command(self, command):
92 if self.verbose:
93 print(command)
94 subprocess.call(command, shell=True)
95
96 def _perform_post_actions(self):
97 pass
98
99
100class pyx_app(_BaseCommandRunner): # pragma: no cover
101 """
102 Base class for encapsulating command line arguments and build process.
103 """
104 _APP_NAME = ''
105 _INPUT_SCRIPT = ""
106
107 description = "Compile a stand-alone application using PyInstaller."
108 user_options = [
109 # The format is (long option, short option, description).
110 ('source-path=', None, 'path to the folder holding source files'),
111 ('verbose=', None, 'controls the logging level (0 - Nothing, 2- Everything) Default: 0 - Nothing'),
112 ('mode=', None, 'define application build mode (one directory or one file mode)'),
113 ('scratch-path=', None, 'path to scratch folder where all temporary data is located during the build event'),
114 ('output-file-path=', None, 'path to the output directory'),
115 ]
116
118 """
119 Set default values for options.
120 """
121 # Each user option must be listed here with their default value.
122 self.verboseverbose = 0
123 self.source_path = ''
124 self.output_file_path = ''
125 self.mode = "onedir"
126 self.scratch_path = os.getcwd()
127 self.include = None
128 self.dependency = None
129
131 """
132 Post-process options.
133 """
134 if self.source_path:
135 assert os.path.exists(self.source_path), (
136 'Source path'+self.source_path+' does not exist.')
137
138 def _run_command(self, command):
139 """
140 Execute build command
141 """
142 from PyXMake.VTL import app # @UnresolvedImport
143
144 # Are additional dependencies given? Defaults to empty lists
145 include = []; dependency = []
146 if self.include:
147 include = self.include
148 if self.dependency:
149 dependency = self.dependency
150
151 # Compile stand-alone python application
152 app(self._APP_NAME,
153 script=self._INPUT_SCRIPT,
154 scratch=self.scratch_path,
155 source=self.source_path,
156 mode=self.mode,
157 output=self.output_file_path,
158 verbosity=self.verboseverbose,
159 encryption=True,
160 include=include, dependency=dependency,
161 preprocessing=command)
162
163class app_pycodac(pyx_app): # pragma: no cover
164 """
165 Runs the application build process using PyCODAC to create runtime for STMLab.
166 """
167 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
168
169 # Set class defining attributes.
170 _KEY_OPT = 8
171 _APP_NAME = 'STMLab'
172 _INPUT_SCRIPT = GetSourceCode(_KEY_OPT)
173
174 def _create_command(self):
175 from PyXMake import VTL #@UnresolvedImport
176 import PyCODAC #@UnresolvedImport
177
178 # Add pre-assembled dependencies from VTL
179 self.includeinclude=VTL.GetIncludeDirectory(PyCODAC.PyCODACPath, self._KEY_OPT),
180 self.dependencydependency=VTL.GetLinkDependency(self._KEY_OPT),
181
182 # Assemble pre-processing command to include Smetana & DEliS
183 delimn = " "; continuation = "&&"
184 command = delimn.join([
185 sys.executable,os.path.join(PyCODAC.PyCODACPath,"Plugin","DELiS","__install__.py"),continuation,
186 sys.executable,os.path.join(PyCODAC.PyCODACPath,"Plugin","DELiS","__update__.py"),continuation,
187 sys.executable,os.path.join(PyCODAC.PyCODACPath,"Plugin","Smetana","__install__.py"),continuation,
188 sys.executable,os.path.join(PyCODAC.PyCODACPath,"Plugin","Smetana","__update__.py")
189 ])
190
191 return command
192
193
194class pyx_bundle(_BaseCommandRunner): # pragma: no cover
195 """
196 Base class for encapsulating command line arguments and build process.
197 """
198 _BUNDLE_NAME = ''
199 _INPUT_FILES = ""
200
201 description = "Compile a stand-alone installer using NSIS."
202 user_options = [
203 # The format is (long option, short option, description).
204 ('source-path=', None, 'path to the folder holding source files'),
205 ('verbose=', None, 'controls the logging level (0 - Nothing, 2- Everything) Default: 0 - Nothing'),
206 ('scratch-path=', None, 'path to scratch folder where all temporary data is located during the build event'),
207 ('output-file-path=', None, 'path to the output directory'),
208 ('install-path=', None, 'path to the default installation directory'),
209 ]
210
212 """
213 Set default values for options.
214 """
215 # Each user option must be listed here with their default value.
216 self.verboseverbose = 0
217 self.source_path = ''
218 self.output_file_path = ''
219 self.scratch_path = os.getcwd()
220 self.install_path = "$Desktop"
221
223 """
224 Post-process options.
225 """
226 if self.source_path:
227 assert os.path.exists(self.source_path), (
228 'Source path'+self.source_path+' does not exist.')
229
230 def _run_command(self, command):
231 """
232 Execute build command
233 """
234 from PyXMake.VTL import bundle # @UnresolvedImport
235
236 # Compile stand-alone python application
237 bundle(self._BUNDLE_NAME,
238 files=self._INPUT_FILES,
239 scratch=self.scratch_path,
240 source=self.source_path,
241 output=self.output_file_path,
242 verbosity=self.verboseverbose,
243 install_path=self.install_path,
244 assembly_path=os.path.dirname(self.source_path),
245 # Upload installer to FTP server.
246 user='ASRI_adm', key='lm9ITHUR', upload =True)
247
248class bundle_pycodac(pyx_bundle): # pragma: no cover
249 """
250 Create an installer for STMLab using PyCODAC.
251 """
252 # Set class defining attributes.
253 _BUNDLE_NAME = 'STMLab'
254 _INPUT_FILES = "*.*"
255
256 def _create_command(self):
257 # Import package
258 import svn.remote
259 from PyXMake.Tools import Utility #@UnresolvedImport
260 # Overwrite default installation directory
261 self.install_pathinstall_path = os.getenv("plugin_central_dir",os.path.join(Utility.AsDrive("c"),"simulia","cae","plugins","2019"))
262 # Define local output directories
263 __url_delimn = "/"
264 __pyc_plugin = os.path.join(self.source_path,"PyCODAC")
265 __smet_plugin = os.path.join(self.source_path,"Smetana")
266 # Set URLs to repositories
267 __pyc_plugin_repo = __url_delimn.join(["https:","","svn.dlr.de","STM-Routines","Analysis_Tools","MCODAC","trunk","src","mcd_pycodac","PyCODAC","Plugin","JupyterLab","src"])
268 __smet_plugin_repo = __url_delimn.join(["https:","","svn.dlr.de","STM-Routines","Analysis_Tools","MCODAC","trunk","src","mcd_pycodac","PyCODAC","Plugin","Smetana","src"])
269 ## Export content of repositories into the current source folder to create a bundle
270 # Added exception to paths containing an @ sign: https://stackoverflow.com/questions/757435/how-to-escape-characters-in-subversion-managed-file-names
271 if "@" in __pyc_plugin: __pyc_plugin += "@"
272 if "@" in __smet_plugin: __smet_plugin += "@"
273 svn.remote.RemoteClient(__pyc_plugin_repo).export(__pyc_plugin, force=True)
274 svn.remote.RemoteClient(__smet_plugin_repo).export(__smet_plugin, force=True)
275 # Remove last character if its an escape character used by SVN
276 if __pyc_plugin.endswith("@"): __pyc_plugin = __pyc_plugin[:-1]
277 # Delete unwanted files and folders
278 shutil.rmtree(os.path.join(__pyc_plugin,".config"), ignore_errors=True)
279 os.remove(os.path.join(__pyc_plugin,"user","Paths.log"))
280 # Return dummy command
281 command = " "
282 # Return
283 return command
284
285
286class pyx_sphinx(_BaseCommandRunner): # pragma: no cover
287 """
288 Base class for encapsulating command line arguments and build process.
289 """
290 _BUILD_NAME = ''
291 _INPUT_FILE = ""
292
293 description = "Runs the html documentation build process of source code using Sphinx."
294 user_options = [
295 # The format is (long option, short option, description).
296 ('source-path=', None, 'path to the folder holding source files'),
297 ('verbose=', None, 'controls the logging level (0 - Nothing, 2- Everything) Default: 0 - Nothing'),
298 ('include-path=', None, 'path to additional files required for processing.'),
299 ('scratch-path=', None, 'path to scratch folder where all temporary data is located during the build event'),
300 ('output-file-path=', None, 'path to the output directory'),
301 ('logo=', None, 'Custom logo for the upper left corner. Defaults to None, leaving the space empty'),
302 ]
303
305 """
306 Set default values for options.
307 """
308 # Each user option must be listed here with their default value.
309 self.verboseverbose = 0
310 self.include_path = ""
311 self.source_path = ''
312 self.output_file_path = ''
313 self.scratch_path = os.getcwd()
314 self.logo = None
315
317 """
318 Post-process options.
319 """
320 if self.source_path:
321 assert os.path.exists(self.source_path), (
322 'Source path'+self.source_path+' does not exist.')
323
324 def _run_command(self, command):
325 """
326 Execute build command
327 """
328 from PyXMake.VTL import sphinx # @UnresolvedImport
329
330 # Build documentation
331 sphinx(self._BUILD_NAME,
332 self._INPUT_FILE,
333 scratch=self.scratch_path,
334 source=self.source_path,
335 include=self.include_path,
336 output=self.output_file_path,
337 verbosity=self.verboseverbose,
338 logo=self.logo)
339
340class sphinx_stmlab(pyx_sphinx): # pragma: no cover
341 """
342 Runs the html documentation build process for Structural Mechanics Lab using a scheme from ReadtheDocs.
343 """
344 # Set class defining attributes
345 _BUILD_NAME = 'Structural Mechanics Lab'
346 _INPUT_FILE = "stm_lab"
347
348 def _create_command(self):
349 from PyXMake.Tools import Utility # @UnresolvedImport
350 # Predefined script local variables
351 __arch = Utility.GetArchitecture()
352 __platform = Utility.GetPlatform()
353
354 from PyCODAC.Tools.Utility import GetPyCODACPath #@UnresolvedImport
355 # Import and set local path to PyCODAC
356 __pyc_core_path = GetPyCODACPath()
357
358 self.include_pathinclude_path=[os.path.join(__pyc_core_path,"Plugin","Smetana"),
359 os.path.join(__pyc_core_path,"Plugin","Smetana","src","Smetana"),
360 os.path.join(__pyc_core_path,"Core","bin",__platform,__arch)]
361 self.logologo = os.path.join(__pyc_core_path,"VTL","doc","mcd_stmlab","pics","stm_lab_logo_bubbles.png")
362
363 command = ' '
364 return command
365
366
367class pyx_doxygen(_BaseCommandRunner): # pragma: no cover
368 """
369 Base class for encapsulating command line arguments and build process.
370 """
371 _BUILD_NAME = ''
372 _INPUT_FILES = []
373
374 description = "Runs the html documentation build process of source code using Doxygen."
375 user_options = [
376 # The format is (long option, short option, description).
377 ('source-path=', None, 'path to the folder holding source files'),
378 ('verbose=', None, 'controls the logging level (0 - Nothing, 2- Everything) Default: 0 - Nothing'),
379 ('stype=', None, 'define type of source files (Java, Python or left blank) Defaults to: Fortran'),
380 ('scratch-path=', None, 'path to scratch folder where all temporary data is located during the build event'),
381 ('output-file-path=', None, 'path to the output directory'),
382 ]
383
385 """
386 Set default values for options.
387 """
388 # Each user option must be listed here with their default value.
389 self.verboseverbose = 0
390 self.source_path = ''
391 self.output_file_path = ''
392 self.stype = "Fortran"
393 self.scratch_path = os.getcwd()
394
396 """
397 Post-process options.
398 """
399 if self.source_path:
400 assert os.path.exists(self.source_path), (
401 'Source path'+self.source_path+' does not exist.')
402
403 def _run_command(self, command):
404 """
405 Execute build command
406 """
407 from PyXMake.VTL import doxygen # @UnresolvedImport
408
409 # Search for all source files in source folder if files have not been specified.
410 if self._INPUT_FILES == []:
411 self._INPUT_FILES = [x[0] for x in os.walk(self.source_path)]
412
413 # Build documentation
414 doxygen(self._BUILD_NAME,
415 title=[self.brief, self.header],
416 files=self._INPUT_FILES,
417 ftype=self.stype,
418 verbosity=self.verboseverbose,
419 scratch=self.scratch_path,
420 source=self.source_path,
421 output=self.output_file_path)
422
423 try:
424 # Delete environment variables specifying color scheme after each run.
425 del os.environ['dox_hue']; del os.environ['dox_sat']; os.environ['dox_gamma']
426 except: pass
427
428class doxy_pyxmake(pyx_doxygen): # pragma: no cover
429 """
430 Runs the html documentation build process for PyXMake.
431 """
432 # Set class defining attributes
433 _BUILD_NAME = 'pyx_core'
434
435# # Set different color scheme.
436# if not all([os.getenv(x) for x in ("dox_hue","dox_sat","dox_gamma")]):
437# import colorsys
438# import numpy as np
439# from PIL import ImageColor
440# os.environ['dox_hue'], os.environ['dox_sat'], os.environ['dox_gamma'] = [str(int(round(x))) for x in np.multiply([360.,100.,100],
441# np.array(colorsys.rgb_to_hsv(*(value/255 for value in
442# ImageColor.getcolor("#ff0000","RGB")))))]
443
444 def _create_command(self):
445 from PyXMake.Tools import Utility # @UnresolvedImport
446 # Files to be processed
447 self._INPUT_FILES_INPUT_FILES = [x[0] for x in Utility.PathWalk(self.source_path, startswith=(".","__"), contains=("doc","bin","config"), endswith=("make","scratch"))]
448
449 self.brief = "PyXMake"
450 self.header = "PyXMake Developer Guide"
451 command = ' '
452 return command
453
454class doxy_mcdpycodac(pyx_doxygen): # pragma: no cover
455 """
456 Runs the html documentation build process for PyCODAC.
457 """
458 # Set class defining attributes
459 _BUILD_NAME = 'pyc_core'
460
461 def _create_command(self):
462 from PyXMake.Tools import Utility # @UnresolvedImport
463 # Files to be processed
464 self._INPUT_FILES_INPUT_FILES = [x[0] for x in Utility.PathWalk(self.source_path, startswith=(".","__"),
465 contains=("DELiS","Smetana","PyXMake","external","doc","cmd","bin","include","lib","config","fetch"),
466 endswith=("VTL","make","scratch","examples","src","config","solver"))]
467
468 self.brief = "PyCODAC"
469 self.header = "PyCODAC Developer Guide"
470 command = ' '
471 return command
472
473class doxy_boxbeam(pyx_doxygen): # pragma: no cover
474 """
475 Runs the html documentation build process for BoxBeam.
476 """
477 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
478 # Set class defining attributes
479 _KEY_OPT = 1
480 _BUILD_NAME = 'box_main'
481 # Files to be processed
482 _INPUT_FILES = GetSourceCode(_KEY_OPT)
483
484 def _create_command(self):
485 self.brief = "BoxBeam"
486 self.header = "BoxBeam Developer Guide"
487 command = ' '
488 return command
489
490class doxy_mcdcore(pyx_doxygen): # pragma: no cover
491 """
492 Runs the html documentation build process for MCODAC.
493 """
494 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
495 # Set class defining attributes
496 _KEY_OPT = 0
497 _BUILD_NAME = 'mcd_core'
498 # Files to be processed
499 _INPUT_FILES = GetSourceCode(_KEY_OPT)
500
501 def _create_command(self):
502 self.brief = "MCODAC"
503 self.header = "MCODAC Developer Guide"
504 command = ' '
505 return command
506
507class doxy_mcdsubbuck(pyx_doxygen): # pragma: no cover
508 """
509 Runs the html documentation build process for BoxBeam.
510 """
511 _BUILD_NAME = 'mcd_subbuck'
512
513 def _create_command(self):
514 self.brief = "SubBuck"
515 self.header = "SubLaminate Buckling Developer Guide"
516 command = ' '
517 return command
518
519class doxy_mcdmapper(pyx_doxygen): # pragma: no cover
520 """
521 Runs the html documentation build process for BoxBeam.
522 """
523 _BUILD_NAME = 'mcd_mapper'
524
525 def _create_command(self):
526 self.brief = "Mapper"
527 self.header = "Damage Mapping Developer Guide"
528 command = ' '
529 return command
530
531
532class pyx_f2py(_BaseCommandRunner): # pragma: no cover
533 """
534 Base class for encapsulating command line arguments and build process.
535 """
536 _PACKAGE_NAME = ''
537 _INPUT_FILES = []
538
539 description = "Runs the build process of Fortran source code for Python using f2py."
540 user_options = [
541 # The format is (long option, short option, description).
542 ('msvsc=', None, 'identifier, which compiler version from Microsoft Visual Studio to be used'),
543 ('source-path=', None, 'path to the folder holding the fortran files'),
544 ('verbose=', None, 'controls the logging level (0 - Nothing) Default: 2 - Everything'),
545 ('scratch-path=', None, 'path to scratch folder where all temporary data is located during the build event'),
546 ('output-file-path=', None, 'path to the output directory'),
547 ('base-path=', None, 'path to base folder - optional'),
548 ]
549
551 """
552 Set default values for options.
553 """
554 # Each user option must be listed here with their default value.
555 self._MAKE_OPT = {"Python":0, "Java":1, "Fortran":2}
556 self.verboseverbose = 2
557 self.source_path = ''
558 self.output_file_path = ''
559 self.base_path = ''
560 self.scratch_path = os.getcwd()
561 self.libs = None
562 self.includes = None
563 self.libpaths = None
564 self.incremental = False
565
566 # Select Visual Studio version in dependence of operating system.
567 if sys.getwindowsversion() >= (10, 0, 0):
568 # Jenkins2 // Windows 10
569 self.msvsc = "vs2015"
570 else:
571 # Jenkins // Windows 7
572 self.msvsc = "vs2010"
573
575 """
576 Post-process options.
577 """
578 if self.source_path:
579 assert os.path.exists(self.source_path), (
580 'Source path for Fortran files '+self.source_path+' does not exist.')
581 if self.base_path:
582 assert os.path.exists(self.base_path), (
583 'Path to base folder '+self.base_path+' does not exist.')
584
585 def _run_command(self, command):
586 """
587 Execute build command
588 """
589 # Build .pyd using f2py (for now!)
590 from PyXMake.VTL import py2x # @UnresolvedImport
591
592 # Are additional dependencies given? Defaults to empty lists
593 includes = []; libs = []; libpaths = []
594 if self.includes:
595 includes = self.includes
596 if self.libs:
597 libs = self.libs
598 if self.libpaths:
599 libpaths = self.libpaths
600
601 # Build Python package from Fortran source.
602 py2x(self._PACKAGE_NAME,
603 self._INPUT_FILES,
604 command=command,
605 libs=libs,include=includes,dependency=libpaths,
606 scratch=self.scratch_path, verbosity=self.verboseverbose,
607 source=self.source_path, output=self.output_file_path,
608 incremental=self.incremental,
609 msvsc=self.msvsc)
610
611class f2py_mcodac(pyx_f2py): # pragma: no cover
612 """
613 Runs the build process for MCODAC.
614 """
615 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
616 # Set class defining attributes
617 _KEY_OPT = 0
618 _PACKAGE_NAME = 'mcd_core'
619 # Files to be processed
620 _INPUT_FILES = GetSourceCode(_KEY_OPT)
621
622 def _create_command(self):
623 from PyXMake import VTL # @UnresolvedImport
624 from PyXMake.Tools import Utility # @UnresolvedImport
625 # Set library path
626 self.includesincludes = [os.path.join(self.base_path,"include",Utility.GetPlatform(),Utility.GetArchitecture(), x)
627 for x in VTL.GetIncludeDirectory(self.base_path, 0, 4, Utility.GetArchitecture())],
628 self.libslibs = VTL.GetLinkDependency(self._KEY_OPT, self._MAKE_OPT["Python"], Utility.GetArchitecture())
629 self.libpathslibpaths = os.path.join(self.base_path,"lib",Utility.GetPlatform(), Utility.GetArchitecture())
630 # Custom compiler command for building a shared Java library.
631 return VTL.GetBuildCommand(self._MAKE_OPT["Python"])
632
633class f2py_boxbeam(pyx_f2py): # pragma: no cover
634 """
635 Runs the build process for BoxBeam.
636 """
637 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
638 # Set class defining attributes
639 _KEY_OPT = 1
640 _PACKAGE_NAME = 'bbeam'
641 # Files to be processed
642 _INPUT_FILES = GetSourceCode(_KEY_OPT)
643
644 def _create_command(self):
645 from PyXMake.VTL import GetBuildCommand # @UnresolvedImport
646 return GetBuildCommand(self._MAKE_OPT["Python"])
647
648class f2py_beos(pyx_f2py): # pragma: no cover
649 """
650 Runs the build process for Beos.
651 """
652 _PACKAGE_NAME = 'beos'
653 _KEY_OPT = 2
654 # Files to be processed
655 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
656 _INPUT_FILES = GetSourceCode(_KEY_OPT)
657
658 def _create_command(self):
659 from PyXMake.VTL import GetBuildCommand # @UnresolvedImport
660 # Incremental compilation
661 self.incrementalincremental=True
662 return GetBuildCommand(self._MAKE_OPT["Python"], _format="free")
663
664class pyx_fortran(_BaseCommandRunner): # pragma: no cover
665 """
666 Base class for encapsulating command line arguments and build process.
667 """
668 _PACKAGE_NAME = ''
669 _INPUT_FILES = []
670
671 description = "Runs the build process of Fortran source code using the Intel Fortran Compiler through Python."
672 user_options = [
673 # The format is (long option, short option, description).
674 ('source-path=', None, 'path to the folder holding the fortran files'),
675 ('scratch-path=', None, 'path to scratch folder where all temporary data is located during the build event'),
676 ('output-file-path=', None, 'path to the output directory'),
677 ('base-path=', None, 'path to base folder - optional'),
678 ('verbose=', None, 'controls the logging level (0 - Nothing) Default: 2 - Everything'),
679 ('btype=', None, 'controls the building type. Defaults to static library. Use shared to indicate a dynamic library shall be created'),
680 ]
681
683 """
684 Set default values for options.
685 """
686 # Each user option must be listed here with their default value.
687 self._MAKE_OPT = {"Python":0, "Java":1, "Fortran":2}
688 self.verboseverbose = 0
689 self.source_path = ''
690 self.output_file_path = ''
691 self.base_path = ''
692 self.scratch_path = os.getcwd()
693 self.btype = 'static'
694 self.libs = None
695 self.includes = None
696 self.libpaths = None
697 self.modules = None
698
700 """
701 Post-process options.
702 """
703 if self.source_path:
704 assert os.path.exists(self.source_path), (
705 'Source path for Fortran files '+self.source_path+' does not exist.')
706 if self.base_path:
707 assert os.path.exists(self.base_path), (
708 'Path to base folder '+self.base_path+' does not exist.')
709
710 def _run_command(self, command):
711 """
712 Execute build command
713 """
714 from PyXMake.Tools import Utility # @UnresolvedImport
715 from PyXMake.VTL import ifort # @UnresolvedImport // Take care to set paths to PyXMake properly
716
717 # Are additional dependencies given? Defaults to empty lists
718 includes = []; libs = []; libpaths = []
719 if self.includes:
720 includes = self.includes
721 if self.libs:
722 libs = self.libs
723 if self.libpaths:
724 libpaths = self.libpaths
725
726 # Build Fortran library from source.
727 ifort(
728 self._PACKAGE_NAME,
729 # Build MCODAC by default
730 files=self._INPUT_FILES,
731 command = command,
732 libs = libs,
733 # Resource paths
734 source=self.source_path,
735 include=includes,
736 dependency=libpaths,
737 make=[self.modules,self.output_file_path],
738 # Architecture, verbose and scratch directory
739 architecture=Utility.GetArchitecture(), scratch=self.scratch_path, verbosity=self.verboseverbose,
740 # Activate / deactivate incremental compilation. Does deactivate preprocessing.
741 incremental = False)
742
743class java_mcodac(pyx_fortran): # pragma: no cover
744 """
745 Runs the build process for MCODAC.
746 """
747 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
748 _KEY_OPT = 0
749 _PACKAGE_NAME = 'mcd_java'
750 # Files to be processed
751 _INPUT_FILES = GetSourceCode(_KEY_OPT)
752
753 def _create_command(self):
754 from PyXMake import VTL # @UnresolvedImport
755 from PyXMake.Tools import Utility # @UnresolvedImport
756 # Set library path
757 self.includesincludes = [os.path.join(self.base_path,"include",Utility.GetPlatform(),Utility.GetArchitecture(), x)
758 for x in VTL.GetIncludeDirectory(self.base_path, 0, 4, Utility.GetArchitecture())],
759 self.libslibs = VTL.GetLinkDependency(self._KEY_OPT, self._MAKE_OPT["Java"], Utility.GetArchitecture())
760 self.libpathslibpaths = os.path.join(self.base_path,"lib",Utility.GetPlatform(), Utility.GetArchitecture())
761 # Custom compiler command for building a shared Java library.
762 return VTL.GetBuildCommand(self._MAKE_OPT["Java"])
763
764class java_boxbeam(pyx_fortran): # pragma: no cover
765 """
766 Runs the build process for BoxBeam.
767 """
768 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
769 # Set class defining attributes
770 _KEY_OPT = 1
771 _PACKAGE_NAME = 'bbeam_java'
772 # Files to be processed
773 _INPUT_FILES = GetSourceCode(_KEY_OPT)
774
775 def _create_command(self):
776 from PyXMake import VTL # @UnresolvedImport
777 from PyXMake.Tools import Utility # @UnresolvedImport
778 # Set library path
779 self.includesincludes = None
780 self.libslibs = VTL.GetLinkDependency(self._KEY_OPT, self._MAKE_OPT["Java"], Utility.GetArchitecture())
781 self.libpathslibpaths = os.path.join(self.base_path,"lib",Utility.GetPlatform(), Utility.GetArchitecture())
782 # Custom compiler command for building a shared Java library.
783 return VTL.GetBuildCommand(self._MAKE_OPT["Java"])
784
785class win_mcodac(pyx_fortran): # pragma: no cover
786 """
787 Runs the build process for MCODAC on Windows.
788 """
789 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
790 # Set class defining attributes.
791 _KEY_OPT = 0
792 _PACKAGE_NAME = 'mcd_core'
793 # Files to be processed
794 _INPUT_FILES = GetSourceCode(_KEY_OPT)
795
796 def _create_command(self):
797 from PyXMake import VTL # @UnresolvedImport
798 from PyXMake.Tools import Utility # @UnresolvedImport
799 # Set relative path & dependencies
800 self.includesincludes = [os.path.join(self.base_path,"include",Utility.GetPlatform(),Utility.GetArchitecture(), x)
801 for x in VTL.GetIncludeDirectory(self.base_path, 0, 4, Utility.GetArchitecture())],
802 self.modulesmodules = os.path.join(self.base_path,"include",Utility.GetPlatform(), Utility.GetArchitecture())
803 self.libpathslibpaths = os.path.join(self.base_path,"lib",Utility.GetPlatform(), Utility.GetArchitecture())
804 self.libslibs = VTL.GetLinkDependency(self._KEY_OPT, self._MAKE_OPT["Fortran"], Utility.GetArchitecture())
805 # Custom compiler command for building a static Fortran library.
806 return VTL.GetBuildCommand(self._MAKE_OPT["Fortran"])
807
808class win_boxbeam(pyx_fortran): # pragma: no cover
809 """
810 Runs the build process for BoxBeam on Windows.
811 """
812 from PyXMake.VTL import GetSourceCode # @UnresolvedImport
813 # Set class defining attributes.
814 _KEY_OPT = 1
815 _PACKAGE_NAME = 'bbeam'
816 # Files to be processed
817 _INPUT_FILES = GetSourceCode(_KEY_OPT)
818
819 def _create_command(self):
820 from PyXMake import VTL # @UnresolvedImport
821 from PyXMake.Tools import Utility # @UnresolvedImport
822 # Set library path
823 self.includesincludes = None
824 self.libslibs = VTL.GetLinkDependency(self._KEY_OPT, self._MAKE_OPT["Fortran"], Utility.GetArchitecture())
825 self.modulesmodules = os.path.join(self.base_path,"include",Utility.GetPlatform(), Utility.GetArchitecture())
826 self.libpathslibpaths = os.path.join(self.base_path,"lib",Utility.GetPlatform(), Utility.GetArchitecture())
827 # Custom compiler command for building a static Fortran library.
828 return VTL.GetBuildCommand(self._MAKE_OPT["Fortran"])
829
830class pyx_custom(_BaseCommandRunner): # pragma: no cover
831 """
832 Base class for encapsulating command line arguments and build process.
833 """
834 _PACKAGE_NAME = ''
835 _INPUT_FILES = []
836
837 description = "Runs an user-defined build process utilizing the PyXMake build environment."
838 user_options = [
839 # The format is (long option, short option, description).
840 ('msvsc=', None, 'identifier, which compiler version from Microsoft Visual Studio to be used'),
841 ('source-path=', None, 'path to the folder holding source files'),
842 ('source-file=', None, 'source file or list of source files. Defaults to "mcd_astandard"'),
843 ('verbose=', None, 'controls the logging level (0 - Nothing) Default: 2 - Everything'),
844 ('scratch-path=', None, 'path to scratch folder where all temporary data is located during the build event'),
845 ('base-path=', None, 'path to base folder - optional'),
846 ('output-file-path=', None, 'path to the output directory'),
847 ]
848
850 """
851 Set default values for options.
852 """
853 # Each user option must be listed here with their default value.
854 self.verboseverbose = 2
855 self.source_path = ''
856 self.source_file = 'mcd_astandard'
857 self.output_file_path = ''
858 self.base_path = ''
859 self.scratch_path = os.getcwd()
860 self.libs = None
861 self.includes = None
862 self.libpaths = None
863
864 # Select Visual Studio version in dependence of operating system.
865 if sys.getwindowsversion() >= (10, 0, 0):
866 # Jenkins2 // Windows 10
867 self.msvsc = "vs2015"
868 else:
869 # Jenkins // Windows 7
870 self.msvsc = "vs2010"
871
873 """
874 Post-process options.
875 """
876 if self.source_path:
877 assert os.path.exists(self.source_path), (
878 'Source path to build files '+self.source_path+' does not exist.')
879 if self.base_path:
880 assert os.path.exists(self.base_path), (
881 'Path to base folder '+self.base_path+' does not exist.')
882
883 def _run_command(self, command):
884 """
885 Execute build command
886 """
887 import PyXMake.Build.Make as pyx # @UnresolvedImport // Take care to set paths to PyXMake properly
888
889 # Execute custom commands directly, but utilize PyXMake syntax to set up the appropriate environment.
890 CBuild = pyx.Custom(self._PACKAGE_NAME, self.source_file, msvsc=self.msvsc, scratch=self.scratch_path, verbose=self.verboseverbose)
891 CBuild.SourcePath(self.source_path)
892 CBuild.OutputPath(self.output_file_path, files=self.copyfiles)
893 CBuild.Preprocessing('fpp /P /e', inend='.f', outend='.for')
894 CBuild.Build(command)
895 if self.includes:
896 CBuild.AddIncludePath(self.includes)
897 if self.libpaths:
898 CBuild.AddDependencyPath(self.libpaths)
899 if self.libs:
900 CBuild.UseLibraries(self.libs)
901 CBuild.create()
902
903class abq_mcodac(pyx_custom): # pragma: no cover
904 """
905 Runs the build process of MCODAC for ABAQUS.
906 """
907 # Set class defining attributes.
908 _PACKAGE_NAME = 'mcd_abaqus'
909 _MAKE_OPT = 6
910
911 def _create_command(self):
912 from PyXMake import VTL # @UnresolvedImport
913 from PyXMake.Tools import Utility # @UnresolvedImport
914
915 # Architecture dependencies
916 if (sys.version_info < (3, 0)):
917 raise NotImplementedError
918
919 elif (sys.version_info > (3, 0)):
920 self.copyfiles = ["standardU.dll","explicitU-D.dll"]
921 self.libslibs = "mcd_corex64"
922 self.includesincludes = [os.path.join(self.base_pathbase_path,"include",Utility.GetPlatform(),Utility.GetArchitecture(), x)
923 for x in VTL.GetIncludeDirectory(self.base_pathbase_path, 0, 4, Utility.GetArchitecture())]
924 self.includesincludes.append(os.path.join(self.base_pathbase_path,"include", Utility.GetPlatform(), Utility.GetArchitecture()))
925 self.libpathslibpaths = os.path.join(self.base_pathbase_path,"lib",Utility.GetPlatform(),Utility.GetArchitecture())
926
927 return VTL.GetBuildCommand(self._MAKE_OPT)
928
929
930class pylint(_BaseCommandRunner): # pragma: no cover
931 """
932 Runs the pylint command.
933 """
934 _PACKAGE_NAME = "src"
935
936 description = "Runs the pylint command."
937 user_options = [
938 ("command=", None, "Path and name of the command line tool."),
939 ("out=", None, "Specifies the output type (html, parseable). Default: html")]
940
941 def initialize_options(self):
942 self.command = "pylint"
943 self.out = "html"
944 self.output_file_path = "build/pylint.txt"
945
946 def finalize_options(self):
947 self.verboseverbose = self.distribution.verbose
948 if self.out == "parseable":
949 self.output_file_path = "build/pylint.txt"
950
951 def _create_command(self):
952 return (
953 "{0} --rcfile=dev/pylintrc --output-format=parseable src > {3}".
954 format(self.command, self.out, self._PACKAGE_NAME, self.output_file_path))
955
956 def _perform_post_actions(self):
957 if self.out == "parseable":
958 new_content = list()
959 with open(self.output_file_path, "rb") as file_object:
960 for line in file_object.readlines():
961 line = line.replace("\\", "/")
962 new_content.append(line)
963 with open(self.output_file_path, "wb") as file_object:
964 file_object.writelines(new_content)
965
966
967class _BaseTest(_BaseCommandRunner): # pragma: no cover
968 """
969 Base class for all test classes
970 """
971 description = "Runs all unit tests using py.test."
972 user_options = [
973 ("command=", None, "Path and name of the command line tool."),
974 ("out=", None, "Specifies the output format of the test results." \
975 + "Formats: xml, standard out. Default: standard out."),
976 ("covout=", None, "Specifies the output format of the coverage report." \
977 + "Formats: xml, html.")]
978
979 def initialize_options(self):
980 self.command = "py.test"
981 self.out = None
982 self.covout = None
983
984 def finalize_options(self):
985 self.verboseverbose = self.distribution.verbose
986
987class Test(_BaseTest): # pragma: no cover
988 """
989 Runs all unit tests.
990 """
991 def _create_command(self):
992 options = " test"
993 if self.outout == "xml":
994 options = "--junitxml=build/xunit.xml test"
995 if not self.covout is None:
996 options = (
997 "--cov=src --cov-report={0} --cov-config=dev/coveragerc {1}".format(self.covout, options))
998 return "py.test --cov=src --cov-report=xml --cov-config=dev/coveragerc --junitxml=build/xunit.xml test -m \"not long and not indevelopment\""
999
1000class pyx_pytest(_BaseTest): # pragma: no cover
1001 """
1002 Base class for encapsulating pytest commands.
1003 """
1004 _PACKAGE_NAME = ''
1005
1006 description = "Run predefined unit tests using Pytest."
1007 user_options = [
1008 # The format is (long option, short option, description).
1009 ('output-file-path=', None, 'path to the output directory'),
1010 ('source-path=', None, 'path to the folder holding source files'),
1011 ('scratch-path=', None, 'path to scratch folder where all temporary data is located during the build event'),
1012 ('verbose=', None, 'controls the logging level (0 - Nothing, 2- Everything) Default: 0 - Nothing'),
1013 ]
1014
1016 """
1017 Set default values for all options.
1018 """
1019 # Each user option must be listed here with their default value.
1020 self.verboseverboseverbose = 0
1021 self.source_path = ''
1022 self.output_file_path = os.getcwd()
1023 self.scratch_path = os.getcwd()
1024 self.include = None
1025
1026 def _run_command(self, command):
1027 """
1028 Execute test command
1029 """
1030 from PyXMake.Build import Make ; # @UnresolvedImport
1031 # Command is not used here
1032 _ = command ; include = [] ;
1033 # Are additional dependencies given? Defaults to empty lists
1034 if not include: include = self.include
1035 # Run an unit-test setup
1036 Coverage = Make.Coverage(self._PACKAGE_NAME, self.source_path);
1037 Coverage.OutputPath(self.output_file_path);
1038 if include: Coverage.AddIncludePath(include);
1039 Coverage.create() ;
1040
1041class pytest_pyxmake(pyx_pytest): # pragma: no cover
1042 """
1043 Runs the test command for PyXMake using PyTest.
1044 """
1045 _PACKAGE_NAME = 'PyXMake'
1046
1047 def _create_command(self):
1048 from PyXMake.Tools import Utility # @UnresolvedImport
1049 # Set relative path & dependencies
1050 if not self.source_pathsource_path: self.source_pathsource_path = Utility.GetPyXMakePath()
1051 self.includeinclude = [ os.path.join(self.source_pathsource_path,"VTL","examples",'pyx_gfortran.py'),
1052 os.path.join(self.source_pathsource_path,"VTL","examples",'pyx_py2x.py'),
1053 os.path.join(self.source_pathsource_path,"VTL","examples",'pyx_doxygen.py'),
1054 os.path.join(self.source_pathsource_path,"VTL","examples",'pyx_openapi.py'),
1055 os.path.join(self.source_pathsource_path,"VTL","examples",'pyx_pyreq.py') ]
1056
1057class InDevelopmentTest(_BaseTest): # pragma: no cover
1058 """
1059 Runs all unit tests.
1060 """
1061 def _create_command(self):
1062 options = " test"
1063 if self.outout == "xml":
1064 options = "--junitxml=build/xunit.xml test"
1065 if not self.covout is None:
1066 options = (
1067 "--cov=src --cov-report={0} --cov-config=dev/coveragerc {1}".format(self.covout, options))
1068 return "py.test test --junitxml=build/xunit.xml -s -m \"indevelopment\""
1069
1070
1071class LongTest(_BaseTest): # pragma: no cover
1072 """
1073 Runs all unit tests.
1074 """
1075 def _create_command(self):
1076 options = " test"
1077 if self.outout == "xml":
1078 options = "--junitxml=build/xunit.xml test"
1079 if not self.covout is None:
1080 options = (
1081 "--cov=src --cov-report={0} --cov-config=dev/coveragerc {1}".format(self.covout, options))
1082 return "py.test --cov=src --cov-report=xml --cov-config=dev/coveragerc --junitxml=build/xunit.xml test -s"
1083
1084
1085def _perform_setup(): # pragma: no cover
1086 _set_pythonpath()
1087 _run_setup()
1088
1089
1090def _set_pythonpath(): # pragma: no cover
1091 python_path = []
1092 python_path = os.pathsep.join(python_path) + os.pathsep + os.environ.get("PYTHONPATH", "")
1093 os.environ["PYTHONPATH"] = python_path
1094
1095
1096def _run_setup(): # pragma: no cover
1097
1098 version = 1.0
1099 attributes = {}
1100
1101 if os.path.exists('test/__pycache__'):
1102 shutil.rmtree('test/__pycache__')
1103
1104 # Add license file explicitly to setup
1105 if parse(setuptools.__version__) > parse("42.0.0"):
1106 attributes.update({"license_files" : ('LICENSE*',"LICENSE")})
1107 warnings.filterwarnings("ignore") #@UndefinedVariable
1108
1109 setuptools.setup(
1110 name='My testing',
1111 version=version,
1112 cmdclass={"clean": Clean,
1113 "doxy_pyxmake": doxy_pyxmake,
1114 "doxy_boxbeam": doxy_boxbeam,
1115 "doxy_mcdcore": doxy_mcdcore,
1116 "doxy_mcdpycodac": doxy_mcdpycodac,
1117 "doxy_mcdmapper": doxy_mcdmapper,
1118 "doxy_mcdsubbuck": doxy_mcdsubbuck,
1119 "sphinx_stmlab": sphinx_stmlab,
1120 "f2py_beos": f2py_beos,
1121 "f2py_boxbeam": f2py_boxbeam,
1122 "f2py_mcodac": f2py_mcodac,
1123 "java_boxbeam": java_boxbeam,
1124 "java_mcodac": java_mcodac,
1125 "win_boxbeam": win_boxbeam,
1126 "win_mcodac": win_mcodac,
1127 "abq_mcodac": abq_mcodac,
1128 "app_pycodac": app_pycodac,
1129 "bundle_pycodac": bundle_pycodac,
1130 "shorttest": Test,
1131 "longtest": LongTest,
1132 "indevelopmenttest": InDevelopmentTest,
1133 "pytest_pyxmake": pytest_pyxmake,
1134 "pylint": pylint
1135 },
1136 author="Deutsches Zentrum fuer Luft- und Raumfahrt e.V. (DLR)",
1137 author_email="marc.garbade@dlr.de",
1138 maintainer="Deutsches Zentrum fuer Luft- und Raumfahrt e.V. (DLR)",
1139 maintainer_email="marc.garbade@dlr.de",
1140 license="Copyright DLR",
1141 platforms=["Linux", "Unix", "Windows"],
1142 packages=setuptools.find_packages("src"),
1143 include_package_data=True,
1144 package_dir={"" : "src"},
1145 command_options={
1146 "build_sphinx": {
1147 "version": ("test.py", version),
1148 "release": ("test.py", version)}},
1149 **attributes
1150 )
1151
1152
1153if __name__ == "__main__":
1154 _perform_setup()
Add PyXMake source folder to system path (if not already present).
Definition stm_make.py:54
_run_command(self, command)
Definition stm_make.py:138
_run_command(self, command)
Definition stm_make.py:585
Create a make object to define the building environment.
Definition Make.py:1
Module containing all relevant modules and scripts associated with the building process.
Definition __init__.py:1
Module of basic functions.
Definition Utility.py:1
Module containing basic functionalities defined for convenience.
Definition __init__.py:1
GetBuildCommand(make_opt=0, _format="fixed", _arch=Utility.GetArchitecture())
Definition __init__.py:404
GetSourceCode(key_opt=0)
Definition __init__.py:311