## MinGW-64 and CompilationTarget -> "C": can't make library

14

9

I'm trying to set up my new Windows 8.1 tablet to compile Mathematica (9.0.1) functions to C, using the MinGW-64 compiler. I have it set up so that the following works:

greeter = CreateExecutable[StringJoin[
"#include <stdio.h>\n",
"int main(){\n",
"  printf(\"Hello MinGW-w64 world.\\n\");\n",
"}\n"],
"hiworld"];
Import["!\"" <> greeter <> "\"", "Text"]


However, function compilation to C fails, as follows:

zeroC = Compile[{
},
0,
CompilationTarget -> "C"
];

CreateLibrary::cmperr: "Compile error: collect2.exe: error: ld returned 1 exit status

Compile::nogen: A library could not be generated from the compiled function.


On an older computer that I had previously set up for compilation, this same function definition works fine.

Any clues as to what is going wrong? It would of course be helpful if I could see exactly what commands Mathematica is passing to the shell, and what complaint ld makes. CreateExecutable has an option "ShellOutputFunction" -> Print that shows what it's doing, but I can't figure out how to pass this to Compile.

1

How to set up MinGW-64 is a good question. But if you want to avoid trouble and have reliably working compilation with minimal fuss, then just install Microsoft's compiler. I recommend this version, which is not the latest, but will only install command line tools and takes a bit less disk space. It works out of the box with Mma. See here.

– Szabolcs – 2014-07-16T16:39:39.143

I tried that: it wouldn't install. I assumed without investigating that it was an incompatibility between Windows 8.1 and the Win7 SDK. – Leon Avery – 2014-07-16T17:02:44.410

1I have successfully installed it on Windows 8.1, so it's not incompatible. (Which I realize doesn't help you install it, but it's good to note that the problem was not incompatibility.) – Szabolcs – 2014-07-16T17:07:25.413

Hmm, thanks. If I hadn't solved the problem with MinGW, your remark would have spurred me to try harder to get Visual Studio working. As it is, I think I'll let it ride. I've been using MinGW for a couple years now and it works fine for me. – Leon Avery – 2014-07-16T17:18:53.927

14

Figured it out. The key was working out that if I included "ShellOutputFunction"->Print in the $CCompiler list, compilation of the function would show me what the shell was doing. Thus I learned that it was failing to find libgcc_s. I found libgcc_s.a in C:\MinGW-64\lib. I created a system environment variable LIBRARY_PATH with value C:\MinGW-64\lib, and the function now compiles and works. (It also works to add "CompileOptions" -> {"-O2", "-LC:/MinGW-64/lib"} to $CCompiler.)

Edit: Here's a summary of what it takes to get MinGW-64 working with Mathematica's Compile and LibraryLink:

1. Download the package manager from win-builds.org. At the time I grabbed it, it was yypkg-1.4.0.exe. Double-click on it and install the 64-bit compiler to C:\MinGW-64.

2. In the System control panel (well-hidden in Windows 8.1, but you can find it by hitting the Windows key + X), click Advanced settings, then Environment variables. Add ;C:\MinGW-64\bin to the end of Path. Create a new environment variable called LIBRARY_PATH and set its value to C:\MinGW-64\lib.

3. Add the following to your init.m:

Needs["CCompilerDriver"]
Needs["CCompilerDriverGenericCCompiler"]
$CCompiler={"Compiler"->GenericCCompiler, "CompilerInstallation"->"C:/MinGW-64","CompilerName"->"x86_64-w64-mingw32-gcc.exe", "CompileOptions"->"-O2"};  I put this in my user init.m in C:\Users\USERNAME\AppData\Roaming\Mathematica\Kernel\. If more than one user uses the machine, you might want to put it in the system-level init.m instead. -O2 is the usual recommended optimization level. You don't need this, but it can speed things up a lot, which is presumably why you're compiling functions to C in the first place. Try -O3 if you like living dangerously. 4. Try it out with the definitions I posted in the question. 1 Related: http://mathforum.org/kb/message.jspa?messageID=7841068 It looks like to use MathLink (not LibraryLink) some libraries need to be converted first. I don't know much about this. – Szabolcs – 2014-07-17T14:34:42.103 2-O3 in gcc is supposed to maintain standards compliance, unlike in e.g. Intel C. -Ofast would be the potentially dangerous option. N.B. -O3 does not always produce faster code than -O2 and can actually be slower due to producing more, or more nonlocal memory accesses, or expanding the working set. – Oleksandr R. – 2014-07-17T15:27:13.873 Note that MinGW-64 from win-builds does not have a fortran compiler. – Denis Cousineau – 2017-06-07T04:50:52.257 +1. And as a note, the default path of MinGW is under C:\Program Files\. The whitespace between"Program Files" will also make the compilation fail. – luyuwuli – 2018-07-04T17:19:45.100 7 This is both a comment, too long to be posted as a comment, on the previous answer, and another answer. The reason for posting is that the steps that I had to do to get MinGW-64 working on my computer are a little bit different and simpler than the steps given by Leon. Obviously, the first step is to get MinGW-64. I was unable to do this on win-builds.org, but just as in this question, I downloaded from sourceforge.net the executable mingw-w64-install.exe. I ran it with the settings Architecture: x86-64 and Threads: win32. That took about 15 minutes. The progress bar was much faster at the end than at the beginning. Inside the map mingw-w64, two levels down, there is a map mingw64. I copied this map to C:\ and renamed it as MinGW-64. Now we are the situation described in the tutorial "Specific Compilers" under the head "MinGW for 64-Bit Targets". So I tried the greeter test mentioned there: greeter=CreateExecutable[StringJoin[ "#include <stdio.h>\n", "int main(){\n", " printf(\"Hello MinGW-w64 world.\\n\");\n", "}\n"], "hiworld","Compiler"->GenericCCompiler,"CompilerInstallation"->"C:\\MinGW-64\\bin","CompilerName"->"x86_64-w64-mingw32-gcc.exe"] (*C:\Users\Fred Simons\AppData\Roaming\Mathematica\SystemFiles\LibraryResources\Windows-x86-64\hiworld.exe*)  It worked immediately. (Observe that there are no spaces in the path to MinGW-64, and that we may leave out '\bin'. See also my comment at the end of this answer.) Import["!\""<>greeter<>"\"","Text"] (* Hello MinGW-w64 world. *)  This works as well. Next, as in the tutorial, I defined$CCompiler:

$CCompiler = {"Compiler"->GenericCCompiler, "CompilerInstallation"->"C:\\MinGW-64\\bin","CompilerName"->"x86_64-w64-mingw32-gcc.exe"}; f = Compile[{x}, Sqrt[1+x^2], CompilationTarget->"C"]; f[1] (* 1.41421 *)  So everything works fine. Even better, it behaves like a correct installation of a C-compiler, without having placed anything in an init.m file or having created system variables; in every session of Mathematica it works immediately. A side remark. Actually, I described my installation of MinGW in Mathematica 10. When I started the testing of Mathematica 11, it did not work any more. I had a very good support of WRI. The reason was that in the map \SystemFiles\FrontEnd\Binaries\Windows-x86-64 in the installation directory there was a file libwinpthread-1.dll, which is missing in the map for Mathematica 11. Copying this file from Mathematica 10 to Mathematica 11 solved the problem. In Mathematica 11.0.0 this file seems to be not needed anymore. After all, installing the MinGW compiler on my computer turned out to be simple. It takes 'only' 421 MB of memory, while an installation of Windows Visual Studio takes at least about 2GB. I hate my computer to be polluted with a lot of software that I do not need. But my installation seems to have a problem: it is not recognized by Mathematica as an installed compiler. CCompilers[] returns an empty list and SystemInformation[] tells me that there are no C-compilers installed, despite the fact that I have it working. I have no idea if this is a serious problem. It works flawless for already a year, both in Mathematica 10 and in Mathematica 11. I just had to get this working under Mathematica 11.0.0. I had the libwinpthread-1.dll problem Fred describes, but after copying that file I needed another file, and yet another file and... I eventually copied all lib*.dll from C:\MinGW\bin to \SystemFiles\FrontEnd\Binaries\Windows-x86-64, and then I was able to compile and run functions. – Leon Avery – 2016-12-30T05:13:26.343 Thanks a lot! This finally worked for me on MMA 10.2 and Win10 64bit. The trick is really to find the "mingw-w64-install.exe" on the net and follow your steps. However, each time I start a new MMA session where I want to compile something I need to execute Needs["CCompilerDriverGenericCCompiler"] and then your code $CCompiler = {"Compiler"->GenericCCompiler,...... Is there any way to incorporate this into the default settings of MMA on start-up? – Quit007 – 2017-10-09T17:13:03.960

@Quit007. Glad to hear that it works for you. For me, at start up the packages CCompilerDriverGenericCCompiler and CCompilerDriver are automatically loaded (they are on \$ContextPath), but I have no idea why. It might have been a side effect of all my attempts to install MinGW. You could try to place the Needs commands on one of the init.m files. – Fred Simons – 2017-10-10T06:46:02.217

@Quit007: You can put the necessary code in init.m. – Leon Avery – 2018-07-10T00:09:20.570