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,35 @@ 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
+ input .load ({}).generate_fpp (self )
158
149
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" )
161
156
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." )
164
158
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 ()]
167
161
168
- system (build , exception_text = f"Failed to build the [bold magenta]{ self .name } [/bold magenta] target." )
169
162
system (install , exception_text = f"Failed to install the [bold magenta]{ self .name } [/bold magenta] target." )
170
163
171
- cons .print (no_indent = True )
172
- cons .unindent ()
173
-
174
164
def clean (self ):
175
- cons .print (f"[bold]Cleaning [magenta]{ self .name } [/magenta]:[/bold]" )
176
- cons .indent ()
177
-
178
165
build_dirpath = self .get_build_dirpath ()
179
166
180
167
if not os .path .isdir (build_dirpath ):
181
- cons .print ("Target not configured. Nothing to clean." )
182
- cons .unindent ()
183
168
return
184
169
185
170
clean = ["cmake" , "--build" , build_dirpath , "--target" , "clean" ,
@@ -190,17 +175,15 @@ def clean(self):
190
175
191
176
system (clean , exception_text = f"Failed to clean the [bold magenta]{ self .name } [/bold magenta] target." )
192
177
193
- cons .unindent ()
194
-
195
178
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 )
204
187
205
188
TARGETS = { FFTW , HDF5 , SILO , PRE_PROCESS , SIMULATION , POST_PROCESS , SYSCHECK , DOCUMENTATION }
206
189
@@ -230,17 +213,55 @@ def get_dependency_install_dirpath() -> str:
230
213
raise MFCException ("No dependency target found." )
231
214
232
215
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
+
233
235
def build_targets (targets : typing .Iterable [typing .Union [MFCTarget , str ]], history : typing .Set [str ] = None ):
234
236
if history is None :
235
237
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 )
236
248
237
- for target in targets :
238
- get_target ( target ). build ( history )
249
+ if t . name in history or not t . is_buildable () :
250
+ return
239
251
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 ()
240
260
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 ()
244
265
245
266
246
267
def get_configured_targets () -> typing .List [MFCTarget ]:
0 commit comments