@@ -48,18 +48,21 @@ class CompilerOptions:
4848 Attributes:
4949 stanc_options - stanc compiler flags, options
5050 cpp_options - makefile options (NAME=value)
51+ user_header - path to a user .hpp file to include during compilation
5152 """
5253
5354 def __init__ (
5455 self ,
5556 * ,
5657 stanc_options : Optional [Dict [str , Any ]] = None ,
5758 cpp_options : Optional [Dict [str , Any ]] = None ,
59+ user_header : Optional [str ] = None ,
5860 logger : Optional [logging .Logger ] = None ,
5961 ) -> None :
6062 """Initialize object."""
6163 self ._stanc_options = stanc_options if stanc_options is not None else {}
6264 self ._cpp_options = cpp_options if cpp_options is not None else {}
65+ self ._user_header = user_header if user_header is not None else ''
6366 if logger is not None :
6467 get_logger ().warning (
6568 "Parameter 'logger' is deprecated."
@@ -88,6 +91,7 @@ def validate(self) -> None:
8891 """
8992 self .validate_stanc_opts ()
9093 self .validate_cpp_opts ()
94+ self .validate_user_header ()
9195
9296 def validate_stanc_opts (self ) -> None :
9397 """
@@ -104,17 +108,15 @@ def validate_stanc_opts(self) -> None:
104108 get_logger ().info ('ignoring compiler option: %s' , key )
105109 ignore .append (key )
106110 elif key not in STANC_OPTS :
107- raise ValueError (
108- 'unknown stanc compiler option: {}' .format (key )
109- )
111+ raise ValueError (f'unknown stanc compiler option: { key } ' )
110112 elif key == 'include_paths' :
111113 paths = val
112114 if isinstance (val , str ):
113115 paths = val .split (',' )
114116 elif not isinstance (val , list ):
115117 raise ValueError (
116118 'Invalid include_paths, expecting list or '
117- 'string, found type: {}.' . format ( type (val ))
119+ f 'string, found type: { type (val )} .'
118120 )
119121 elif key == 'use-opencl' :
120122 if self ._cpp_options is None :
@@ -149,10 +151,48 @@ def validate_cpp_opts(self) -> None:
149151 val = self ._cpp_options [key ]
150152 if not isinstance (val , int ) or val < 0 :
151153 raise ValueError (
152- '{ } must be a non-negative integer value,'
153- ' found {}.' . format ( key , val )
154+ f' { key } must be a non-negative integer value,'
155+ f ' found { val } .'
154156 )
155157
158+ def validate_user_header (self ) -> None :
159+ """
160+ User header exists.
161+ Raise ValueError if bad config is found.
162+ """
163+ if self ._user_header != "" :
164+ if not (
165+ os .path .exists (self ._user_header )
166+ and os .path .isfile (self ._user_header )
167+ ):
168+ raise ValueError (
169+ f"User header file { self ._user_header } cannot be found"
170+ )
171+ if self ._user_header [- 4 :] != '.hpp' :
172+ raise ValueError (
173+ f"Header file must end in .hpp, got { self ._user_header } "
174+ )
175+ if "allow_undefined" not in self ._stanc_options :
176+ self ._stanc_options ["allow_undefined" ] = True
177+ # set full path
178+ self ._user_header = os .path .abspath (self ._user_header )
179+
180+ if ' ' in self ._user_header :
181+ raise ValueError (
182+ "User header must be in a location with no spaces in path!"
183+ )
184+
185+ if (
186+ 'USER_HEADER' in self ._cpp_options
187+ and self ._user_header != self ._cpp_options ['USER_HEADER' ]
188+ ):
189+ raise ValueError (
190+ "Disagreement in user_header C++ options found!\n "
191+ f"{ self ._user_header } , { self ._cpp_options ['USER_HEADER' ]} "
192+ )
193+
194+ self ._cpp_options ['USER_HEADER' ] = self ._user_header
195+
156196 def add (self , new_opts : "CompilerOptions" ) -> None : # noqa: disable=Q000
157197 """Adds options to existing set of compiler options."""
158198 if new_opts .stanc_options is not None :
@@ -167,6 +207,8 @@ def add(self, new_opts: "CompilerOptions") -> None: # noqa: disable=Q000
167207 if new_opts .cpp_options is not None :
168208 for key , val in new_opts .cpp_options .items ():
169209 self ._cpp_options [key ] = val
210+ if new_opts ._user_header != '' and self ._user_header == '' :
211+ self ._user_header = new_opts ._user_header
170212
171213 def add_include_path (self , path : str ) -> None :
172214 """Adds include path to existing set of compiler options."""
@@ -191,10 +233,10 @@ def compose(self) -> List[str]:
191233 )
192234 )
193235 elif key == 'name' :
194- opts .append ('STANCFLAGS+=--{}={}' . format ( key , val ) )
236+ opts .append (f 'STANCFLAGS+=--name= { val } ' )
195237 else :
196- opts .append ('STANCFLAGS+=--{}' . format ( key ) )
238+ opts .append (f 'STANCFLAGS+=--{ key } ' )
197239 if self ._cpp_options is not None and len (self ._cpp_options ) > 0 :
198240 for key , val in self ._cpp_options .items ():
199- opts .append ('{ }={}' . format ( key , val ) )
241+ opts .append (f' { key } ={ val } ' )
200242 return opts
0 commit comments