loentar/ngrest

Build issues on Windows 10

Closed this issue · 11 comments

When I try to call ngrest or ngrest build to start a service on Windows 10, I notice a couple quirks in the build process. First, the ngrest bash script (invoked from ngrest.cmd on Windows) does not seem to override my default CMake generator (Visual Studio project files) as it is supposed to. This appears to be due to the following code in the script's build() function definition:

if [ $OS = MSYS ]
then
  CMAKE_FLAGS+=" '-GUnix Makefiles' -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc"
fi

cmake $CMAKE_FLAGS $PROJECT_DIR >cmake.log || return $?

The generator argument gets ignored for some reason, and CMake proceeds as if it were generating a Visual Studio project. If I slightly modify the code as follows, then it generates the expected Unix Makefiles:

if [ $OS = MSYS ]
then
  CMAKE_GENERATOR="Unix Makefiles"
  cmake -G"$CMAKE_GENERATOR" -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc $PROJECT_DIR >cmake.log || return $?
else
  cmake -DCMAKE_BUILD_TYPE=DEBUG $PROJECT_DIR >cmake.log || return $?
fi

I think the issue had something to do with the space in the generator name. A similar change might be advisable in the definition for build_package():

if [ $OS = MSYS ]
then
  CMAKE_GENERATOR="Unix Makefiles"
  cmake -G"$CMAKE_GENERATOR" ${CMAKE_FLAGS:-} "$2" >cmake-build.log
else
  cmake ${CMAKE_FLAGS:-} "$2" >cmake-build.log
fi
#[ $OS != MSYS ] || CMAKE_FLAGS="'-GUnix Makefiles' ${CMAKE_FLAGS:-}"
#cmake "${CMAKE_FLAGS:-}" "$2" >cmake-build.log

The other quirk I noticed was that when I try to run ngrest(.cmd) from a standard command prompt, I run into the following error when the script is running the make command on the generated Makefile:

Cannot create temporary file in C:\WINDOWS\: Permission denied

I'm not sure if this is something that I could easily change through some setting, but by default, make seems to try putting temporary files in the WINDOWS directory by default. I can get around this if I run the ngrest command from a command prompt as an administrator, but I was curious if there was any simpler way to deal with this problem. If not, then it might be useful to add a remark about this to the "Create a new project" section of the readme.

Significantly, this issue causes the same problems for the basic installation on Windows. The problem in this case occurs on lines 114-121 of scripts/inst:

echo "Configuring ngrest for the build..."
if [ $OS = MSYS ]
then
  # supress platform warnings
  touch /usr/share/cmake-$(cmake --version | sed '1{s/cmake version //;q}')/Modules/Platform/$(uname -s).cmake 2>/dev/null || true
  CMAKE_FLAGS="${CMAKE_FLAGS:-} '-GUnix Makefiles' -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc"
fi
cmake ${CMAKE_FLAGS:-} ../ngrest >cmake-build.log

By changing these lines to the followig, the inst script called from MSYS2 works as expected:

echo "Configuring ngrest for the build..."
if [ $OS = MSYS ]
then
  # supress platform warnings
  touch /usr/share/cmake-$(cmake --version | sed '1{s/cmake version //;q}')/Modules/Platform/$(uname -s).cmake 2>/dev/null || true
  CMAKE_GENERATOR="Unix Makefiles"
  cmake ${CMAKE_FLAGS:-} -G"$CMAKE_GENERATOR" -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc ../ngrest >cmake-build.log
else
  cmake ${CMAKE_FLAGS:-} ../ngrest >cmake-build.log
fi

The version of the inst script at http://bit.ly/ngrest may need to be updated accordingly. Unfortunately, I haven't been able to test if this works yet; running inst directly from the MSYS2 MinGW 64-bit terminal gives me a "permission denied" error when the script tries to rename the ngrest directory temporarily.

I'm sorry but it the windows support was not completed.

BTW, try starting the script from your home.

Also there is an option to run it under Ubuntu for Windows.

If I open up a new MSYS2 MinGW 64-bit terminal and try to run inst from the home location, I still get the same "permission denied" error when the script invokes the mv command.

It's good to know that Windows support isn't completed yet; I would have spent a lot of frustrating time trying to figure out what was going wrong, so thank you for letting me know ahead of time! I have an Ubuntu machine, so it will probably be easiest for me to develop on that.

The Permission error is a very strange error. It says you don't have permission to rename directory in your own home directory?

Try removing that directory manually and re-run installation script. Run this from MinGW terminal:

rm -rf $APPDATA/ngrest/ngrest $HOME/.ngrest

and then start usual installation process.

Also if you say you have cmake installed from visual studio - it wouldn't work because it configured for visual studio but it is not supported. Only cmake with WinGW gcc is supported.

Ah, I see what my problem was. I was getting the "permission denied" error because I was trying to call the inst script in the $APPDATA/ngrest/ngrest directory after I'd edited it; the mv command didn't work because the inst script was trying to move the directory that contains it. If I modify the script as outlined above, then copy it from $APPDATA/ngrest/ngrest/scripts to $HOME and run it from there (as I would if I was using the wget command), then everything works.

I'm happy to say that the changes to the bash script also work as I hoped. The problem isn't that I have cmake installed from Visual Studio; even if I change my PATH so that the version of cmake packaged in mingw64/bin is the version I use, it defaults to generating Visual Studio Projects unless a different generator (e.g., Unix Makefiles) is specified. My point is that when you try to specify a different generator in the inst script (and the ngrest script) with something like

CMAKE_FLAGS="${CMAKE_FLAGS:-} '-GUnix Makefiles' -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc"
...
cmake ${CMAKE_FLAGS:-} ../ngrest

cmake doesn't parse the -G argument the way you expect it to. It just ignores it, and if it detects a Windows machine with Visual Studio installed, it will default to generating a Visual Studio project instead of a Makefile. Rather than surrounding the -G argument with single quotes, you need to place the Unix Makefiles argument within quotes. But because of the space in the name, it doesn't quite work if you try to do it in a single line like you have here. I had to define a variable (CMAKE_GENERATOR) that contained the generator string and then escape that in the cmake call, with something like

cmake ${CMAKE_FLAGS:-} -G"$CMAKE_GENERATOR" -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc ../ngrest >cmake-build.log

Once I did that, the Makefile was correctly generated, and the installation process completed.

I'm also curious about the naming convention of ngrest libraries on Windows. On lines 42-48 of ngrest/CMakeFiles.txt, you appear to use the following lines to strip the Unix lib prefix and .a suffix from the generated libraries:

if (MINGW)
    add_definitions(-D_WIN32_WINNT=0x0501)
    set(CMAKE_SHARED_LIBRARY_PREFIX "")
    set(CMAKE_SHARED_MODULE_PREFIX "")
    set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll")
    set(CMAKE_SHARED_MODULE_SUFFIX ".dll")
endif()

This seems to work for the libraries placed in the deploy/bin directory, but not for the ones placed in deploy/lib. Is this the intended behavior?

As I understand under Windows any dynamic library must be placed into the same dir as executable.. Unlike linux to link the dynamic library you must link .a file instead.. So guess that's correct..

That makes sense. The shared libraries seem to be getting written correctly, then. Apart from my suggested changes to the cmake calls in ngrest and inst, I don't have anything else to add to this issue.

Ok, I think I fixed it, can you please re-test?

I just re-tested it. The installation completely successfully, and ngrest is generating Unix Makefiles for services as expected. Thanks!

Great! Thank you.