Home > Software design >  Cannot compile Makefile using make command on Windows
Cannot compile Makefile using make command on Windows

Time:10-04

Problem summary

I am trying to install an open-source parallel finite-element code called TACS and available at enter image description here

Chocolatey make

Running Windows Command Prompt as administrator with C:\ProgramData\chocolatey\bin at the top of PATH environment variable, I typed make in TACS base directory and I got

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

enter image description here

Cygwin make

Running Windows Command Prompt as administrator with C:\cygwin64\bin at the top of PATH environment variables, I typed make in TACS base directory and I got three types of error:

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)'

I tried to change some variable names in the affected scripts (like N_ in place of _N) and I got rid of the first and the third type of error, but not of the second one.

enter image description here

enter image description here

enter image description here

GnuWin make

Running Windows Command Prompt as administrator with C:\Program Files (x86)\GnuWin32\bin at the top of PATH environment variables, I typed make in TACS base directory and I got

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

enter image description here

MinGW mingw32-make

Running Windows Command Prompt as administrator with C:\MinGW\bin at the top of PATH environment variables, I typed mingw32-make in TACS base directory and I got

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

enter image description here

MSYS MinGW 64-bit make

Running Windows Command Prompt as administrator with C:\msys64\usr\bin at the top of PATH environment variables, I typed make in TACS base directory and I got

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

This is quite difficult for me to understand, as the mpicxx file is C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin, which in turn is in the PATH environment variable. When I tried to add C:\cygwin64\bin to PATH (below C:\msys64\usr\bin) and to rerun make, I got

      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.

I tried to follow these instructions and then rebooted my computer, but nothing changed.

enter image description here

enter image description here

Ubuntu Bash for Windows 10 make

This attempt was inspired by enter image description here

Codes

Below you can find the Makefile.in and Makefile that I am using.

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

CodePudding user response:

I can't answer but maybe I can orient you.

First nmake is not make. It will not work with any makefile not written specifically as an nmake makefile. And it's only available on Windows. So, best to just forget it exists.

Second, it's important to understand how make works: rules in makefiles are a combination of targets/prerequisites, and a recipe. The recipe is not in "makefile" syntax, it's a shell script (batch file). So make works in tandem with the shell, to run commands. Which shell? On POSIX systems like GNU/Linux and MacOS it's very simple: a POSIX shell; by default /bin/sh.

On Windows systems it's much less simple: there are a lot of options. It could be cmd.exe. It could be PowerShell. It could be a POSIX shell, that was installed by the user. Which one is chosen by default, depends on how your version of make was compiled. That's why you see different behaviors for different "ports" of make to Windows.

So, if you look at the makefiles you are trying to use you can see they are unquestionably written specifically for a POSIX system and expect a POSIX shell and a POSIX environment. Any attempt to use a version of make that invokes cmd.exe as its default shell will fail immediately with syntax errors ("" was unexpected at this time.).

OK, so you find a version of make that invokes a POSIX shell, and you don't get that error anymore.

But then you have to contend with another difference: directory separators. In Windows they use backslash. In POSIX systems, they use forward slash and backslash is an escape character (so it's not just passed through the shell untouched). If you are going to use paths in a POSIX shell, you need to make sure your paths use forward slashes else the shell will remove them as escape characters. Luckily, most Windows programs accept forward slashes as well as backslashes as directory separators (but not all: for example cmd.exe built-in tools do not).

Then you have to contend with the Windows abomination known as drive letters. This is highly problematic for make because to make, the : character is special in various places. So when make sees a line like C:/foo:C:/bar its parser will get confused, and you get errors. Some versions of make compiled for Windows enable a heuristic which tries to see if a path looks like a drive letter or not. Some just assume POSIX-style paths. They can also be a problem for the POSIX shell: many POSIX environments on Windows map drive letters to standard POSIX paths, so C:\foo is written as /c/foo or /mnt/c/foo or something else. If you are adding paths to your makefile you need to figure out what the right mapping, if any, is and use that.

That's not even to start discussing the other differences between POSIX and Windows... there are so many.

From what you've shown above, this project was not written with any sort of portability to Windows in mind. Given the complexity of this, that's not surprising: it takes a huge amount of work. So you have these options that I can see:

  1. Port it yourself to be Windows-compatible
  2. Try to get it working inside cygwin (cygwin is intended to be a POSIX-style environment that runs on Windows)
  3. Try to get it working in WSL
  4. Install a virtual machine using VMWare, VirtualBox, etc. running a Linux distribution and build and run it there

Unfortunately I don't know much about the pros and cons of these approaches so I can't advise you as to the best course.

The route I chose, long long ago, was to get rid of Windows entirely and just use GNU/Linux. But of course that won't be possible for everyone :).

CodePudding user response:

You need a real answer: you can't compile using the Windows Command Prompt.

Get yourself MSYS2 -- which will also install MinGW-w64 -- and follow the setup instructions. Then launch the MSYS shell to get a unix-y terminal prompt (zsh, IIRC), and change directory to the head of the project folder.

To access the Windows filesystem the root directory will be either /c or /mnt/c (sorry, on my mobile ATM, I can improve this in a day or two). For example,

C:\Users\qa21944\git\tacs

becomes

/c/Users/qa21944/git/tacs

From there the GNU/Windows make command should work:

mingw32-make

There is also this post to use more modern *nix environments under Windows: How to install and use "make" in Windows? Thanks may be overkill for what you need, though.

When I finish traveling and can sit down to look at this properly I can improve this answer's details, but getting a Linux shell terminal is what you need.

  • Related