【问题标题】:MinGW system() system call and %PATH% behaviourMinGW system() 系统调用和 %PATH% 行为
【发布时间】:2012-01-28 15:35:27
【问题描述】:

我正在尝试用 MinGW 编译 ATLAS。我开始解决问题,但现在我遇到了一个简单的问题:ATLAS 的 Makefile 尝试使用 MinGW 提供的 uname.exe 来探测操作系统。

如果我运行 MinGW shell (sh.exe),我可以调用 uname。如果我打开 Windows 命令提示符,我可以调用 uname(因此 %PATH% 变量和 $PATH 变量设置正确)。

代码在内部调用类似 system("uname -s >\tempfilneame &2>1") 的东西。主要问题是(正如我分析 FileMon 的输出)应用程序(sh.exe)创建一个 cmd.exe 进程,然后执行我的命令,但未找到 uname。如果我将 system("d:/.../bin/uname -s >\tempfilename &2>1") 添加到代码中,一切正常。所以应该是PATH变量的问题。如果没有必要,我不会修改代码中的每一个调用。问题是:cmd.exe进程启动有什么特别之处,所以无法识别uname,请问如何解决这个问题。

【问题讨论】:

    标签: mingw msys


    【解决方案1】:

    Msys 的目的是提供一个最小的准“*nix”(即非 POSIX)Bourne Shell(一个“*nix”命令行解释器),在其中执行程序、命令和 shell 脚本就像在一个“*nix”系统(参考http://www.mingw.org/)。如果出于某种原因,希望从 MS Windows 命令行解释器 (cmd.exe) 运行 MinGW/bin Msys/1.0/bin 可执行文件,则 MS Windows 环境 %PATH% 变量必须包括这两个“bin”子目录的路径——例如“.;C:\MinGW\bin;C:\MinGW\msys\1.0\bin;%PATH%”。

    以下信息严格指的是使用 MinGW 提供的 GCC 4.6.2 编译器套件从通过 msys.bat 调用的 Msys sh.exe 中构建 ATLAS 库。

    确保您的 Msys $PATH 环境变量包含“.:您的 MinGW 和 Msys bin 目录的路径”——即“.:/C/MinGW/bin:/C/MinGW/msys/1.0/bin:$ PATH”,如果那是您安装 MinGW 和 Msys 的位置(这应该在发生 sh 登录时由 /etc/profile 脚本完成,如 \msys\1.0\msys.bat 文件)。

    必须对使用 system() 函数调用 shell 命令或可执行文件(“make”除外)的任何 ATLAS 程序语句进行以下更改:

    1) 将“./executable”更改为“.\\executable”或“executable”,因为 MS Windows cmd.exe shell(或更准确地说,称为 MS Windows 系统库例程)将“./executable”解释为可执行文件'.'带有命令选项'/executable',因此错误消息:“'。'未被识别为内部或外部命令、可运行程序或批处理文件。”确保使用“-v 2”调用 ATLAS/configure 以定位任何有问题的 system() 调用——只有少数!!!

    ATLAS/bin/atlas_install.c
    ATLAS/CONFIG/src/atlbench.c
    ATLAS/CONFIG/src/config.c
    ATLAS/tune/blas/gemm/userindex.c
    ATLAS/tune/blas/ger/r1search.c
    ATLAS/tune/sysinfo/emit_buildinfo.c
    

    2) 将“command ; command”更改为“command && command”,因为 MS Windows cmd.exe 不接受使用 ';' 的复合命令语句与其他“*nix”外壳或“make”中的分隔符。

    3) 用双引号将任何出现的单引号替换为 sprintf() 语句中用于传递给 system() 调用的命令的分隔字符串格式说明符;特别是在 ATLAS/CONFIG/src/config.c 文件的 SpewItForth 函数中。例如,将 "... '%s' ..." 更改为 "... \"%s\" ..."。对于使用 system() 调用调用的“make”命令,这不是必需的。由于 MS Windows cmd.exe shell 需要 CRLF 行尾终止,因此必须对 ATLAS/bin/atlas_install.c 和 ATLAS/tune/sysinfo/emit_buildinfo.c 文件进行以下更改。

    在 ATLAS/bin/atlas_install.c 中,第 133 行来自:

        if ( (sp == NULL) || (str[0] == '\0') || (str[0] == '\n') )
    

    到:

        if ( (sp == NULL) || (str[0] == '\0') || (str[0] == '\r') || (str[0] == '\n') )
    

    第 165 行,来自:

        else if (ln[0] == '\0' || ln[0] == '\n') ch=def;
    

    到:

        else if (ln[0] == '\0' || ln[0] == '\r' || ln[0] == '\n') ch=def;
    

    第 175 行,来自:

        else if (ln[0] == '\0' || ln[0] == '\n') ch=def;
    

    到:

        else if (ln[0] == '\0' || ln[0] == '\r' || ln[0] == '\n') ch=def;
    

    在 ATLAS/tune/sysinfo/emit_buildinfo.c 中,第 66 行来自:

        for (i=0; ln[i]; i++) if (ln[i] == '"' || ln[i] == '`') ln[i] = '\'';
    

    到:

        for (i=0; ln[i]; i++) if (ln[i] == '"' || ln[i] == '`') ln[i] = '\"';
    

    第 68 行来自:

        for (i--; i >= 0 && (ln[i] == ' ' || ln[i] == '\n' || ln[i] == '\t'); i--);
    

    到:

        for (i--; i >= 0 && (ln[i] == ' ' || ln[i] == '\r' || ln[i] == '\n' || ln[i] == '\t'); i--);
    

    另外,在 ATLAS/tune/sysinfo/emit_buildinfo.c 文件中,更改:

      if (CommandOneLine("date",DATE)) strcpy(DATE, "UNKNOWN");
    

    到:

      if (CommandOneLine("date /t",DATE)) strcpy(DATE, "UNKNOWN");
    

    因为 MS Windows cmd.exe "date" 命令会提示 "Enter the new date: (mm-dd-yy)" 并等待永远不会输入的响应。

    虽然我对每个受影响的文件进行了上述更改,但遵守基本的软件工程和配置管理原则将要求将重复的代码合并到使用某种形式的“#if defined(ATL_OS_WinNT) && defined(__MINGW32__)”包装的单个过程中处理指令,以防止更改对其他“*nix”操作系统上的 ATLAS 安装产生不利影响。在这方面,我不建议使用“补丁”方法将 MinGW32 特定更改合并到 ATLAS 发行版中,而是将必要的更改合并到最新的 ATLAS 开发版本中。当然,“修补”可能是修复不受支持的 ATLAS 版本的唯一替代方法。

    在过去的几天里,我能够使用 MinGW、Msys 和从以下网址下载的 GCC 4.6.2 编译器套件构建经过调整的 ATLAS 3.8.4 静态库:

    http://sourceforge.net/projects/mingw/files/

    并使用 mingw-get-inst-20111118.exe 安装在具有双 Intel Xeon(具有 MMX、SSE 和 SSE2 的 Pentium 4 [L1 缓存 8 KB,L2 缓存 256 KB] 的 11 岁戴尔工作站 530 上),但没有超线程)1.5 GHz 处理器、400 MHz FSB 和 1024 MB RDRAM,运行 Windows 2000 Professional SP4。

    上述修改并不全面,但应该能让您走得更远。我计划记录我对 ATLAS 3.8.4 发行版所做的所有更改,并在验证我的调整配置并使用 LAPACK-3.4.0 构建完整的共享库后将其发布在 http://sourceforge.net/projects/math-atlas/forums/ 的“Windows 上的 ATLAS”论坛上.

    我希望这些信息对您和其他尝试在 Windows 平台上使用 MinGW 和 没有 Cygwin 构建 ATLAS 的人有所帮助。

    特别说明:

    使用将输出定向到从调用 tmpnam() 获得的临时文件名的命令调用 system() 将导致在当前驱动器的根目录中创建临时文件。临时文件名以“\\”为前缀,在 MinGW/include/stdio.h 中定义(参见 P_tmpdir)。

    重要附录:

    (A) 确保在使用 ATLAS/configure 的“-s”和“-b”命令选项指定源目录和构建目录时使用完整路径名。就我而言,以下 sh 脚本显示了我如何从 ATLAS_build 调用 ATLAS/configure:

    #!/bin/sh
    
    SRCDIR=/g/Progs/MinGW/msys/1.0/home/GaryD/temp/ATLAS
    BLDDIR=/g/Progs/MinGW/msys/1.0/home/GaryD/temp/ATLAS_build
    LAPACK=/g/Progs/MinGW/lib/gcc/mingw32/4.6.2/liblapack.dll.a
    
    CC=gcc
    C_DEFS="-D c -DL2SIZE=262144"  # Not used, set using -f 256
    F_DEFS="-D f ''"               # Not used, let configure set these
    C_FLGS="--cc=$CC --with-netlib-lapack=$LAPACK"
    D_FLGS="-d s $SRCDIR -d b $BLDDIR"
    A_FLGS="-O 8 -s 1 -A 20 -V 8 -b 32 -f 256 -t 2 -m 1495"
    S_FLGS="-Si bozol1 1 -Si archdef 0 -Si cputhrchk 0"
    
    $SRCDIR/configure $C_FLGS -v 2 $D_FLGS $A_FLGS $S_FLGS
    

    (B) 我认为首选构建目录是 ATLAS 源目录下的子目录,例如 ATLAS/ATLAS_build,因为 ATLAS 不可能找到文件 ../../CONFIG/error.txt /bin/atlas_install.c 如果源目录和构建目录在同一级别。

    (C) 不要犯我在假设“-m ####”配置选项隐式创建“-D c DPentiumCPS=####”配置标志时所犯的错误。您可能需要显式传递“-D c -DPentiumCPS=####”或“-D c -DWALL”,如“ATLAS 安装指南”第 3.4 节“更改 ATLAS 执行计时方式”中所述在这里查看:

    http://math-atlas.sourceforge.net/atlas_install/atlas_install.html#SECTION00044000000000000000

    由于不使用周期精确的挂钟,健全性测试的结果(例如来自“xsslvtst.exe -n 167 -r 83 -O 2 c r -U 2 u l”的结果)类似于以下内容:

        ORD  UPLO       N    NRHS     lda     ldb       TIME     MFLOP        RESID
        ===  ====  ======  ======  ======  ======  =========  ========  ===========
    
          C     U     167      83     167     167      0.015    257.82  1.762022e-003
          C     L     167      83     167     167      0.016    241.70  1.870298e-003
          R     U     167      83     167     167      0.000 2229332063710638100.00  1.870298e-003
          R     L     167      83     167     167      0.000 2229332063710638100.00  1.762022e-003
    
        4 TESTS RUN, ALL PASSED.
    

    测试的每次调用都会为 MFLOP 产生不同的虚假值,这可能是由一个非常、非常、非常小的非零值进行算术除法造成的。在使用“-D c -DWALL”重建 ATLAS 后,这些 MFLOP 结果(无疑还有其他计时措施)得到了纠正。

    (D) ATLAS/CONFIG/src/probe_OS.c 的第 35 行需要检查 MinGW,如下所示:

    else if(strstr(ln, "WIN") || strstr(ln, "MINGW"))
    

    并在 ATLAS/CONFIG/src/Makefile 中的“IRunArchInfo_linux: xarchinfo_linux”块之后插入以下内容(只需剪切、粘贴和编辑 Makefile 中的 IRunArchInfo_linux 块):

    IRunArchInfo_winnt: xarchinfo_x86
        - rm -f config0.out
        $(MAKE) $(atlrun) atldir=$(mydir) exe=xarchinfo_x86 args="$(args)" \
                redir=config0.out
        - cat config0.out
    

    (E) 可能需要在 ATLAS/CONFIG/src/atlconf.txt 文件中将 gcc-4 行更改为 gcc,因为 MinGW gcc 可执行文件只是 gcc.exe 而不是 gcc-4.exe MinGW32 gcc 编译器套件的最新版本。 ATLAS 开发人员可能更倾向于使用配置标志来覆盖编译器选择和更改/附加编译标志,而不是编辑 atlconf.txt 文件(请参阅“ATLAS 安装指南”的第 3.2 节);但我很不耐烦。

    (F) 如果您使用“-V 8”ATLAS/configure 选项为我的架构指定 SSE2,则必须对 ATLAS/include/atlas_asm.h 文件进行以下更改。

    第 133 行来自:

        #if defined(ATL_SSE1) && !defined(ATL_3DNow)
    

    到:

        #if (defined(ATL_SSE1) || defined(ATL_SSE2)) && !defined(ATL_3DNow)
    

    【讨论】:

      猜你喜欢
      • 2011-03-26
      • 1970-01-01
      • 2011-07-05
      • 1970-01-01
      • 2011-09-26
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 1970-01-01
      相关资源
      最近更新 更多