Как заставить SAS компилировать макрос каждый раз, когда он вызывается, вместо того, чтобы делать это вручную - PullRequest
1 голос
/ 29 марта 2019

Контекст: Мы используем SAS 9.4 и Enterprise Guide 7.15. В настоящее время мы внедряем несколько новых макросов и, конечно же, должны многое изменить на этом пути. Иногда меньше, иногда больше изменений. Проблема в том, что для того, чтобы изменения работали, SAS требует, чтобы мы вручную скомпилировали код макроса или перезапустили сеанс, который немного утомителен.

Это текущая настройка в нашем главном файле (который вызывает все макросы):

/* Macro options */
     MAUTOSOURCE  sasautos = "<path to macro>" mlogic mlogicnest mprint mprintnest MRECALL

Возможно ли при использовании опции MAUTOSOURCE */ sasautos ="" сообщать SAS каждый раз, когда вызывается макрос, для фактической компиляции макроса вместо использования сохраненного в сеансе макроса? В идеале, макрос должен быть скомпилирован только при выполнении всей строки кода из основного файла (MAUTOSOURCE */ sasautos ="" и т. Д.), В противном случае он должен сохранять скомпилированную версию в сеансе.

Я нашел эту статью (Макро-средство Autocall в среде SAS для Windows) , в которой говорится

После этого SAS будет использовать код, который уже был скомпилирован. Если в макрос внесены изменения, он должен быть Скомпилируется еще раз до вступления изменений в силу.

что, я надеюсь, не означает, что я должен сделать это вручную . Можно ли установить макрокоманду?

Ответы [ 3 ]

3 голосов
/ 29 марта 2019

Для ваших обычных пользователей вы должны установить график выпуска изменений. Пользователи будут знать, что им нужно перезапустить новую сессию после выпуска релиза.

Для ваших разработчиков, которые тестируют изменения по мере их внесения, им просто нужно использовать% INCLUDE для повторной компиляции макроса. Поэтому, если вы знаете, что макрос XYZ изменен, просто запустите:

%include maclib('xyz.sas');

Или вы можете перебрать его и перекомпилировать все макросы в вашей библиотеке автоколонок.

%incldue maclib('*.sas');

Вы могли бы придумать и создать макрос, который очищает фактический каталог скомпилированных макросов. Что-то вроде:

%macro clean_autocall;
proc catalog force c=work.sasmacr;
 save clean_autocall /et=macro;
quit;
options mrecall mautosource;
%mend clean_autocall;

Но если вы используете Enterprise Guide, есть две проблемы.

Сначала по какой-то причине он использует другой каталог для хранения скомпилированных макросов. (Почему?) Я думаю, что это WORK.SASMAC1 вместо WORK.SASMACR.

Второй EG вручную скомпилирует кучу вспомогательных макросов, в которых он нуждается. Я не уверен, есть ли официальный источник для полного списка этих макросов? Вы можете попробовать добавить код в ваш проект, чтобы автоматически создавать список на основе того, какие записи находятся в каталоге при запуске вашего проекта. Вот список, который я сделал 10+ лет назад, когда пытался использовать EG в производственной среде. Но я уверен, что это устарело.

%let s_eg_save= checkfmt checkhotfix
  eclibassign eclibunassign enterpriseguide gaccessible
  _eg_conditional_dropds
;
3 голосов
/ 29 марта 2019

В SAS 9.3 добавлена ​​макрофункция %SYSMACDELETE.Поэтому, если вы просто хотите, чтобы autocall переопределил один макрос, используйте его для удаления текущего определения.

%symacdelete mymacro;

Вот служебный макрос, который будет запрашивать представление SASHELP.VCATALG для поиска скомпилированных макросов в библиотеке WORK.и удалите их.У этого есть варианты или перечислить имена макросов, чтобы удалить или сохранить.Обратите внимание, что обычные сеансы SAS используют WORK.SASMACR для хранения скомпилированных макросов.Но SAS / Studio и EG (и, возможно, другие способы запуска SAS) вместо этого используют WORK.SASMAC1.

https://github.com/sasutils/macros/blob/master/macdelete.sas

%macro macdelete(delete,keep);
/*----------------------------------------------------------------------------
Remove compiled macros using %SYSMACDELETE macro statement.

Use DELETE parameter to list macro names to delete.
Use KEEP parameter to list macro names to NOT delete.
Calling it with no values will delete all macros not currently running.
----------------------------------------------------------------------------*/
%local libname memname objname objtype fid i;
%do i=1 %to %sysmexecdepth;
  %let keep=%sysmexecname(&i) &keep;
%end;
%if %length(&delete) %then %let delete=and findw("&delete",objname,',','sit');
%let fid=%sysfunc(open( sashelp.vcatalg(keep=libname memname objname objtype
 where=(libname='WORK' and objtype='MACRO' and memname like 'SASMAC_'
   and not findw("&keep",objname,',','sit') &delete))));
%if (&fid) %then %do;
  %syscall set(fid);
  %do %while(0=%sysfunc(fetch(&fid)));
    %put %sysfunc(compbl(Removing &objname from &libname catalog &memname));
    %sysmacdelete &objname;
  %end;
  %let fid=%sysfunc(close(&fid));
%end;
%else %put %qsysfunc(sysmsg());
%mend macdelete;

Пример:

3348  %macro test1; %mend;
3349  %macro test2; %mend;
3350  %macro test3; %mend;
3351  %macro test4; %mend;
3352  %macdelete(test1 test3);
Removing TEST1 from WORK catalog SASMACR
Removing TEST3 from WORK catalog SASMACR
3353  %macdelete(keep=test2);
Removing TEST4 from WORK catalog SASMACR

Пример при запуске SAS / Studio:

 97         %macro test1; %mend;
 98         %macro test2; %mend;
 99         %macro test3; %mend;
 100        %macro test4; %mend;
 101        %macdelete(test1 test3);
 Removing TEST1 from WORK catalog SASMAC1
 Removing TEST3 from WORK catalog SASMAC1
3 голосов
/ 29 марта 2019

Если вы удалите скомпилированный макрос из WORK. SASMACR SAS придется перекомпилировать макрос при повторном вызове.

proc catalog c=work.sasmacr;
   *contents;
   delete your-macro-to-recompile.macro;
   run;
   quit;
...