繁体   English   中英

无法在 Windows 上使用 make 命令编译 Makefile

[英]Cannot compile Makefile using make command on Windows

问题总结

我正在尝试安装一个名为 TACS 的开源并行有限元代码,可在github 存储库中获得。 为了符合指定的先决条件,我按照此 github 存储库中的说明进行操作,这使我可以使用预编译的 BLAS/LAPACK DLL 在 Windows 上安装SuiteSparseMETIS 对于 MPI,我通过 Cygwin 安装了 Intel MPI Library 和 Open MPI。 最后一步应该是编译运行make ,但是这个命令在 Windows 10 中不直接可用。因此,我探索了这个问题中建议的选项,不幸的是没有成功。 我觉得在死胡同,任何帮助将不胜感激。

我试过的

请看下面我的尝试。 我主要是一个 Windows 用户,我不太了解使用Makefile编译程序。 我目前的理解是,我正在尝试编译的Makefile是为 Linux 编写的,而我使用的任何用于 Windows 的 GNU 编译器都不会工作,因为需要不同的语法。 如果我错了,请纠正我。 我无法理解的是,为什么当我尝试使用 Ubuntu Bash 编译 Windows 10(下面列表的最后一次尝试)时也会出现错误。

Visual Studio nmake

以管理员身份运行 VS 2019 的开发人员命令提示符,我在 TACS 基本目录中键入nmake -f Makefile ,我得到Makefile.in(28): fatal error U1001: syntax error: illegal character '{' in macro Stop.

在此处输入图像描述

巧克力make

以管理员身份运行 Windows 命令提示符,在PATH环境变量顶部使用C:\ProgramData\chocolatey\bin ,我在 TACS 基本目录中键入make ,我得到了

"" was unexpected at this time.
make: *** [Makefile:23: default] Error 255

在此处输入图像描述

Cygwin make

以管理员身份运行 Windows 命令提示符,在PATH环境变量的顶部设置C:\cygwin64\bin ,我在 TACS 基本目录中键入make ,我得到了三种类型的错误:

error: expected ',' or '...' before numeric constant
error: cannot convert 'int*' to 'idx_t*' {aka 'long int*'}
error: no matching function for call to 'TACSSchurMat::getBCSRMat(BCSRMat**, NULL, NULL, NULL)'

我尝试更改受影响脚本中的一些变量名称(例如用N_代替_N ),我摆脱了第一种和第三种错误,但没有摆脱第二种错误。

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

GnuWin make

以管理员身份运行 Windows 命令提示符,在PATH环境变量顶部使用C:\Program Files (x86)\GnuWin32\bin ,我在 TACS 基本目录中键入make ,我得到了

"" was unexpected at this time.
make: *** [Makefile:23: default] Error 255

在此处输入图像描述

MinGW mingw32-make

以管理员身份运行 Windows 命令提示符,在PATH环境变量顶部使用C:\MinGW\bin ,我在 TACS 基本目录中键入mingw32-make ,我得到了

"" was unexpected at this time.
Makefile:23: recipe for target 'default' failed
mingw32-make: *** [default] Error 255

在此处输入图像描述

MSYS MinGW 64 位make

以管理员身份运行 Windows 命令提示符,在PATH环境变量顶部使用C:\msys64\usr\bin ,我在 TACS 基本目录中键入make ,我得到了

make[1]: mpicxx: No such file or directory
make[1]: *** [../TACS_Common.mk:28: C:/Users/qa21944/git/tacs/src/TACSAssembler.o] Error 127
make[1]: *** Waiting for unfinished jobs....
make[1]: mpicxx: No such file or directory
make[1]: *** [../TACS_Common.mk:28: C:/Users/qa21944/git/tacs/src/TACSCreator.o] Error 127
make[1]: Leaving directory '/c/Users/qa21944/git/tacs/src'
make: *** [Makefile:23: default] Error 1

这对我来说很难理解,因为mpicxx文件是C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin ,它又位于PATH环境变量中。 当我尝试将C:\cygwin64\bin添加到PATH (低于C:\msys64\usr\bin )并重新运行make时,我得到了

      0 [main] opal_wrapper (14432) C:\cygwin64\bin\opal_wrapper.exe: *** fatal error - cygheap base mismatch detected - 0x180352408/0x180357408.
This problem is probably due to using incompatible versions of the cygwin DLL.
Search for cygwin1.dll using the Windows Start->Find/Search facility
and delete all but the most recent version.  The most recent version *should*
reside in x:\cygwin\bin, where 'x' is the drive on which you have
installed the cygwin distribution.  Rebooting is also suggested if you
are unable to find another cygwin DLL.

我尝试按照这些说明进行操作,然后重新启动计算机,但没有任何改变。

在此处输入图像描述

在此处输入图像描述

Ubuntu Bash 对于 Windows 10 make

本次尝试的灵感来自于这个答案 我从 Microsoft Store 下载了 Ubuntu 并安装了make 从 Ubuntu Bash 我在 TACS 基本目录中键入make ,我得到了

make[1]: Entering directory '/mnt/c/Users/qa21944/git/tacs/src'
Makefile:26: *** target pattern contains no '%'.  Stop.
make[1]: Leaving directory '/mnt/c/Users/qa21944/git/tacs/src'
make: *** [Makefile:23: default] Error 1 

我不明白为什么我会得到这个错误。 我还确保所有行都以制表符而不是空格开头,但没有任何改变。

在此处输入图像描述

代码

您可以在下面找到我正在使用的Makefile.inMakefile

Makefile.in

# Do not modify this file. Copy this file to Makefile.in and then modify it.

# In order to get TACS to compile, you'll need to fill in the
# following path information. Some of the items below are required
# only if you're going to use the python interface.

# the full path to the root TACS directory
TACS_DIR = C:/Users/qa21944/git/tacs
CXX = mpicxx
RM = rm -f
PYTHON = python
PYTHON_CONFIG = python-config

# Set up for parallel make
MAKE = make -j 8

# Set the ar flags
AR_FLAGS = rcs

# Flags for debugging and regular compilation versions
EXTRA_DEBUG_CC_FLAGS = -fPIC -g 
EXTRA_CC_FLAGS = -fPIC -O3

# Use this if you have problems with mpich
# TACS_DEF = -DMPICH_IGNORE_CXX_SEEK

# Defines whether to use static or dynamic linking
# TACS_LD_CMD=${TACS_DIR}/lib/libtacs.a
TACS_LD_CMD=-L${TACS_DIR}/lib/ -Wl,-rpath,${TACS_DIR}/lib -ltacs

# For linux systems, use the following settings:
SO_EXT=so
SO_LINK_FLAGS=-fPIC -shared

# For MAC OS X, use the following settings:
# SO_EXT=so
# SO_LINK_FLAGS=-fPIC -dynamiclib

# This uses the default installation of LAPACK. 
# Use an optimized version of LAPACK if available.
# You may also have to include -lblas as well.

LAPACK_LIBS = -LC:/SP_ROOT/lapack_windows/x64 -llapack -lpthread -lblas

# For MAC OSX use the accelerate framework
# LAPACK_LIBS=-framework accelerate

# METIS is handy for partitioning graphs, but can be problematic for
# compilation.  If you compile METIS using a C++ compiler you must add
# -DTACS_CPLUSPLUS_METIS to the TACS_DEF arguments below. If you
# compile METIS using a C compiler, there should be no issues.

METIS_INCLUDE = -IC:/SP_ROOT/build/install/include
METIS_LIB = -LC:/SP_ROOT/build/install/lib -lmetis

# AMD is a set of routines for ordering matrices. It is not required by default.

AMD_INCLUDE = -IC:/SP_ROOT/build/install/include/suitesparse
AMD_LIBS = -LC:/SP_ROOT/build/install/lib -llibamd

Makefile

# ============================================
#
# Make file for TACS_DIR/
#
# ============================================

include Makefile.in
include TACS_Common.mk

TACS_SUBDIRS = src \
    src/bpmat \
    src/elements \
    src/elements/dynamics \
    src/elements/basis \
    src/elements/shell \
    src/constitutive \
    src/functions \
    src/io

TACS_OBJS := $(addsuffix /*.o, ${TACS_SUBDIRS})

default:
    @if [ "${TACS_IS_COMPLEX}" = "true" ]; then \
       echo "Building Complex TACS"; \
       for subdir in $(TACS_SUBDIRS) ; do \
          echo "making $@ in $$subdir"; \
          echo; (cd $$subdir && $(MAKE) TACS_DIR=${TACS_DIR} TACS_DEF="${TACS_DEF} -DTACS_USE_COMPLEX") || exit 1; \
            done \
    else \
       echo "Building Real TACS"; \
       for subdir in $(TACS_SUBDIRS) ; do \
          echo "making $@ in $$subdir"; \
          echo; (cd $$subdir && $(MAKE) TACS_DIR=${TACS_DIR}) || exit 1; \
            done \
    fi
    ${CXX} ${SO_LINK_FLAGS} ${TACS_OBJS} ${TACS_EXTERN_LIBS} -o ${TACS_DIR}/lib/libtacs.${SO_EXT}
    @if [ "${TACS_IS_COMPLEX}" = "true" ]; then \
        echo "ctypedef complex TacsScalar" > tacs/TacsTypedefs.pxi; \
        echo "TACS_NPY_SCALAR = np.NPY_CDOUBLE" > tacs/TacsDefs.pxi; \
        echo "dtype = complex" >> tacs/TacsDefs.pxi; \
    else \
        echo "ctypedef double TacsScalar" > tacs/TacsTypedefs.pxi; \
        echo "TACS_NPY_SCALAR = np.NPY_DOUBLE" > tacs/TacsDefs.pxi; \
        echo "dtype = np.double" >> tacs/TacsDefs.pxi; \
    fi

debug:
    @if [ "${TACS_IS_COMPLEX}" = "true" ]; then \
       echo "Building Complex TACS"; \
       for subdir in $(TACS_SUBDIRS) ; do \
          echo "making $@ in $$subdir"; \
          echo; (cd $$subdir && $(MAKE) debug TACS_DIR=${TACS_DIR} TACS_DEF="${TACS_DEF} -DTACS_USE_COMPLEX") || exit 1; \
            done \
    else \
       echo "Building Real TACS"; \
       for subdir in $(TACS_SUBDIRS) ; do \
          echo "making $@ in $$subdir"; \
          echo; (cd $$subdir && $(MAKE) debug TACS_DIR=${TACS_DIR}) || exit 1; \
            done \
    fi
    ${CXX} ${SO_LINK_FLAGS} ${TACS_OBJS} ${TACS_EXTERN_LIBS} -o ${TACS_DIR}/lib/libtacs.${SO_EXT}
    @if [ "${TACS_IS_COMPLEX}" = "true" ]; then \
        echo "ctypedef complex TacsScalar" > tacs/TacsTypedefs.pxi; \
        echo "TACS_NPY_SCALAR = np.NPY_CDOUBLE" > tacs/TacsDefs.pxi; \
        echo "dtype = complex" >> tacs/TacsDefs.pxi; \
    else \
        echo "ctypedef double TacsScalar" > tacs/TacsTypedefs.pxi; \
        echo "TACS_NPY_SCALAR = np.NPY_DOUBLE" > tacs/TacsDefs.pxi; \
        echo "dtype = np.double" >> tacs/TacsDefs.pxi; \
    fi

interface:
    ${PYTHON} setup.py build_ext --inplace

complex_interface:
    ${PYTHON} setup.py build_ext --inplace --define TACS_USE_COMPLEX

complex: TACS_IS_COMPLEX=true
complex: default

complex_debug: TACS_IS_COMPLEX=true
complex_debug: debug

clean:
    ${RM} lib/libtacs.a lib/libtacs.so
    ${RM} tacs/*.so tacs/*.cpp
    @for subdir in $(TACS_SUBDIRS) ; do \
      echo "making $@ in $$subdir"; \
      echo; \
         (cd $$subdir && $(MAKE) $@ TACS_DIR=${TACS_DIR}) || exit 1; \
    done

编辑:我正在按照评论中的要求添加TACS_Common.mk的片段。

TACS_Common.mk

TACS_LIB = ${TACS_DIR}/lib/libtacs.a

TACS_INCLUDE = -I${TACS_DIR}/src \
    -I${TACS_DIR}/src/bpmat \
    -I${TACS_DIR}/src/elements \
    -I${TACS_DIR}/src/elements/dynamics \
    -I${TACS_DIR}/src/elements/basis \
    -I${TACS_DIR}/src/elements/shell \
    -I${TACS_DIR}/src/constitutive \
    -I${TACS_DIR}/src/functions \
    -I${TACS_DIR}/src/io

# Set the command line flags to use for compilation
TACS_OPT_CC_FLAGS = ${TACS_DEF} ${EXTRA_CC_FLAGS} ${METIS_INCLUDE} ${AMD_INCLUDE} ${TACS_INCLUDE}
TACS_DEBUG_CC_FLAGS = ${TACS_DEF} ${EXTRA_DEBUG_CC_FLAGS} ${METIS_INCLUDE} ${AMD_INCLUDE} ${TACS_INCLUDE}

# By default, use the optimized flags
TACS_CC_FLAGS = ${TACS_OPT_CC_FLAGS}

# Set the linking flags to use
TACS_EXTERN_LIBS = ${AMD_LIBS} ${METIS_LIB} ${LAPACK_LIBS}
TACS_LD_FLAGS = ${EXTRA_LD_FLAGS} ${TACS_LD_CMD} ${TACS_EXTERN_LIBS}

# This is the one rule that is used to compile all the
# source code in TACS
%.o: %.cpp
    ${CXX} ${TACS_CC_FLAGS} -c $< -o $*.o
    @echo
    @echo "        --- Compiled $*.cpp successfully ---"
    @echo

我无法回答,但也许我可以引导你。

首先nmake不是make。 它不适用于任何不是专门编写为 nmake makefile 的 makefile。它仅在 Windows 上可用。所以,最好忘记它的存在。

其次,了解 make 的工作原理很重要:makefile 中的规则是目标/先决条件和配方的组合。 配方不是“makefile”语法,它是一个 shell 脚本(批处理文件)。 因此,make 与 shell 协同工作,以运行命令。 哪个shell? 在 GNU/Linux 和 MacOS 等 POSIX 系统上,它非常简单:一个 POSIX shell; 默认情况下/bin/sh

在 Windows 系统上就没那么简单了:有很多选项。 它可能是cmd.exe 它可能是 PowerShell。它可能是用户安装的 POSIX shell。 默认情况下选择哪一个取决于您的make版本是如何编译的。 这就是为什么您看到make到 Windows 的不同“端口”有不同的行为。

因此,如果您查看尝试使用的 makefile,您会发现它们无疑是专门为 POSIX 系统编写的,并且期望 POSIX shell 和 POSIX 环境。 任何尝试使用调用cmd.exe作为其默认值 shell 的make版本的任何尝试都会立即失败并出现语法错误( “”此时是意外的。 )。

好的,所以您找到了调用 POSIX shell 的 make 版本,并且您不会再收到该错误。

但是你必须应对另一个不同之处:目录分隔符。 在 Windows 中,他们使用反斜杠。 在 POSIX 系统中,他们使用正斜杠和反斜杠作为转义字符(因此它不只是通过 shell 原封不动地传递)。 如果你打算在 POSIX shell 中使用路径,你需要确保你的路径使用正斜杠,否则 shell 会将它们作为转义字符删除。 幸运的是,大多数 Windows 程序都接受正斜杠和反斜杠作为目录分隔符(但不是所有:例如cmd.exe内置工具不接受)。

然后,您必须应对 Windows 驱动器号这一令人厌恶的东西。 这对make make:字符在很多地方都很特殊。 因此,当 make 看到像C:/foo:C:/bar这样的行时,它的解析器会感到困惑,你会得到错误。 某些为 Windows 编译的make版本启用试探法,它会尝试查看路径是否看起来像驱动器号。 有些只是采用 POSIX 风格的路径。 它们也可能是 POSIX shell 的问题:Windows map 驱动器号到标准 POSIX 路径的许多 POSIX 环境,因此C:\foo被写为/c/foo/mnt/c/foo或其他。 如果要向 makefile 添加路径,则需要找出正确的映射(如果有)并使用它。

这甚至还没有开始讨论 POSIX 和 Windows 之间的其他区别……有太多了。

从上面显示的内容来看,这个项目在编写时并没有考虑到 Windows 的任何类型的可移植性。 考虑到这一点的复杂性,这并不奇怪:它需要大量的工作。 所以你有这些选项,我可以看到:

  1. 自己移植以与 Windows 兼容
  2. 尝试让它在 cygwin 中工作(cygwin 旨在成为在 Windows 上运行的 POSIX 风格的环境)
  3. 尝试让它在 WSL 中工作
  4. 使用运行 Linux 发行版的 VMWare、VirtualBox 等安装虚拟机,并在那里构建和运行它

不幸的是,我对这些方法的优缺点知之甚少,所以我无法就最佳方案向您提供建议。

很久很久以前,我选择的路线是完全摆脱 Windows,只使用 GNU/Linux。 但当然这对每个人来说都是不可能的:)。

您需要一个真正的答案:您不能使用 Windows 命令提示符进行编译。

获取自己的 MSYS2——它也将安装 MinGW-w64——并按照安装说明进行操作。 然后启动 MSYS shell 以获得 unix-y 终端提示符(zsh,IIRC),并将目录更改为项目文件夹的头部。

要访问 Windows 文件系统,根目录将是/c/mnt/c (抱歉,在我的移动 ATM 上,我可以在一两天内改进它)。 例如,

C:\Users\qa21944\git\tacs

成为

/c/Users/qa21944/git/tacs

从那里 GNU/Windows make 命令应该可以工作:

mingw32-make

还有这篇文章在 Windows 下使用更现代的 *nix 环境: How to install and use "make" in Windows? 不过,对于您需要的东西,感谢可能有点矫枉过正。

当我完成旅行并且可以坐下来好好看看这个时,我可以改进这个答案的细节,但是你需要一个 Linux shell 终端。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM