Reputation: 12691
We have hundreds of macros across several autocall libraries that I'd like to compile using the MSTORE
facility.
The problem is that some of those libraries are used on other sites - and we don't want to add /STORE
to every definition, as then it is required to use the MSTORED
option.
I guess the answer is to add /* /STORE */
at the end of every %macro
statement, so that the .sas program files can be updated with a regular expression (or some other text replacement technique) on every redeploy, but this seems like a messy workaround.
Is it possible / in some way supported, to compile regular (unmodified) autocall macros and store the definitions? Eg by %inc
'ing each one and saving the work macro catalog, or something like that?
Upvotes: 2
Views: 286
Reputation: 12691
Here was the approach I took for compilation (of course there are many alternative ways). The locations to query can be extracted from:
%put %sysfunc(getoption(sasautos));
The approach relies on macros being closed off with )/*/STORE SOURCE*/;
as follows:
%macro some_macro(var1=x, var2=y
)/*/STORE SOURCE*/;
The SAS code has to be a program, as you can't create a stored compiled macro from within a macro.
/* set mstore options */
options mstored sasmstore=yourlib;
/* get list of macros */
/* taken from macrocore library */
/*https://github.com/sasjs/core/blob/main/base/mp_dirlist.sas*/
%mp_dirlist(path=/location/one,outds=in1)
%mp_dirlist(path=/location/two,outds=in2)
/* set up a temporary fileref */
filename tmp temp;
/**
* write each source macro to the fileref
* and switch on the STORE option
*/
data want;
set in1 in2;
infile dummy filevar=filepath end=last ;
file tmp;
do until(last);
file tmp;
input;
if _infile_=')/*/STORE SOURCE*/;' then put ')/STORE SOURCE;';
else put _infile_;
end;
run;
%inc tmp; /* compile macros */
filename tmp clear; /* clear ref */
Upvotes: 2
Reputation: 51601
What is the problem that you had?
First compile all of your autocall macros. Say you have a fileref named MYMACS that points to the directory with the source code.
%include mymacs(macro1,macro2,.....);
You might use a program to search for all of the source files so that you could automate generating the %include statement(s). Or you could use a datastep and copy all of the source files into a single temporary file and include that.
filename src temp;
data _null_;
infile "&inpath\*.sas" ;
file src ;
input;
put _infile_;
run;
%inc src ;
Then copy the WORK catalog to you a new location. Note that the name is different if you are running SAS on an application server. In that case try copying from WORK.SASMAC1
instead of WORK.SASMACR
.
libname out base "&path";
proc catalog cat=work.sasmacr et=macro ;
copy out=out.sasmacr ;
run;
quit;
You can test if it worked by clearing your current work macro catalog, so you know SAS is not finding the macro there, and setting options to point to the new catalog of compiled macros.
proc catalog cat=work.sasmacr kill force ;
quit;
options mrecall mstored sasmstore=out ;
Then trying to run one of the copied compiled macros.
Now start up a new session and try using the compiled macros in that session.
Upvotes: 2
Reputation: 9569
I won't say definitively that this isn't possible, but I can report that I tried to do the same thing some time ago and got stuck on the same point. I was also unable to find any way of doing this other than adding /store
to every %macro
statement.
I vaguely remember that I was able to upload the work.sasmacr
catalogue from one session to another on the same machine (after first compiling a few autocall macros to populate it), but the other session didn't recognise the macro definitions from transferred catalogue even though the appropriate options were set for using stored compiled macros.
My motivation was different from yours - I was looking for a way to define a macro in one session and execute it in another without saving it in an autocall folder or %including
it in both sessions - but the conclusion was the same.
Upvotes: 3