1
- import re , os , typing , dataclasses
1
+ import re , os , typing , hashlib , dataclasses
2
2
3
3
from .common import MFCException , system , delete_directory , create_directory
4
4
from .state import ARG , CFG
5
5
from .printer import cons
6
- from .run .input import MFCInputFile
7
-
6
+ from .run import input
8
7
9
8
@dataclasses .dataclass
10
9
class MFCTarget :
@@ -26,19 +25,27 @@ def compute(self) -> typing.Set:
26
25
isDefault : bool # Should it be built by default? (unspecified -t | --targets)
27
26
isRequired : bool # Should it always be built? (no matter what -t | --targets is)
28
27
requires : Dependencies # Build dependencies of the target
28
+ runOrder : int # For MFC Targets: Order in which targets should logically run
29
29
30
30
def __hash__ (self ) -> int :
31
31
return hash (self .name )
32
32
33
33
# Get path to directory that will store the build files
34
34
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
+
35
42
return os .sep .join ([
36
43
os .getcwd (),
37
44
"build" ,
38
- [ CFG (). make_slug (), 'dependencies' ][ int ( self . isDependency )] ,
45
+ subdir ,
39
46
self .name
40
47
])
41
-
48
+
42
49
# Get the directory that contains the target's CMakeLists.txt
43
50
def get_cmake_dirpath (self ) -> str :
44
51
# The CMakeLists.txt file is located:
@@ -84,31 +91,16 @@ def get_configuration_txt(self) -> typing.Optional[dict]:
84
91
85
92
return None
86
93
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 :
102
95
if ARG ("no_build" ):
103
- cons .print ("--no-build specified, skipping..." )
104
- cons .unindent ()
105
- return
96
+ return False
106
97
107
98
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
111
100
101
+ return True
102
+
103
+ def configure (self ):
112
104
build_dirpath = self .get_build_dirpath ()
113
105
cmake_dirpath = self .get_cmake_dirpath ()
114
106
install_dirpath = self .get_install_dirpath ()
@@ -144,42 +136,36 @@ def build(self, history: typing.Set[str] = None):
144
136
flags .append (f"-DMFC_OpenACC={ 'ON' if ARG ('gpu' ) else 'OFF' } " )
145
137
146
138
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" )
153
139
154
- install = ["cmake" , "--install" , build_dirpath ]
140
+ delete_directory (build_dirpath )
141
+ create_directory (build_dirpath )
155
142
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
+ if ARG ("case_optimization" ):
149
+ input .load ().generate_fpp (self )
158
150
159
- delete_directory (build_dirpath )
160
- create_directory (build_dirpath )
151
+ build = ["cmake" , "--build" , self .get_build_dirpath (),
152
+ "--target" , self .name ,
153
+ "-j" , ARG ("jobs" ),
154
+ "--config" , 'Debug' if ARG ('debug' ) else 'Release' ]
155
+ if ARG ('verbose' ):
156
+ build .append ("--verbose" )
161
157
162
- if system (configure , no_exception = True ) != 0 :
163
- raise MFCException (f"Failed to configure the [bold magenta]{ self .name } [/bold magenta] target." )
158
+ system (build , exception_text = f"Failed to build the [bold magenta]{ self .name } [/bold magenta] target." )
164
159
165
- if not self . isDependency and ARG ( "command" ) == "build" :
166
- MFCInputFile ( " " , "" , {}). generate ( self , bOnlyFPPs = True )
160
+ def install ( self ) :
161
+ install = [ "cmake " , "--install " , self . get_build_dirpath ()]
167
162
168
- system (build , exception_text = f"Failed to build the [bold magenta]{ self .name } [/bold magenta] target." )
169
163
system (install , exception_text = f"Failed to install the [bold magenta]{ self .name } [/bold magenta] target." )
170
164
171
- cons .print (no_indent = True )
172
- cons .unindent ()
173
-
174
165
def clean (self ):
175
- cons .print (f"[bold]Cleaning [magenta]{ self .name } [/magenta]:[/bold]" )
176
- cons .indent ()
177
-
178
166
build_dirpath = self .get_build_dirpath ()
179
167
180
168
if not os .path .isdir (build_dirpath ):
181
- cons .print ("Target not configured. Nothing to clean." )
182
- cons .unindent ()
183
169
return
184
170
185
171
clean = ["cmake" , "--build" , build_dirpath , "--target" , "clean" ,
@@ -190,17 +176,15 @@ def clean(self):
190
176
191
177
system (clean , exception_text = f"Failed to clean the [bold magenta]{ self .name } [/bold magenta] target." )
192
178
193
- cons .unindent ()
194
-
195
179
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 ([], [], []))
180
+ FFTW = MFCTarget ('fftw' , ['-DMFC_FFTW=ON' ], True , False , False , MFCTarget .Dependencies ([], [], []), - 1 )
181
+ HDF5 = MFCTarget ('hdf5' , ['-DMFC_HDF5=ON' ], True , False , False , MFCTarget .Dependencies ([], [], []), - 1 )
182
+ SILO = MFCTarget ('silo' , ['-DMFC_SILO=ON' ], True , False , False , MFCTarget .Dependencies ([HDF5 ], [], []), - 1 )
183
+ PRE_PROCESS = MFCTarget ('pre_process' , ['-DMFC_PRE_PROCESS=ON' ], False , True , False , MFCTarget .Dependencies ([], [], []), 0 )
184
+ SIMULATION = MFCTarget ('simulation' , ['-DMFC_SIMULATION=ON' ], False , True , False , MFCTarget .Dependencies ([], [FFTW ], []), 1 )
185
+ POST_PROCESS = MFCTarget ('post_process' , ['-DMFC_POST_PROCESS=ON' ], False , True , False , MFCTarget .Dependencies ([FFTW , SILO ], [], []), 2 )
186
+ SYSCHECK = MFCTarget ('syscheck' , ['-DMFC_SYSCHECK=ON' ], False , False , True , MFCTarget .Dependencies ([], [], []), - 1 )
187
+ DOCUMENTATION = MFCTarget ('documentation' , ['-DMFC_DOCUMENTATION=ON' ], False , False , False , MFCTarget .Dependencies ([], [], []), - 1 )
204
188
205
189
TARGETS = { FFTW , HDF5 , SILO , PRE_PROCESS , SIMULATION , POST_PROCESS , SYSCHECK , DOCUMENTATION }
206
190
@@ -230,17 +214,55 @@ def get_dependency_install_dirpath() -> str:
230
214
raise MFCException ("No dependency target found." )
231
215
232
216
217
+ def build_target (target : typing .Union [MFCTarget , str ], history : typing .Set [str ] = None ):
218
+ if history is None :
219
+ history = set ()
220
+
221
+ t = get_target (target )
222
+
223
+ if t .name in history or not t .is_buildable ():
224
+ return
225
+
226
+ history .add (t .name )
227
+
228
+ build_targets (t .requires .compute (), history )
229
+
230
+ if not t .is_configured ():
231
+ t .configure ()
232
+
233
+ t .build ()
234
+ t .install ()
235
+
233
236
def build_targets (targets : typing .Iterable [typing .Union [MFCTarget , str ]], history : typing .Set [str ] = None ):
234
237
if history is None :
235
238
history = set ()
239
+
240
+ for target in list (REQUIRED_TARGETS ) + targets :
241
+ build_target (target , history )
242
+
243
+
244
+ def clean_target (target : typing .Union [MFCTarget , str ], history : typing .Set [str ] = None ):
245
+ if history is None :
246
+ history = set ()
247
+
248
+ t = get_target (target )
236
249
237
- for target in targets :
238
- get_target ( target ). build ( history )
250
+ if t . name in history or not t . is_buildable () :
251
+ return
239
252
253
+ history .add (t .name )
254
+
255
+ t .clean ()
256
+
257
+
258
+ def clean_targets (targets : typing .Iterable [typing .Union [MFCTarget , str ]], history : typing .Set [str ] = None ):
259
+ if history is None :
260
+ history = set ()
240
261
241
- def clean_targets (targets : typing .Iterable [typing .Union [MFCTarget , str ]]):
242
- for target in targets :
243
- get_target (target ).clean ()
262
+ for target in list (REQUIRED_TARGETS ) + targets :
263
+ t = get_target (target )
264
+ if t .is_configured ():
265
+ t .clean ()
244
266
245
267
246
268
def get_configured_targets () -> typing .List [MFCTarget ]:
0 commit comments