root/opal/tools/wrappers/opal_wrapper.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. options_data_init
  2. options_data_free
  3. options_data_expand
  4. find_options_index
  5. expand_flags
  6. data_callback
  7. data_init
  8. data_finalize
  9. print_flags
  10. load_env_data
  11. load_env_data_argv
  12. main

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2005 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2007-2015 Cisco Systems, Inc.  All rights reserved.
  13  * Copyright (c) 2007-2013 Los Alamos National Security, LLC.  All rights
  14  *                         reserved.
  15  * Copyright (c) 2010      Oracle and/or its affiliates.  All rights reserved.
  16  * Copyright (c) 2015      Research Organization for Information Science
  17  *                         and Technology (RIST). All rights reserved.
  18  * Copyright (c) 2018      Amazon.com, Inc. or its affiliates.  All Rights reserved.
  19  * $COPYRIGHT$
  20  *
  21  * Additional copyrights may follow
  22  *
  23  * $HEADER$
  24  */
  25 
  26 #include "opal_config.h"
  27 
  28 #include <stdio.h>
  29 #include <errno.h>
  30 #include <stdlib.h>
  31 #ifdef HAVE_SYS_STAT_H
  32 #include <sys/stat.h>
  33 #endif  /* HAVE_SYS_STAT_H */
  34 #ifdef HAVE_SYS_TYPES_H
  35 #include <sys/types.h>
  36 #endif  /* HAVE_SYS_TYPES_H */
  37 #ifdef HAVE_REGEX_H
  38 #include <regex.h>
  39 #endif
  40 #ifdef HAVE_SYS_WAIT_H
  41 #include <sys/wait.h>
  42 #endif  /* HAVE_SYS_WAIT_H */
  43 #include <string.h>
  44 
  45 #include "opal/mca/installdirs/installdirs.h"
  46 #include "opal/runtime/opal.h"
  47 #include "opal/constants.h"
  48 #include "opal/util/argv.h"
  49 #include "opal/util/error.h"
  50 #include "opal/util/keyval_parse.h"
  51 #include "opal/util/opal_environ.h"
  52 #include "opal/util/show_help.h"
  53 #include "opal/util/path.h"
  54 #include "opal/util/few.h"
  55 #include "opal/util/basename.h"
  56 #include "opal/util/os_path.h"
  57 #include "opal/util/printf.h"
  58 
  59 #define OPAL_INCLUDE_FLAG  "-I"
  60 #define OPAL_LIBDIR_FLAG   "-L"
  61 
  62 struct options_data_t {
  63     char **compiler_args;
  64     char *language;
  65     char *project;
  66     char *project_short;
  67     char *version;
  68     char *compiler_env;
  69     char *compiler_flags_env;
  70     char *compiler;
  71     char **preproc_flags;
  72     char **comp_flags;
  73     char **comp_flags_prefix;
  74     char **link_flags;
  75     char **libs;
  76     char **libs_static;
  77     char *dyn_lib_file;
  78     char *static_lib_file;
  79     char *req_file;
  80     char *path_includedir;
  81     char *path_libdir;
  82     char *path_opalincludedir;
  83     char *path_opallibdir;
  84 };
  85 
  86 static struct options_data_t *options_data = NULL;
  87 /* index used by parser */
  88 static int parse_options_idx = -1;
  89 /* index of options specified by user */
  90 static int user_data_idx = -1;
  91 /* index of options to use by default */
  92 static int default_data_idx = -1;
  93 
  94 #define COMP_DRY_RUN       0x001
  95 #define COMP_SHOW_ERROR    0x002
  96 #define COMP_WANT_COMMAND  0x004
  97 #define COMP_WANT_PREPROC  0x008
  98 #define COMP_WANT_COMPILE  0x010
  99 #define COMP_WANT_LINK     0x020
 100 #define COMP_WANT_PMPI     0x040
 101 #define COMP_WANT_STATIC   0x080
 102 #define COMP_WANT_LINKALL  0x100
 103 
 104 static void
 105 options_data_init(struct options_data_t *data)
 106 {
 107     data->compiler_args = (char **) malloc(sizeof(char*));
 108     data->compiler_args[0] = NULL;
 109     data->language = NULL;
 110     data->compiler = NULL;
 111     data->project = NULL;
 112     data->project_short = NULL;
 113     data->version = NULL;
 114     data->compiler_env = NULL;
 115     data->compiler_flags_env = NULL;
 116     data->preproc_flags = (char **) malloc(sizeof(char*));
 117     data->preproc_flags[0] = NULL;
 118     data->comp_flags = (char **) malloc(sizeof(char*));
 119     data->comp_flags[0] = NULL;
 120     data->comp_flags_prefix = (char **) malloc(sizeof(char*));
 121     data->comp_flags_prefix[0] = NULL;
 122     data->link_flags = (char **) malloc(sizeof(char*));
 123     data->link_flags[0] = NULL;
 124     data->libs = (char **) malloc(sizeof(char*));
 125     data->libs[0] = NULL;
 126     data->libs_static = (char **) malloc(sizeof(char*));
 127     data->libs_static[0] = NULL;
 128     data->dyn_lib_file = NULL;
 129     data->static_lib_file = NULL;
 130     data->req_file = NULL;
 131     data->path_includedir = NULL;
 132     data->path_libdir = NULL;
 133     data->path_opalincludedir = NULL;
 134     data->path_opallibdir = NULL;
 135 }
 136 
 137 static void
 138 options_data_free(struct options_data_t *data)
 139 {
 140     if (NULL != data->compiler_args) {
 141         opal_argv_free(data->compiler_args);
 142     }
 143     if (NULL != data->language) free(data->language);
 144     if (NULL != data->compiler) free(data->compiler);
 145     if (NULL != data->project) free(data->project);
 146     if (NULL != data->project_short) free(data->project_short);
 147     if (NULL != data->version) free(data->version);
 148     if (NULL != data->compiler_env) free(data->compiler_env);
 149     if (NULL != data->compiler_flags_env) free(data->compiler_flags_env);
 150     opal_argv_free(data->preproc_flags);
 151     opal_argv_free(data->comp_flags);
 152     opal_argv_free(data->comp_flags_prefix);
 153     opal_argv_free(data->link_flags);
 154     opal_argv_free(data->libs);
 155     opal_argv_free(data->libs_static);
 156     if (NULL != data->dyn_lib_file) free(data->dyn_lib_file);
 157     if (NULL != data->static_lib_file) free(data->static_lib_file);
 158     if (NULL != data->req_file) free(data->req_file);
 159     if (NULL != data->path_includedir) free(data->path_includedir);
 160     if (NULL != data->path_libdir) free(data->path_libdir);
 161     if (NULL != data->path_opalincludedir) free(data->path_opalincludedir);
 162     if (NULL != data->path_opallibdir) free(data->path_opallibdir);
 163 }
 164 
 165 static void
 166 options_data_expand(const char *value)
 167 {
 168     /* make space for the new set of args */
 169     parse_options_idx++;
 170     options_data = (struct options_data_t *) realloc(options_data, sizeof(struct options_data_t) * (parse_options_idx + 1));
 171     options_data_init(&(options_data[parse_options_idx]));
 172 
 173     /* if there are values, this is not the default case.
 174        Otherwise, it's the default case... */
 175     if (NULL != value && 0 != strcmp(value, "")) {
 176         char **values = opal_argv_split(value, ';');
 177         opal_argv_insert(&(options_data[parse_options_idx].compiler_args),
 178                          opal_argv_count(options_data[parse_options_idx].compiler_args),
 179                          values);
 180         opal_argv_free(values);
 181     } else {
 182         free(options_data[parse_options_idx].compiler_args);
 183         options_data[parse_options_idx].compiler_args = NULL;
 184         /* this is a default */
 185         default_data_idx = parse_options_idx;
 186     }
 187 }
 188 
 189 
 190 static int
 191 find_options_index(const char *arg)
 192 {
 193     int i, j;
 194 #ifdef HAVE_REGEXEC
 195     int args_count;
 196     regex_t res;
 197 #endif
 198 
 199     for (i = 0 ; i <= parse_options_idx ; ++i) {
 200         if (NULL == options_data[i].compiler_args) {
 201             continue;
 202         }
 203 
 204 #ifdef HAVE_REGEXEC
 205         args_count = opal_argv_count(options_data[i].compiler_args);
 206         for (j = 0 ; j < args_count ; ++j) {
 207             if (0 != regcomp(&res, options_data[i].compiler_args[j], REG_NOSUB)) {
 208                 return -1;
 209             }
 210 
 211             if (0 == regexec(&res, arg, (size_t) 0, NULL, 0)) {
 212                 regfree(&res);
 213                 return i;
 214             }
 215 
 216             regfree(&res);
 217         }
 218 #else
 219         for (j = 0 ; j < opal_argv_count(options_data[i].compiler_args) ; ++j) {
 220             if (0 == strcmp(arg, options_data[i].compiler_args[j])) {
 221                 return i;
 222             }
 223         }
 224 #endif
 225     }
 226 
 227     return -1;
 228 }
 229 
 230 
 231 static void
 232 expand_flags(char **argv)
 233 {
 234     int i;
 235     char *tmp;
 236 
 237     for (i = 0 ; argv[i] != NULL ; ++i) {
 238         tmp = opal_install_dirs_expand(argv[i]);
 239         if (tmp != argv[i]) {
 240             free(argv[i]);
 241             argv[i] = tmp;
 242         }
 243     }
 244 }
 245 
 246 
 247 static void
 248 data_callback(const char *key, const char *value)
 249 {
 250     /* handle case where text file does not contain any special
 251        compiler options field */
 252     if (parse_options_idx < 0 && 0 != strcmp(key, "compiler_args")) {
 253         options_data_expand(NULL);
 254     }
 255 
 256     if (0 == strcmp(key, "compiler_args")) {
 257         options_data_expand(value);
 258     } else if (0 == strcmp(key, "language")) {
 259         if (NULL != value) options_data[parse_options_idx].language = strdup(value);
 260     } else if (0 == strcmp(key, "compiler")) {
 261         if (NULL != value) options_data[parse_options_idx].compiler = strdup(value);
 262     } else if (0 == strcmp(key, "project")) {
 263         if (NULL != value) options_data[parse_options_idx].project = strdup(value);
 264     } else if (0 == strcmp(key, "version")) {
 265         if (NULL != value) options_data[parse_options_idx].version = strdup(value);
 266     } else if (0 == strcmp(key, "preprocessor_flags")) {
 267         char **values = opal_argv_split(value, ' ');
 268         opal_argv_insert(&options_data[parse_options_idx].preproc_flags,
 269                          opal_argv_count(options_data[parse_options_idx].preproc_flags),
 270                          values);
 271         expand_flags(options_data[parse_options_idx].preproc_flags);
 272         opal_argv_free(values);
 273     } else if (0 == strcmp(key, "compiler_flags")) {
 274         char **values = opal_argv_split(value, ' ');
 275         opal_argv_insert(&options_data[parse_options_idx].comp_flags,
 276                          opal_argv_count(options_data[parse_options_idx].comp_flags),
 277                          values);
 278         expand_flags(options_data[parse_options_idx].comp_flags);
 279         opal_argv_free(values);
 280     } else if (0 == strcmp(key, "compiler_flags_prefix")) {
 281         char **values = opal_argv_split(value, ' ');
 282         opal_argv_insert(&options_data[parse_options_idx].comp_flags_prefix,
 283                          opal_argv_count(options_data[parse_options_idx].comp_flags_prefix),
 284                          values);
 285         expand_flags(options_data[parse_options_idx].comp_flags_prefix);
 286         opal_argv_free(values);
 287     } else if (0 == strcmp(key, "linker_flags")) {
 288         char **values = opal_argv_split(value, ' ');
 289         opal_argv_insert(&options_data[parse_options_idx].link_flags,
 290                          opal_argv_count(options_data[parse_options_idx].link_flags),
 291                          values);
 292         expand_flags(options_data[parse_options_idx].link_flags);
 293         opal_argv_free(values);
 294     } else if (0 == strcmp(key, "libs")) {
 295         char **values = opal_argv_split(value, ' ');
 296         opal_argv_insert(&options_data[parse_options_idx].libs,
 297                          opal_argv_count(options_data[parse_options_idx].libs),
 298                          values);
 299         opal_argv_free(values);
 300     } else if (0 == strcmp(key, "libs_static")) {
 301         char **values = opal_argv_split(value, ' ');
 302         opal_argv_insert(&options_data[parse_options_idx].libs_static,
 303                          opal_argv_count(options_data[parse_options_idx].libs_static),
 304                          values);
 305         opal_argv_free(values);
 306     } else if (0 == strcmp(key, "dyn_lib_file")) {
 307         if (NULL != value) options_data[parse_options_idx].dyn_lib_file = strdup(value);
 308     } else if (0 == strcmp(key, "static_lib_file")) {
 309         if (NULL != value) options_data[parse_options_idx].static_lib_file = strdup(value);
 310     } else if (0 == strcmp(key, "required_file")) {
 311         if (NULL != value) options_data[parse_options_idx].req_file = strdup(value);
 312     } else if (0 == strcmp(key, "project_short")) {
 313         if (NULL != value) options_data[parse_options_idx].project_short = strdup(value);
 314     } else if (0 == strcmp(key, "compiler_env")) {
 315         if (NULL != value) options_data[parse_options_idx].compiler_env = strdup(value);
 316     } else if (0 == strcmp(key, "compiler_flags_env")) {
 317         if (NULL != value) options_data[parse_options_idx].compiler_flags_env = strdup(value);
 318     } else if (0 == strcmp(key, "includedir")) {
 319         if (NULL != value) {
 320             options_data[parse_options_idx].path_includedir =
 321                 opal_install_dirs_expand(value);
 322             if (0 != strcmp(options_data[parse_options_idx].path_includedir, "/usr/include") ||
 323                 0 == strncmp(options_data[parse_options_idx].language, "Fortran", strlen("Fortran"))) {
 324                 char *line;
 325                 opal_asprintf(&line, OPAL_INCLUDE_FLAG"%s",
 326                          options_data[parse_options_idx].path_includedir);
 327                 opal_argv_append_nosize(&options_data[parse_options_idx].preproc_flags, line);
 328                 free(line);
 329             }
 330         }
 331     } else if (0 == strcmp(key, "libdir")) {
 332         if (NULL != value) options_data[parse_options_idx].path_libdir =
 333                                opal_install_dirs_expand(value);
 334         if (0 != strcmp(options_data[parse_options_idx].path_libdir, "/usr/lib")) {
 335             char *line;
 336             opal_asprintf(&line, OPAL_LIBDIR_FLAG"%s",
 337                      options_data[parse_options_idx].path_libdir);
 338             opal_argv_append_nosize(&options_data[parse_options_idx].link_flags, line);
 339             free(line);
 340         }
 341     } else if (0 == strcmp(key, "opalincludedir")) {
 342         printf("EXPANDING!\n");
 343         if (NULL != value) {
 344             options_data[parse_options_idx].path_opalincludedir =
 345                 opal_install_dirs_expand(value);
 346             if (0 != strcmp(options_data[parse_options_idx].path_opalincludedir, "/usr/include") ||
 347                 0 == strncmp(options_data[parse_options_idx].language, "Fortran", strlen("Fortran"))) {
 348                 char *line;
 349                 opal_asprintf(&line, OPAL_INCLUDE_FLAG"%s",
 350                          options_data[parse_options_idx].path_opalincludedir);
 351                 opal_argv_append_nosize(&options_data[parse_options_idx].preproc_flags, line);
 352                 free(line);
 353             }
 354         }
 355     } else if (0 == strcmp(key, "opallibdir")) {
 356         if (NULL != value) options_data[parse_options_idx].path_opallibdir =
 357                                opal_install_dirs_expand(value);
 358         if (0 != strcmp(options_data[parse_options_idx].path_opallibdir, "/usr/lib")) {
 359             char *line;
 360             opal_asprintf(&line, OPAL_LIBDIR_FLAG"%s",
 361                      options_data[parse_options_idx].path_opallibdir);
 362             opal_argv_append_nosize(&options_data[parse_options_idx].link_flags, line);
 363             free(line);
 364         }
 365     }
 366 }
 367 
 368 
 369 static int
 370 data_init(const char *appname)
 371 {
 372     int ret;
 373     char *datafile;
 374 
 375     /* now load the data */
 376     opal_asprintf(&datafile, "%s%s%s-wrapper-data.txt",
 377              opal_install_dirs.opaldatadir, OPAL_PATH_SEP, appname);
 378     if (NULL == datafile) return OPAL_ERR_TEMP_OUT_OF_RESOURCE;
 379 
 380     ret = opal_util_keyval_parse(datafile, data_callback);
 381     if( OPAL_SUCCESS != ret ) {
 382         fprintf(stderr, "Cannot open configuration file %s\n", datafile );
 383     }
 384     free(datafile);
 385 
 386     return ret;
 387 }
 388 
 389 
 390 static int
 391 data_finalize(void)
 392 {
 393     int i;
 394 
 395     for (i = 0 ; i <= parse_options_idx ; ++i) {
 396         options_data_free(&(options_data[i]));
 397     }
 398     free(options_data);
 399 
 400     return OPAL_SUCCESS;
 401 }
 402 
 403 
 404 static void
 405 print_flags(char **args, char *pattern)
 406 {
 407     int i;
 408     bool found = false;
 409 
 410     for (i = 0 ; args[i] != NULL ; ++i) {
 411         if (0 == strncmp(args[i], pattern, strlen(pattern))) {
 412             if (found)  printf(" ");
 413             printf("%s", args[i] + strlen(pattern));
 414             found = true;
 415         }
 416     }
 417 
 418     if (found) printf("\n");
 419 }
 420 
 421 
 422 static void
 423 load_env_data(const char *project, const char *flag, char **data)
 424 {
 425     char *envname;
 426     char *envvalue;
 427 
 428     if (NULL == project || NULL == flag) return;
 429 
 430     opal_asprintf(&envname, "%s_MPI%s", project, flag);
 431     if (NULL == (envvalue = getenv(envname))) {
 432         free(envname);
 433         opal_asprintf(&envname, "%s_%s", project, flag);
 434         if (NULL == (envvalue = getenv(envname))) {
 435             free(envname);
 436             return;
 437         }
 438     }
 439     free(envname);
 440 
 441     if (NULL != *data) free(*data);
 442     *data = strdup(envvalue);
 443 }
 444 
 445 
 446 static void
 447 load_env_data_argv(const char *project, const char *flag, char ***data)
 448 {
 449     char *envname;
 450     char *envvalue;
 451 
 452     if (NULL == project || NULL == flag) return;
 453 
 454     opal_asprintf(&envname, "%s_MPI%s", project, flag);
 455     if (NULL == (envvalue = getenv(envname))) {
 456         free(envname);
 457         opal_asprintf(&envname, "%s_%s", project, flag);
 458         if (NULL == (envvalue = getenv(envname))) {
 459             free(envname);
 460             return;
 461         }
 462     }
 463     free(envname);
 464 
 465     if (NULL != *data) opal_argv_free(*data);
 466 
 467     *data = opal_argv_split(envvalue, ' ');
 468 }
 469 
 470 
 471 int
 472 main(int argc, char *argv[])
 473 {
 474     int exit_status = 0, ret, flags = 0, i;
 475     int exec_argc = 0, user_argc = 0;
 476     char **exec_argv = NULL, **user_argv = NULL;
 477     char *exec_command, *base_argv0 = NULL;
 478     bool disable_flags = true;
 479     bool real_flag = false;
 480 
 481     if (OPAL_SUCCESS != (ret = opal_init_util(&argc, &argv))) {
 482         return ret;
 483     }
 484 
 485     /****************************************************
 486      *
 487      * Setup compiler information
 488      *
 489      ****************************************************/
 490 
 491     base_argv0 = opal_basename(argv[0]);
 492 #if defined(EXEEXT)
 493     if( 0 != strlen(EXEEXT) ) {
 494         char extension[] = EXEEXT;
 495         char* temp = strstr( base_argv0, extension );
 496         char* old_match = temp;
 497         while( NULL != temp ) {
 498             old_match = temp;
 499             temp = strstr( temp + 1, extension );
 500         }
 501         /* Only if there was a match of .exe, erase the last occurence of .exe */
 502         if ( NULL != old_match ) {
 503             *old_match = '\0';
 504         }
 505     }
 506 #endif  /* defined(EXEEXT) */
 507 
 508     if (OPAL_SUCCESS != (ret = data_init(base_argv0))) {
 509         fprintf(stderr, "Error parsing data file %s: %s\n", base_argv0, opal_strerror(ret));
 510         return ret;
 511     }
 512 
 513     for (i = 1 ; i < argc && user_data_idx < 0 ; ++i) {
 514         user_data_idx = find_options_index(argv[i]);
 515     }
 516     /* if we didn't find a match, look for the NULL (base case) options */
 517     if (user_data_idx < 0) {
 518         user_data_idx = default_data_idx;
 519     }
 520     /* if we still didn't find a match, abort */
 521     if (user_data_idx < 0) {
 522         char *flat = opal_argv_join(argv, ' ');
 523         opal_show_help("help-opal-wrapper.txt", "no-options-support", true,
 524                        base_argv0, flat, NULL);
 525         free(flat);
 526         exit(1);
 527     }
 528 
 529     /* compiler */
 530     load_env_data(options_data[user_data_idx].project_short, options_data[user_data_idx].compiler_env, &options_data[user_data_idx].compiler);
 531 
 532     /* preprocessor flags */
 533     load_env_data_argv(options_data[user_data_idx].project_short, "CPPFLAGS", &options_data[user_data_idx].preproc_flags);
 534 
 535     /* compiler flags */
 536     load_env_data_argv(options_data[user_data_idx].project_short, options_data[user_data_idx].compiler_flags_env,
 537                        &options_data[user_data_idx].comp_flags);
 538 
 539     /* linker flags */
 540     load_env_data_argv(options_data[user_data_idx].project_short, "LDFLAGS", &options_data[user_data_idx].link_flags);
 541 
 542     /* libs */
 543     load_env_data_argv(options_data[user_data_idx].project_short, "LIBS", &options_data[user_data_idx].libs);
 544 
 545 
 546     /****************************************************
 547      *
 548      * Sanity Checks
 549      *
 550      ****************************************************/
 551 
 552     if (NULL != options_data[user_data_idx].req_file) {
 553         /* make sure the language is supported */
 554         if (0 == strcmp(options_data[user_data_idx].req_file, "not supported")) {
 555             opal_show_help("help-opal-wrapper.txt", "no-language-support", true,
 556                            options_data[user_data_idx].language, base_argv0, NULL);
 557             exit_status = 1;
 558             goto cleanup;
 559         }
 560 
 561         if (options_data[user_data_idx].req_file[0] != '\0') {
 562             char *filename;
 563             struct stat buf;
 564             filename = opal_os_path( false, options_data[user_data_idx].path_libdir, options_data[user_data_idx].req_file, NULL );
 565             if (0 != stat(filename, &buf)) {
 566                 opal_show_help("help-opal-wrapper.txt", "file-not-found", true,
 567                                base_argv0, options_data[user_data_idx].req_file, options_data[user_data_idx].language, NULL);
 568             }
 569         }
 570     }
 571 
 572     /****************************************************
 573      *
 574      * Parse user flags
 575      *
 576      ****************************************************/
 577     flags = COMP_WANT_COMMAND|COMP_WANT_PREPROC|
 578         COMP_WANT_COMPILE|COMP_WANT_LINK;
 579 
 580     user_argv = opal_argv_copy(argv + 1);
 581     user_argc = opal_argv_count(user_argv);
 582 
 583     for (i = 0 ; i < user_argc ; ++i) {
 584         if (0 == strncmp(user_argv[i], "-showme", strlen("-showme")) ||
 585             0 == strncmp(user_argv[i], "--showme", strlen("--showme")) ||
 586             0 == strncmp(user_argv[i], "-show", strlen("-show")) ||
 587             0 == strncmp(user_argv[i], "--show", strlen("--show"))) {
 588             bool done_now = false;
 589 
 590             /* check for specific things we want to see.  First three
 591                still invoke all the building routines.  Last set want
 592                to parse out certain flags, so we don't go through the
 593                normal build routine - skip to cleanup. */
 594             if (0 == strncmp(user_argv[i], "-showme:command", strlen("-showme:command")) ||
 595                 0 == strncmp(user_argv[i], "--showme:command", strlen("--showme:command"))) {
 596                 flags = COMP_WANT_COMMAND;
 597                 /* we know what we want, so don't process any more args */
 598                 done_now = true;
 599             } else if (0 == strncmp(user_argv[i], "-showme:compile", strlen("-showme:compile")) ||
 600                 0 == strncmp(user_argv[i], "--showme:compile", strlen("--showme:compile"))) {
 601                 flags = COMP_WANT_PREPROC|COMP_WANT_COMPILE;
 602                 /* we know what we want, so don't process any more args */
 603                 done_now = true;
 604             } else if (0 == strncmp(user_argv[i], "-showme:link", strlen("-showme:link")) ||
 605                        0 == strncmp(user_argv[i], "--showme:link", strlen("--showme:link"))) {
 606                 flags = COMP_WANT_COMPILE|COMP_WANT_LINK;
 607                 /* we know what we want, so don't process any more args */
 608                 done_now = true;
 609             } else if (0 == strncmp(user_argv[i], "-showme:incdirs", strlen("-showme:incdirs")) ||
 610                        0 == strncmp(user_argv[i], "--showme:incdirs", strlen("--showme:incdirs"))) {
 611                 print_flags(options_data[user_data_idx].preproc_flags, OPAL_INCLUDE_FLAG);
 612                 goto cleanup;
 613             } else if (0 == strncmp(user_argv[i], "-showme:libdirs", strlen("-showme:libdirs")) ||
 614                        0 == strncmp(user_argv[i], "--showme:libdirs", strlen("--showme:libdirs"))) {
 615                 print_flags(options_data[user_data_idx].link_flags, OPAL_LIBDIR_FLAG);
 616                 goto cleanup;
 617             } else if (0 == strncmp(user_argv[i], "-showme:libs", strlen("-showme:libs")) ||
 618                        0 == strncmp(user_argv[i], "--showme:libs", strlen("--showme:libs"))) {
 619                 print_flags(options_data[user_data_idx].libs, "-l");
 620                 goto cleanup;
 621             } else if (0 == strncmp(user_argv[i], "-showme:version", strlen("-showme:version")) ||
 622                        0 == strncmp(user_argv[i], "--showme:version", strlen("--showme:version"))) {
 623                 char * str;
 624                 str = opal_show_help_string("help-opal-wrapper.txt",
 625                                             "version", false,
 626                                             argv[0], options_data[user_data_idx].project, options_data[user_data_idx].version, options_data[user_data_idx].language, NULL);
 627                 if (NULL != str) {
 628                     printf("%s", str);
 629                     free(str);
 630                 }
 631                 goto cleanup;
 632             } else if (0 == strncmp(user_argv[i], "-showme:help", strlen("-showme:help")) ||
 633                        0 == strncmp(user_argv[i], "--showme:help", strlen("--showme:help"))) {
 634                 char *str;
 635                 str = opal_show_help_string("help-opal-wrapper.txt", "usage",
 636                                             false, argv[0],
 637                                             options_data[user_data_idx].project,
 638                                             NULL);
 639                 if (NULL != str) {
 640                     printf("%s", str);
 641                     free(str);
 642                 }
 643 
 644                 exit_status = 0;
 645                 goto cleanup;
 646             } else if (0 == strncmp(user_argv[i], "-showme:", strlen("-showme:")) ||
 647                        0 == strncmp(user_argv[i], "--showme:", strlen("--showme:"))) {
 648                 fprintf(stderr, "%s: unrecognized option: %s\n", argv[0],
 649                         user_argv[i]);
 650                 fprintf(stderr, "Type '%s --showme:help' for usage.\n",
 651                         argv[0]);
 652                 exit_status = 1;
 653                 goto cleanup;
 654             }
 655 
 656             flags |= (COMP_DRY_RUN|COMP_SHOW_ERROR);
 657             /* remove element from user_argv */
 658             opal_argv_delete(&user_argc, &user_argv, i, 1);
 659             --i;
 660 
 661             if (done_now) {
 662                 disable_flags = false;
 663                 break;
 664             }
 665 
 666         } else if (0 == strcmp(user_argv[i], "-c")) {
 667             flags &= ~COMP_WANT_LINK;
 668             real_flag = true;
 669         } else if (0 == strcmp(user_argv[i], "-E") ||
 670                    0 == strcmp(user_argv[i], "-M")) {
 671             flags &= ~(COMP_WANT_COMPILE | COMP_WANT_LINK);
 672             real_flag = true;
 673         } else if (0 == strcmp(user_argv[i], "-S")) {
 674             flags &= ~COMP_WANT_LINK;
 675             real_flag = true;
 676         } else if (0 == strcmp(user_argv[i], "-lpmpi")) {
 677             flags |= COMP_WANT_PMPI;
 678 
 679             /* remove element from user_argv */
 680             opal_argv_delete(&user_argc, &user_argv, i, 1);
 681             --i;
 682         } else if (0 == strcmp(user_argv[i], "-static") ||
 683                    0 == strcmp(user_argv[i], "--static") ||
 684                    0 == strcmp(user_argv[i], "-Bstatic") ||
 685                    0 == strcmp(user_argv[i], "-Wl,-static") ||
 686                    0 == strcmp(user_argv[i], "-Wl,--static") ||
 687                    0 == strcmp(user_argv[i], "-Wl,-Bstatic")) {
 688             flags |= COMP_WANT_STATIC;
 689         } else if (0 == strcmp(user_argv[i], "-dynamic") ||
 690                    0 == strcmp(user_argv[i], "--dynamic") ||
 691                    0 == strcmp(user_argv[i], "-Bdynamic") ||
 692                    0 == strcmp(user_argv[i], "-Wl,-dynamic") ||
 693                    0 == strcmp(user_argv[i], "-Wl,--dynamic") ||
 694                    0 == strcmp(user_argv[i], "-Wl,-Bdynamic")) {
 695             flags &= ~COMP_WANT_STATIC;
 696         } else if (0 == strcmp(user_argv[i], "--openmpi:linkall")) {
 697             /* This is an intentionally undocummented wrapper compiler
 698                switch.  It should only be used by Open MPI developers
 699                -- not end users.  It will cause mpicc to use the
 700                static library list, even if we're compiling
 701                dynamically (i.e., it'll specifically -lopen-rte and
 702                -lopen-pal (and all their dependent libs)).  We provide
 703                this flag for test MPI applications that also invoke
 704                ORTE and/or OPAL function calls.
 705 
 706                On some systems (e.g., OS X), if the top-level
 707                application calls ORTE/OPAL functions and you don't -l
 708                ORTE and OPAL, then the functions won't be resolved at
 709                link time (i.e., the implicit library dependencies of
 710                libmpi won't be pulled in at link time), and therefore
 711                the link will fail.  This flag will cause the wrapper
 712                to explicitly list the ORTE and OPAL libs on the
 713                underlying compiler command line, so the application
 714                will therefore link properly. */
 715             flags |= COMP_WANT_LINKALL;
 716 
 717             /* remove element from user_argv */
 718             opal_argv_delete(&user_argc, &user_argv, i, 1);
 719         } else if ('-' != user_argv[i][0]) {
 720             disable_flags = false;
 721             flags |= COMP_SHOW_ERROR;
 722             real_flag = true;
 723         } else {
 724             /* if the option flag is one that we use to determine
 725                which set of compiler data to use, don't count it as a
 726                real option */
 727             if (find_options_index(user_argv[i]) < 0) {
 728                 real_flag = true;
 729             }
 730         }
 731     }
 732 
 733     /* clear out the want_flags if we got no arguments not starting
 734        with a - (dash) and -showme wasn't given OR -showme was given
 735        and we had at least one more non-showme argument that started
 736        with a - (dash) and no other non-dash arguments.  Some examples:
 737 
 738        opal_wrapper                : clear our flags
 739        opal_wrapper -v             : clear our flags
 740        opal_wrapper -E a.c         : don't clear our flags
 741        opal_wrapper a.c            : don't clear our flags
 742        opal_wrapper -showme        : don't clear our flags
 743        opal_wrapper -showme -v     : clear our flags
 744        opal_wrapper -showme -E a.c : don't clear our flags
 745        opal_wrapper -showme a.c    : don't clear our flags
 746     */
 747     if (disable_flags && !((flags & COMP_DRY_RUN) && !real_flag)) {
 748         flags &= ~(COMP_WANT_PREPROC|COMP_WANT_COMPILE|COMP_WANT_LINK);
 749     }
 750 
 751     /****************************************************
 752      *
 753      * Assemble the command line
 754      *
 755      ****************************************************/
 756 
 757     /* compiler (may be multiple arguments, so split) */
 758     if (flags & COMP_WANT_COMMAND) {
 759         exec_argv = opal_argv_split(options_data[user_data_idx].compiler, ' ');
 760         exec_argc = opal_argv_count(exec_argv);
 761     } else {
 762         exec_argv = (char **) malloc(sizeof(char*));
 763         exec_argv[0] = NULL;
 764         exec_argc = 0;
 765     }
 766 
 767     /* This error would normally not happen unless the user edits the
 768        wrapper data files manually */
 769     if (NULL == exec_argv) {
 770         opal_show_help("help-opal-wrapper.txt", "no-compiler-specified", true);
 771         return 1;
 772     }
 773 
 774     if (flags & COMP_WANT_COMPILE) {
 775         opal_argv_insert(&exec_argv, exec_argc,
 776                          options_data[user_data_idx].comp_flags_prefix);
 777         exec_argc = opal_argv_count(exec_argv);
 778     }
 779 
 780     /* Per https://svn.open-mpi.org/trac/ompi/ticket/2201, add all the
 781        user arguments before anything else. */
 782     opal_argv_insert(&exec_argv, exec_argc, user_argv);
 783     exec_argc = opal_argv_count(exec_argv);
 784 
 785     /* preproc flags */
 786     if (flags & COMP_WANT_PREPROC) {
 787         opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].preproc_flags);
 788         exec_argc = opal_argv_count(exec_argv);
 789     }
 790 
 791     /* compiler flags */
 792     if (flags & COMP_WANT_COMPILE) {
 793         opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].comp_flags);
 794         exec_argc = opal_argv_count(exec_argv);
 795     }
 796 
 797     /* link flags and libs */
 798     if (flags & COMP_WANT_LINK) {
 799         bool have_static_lib;
 800         bool have_dyn_lib;
 801         bool use_static_libs;
 802         char *filename1, *filename2;
 803         struct stat buf;
 804 
 805         opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].link_flags);
 806         exec_argc = opal_argv_count(exec_argv);
 807 
 808         /* Are we linking statically?  If so, decide what libraries to
 809            list.  It depends on two factors:
 810 
 811            1. Was --static (etc.) specified?
 812            2. Does OMPI have static, dynamic, or both libraries installed?
 813 
 814            Here's a matrix showing what we'll do in all 6 cases:
 815 
 816            What's installed    --static    no --static
 817            ----------------    ----------  -----------
 818            ompi .so libs       -lmpi       -lmpi
 819            ompi .a libs        all         all
 820            ompi both libs      all         -lmpi
 821 
 822         */
 823 
 824         filename1 = opal_os_path( false, options_data[user_data_idx].path_libdir, options_data[user_data_idx].static_lib_file, NULL );
 825         if (0 == stat(filename1, &buf)) {
 826             have_static_lib = true;
 827         } else {
 828             have_static_lib = false;
 829         }
 830 
 831         filename2 = opal_os_path( false, options_data[user_data_idx].path_libdir, options_data[user_data_idx].dyn_lib_file, NULL );
 832         if (0 == stat(filename2, &buf)) {
 833             have_dyn_lib = true;
 834         } else {
 835             have_dyn_lib = false;
 836         }
 837 
 838         /* Determine which set of libs to use: dynamic or static.  Be
 839            pedantic to make the code easy to read. */
 840         if (flags & COMP_WANT_LINKALL) {
 841             /* If --openmpi:linkall was specified, list all the libs
 842                (i.e., the static libs) if they're available, either in
 843                static or dynamic form. */
 844             if (have_static_lib || have_dyn_lib) {
 845                 use_static_libs = true;
 846             } else {
 847                 fprintf(stderr, "The linkall option has failed as we were unable to find either static or dynamic libs\n"
 848                         "Files looked for:\n  Static: %s\n  Dynamic: %s\n",
 849                         filename1, filename2);
 850                 free(filename1);
 851                 free(filename2);
 852                 exit(1);
 853             }
 854         } else if (flags & COMP_WANT_STATIC) {
 855             /* If --static (or something like it) was specified, if we
 856                have the static libs, then use them.  Otherwise, use
 857                the dynamic libs. */
 858             if (have_static_lib) {
 859                 use_static_libs = true;
 860             } else {
 861                 use_static_libs = false;
 862             }
 863         } else {
 864             /* If --static (or something like it) was NOT specified
 865                (or if --dyanic, or something like it, was specified),
 866                if we have the dynamic libs, then use them.  Otherwise,
 867                use the static libs. */
 868             if (have_dyn_lib) {
 869                 use_static_libs = false;
 870             } else {
 871                 use_static_libs = true;
 872             }
 873         }
 874         free(filename1);
 875         free(filename2);
 876 
 877         if (use_static_libs) {
 878             opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].libs_static);
 879         } else {
 880             opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].libs);
 881         }
 882         exec_argc = opal_argv_count(exec_argv);
 883     }
 884 
 885 
 886     /****************************************************
 887      *
 888      * Execute the command
 889      *
 890      ****************************************************/
 891 
 892     if (flags & COMP_DRY_RUN) {
 893         exec_command = opal_argv_join(exec_argv, ' ');
 894         printf("%s\n", exec_command);
 895     } else {
 896         char *tmp;
 897 
 898 #if 0
 899         exec_command = opal_argv_join(exec_argv, ' ');
 900         printf("command: %s\n", exec_command);
 901 #endif
 902 
 903         tmp = opal_path_findv(exec_argv[0], 0, environ, NULL);
 904         if (NULL == tmp) {
 905             opal_show_help("help-opal-wrapper.txt", "no-compiler-found", true,
 906                            exec_argv[0], NULL);
 907             errno = 0;
 908             exit_status = 1;
 909         }  else {
 910             int status;
 911 
 912             free(exec_argv[0]);
 913             exec_argv[0] = tmp;
 914             ret = opal_few(exec_argv, &status);
 915             exit_status = WIFEXITED(status) ? WEXITSTATUS(status) :
 916                               (WIFSIGNALED(status) ? WTERMSIG(status) :
 917                                   (WIFSTOPPED(status) ? WSTOPSIG(status) : 255));
 918             if( (OPAL_SUCCESS != ret) || ((0 != exit_status) && (flags & COMP_SHOW_ERROR)) ) {
 919                 char* exec_command = opal_argv_join(exec_argv, ' ');
 920                 if( OPAL_SUCCESS != ret ) {
 921                     opal_show_help("help-opal-wrapper.txt", "spawn-failed", true,
 922                                    exec_argv[0], strerror(status), exec_command, NULL);
 923                 } else {
 924 #if 0
 925                     opal_show_help("help-opal-wrapper.txt", "compiler-failed", true,
 926                                    exec_argv[0], exit_status, exec_command, NULL);
 927 #endif
 928                 }
 929                 free(exec_command);
 930             }
 931         }
 932     }
 933 
 934     /****************************************************
 935      *
 936      * Cleanup
 937      *
 938      ****************************************************/
 939  cleanup:
 940 
 941     opal_argv_free(exec_argv);
 942     opal_argv_free(user_argv);
 943     if (NULL != base_argv0) free(base_argv0);
 944 
 945     if (OPAL_SUCCESS != (ret = data_finalize())) {
 946         return ret;
 947     }
 948 
 949     if (OPAL_SUCCESS != (ret = opal_finalize_util())) {
 950         return ret;
 951     }
 952 
 953     return exit_status;
 954 }

/* [<][>][^][v][top][bottom][index][help] */