1- import re , os , typing , dataclasses
1+ import re , os , typing , hashlib , dataclasses
22
33from .common import MFCException , system , delete_directory , create_directory
44from .state import ARG , CFG
55from .printer import cons
6- from .run .input import MFCInputFile
7-
6+ from .run import input
87
98@dataclasses .dataclass
109class MFCTarget :
@@ -26,19 +25,27 @@ def compute(self) -> typing.Set:
2625 isDefault : bool # Should it be built by default? (unspecified -t | --targets)
2726 isRequired : bool # Should it always be built? (no matter what -t | --targets is)
2827 requires : Dependencies # Build dependencies of the target
28+ runOrder : int # For MFC Targets: Order in which targets should logically run
2929
3030 def __hash__ (self ) -> int :
3131 return hash (self .name )
3232
3333 # Get path to directory that will store the build files
3434 def get_build_dirpath (self ) -> str :
35+ subdir = 'dependencies' if self .isDependency else CFG ().make_slug ()
36+
37+ if not self .isDependency and ARG ("case_optimization" ):
38+ m = hashlib .sha256 ()
39+ m .update (input .load ().get_fpp (self ).encode ())
40+ subdir = f"{ subdir } -{ m .hexdigest ()[:6 ]} "
41+
3542 return os .sep .join ([
3643 os .getcwd (),
3744 "build" ,
38- [ CFG (). make_slug (), 'dependencies' ][ int ( self . isDependency )] ,
45+ subdir ,
3946 self .name
4047 ])
41-
48+
4249 # Get the directory that contains the target's CMakeLists.txt
4350 def get_cmake_dirpath (self ) -> str :
4451 # The CMakeLists.txt file is located:
@@ -84,31 +91,16 @@ def get_configuration_txt(self) -> typing.Optional[dict]:
8491
8592 return None
8693
87-
88- def build (self , history : typing .Set [str ] = None ):
89- if history is None :
90- history = set ()
91-
92- if self .name in history :
93- return
94-
95- history .add (self .name )
96-
97- build_targets (REQUIRED_TARGETS , history )
98-
99- cons .print (f"[bold]Building [magenta]{ self .name } [/magenta]:[/bold]" )
100- cons .indent ()
101-
94+ def is_buildable (self ) -> bool :
10295 if ARG ("no_build" ):
103- cons .print ("--no-build specified, skipping..." )
104- cons .unindent ()
105- return
96+ return False
10697
10798 if self .isDependency and ARG (f"no_{ self .name } " ):
108- cons .print (f"--no-{ self .name } given, skipping..." )
109- cons .unindent ()
110- return
99+ return False
111100
101+ return True
102+
103+ def configure (self ):
112104 build_dirpath = self .get_build_dirpath ()
113105 cmake_dirpath = self .get_cmake_dirpath ()
114106 install_dirpath = self .get_install_dirpath ()
@@ -144,42 +136,35 @@ def build(self, history: typing.Set[str] = None):
144136 flags .append (f"-DMFC_OpenACC={ 'ON' if ARG ('gpu' ) else 'OFF' } " )
145137
146138 configure = ["cmake" ] + flags + ["-S" , cmake_dirpath , "-B" , build_dirpath ]
147- build = ["cmake" , "--build" , build_dirpath ,
148- "--target" , self .name ,
149- "-j" , ARG ("jobs" ),
150- "--config" , 'Debug' if ARG ('debug' ) else 'Release' ]
151- if ARG ('verbose' ):
152- build .append ("--verbose" )
153139
154- install = ["cmake" , "--install" , build_dirpath ]
140+ delete_directory (build_dirpath )
141+ create_directory (build_dirpath )
155142
156- if not self .is_configured ():
157- build_targets (self .requires .compute (), history )
143+ if system (configure , no_exception = True ) != 0 :
144+ raise MFCException (f"Failed to configure the [bold magenta]{ self .name } [/bold magenta] target." )
145+
146+
147+ def build (self ):
148+ input .load ({}).generate_fpp (self )
158149
159- delete_directory (build_dirpath )
160- create_directory (build_dirpath )
150+ build = ["cmake" , "--build" , self .get_build_dirpath (),
151+ "--target" , self .name ,
152+ "-j" , ARG ("jobs" ),
153+ "--config" , 'Debug' if ARG ('debug' ) else 'Release' ]
154+ if ARG ('verbose' ):
155+ build .append ("--verbose" )
161156
162- if system (configure , no_exception = True ) != 0 :
163- raise MFCException (f"Failed to configure the [bold magenta]{ self .name } [/bold magenta] target." )
157+ system (build , exception_text = f"Failed to build the [bold magenta]{ self .name } [/bold magenta] target." )
164158
165- if not self . isDependency and ARG ( "command" ) == "build" :
166- MFCInputFile ( " " , "" , {}). generate ( self , bOnlyFPPs = True )
159+ def install ( self ) :
160+ install = [ "cmake " , "--install " , self . get_build_dirpath ()]
167161
168- system (build , exception_text = f"Failed to build the [bold magenta]{ self .name } [/bold magenta] target." )
169162 system (install , exception_text = f"Failed to install the [bold magenta]{ self .name } [/bold magenta] target." )
170163
171- cons .print (no_indent = True )
172- cons .unindent ()
173-
174164 def clean (self ):
175- cons .print (f"[bold]Cleaning [magenta]{ self .name } [/magenta]:[/bold]" )
176- cons .indent ()
177-
178165 build_dirpath = self .get_build_dirpath ()
179166
180167 if not os .path .isdir (build_dirpath ):
181- cons .print ("Target not configured. Nothing to clean." )
182- cons .unindent ()
183168 return
184169
185170 clean = ["cmake" , "--build" , build_dirpath , "--target" , "clean" ,
@@ -190,17 +175,15 @@ def clean(self):
190175
191176 system (clean , exception_text = f"Failed to clean the [bold magenta]{ self .name } [/bold magenta] target." )
192177
193- cons .unindent ()
194-
195178
196- FFTW = MFCTarget ('fftw' , ['-DMFC_FFTW=ON' ], True , False , False , MFCTarget .Dependencies ([], [], []))
197- HDF5 = MFCTarget ('hdf5' , ['-DMFC_HDF5=ON' ], True , False , False , MFCTarget .Dependencies ([], [], []))
198- SILO = MFCTarget ('silo' , ['-DMFC_SILO=ON' ], True , False , False , MFCTarget .Dependencies ([HDF5 ], [], []))
199- PRE_PROCESS = MFCTarget ('pre_process' , ['-DMFC_PRE_PROCESS=ON' ], False , True , False , MFCTarget .Dependencies ([], [], []))
200- SIMULATION = MFCTarget ('simulation' , ['-DMFC_SIMULATION=ON' ], False , True , False , MFCTarget .Dependencies ([], [FFTW ], []))
201- POST_PROCESS = MFCTarget ('post_process' , ['-DMFC_POST_PROCESS=ON' ], False , True , False , MFCTarget .Dependencies ([FFTW , SILO ], [], []))
202- SYSCHECK = MFCTarget ('syscheck' , ['-DMFC_SYSCHECK=ON' ], False , False , True , MFCTarget .Dependencies ([], [], []))
203- DOCUMENTATION = MFCTarget ('documentation' , ['-DMFC_DOCUMENTATION=ON' ], False , False , False , MFCTarget .Dependencies ([], [], []))
179+ FFTW = MFCTarget ('fftw' , ['-DMFC_FFTW=ON' ], True , False , False , MFCTarget .Dependencies ([], [], []), - 1 )
180+ HDF5 = MFCTarget ('hdf5' , ['-DMFC_HDF5=ON' ], True , False , False , MFCTarget .Dependencies ([], [], []), - 1 )
181+ SILO = MFCTarget ('silo' , ['-DMFC_SILO=ON' ], True , False , False , MFCTarget .Dependencies ([HDF5 ], [], []), - 1 )
182+ PRE_PROCESS = MFCTarget ('pre_process' , ['-DMFC_PRE_PROCESS=ON' ], False , True , False , MFCTarget .Dependencies ([], [], []), 0 )
183+ SIMULATION = MFCTarget ('simulation' , ['-DMFC_SIMULATION=ON' ], False , True , False , MFCTarget .Dependencies ([], [FFTW ], []), 1 )
184+ POST_PROCESS = MFCTarget ('post_process' , ['-DMFC_POST_PROCESS=ON' ], False , True , False , MFCTarget .Dependencies ([FFTW , SILO ], [], []), 2 )
185+ SYSCHECK = MFCTarget ('syscheck' , ['-DMFC_SYSCHECK=ON' ], False , False , True , MFCTarget .Dependencies ([], [], []), - 1 )
186+ DOCUMENTATION = MFCTarget ('documentation' , ['-DMFC_DOCUMENTATION=ON' ], False , False , False , MFCTarget .Dependencies ([], [], []), - 1 )
204187
205188TARGETS = { FFTW , HDF5 , SILO , PRE_PROCESS , SIMULATION , POST_PROCESS , SYSCHECK , DOCUMENTATION }
206189
@@ -230,17 +213,55 @@ def get_dependency_install_dirpath() -> str:
230213 raise MFCException ("No dependency target found." )
231214
232215
216+ def build_target (target : typing .Union [MFCTarget , str ], history : typing .Set [str ] = None ):
217+ if history is None :
218+ history = set ()
219+
220+ t = get_target (target )
221+
222+ if t .name in history or not t .is_buildable ():
223+ return
224+
225+ history .add (t .name )
226+
227+ build_targets (t .requires .compute (), history )
228+
229+ if not t .is_configured ():
230+ t .configure ()
231+
232+ t .build ()
233+ t .install ()
234+
233235def build_targets (targets : typing .Iterable [typing .Union [MFCTarget , str ]], history : typing .Set [str ] = None ):
234236 if history is None :
235237 history = set ()
238+
239+ for target in list (REQUIRED_TARGETS ) + targets :
240+ build_target (target , history )
241+
242+
243+ def clean_target (target : typing .Union [MFCTarget , str ], history : typing .Set [str ] = None ):
244+ if history is None :
245+ history = set ()
246+
247+ t = get_target (target )
236248
237- for target in targets :
238- get_target ( target ). build ( history )
249+ if t . name in history or not t . is_buildable () :
250+ return
239251
252+ history .add (t .name )
253+
254+ t .clean ()
255+
256+
257+ def clean_targets (targets : typing .Iterable [typing .Union [MFCTarget , str ]], history : typing .Set [str ] = None ):
258+ if history is None :
259+ history = set ()
240260
241- def clean_targets (targets : typing .Iterable [typing .Union [MFCTarget , str ]]):
242- for target in targets :
243- get_target (target ).clean ()
261+ for target in list (REQUIRED_TARGETS ) + targets :
262+ t = get_target (target )
263+ if t .is_configured ():
264+ t .clean ()
244265
245266
246267def get_configured_targets () -> typing .List [MFCTarget ]:
0 commit comments