{"id":19706158,"url":"https://github.com/llnl/wrap","last_synced_at":"2025-04-29T16:32:58.428Z","repository":{"id":44893805,"uuid":"926317","full_name":"LLNL/wrap","owner":"LLNL","description":"MPI wrapper generator, for writing PMPI tool libraries","archived":false,"fork":false,"pushed_at":"2025-03-20T07:22:15.000Z","size":163,"stargazers_count":34,"open_issues_count":7,"forks_count":22,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-05T18:11:26.330Z","etag":null,"topics":["generator","mpi","pmpi","tool","wrapper"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LLNL.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-09-20T23:04:28.000Z","updated_at":"2025-03-20T07:22:19.000Z","dependencies_parsed_at":"2023-01-19T23:34:07.322Z","dependency_job_id":null,"html_url":"https://github.com/LLNL/wrap","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LLNL%2Fwrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LLNL%2Fwrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LLNL%2Fwrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LLNL%2Fwrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LLNL","download_url":"https://codeload.github.com/LLNL/wrap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251540434,"owners_count":21605903,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["generator","mpi","pmpi","tool","wrapper"],"created_at":"2024-11-11T21:34:23.158Z","updated_at":"2025-04-29T16:32:53.388Z","avatar_url":"https://github.com/LLNL.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"wrap.py\n===========================\na [PMPI](http://www.open-mpi.org/faq/?category=perftools#PMPI) wrapper generator\n\nby Todd Gamblin, tgamblin@llnl.gov, https://github.com/tgamblin/wrap\n\n    Usage: wrap.py [-fgd] [-i pmpi_init] [-c mpicc_name] [-o file] wrapper.w [...]\n     Python script for creating PMPI wrappers. Roughly follows the syntax of\n       the Argonne PMPI wrapper generator, with some enhancements.\n     Options:\"\n       -d             Just dump function declarations parsed out of mpi.h\n       -f             Generate fortran wrappers in addition to C wrappers.\n       -g             Generate reentry guards around wrapper functions.\n       -c exe         Provide name of MPI compiler (for parsing mpi.h).\n                      Default is \\'mpicc\\'.\n       -s             Skip writing #includes, #defines, and other\n                      front-matter (for non-C output).\n       -i pmpi_init   Specify proper binding for the fortran pmpi_init\n                      function.  Default is \\'pmpi_init_\\'.  Wrappers\n                      compiled for PIC will guess the right binding\n                      automatically (use -DPIC when you compile dynamic\n                      libs).\n       -o file        Send output to a file instead of stdout.\n       -w             Do not print compiler warnings for deprecated MPI functions.\n                      This option will add macros around {{callfn}} to disable (and\n                      restore) the compilers diagnostic functions, if the compiler\n                      supports this functionality.\n\n\nMany thanks to our [contributors](https://github.com/LLNL/wrap/graphs/contributors).\n\nKnown Bugs:\n\n* Certain fortran bindings need some bugfixes and may not work.\n\nTutorial\n-----------------------------\nFor a thorough tutorial, look at `examples/tutorial.w`!  It walks you through\nthe process of using `wrap.py`.  It is also legal `wrap.py` code, so you\ncan run `wrap.py` on it and see the output to better understand what's\ngoing on.\n\n\nCMake Integration\n-----------------------------\n`wrap.py` includes a `WrapConfig.cmake` file.  You can use this in your CMake project to automatically generate rules to generate wrap.py code.\n\nHere's an example.  Suppose you put `wrap.py` in a subdirectory of your project called wrap, and your project looks like this:\n\n    project/\n        CMakeLists.txt\n        wrap/\n            wrap.py\n            WrapConfig.cmake\nIn your top-level CMakeLists.txt file, you can now do this:\n\n    # wrap.py setup -- grab the add_wrapped_file macro.\n    set(WRAP ${PROJECT_SOURCE_DIR}/wrap/wrap.py)\n    include(wrap/WrapConfig.cmake)\n\nIf you have a wrapped source file, you can use the wrapper auto-generation like this:\n\n    add_wrapped_file(wrappers.C wrappers.w)\n    add_library(tool_library wrappers.C)\n\nThe `add_wrapped_file` function takes care of the dependences and code generation for you.  If you need fortran support, call it like this:\n\n    add_wrapped_file(wrappers.C wrappers.w -f)\n\nAnd note that if you generate a header that your .C files depend on, you need to explicitly include it in a target's sources, unlike non-generated headers.  e.g.:\n\n    add_wrapped_file(my-header.h my-header.w)\n    add_library(tool_library\n        tool.C         # say that this includes my-header.h\n        my-header.h)   # you need to add my-header.h here.\n\nIf you don't do this, then the header dependence won't be accounted for when tool.C is built.\n\nWrapper file syntax\n-----------------------------\nWrap syntax is a superset of the syntax defined in Appendix C of\nthe MPE manual [1], but many commands from the original wrapper\ngenerator are now deprecated.\n\n\nThe following two macros generate skeleton wrappers and allow\ndelegation via `{{callfn}}`:\n\n* `fn` iterates over only the listed functions.\n\n    ```\n    {{fn \u003citerator variable name\u003e \u003cfunction A\u003e \u003cfunction B\u003e ... }}\n    {{endfn}\n    ```\n\n    Example:\n    ```\n    {{fn FOO MPI_Abort}}\n    \t// Do-nothing wrapper for {{FOO}}\n    {{endfn}}\n    ```\n    ```\n    /* ================== C Wrappers for MPI_Abort ================== */\n    _EXTERN_C_ int PMPI_Abort(MPI_Comm comm, int errorcode);\n    _EXTERN_C_ int MPI_Abort(MPI_Comm comm, int errorcode)\n    {\n      int _wrap_py_return_val = 0;\n\n      // Do-nothing wrapper for MPI_Abort\n      return _wrap_py_return_val;\n    }\n    ```\n\n* `fnall` iterates over all functions *minus* the named functions.\n\n    ```\n    {{fnall \u003citerator variable name\u003e \u003cfunction A\u003e \u003cfunction b\u003e ... }}\n      // code here\n    {{endfnall}}\n    ```\n\n* `callfn` expands to the call of the function being profiled.\n\n* `foreachfn` and `forallfn` are the counterparts of `fn` and `fnall`, but they don't generate the\nskeletons (and therefore you can't delegate with `{{callfn}}`).  However, you\ncan use things like `fn_name` (or `foo`) and `argTypeList`, `retType`, `argList`, etc.\n\nThey're not designed for making wrappers, but declarations of lots of variables and other things you need to declare per MPI function.  e.g., say you wanted a static variable per MPI call for some flag.\n\n    ```\n    {{forallfn \u003citerator variable name\u003e \u003cfunction A\u003e \u003cfunction B\u003e ... }}\n      // code here\n    {{endforallfn}\n\n    {foreachfn \u003citerator variable name\u003e \u003cfunction A\u003e \u003cfunction B\u003e ... }}\n      // code here\n    {{endforeachfn}}\n    ```\n\n    The code between {{forallfn}} and {{endforallfn}} is copied once for every function profiled, except for the functions listed.\n\n\tFor example:\n    ```\n    {{forallfn fn_name}}\n      static int {{fn_name}}_ncalls_{{fileno}};\n    {{endforallfn}}\n    ```\n    might expand to:\n    ```\n    static int MPI_Send_ncalls_1;\n    static int MPI_Recv_ncalls_1;\n    ```\n\n* `{{get_arg \u003cargnum\u003e}}` OR `{{\u003cargnum\u003e}}`\n\tArguments to the function being profiled may be referenced by\n\tnumber, starting with 0 and increasing.  e.g., in a wrapper file:\n\n        void process_argc_and_argv(int *argc, char ***argv) {\n        // do stuff to argc and argv.\n        }\n\n        {{fn fn_name MPI_Init}}\n            process_argc_and_argv({{0}}, {{1}});\n        {{callfn}}\n        {{endfn}}\n    Note that `{{0}}` is just a synonym for `{{get_arg 0}}`\n\n* `{{ret_val}}`\n\tReturnVal expands to the variable that is used to hold the return\n\tvalue of the function being profiled.   (was: `{{returnVal}}`)\n\n* `{{fn_num}}`\n\tThis is a number, starting from zero.  It is incremented every time\n\tit is used.\n\n* `{{ret_type}}`\n\tThe return type of the function. (was: `{{retType}}`)\n\n* `{{formals}}`\n\tEssentially what would be in a formal declaration for the function.\n\tCan be used this with forallfn and foreachfn; these don't generate\n\tprototypes, they just iterate over the functions without making a\n    skeleton.  (was: `{{argTypeList}}`)\n\n* `{{args}}`\n\tNames of the arguments in a comma-separated list, e.g.:\n    `buf, type, count, comm`\n\n* `{{argList}}`\n\tSame as `{{args}}`, but with parentheses around the list, e.g.:\n    `(buf, type, count, comm)`\n\n* `{{applyToType \u003ctype\u003e \u003ccallable\u003e}}`\n    This macro must be nested inside either a fn or fnall block.\n    Within the functions being wrapped by fn or fnall, this macro will\n    apply `\u003ccallable\u003e` to any arguments of the function with type\n    `\u003ctype\u003e`.   For example, you might write a wrapper file like this:\n\n        #define my_macro(comm) do_something_to(comm);\n        {{fn fn_name MPI_Send MPI_Isend MPI_Ibsend}}\n            {{applyToType MPI_Comm my_macro}}\n            {{callfn}}\n        {{endfn}}\n\n    Now the generated wrappers to `MPI_Send`, `MPI_Isend`, and `MPI_Ibsend` will do something like this:\n\n    int MPI_Isend(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request) {\n      int _wrap_py_return_val = 0;\n      my_macro(comm);\n      PMPI_Isend(buf, count, datatype, dest, tag, comm, request);\n    }\n\n* `{{sub \u003cnew_string\u003e \u003cold_string\u003e \u003cregexp\u003e \u003csubstitution\u003e}}`\n    Declares `\u003cnew_string\u003e` in the current scope and gives it the value\n    of `\u003cold_string\u003e` with all instances of `\u003cregexp\u003e` replaced with\n    `\u003csubstitution\u003e`.  You may use any valid python regexp for `\u003cregexp\u003e`\n    and any valid substitution value for `\u003csubstitution\u003e`.  The regexps\n    follow the same syntax as Python's re.sub(), and they may be single\n    or double quoted (though it's not necessary unless you use spaces in\n    the expressions).\n\n    Example:\n\n        {{forallfn foo}}\n            {{sub nqjfoo foo '^MPI_' NQJ_}}\n            {{nqjfoo}}\n        {{endforallfn}}\n\n  This will print `NQJ_xxx` instead of `MPI_xxx` for each MPI function.\n\n* `{{fileno}}`\n\tAn integral index representing which wrapper file the macro\n\tcame from.  This is useful when decalring file-global variables\n\tto prevent name collisions.  Identifiers declared outside\n\tfunctions should end with _{{fileno}}.  For example:\n\n\t\tstatic double overhead_time_{{fileno}};\n\n\tmight expand to\n\n\t\tstatic double overhead_time_0;\n\n\n* `{{vardecl \u003ctype\u003e \u003carg\u003e \u003carg\u003e ...}}` *(not yet supported)*\n\tDeclare variables within a wrapper definition.  Wrap will decorate\n    the variable name to prevent collisions.\n\n* `{{\u003cvarname\u003e}}` *(not yet supported)*\n\tAccess a variable declared by `{{vardecl}}`.\n\nNotes on the fortran wrappers\n-------------------------------\n    #if (!defined(MPICH_HAS_C2F) \u0026\u0026 defined(MPICH_NAME) \u0026\u0026 (MPICH_NAME == 1))\n\t    /* MPICH call */\n        return_val = MPI_Abort((MPI_Comm)(*arg_0), *arg_1);\n\t#else\n        /* MPI-2 safe call */\n\t    return_val = MPI_Abort(MPI_Comm_f2c(*arg_0), *arg_1);\n\t#endif\n\nThis is the part of the wrapper that delegates from Fortran\nto C.  There are two ways to do that.  The MPI-2 way is to\ncall the appropriate _f2c call on the handle and pass that\nto the C function.  The f2c/c2f calls are also available in\nsome versions of MPICH1, but not all of them (I believe they\nwere backported), so you can do the MPI-2 thing if\n`MPICH_HAS_C2F` is defined.\n\nIf c2f functions are not around, then the script tries to\nfigure out if it's dealing with MPICH1, where all the\nhandles are ints.  In that case, you can just pass the int\nthrough.\n\nRight now, if it's not *specifically* MPICH1, wrap.py does\nthe MPI-2 thing.  From what Barry was telling me, your MPI\nenvironment might have int handles, but it is not MPICH1.\nSo you could either define all the `MPI_Foo_c2f`/`MPI_Foo_f2c`\ncalls to identity macros, e.g.:\n\n    #define MPI_File_c2f(x) (x)\n    #define MPI_File_f2c(x) (x)\n\nor you could add something to wrap.py to force the\nint-passing behavior.  I'm not sure if you have to care\nabout this, but I thought I'd point it out.\n\n-s, or 'structural' mode\n-------------------------------\n\nIf you use the `-s` option, this skips the includes and defines used for C\nwrapper functions.  This is useful if you want to use wrap to generate\nnon-C files, such as XML.\n\nIf you use -s, we recommend that you avoid using `{{fn}}` and `{{fnall}}`,\nas these generate proper wrapper functions that rely on some of the\nheader information.  Instead, use `{{foreachfn}}` and `{{forallfn}}`, as\nthese do not generate wrappers around each iteration of the macro.\n\ne.g. if you want to generate a simple XML file with descriptions of the\nMPI arguments, you might write this in a wrapper file:\n\n    {{forallfn fun}}\n        \u003cfunction name=\"{{fun}}\" args=\"{{args}}\"/\u003e\n    {{endforallfn}}\n\nWe don't disallow `{{fnall}}` or `{{fn}}` with `-s`, but If you used\n`{{fnall}}` here, each XML tag would have a C wrapper function around it,\nwhich is probably NOT what you want.\n\n\n-w: Disable MPI deprecation warnings\n----------------------------------------\n\nAt the time of implementing this feature, many old MPI functions got declared\ndeprecated in OpenMPI:\n\n```\nwarning: 'PMPI_Type_extent' is deprecated: MPI_Type_extent is superseded by MPI_Type_get_extent in MPI-2.0 [-Wdeprecated-declarations]\n          PMPI_Type_extent(recvtype, \u0026re);\n          ^\n```\n\nEven if these functions are deprecated, they may be wrapped for older\napplications, so these warnings may confuse the user. Even worse: warnings about\ndeprecated non-MPI functions may be missed.\n\nWith enabling the  `-w` option of wrap, macros will be added around `{{callfn}}`\nto disable the warnings for MPI calls. However, if you use `{{fn_name}}`,\n`{{args}}`, etc. for custom invocations, you may add `WRAP_MPI_CALL_PREFIX` and\n`WRAP_MPI_CALL_POSTFIX` around your MPI calls, to suppress deprecation warnings\nfor these calls, too.\n\n**Note:** If the could should be compatible with and without this functionality\nenabled, you'll have to check if the macros are available.\n\nExample:\n```\n#ifndef WRAP_MPI_CALL_PREFIX\n#define WRAP_MPI_CALL_PREFIX\n#endif\n\n#ifndef WRAP_MPI_CALL_POSTFIX\n#define WRAP_MPI_CALL_POSTFIX\n#endif\n\n\n{{fnall fn_name MPI_Pcontrol}}\n    WRAP_MPI_CALL_PREFIX\n    return P{{fn_name}}({{args}});\n    WRAP_MPI_CALL_POSTFIX\n{{endfnall}}\n```\n--------------\n\n1. Anthony Chan, William Gropp and Weing Lusk.  *User's Guide for MPE:\nExtensions for MPI Programs*.  ANL/MCS-TM-ANL-98/xx.\nftp://ftp.mcs.anl.gov/pub/mpi/mpeman.pdf\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllnl%2Fwrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fllnl%2Fwrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllnl%2Fwrap/lists"}