Categories: Java, Testing

Investigating a jtreg Failure

Download jtreg from the AdoptOpenJDK dependency pipeline (adoptopenjdk.net). For this investigation, I’ll be using my MacBook M1 running Monterey 12.1.

mkdir investigate
cd investigate
git clone https://github.com/openjdk/jdk11u

# Download jtreg 6
curl -Lo jtreg-6+1.tar.gz https://ci.adoptopenjdk.net/view/Dependencies/job/dependency_pipeline/lastSuccessfulBuild/artifact/jtreg/jtreg-6+1.tar.gz

tar xzfv jtreg-6+1.tar.gz

cd jdk11u

We switch the current directory to the root of jdk11u repo so that test paths are relative to the repo root. I will assume that we’re in the jdk11u repo root directory and are using the directory structure generated by the commands above. To see a detailed list of all the jtreg options, run this command:

../jtreg/bin/jtreg -help all

Now let us try to run a jtreg test, specifically AmazonCA.java:

../jtreg/bin/jtreg test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

There are some failure messages but it looks like a test ran.

failed to get value for vm.hasJFR
java.lang.UnsatisfiedLinkError: 'boolean sun.hotspot.WhiteBox.isJFRIncludedInVmBuild()'
	at sun.hotspot.WhiteBox.isJFRIncludedInVmBuild(Native Method)
	at requires.VMProps.vmHasJFR(VMProps.java:343)
	at requires.VMProps$SafeMap.put(VMProps.java:72)
	at requires.VMProps.call(VMProps.java:107)
	at requires.VMProps.call(VMProps.java:60)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:80)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
failed to get value for vm.aot.enabled
java.lang.UnsatisfiedLinkError: 'int sun.hotspot.WhiteBox.aotLibrariesCount()'
	at sun.hotspot.WhiteBox.aotLibrariesCount(Native Method)
	at requires.VMProps.vmAotEnabled(VMProps.java:408)
	at requires.VMProps$SafeMap.put(VMProps.java:72)
	at requires.VMProps.call(VMProps.java:112)
	at requires.VMProps.call(VMProps.java:60)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:80)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
.
.
.
Test results: passed: 1
Report written to /Users/saint/repos/java/jdk11u/JTreport/html/report.html
Results written to /Users/saint/repos/java/jdk11u/JTwork

Are these failure messages concerning given that the test passed? Reviewing the test report suggests not. The report keywords mention bug 8233223, which must be Bug ID: JDK-8233223 Add Amazon Root CA certificates (java.com). From the look of things, the java.lang.UnsatisfiedLinkErrors can be safely ignored (for this test anyway). That said, let us dig into these errors to ensure we understand what is happening.

The immediate cause of these errors is the failure to get the values for the SafeMap in VMProps.java. This raises the question of which JDK is being used by jtreg? My MacBook has both JDK11 and JDK17. The default java version is:

java -version
openjdk version "17.0.1" 2021-10-19 LTS
OpenJDK Runtime Environment Microsoft-28056 (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM Microsoft-28056 (build 17.0.1+12-LTS, mixed mode)

Let’s ensure jtreg is using JDK11 by setting JTREG_JAVA.

JTREG_JAVA=/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home

$JTREG_JAVA/bin/java -version

openjdk version "11.0.14" 2022-01-18 LTS
OpenJDK Runtime Environment Microsoft-30257 (build 11.0.14+9-LTS)
OpenJDK 64-Bit Server VM Microsoft-30257 (build 11.0.14+9-LTS, mixed mode)

../jtreg/bin/jtreg test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

We still see the same warnings though so let us explicitly use the -jdk option:

../jtreg/bin/jtreg -jdk:$JTREG_JAVA test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

We now get an interesting error message indicating that the -jdk option was using the newer JDK17.

Exception while calling user-specified class: requires.VMProps
java.lang.UnsupportedClassVersionError: requires/VMProps has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	...
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:315)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:78)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
failed to get JDK properties for /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/java ; exit code 1
Error: failed to get JDK properties for /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/java ; exit code 1

On my machine, I can remove these files as follows:

ls -l /Users/saint/repos/java/jdk11u/JTwork/extraPropDefns/classes/requires

rm -fr /Users/saint/repos/java/jdk11u/JTwork/extraPropDefns/classes/requires

Rerunning the test now results in a single (different) UnsatisfiedLinkError AND a test failure! However, we now have a properly set up environment since we control the JDK version tested by jtreg.

jdk11u % ../jtreg/bin/jtreg -jdk:$JTREG_JAVA test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

failed to get value for vm.musl
java.lang.UnsatisfiedLinkError: 'java.lang.String sun.hotspot.WhiteBox.getLibcName()'
	at sun.hotspot.WhiteBox.getLibcName(Native Method)
	at requires.VMProps.isMusl(VMProps.java:514)
	at requires.VMProps$SafeMap.put(VMProps.java:72)
	at requires.VMProps.call(VMProps.java:122)
	at requires.VMProps.call(VMProps.java:60)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:80)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
Test results: failed: 1
Report written to /Users/saint/repos/java/jdk11u/JTreport/html/report.html
Results written to /Users/saint/repos/java/jdk11u/JTwork
Error: Some tests failed or other problems occurred.

Now here’s an interesting question: why doesn’t this approach yield identical result to setting the -jdk flag to this same JTREG_JAVA path?

JTREG_JAVA=/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home

../jtreg/bin/jtreg test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

After doing some printf (or rather echo) debugging and observing an empty string for JTREG_JAVA, the culprit turns out to be the difference between a shell variable and an environment variable. See command line – What is the difference in usage between shell variables and environment variables? – Unix & Linux Stack Exchange. For the jtreg script to pull in this value of JTREG_JAVA, it needs to be an environment variable. It should therefore show up when this command is executed:

printenv | grep -i java

The proper way to execute this test then is:

JTREG_JAVA=/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home

export JTREG_JAVA

../jtreg/bin/jtreg test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

The outcome of the experiment so far though is that the AmazonCA test appears to fail when run with JDK11 and pass when run with JDK17 (of the respective versions). To convince ourselves that the infrastructure is fine, we can run this test with JDK11 (which is our focus) after exporting JTREG_JAVA.

../jtreg/bin/jtreg test/hotspot/jtreg/compiler/aot/cli/IncorrectAOTLibraryTest.java

This test passes, despite the single UnsatisfiedLinkError printed out.

failed to get value for vm.musl
java.lang.UnsatisfiedLinkError: 'java.lang.String sun.hotspot.WhiteBox.getLibcName()'
	at sun.hotspot.WhiteBox.getLibcName(Native Method)
	at requires.VMProps.isMusl(VMProps.java:514)
	at requires.VMProps$SafeMap.put(VMProps.java:72)
	at requires.VMProps.call(VMProps.java:122)
	at requires.VMProps.call(VMProps.java:60)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:80)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
Test results: passed: 1
Report written to /Users/saint/repos/java/jdk11u/JTreport/html/report.html
Results written to /Users/saint/repos/java/jdk11u/JTwork

An Interesting Test

The above experimentation was inspired by AotInvokeDynamic2AotTest.java. The first time I tried to run this test, I used this command line.

../jtreg/bin/jtreg test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java

We first set of 5 UnsatisfiedLinkError failures in the previous experiment were displayed but no tests were executed.

...
Test results: no tests selected
Report written to /Users/saint/repos/java/jdk11u/JTreport/html/report.html

This was happening while jtreg was using JDK17 and one of the values that could not be get()ed vm.aot.enabled. Could that be why there were no selected tests? Ignoring that rabbit hole for now sine jdk11u is our focus. We can now run the test with JTREG_JAVA exported. The test is now run but fails with this message in JTreport/text/summary.txt:

compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java  Failed. Execution failed: `main' threw exception: java.lang.RuntimeException: Expected to get exit value of [0]

To see more details about the test failure, use the -verbose flag:

../jtreg/bin/jtreg -verbose:fail,error,summary test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java

Here is the a portion of the output of the test run. Notice the linker error in there!

ACTION: build -- Passed. All files up to date
REASON: Named class compiled on demand
TIME:   0.0 seconds
messages:
command: build compiler.aot.AotCompiler
reason: Named class compiled on demand
elapsed time (seconds): 0.0

ACTION: driver -- Failed. Execution failed: `main' threw exception: java.lang.RuntimeException: Expected to get exit value of [0]
REASON: User specified action: run driver compiler.aot.AotCompiler -libname AotInvokeDynamic2AotTest.so -class compiler.calls.common.InvokeDynamic -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:. 
TIME:   4.821 seconds
messages:
command: driver compiler.aot.AotCompiler -libname AotInvokeDynamic2AotTest.so -class compiler.calls.common.InvokeDynamic -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
reason: User specified action: run driver compiler.aot.AotCompiler -libname AotInvokeDynamic2AotTest.so -class compiler.calls.common.InvokeDynamic -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:. 
Mode: othervm
Additional options from @modules: --add-modules java.base --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-exports java.base/jdk.internal.misc=ALL-UNNAMED
elapsed time (seconds): 4.821
configuration:
Boot Layer
  add modules: java.base                                
  add exports: java.base/jdk.internal.misc              ALL-UNNAMED
               java.base/jdk.internal.org.objectweb.asm ALL-UNNAMED

STDOUT:
Command line: [/usr/bin/ld -v]
@(#)PROGRAM:ld  PROJECT:ld64-764
BUILD 11:22:50 Apr 28 2022
configured to support archs: armv6 armv7 armv7s arm64 arm64e arm64_32 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em
LTO support using: LLVM version 13.1.6, (clang-1316.0.21.2.5) (static support for 28, runtime is 28)
TAPI support using: Apple TAPI version 13.1.6 (tapi-1316.0.7.3)

found working linker: /usr/bin/ld
Command line: [/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/jaotc -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI -J-Xbootclasspath/a:. -J-classpath -J/Users/saint/repos/java/jdk11u/JTwork/classes/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.d:/Users/saint/repos/java/jdk11u/JTwork/classes/test/lib:/Users/saint/repos/java/jdk11u/JTwork/classes/testlibrary:/Users/saint/repos/java/jdk11u/JTwork/classes:/Users/saint/repos/java/jdk11u/test/hotspot/jtreg/compiler/aot/calls/fromAot --compile-with-assertions --info --output AotInvokeDynamic2AotTest.so --class-name compiler.calls.common.InvokeDynamic -J-ea -J-esa -J-Xmixed]
Compiling AotInvokeDynamic2AotTest.so...
1 classes found (22 ms)
9 methods total, 8 methods to compile (12 ms)
Compiling with 10 threads
.
8 methods compiled, 0 methods failed (2785 ms)
Parsing compiled code (7 ms)
Processing metadata (46 ms)
Preparing stubs binary (3 ms)
Preparing compiled binary (2 ms)
Creating binary: AotInvokeDynamic2AotTest.so.o (18 ms)
Creating shared library: AotInvokeDynamic2AotTest.so (30 ms)
Exception in thread "main" java.lang.InternalError: ld: dynamic main executables must link with libSystem.dylib for architecture x86_64
	at jdk.aot@11.0.14/jdk.tools.jaotc.Linker.link(Linker.java:142)
	at jdk.aot@11.0.14/jdk.tools.jaotc.Main.run(Main.java:262)
	at jdk.aot@11.0.14/jdk.tools.jaotc.Main.run(Main.java:133)
	at jdk.aot@11.0.14/jdk.tools.jaotc.Main.main(Main.java:89)

Why on earth is there an error about x86_64 on my M1? Here is the failing command line, listed separately for easy execution:

/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/jaotc -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI -J-Xbootclasspath/a:. -J-classpath -J/Users/saint/repos/java/jdk11u/JTwork/classes/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.d:/Users/saint/repos/java/jdk11u/JTwork/classes/test/lib:/Users/saint/repos/java/jdk11u/JTwork/classes/testlibrary:/Users/saint/repos/java/jdk11u/JTwork/classes:/Users/saint/repos/java/jdk11u/test/hotspot/jtreg/compiler/aot/calls/fromAot --compile-with-assertions --info --output AotInvokeDynamic2AotTest.so --class-name compiler.calls.common.InvokeDynamic -J-ea -J-esa -J-Xmixed

Once this command completes (and fails), a file named AotInvokeDynamic2AotTest.so.o exists on disk. The format of the ld command can be deduced from Linker.java:101. The ld command can then be directly invoked to see the actual failure:

% ld -dylib -o AotInvokeDynamic2AotTest.so AotInvokeDynamic2AotTest.so.o
ld: dynamic main executables must link with libSystem.dylib for architecture x86_64

As per Clang -nostdlib option not working | Apple Developer Forums I tried adding the -lSystem option but that was not sufficient.

% ld -lSystem -dylib -o AotInvokeDynamic2AotTest.so AotInvokeDynamic2AotTest.so.o
ld: library not found for -lSystem

Exploring Mach-O, Part 1 | g.p. anders (gpanders.com) pointed out that the solution is to include the path to the lib folder as well!

ld -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/ -lSystem -dylib -o AotInvokeDynamic2AotTest.so AotInvokeDynamic2AotTest.so.o

The proper way to address this test failure then is to fix Linker.java to pass these additional flags to ld.


Categories: Graphics

Building Gmsh in Windows

To build Gmsh on Windows, launch MSYS via the “MSYS2 MinGW x64” shortcut then run these commands:

git clone https://gitlab.onelab.info/gmsh/gmsh.git
cd gmsh
mkdir build
cd build
cmake .. -G "MSYS Makefiles" -DENABLE_FLTK:BOOL=TRUE -DCMAKE_INSTALL_PREFIX=../install

make install

Background

The build instructions for the Gmsh repo require the make command to build the code. The build instructions do not seem particularly specific for Windows. At the very least, they imply a Cygwin environment. I ended up using the environment I configured for building Elmer. Interestingly, the Ninja system is selected (not Visual Studio).

git clone https://gitlab.onelab.info/gmsh/gmsh.git
cd gmsh
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../install
-- Building for: Ninja
-- The CXX compiler identification is GNU 12.1.0
-- The C compiler identification is GNU 12.1.0
...

Compiler for Shipped Gmsh

Out of curiosity, I used a text editor to open the gmsh.exe binary I downloaded. I was curious to see if I could determine which compiler was used to generate it. The data in gmsh.exe was so much richer than I could have expected – there is information about not just the compiler, but also the compilation flags! Granted, I’m not yet 100% sure that this metadata is describing the gmsh.exe binary.

General Information:
-------------------
                   HDF5 Version: 1.10.5
                  Configured on: Mon May 17 05:00:08 PDT 2021
                  Configured by: geuzaine@DESKTOP-BH6899J
                    Host system: x86_64-unknown-cygwin
              Uname information: CYGWIN_NT-10.0 DESKTOP-BH6899J 3.2.0(0.340/5/3) 2021-03-29 08:42 x86_64 Cygwin
                       Byte sex: little-endian
             Installation point: /usr/local

Compiling Options:
------------------
                     Build Mode: production
              Debugging Symbols: no
                        Asserts: no
                      Profiling: no
             Optimization Level: high

Linking Options:
----------------
                      Libraries: static
  Statically Linked Executables: 
                        LDFLAGS: 
                     H5_LDFLAGS: 
                     AM_LDFLAGS: 
                Extra libraries: -lm 
                       Archiver: ar
                       AR_FLAGS: cr
                         Ranlib: ranlib

Languages:
----------
                              C: yes
                     C Compiler: /usr/bin/x86_64-w64-mingw32-gcc ( x86_64-w64-mingw32-gcc (GCC) 10.2.0)
                       CPPFLAGS: 
                    H5_CPPFLAGS:   -DNDEBUG -UH5_DEBUG_API
                    AM_CPPFLAGS: -D_FILE_OFFSET_BITS=64 
                        C Flags: 
                     H5 C Flags:   -pedantic -Wall -Wextra -Wbad-function-cast -Wc++-compat -Wcast-align -Wcast-qual -Wconversion -Wdeclaration-after-statement -Wdisabled-optimization -Wfloat-equal -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-declarations -Wmissing-include-dirs -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-prototypes -Wswitch-default -Wswitch-enum -Wundef -Wunused-macros -Wunsafe-loop-optimizations -Wwrite-strings -finline-functions -s -Wno-inline -Wno-aggregate-return -Wno-missing-format-attribute -Wno-missing-noreturn -O
                     AM C Flags: 
               Shared C Library: no
               Static C Library: yes


                        Fortran: no

                            C++: no

                           Java: no


Features:
---------
                   Parallel HDF5: no
Parallel Filtered Dataset Writes: no
              Large Parallel I/O: no
              High-level library: yes
                    Threadsafety: no
             Default API mapping: v110
  With deprecated public symbols: yes
          I/O filters (external): 
                             MPE: no
                      Direct VFD: no
                         dmalloc: no
  Packages w/ extra debug output: none
                     API tracing: no
            Using memory checker: no
 Memory allocation sanity checks: no
          Function stack tracing: no
       Strict file format checks: no
    Optimization instrumentation: no

Preceding this info was the substring SUMMARY OF THE HDF5 CONFIGURATION. It’s only now that I’m learning about HDF. Reviewing the cmake output also shows that cmake searched for HDF5 (output from CMakeLists.txt):

...
-- Could NOT find HDF5 (missing: HDF5_LIBRARIES HDF5_INCLUDE_DIRS) (found version "")
-- HDF5 not found
...

Finding Program Entry Point via GDB

Which GUI does Gmsh use? This was the simple question I wanted to answer. Looking around the tree I wasn’t sure where the program entry point was. Ended up searching for the regex main([^)] and there are still so many results (looks like benchmarks). Hmm, I could just launch it under the debugger and see which main function is being invoked. Finding instructions for this took longer than I expected (because I ignored the GDB manual). I eventually stumbled into debugging – GDB is not stopping at the first machine code instruction with break _start or info files Entry point address – Stack Overflow, which had the very useful info file command for showing the program’s entry point.

gdb gmsh.exe
GNU gdb (GDB) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
...
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gmsh.exe...
(gdb) b main
Function "main" not defined.
...
(gdb) b winmain
Function "winmain" not defined.
...
(gdb) step 1
The program is not being run.
(gdb) info file
Symbols from "D:\dev\repos\other\gmsh\build\gmsh.exe".
Local exec file:
        `D:\dev\repos\other\gmsh\build\gmsh.exe', file type pei-x86-64.
         Entry point: 0x100014f0
        0x0000000010001000 - 0x0000000010d73100 is .text
        0x0000000010d74000 - 0x0000000010dcb700 is .data
...
(gdb) b 0x100014f0
Function "0x100014f0" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
(gdb) b *0x100014f0
Breakpoint 1 at 0x100014f0: file C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c, line 196.

Running the program runs it to termination but by this point in time, I had already found what I was pretty sure was the program’s entry point (by browsing the sources in VSCode). Sure enough, relaunching gdb is now seamless:

(gdb) b wmain
Breakpoint 1 at 0x10001550: file D:/dev/repos/other/gmsh/src/common/Main.cpp, line 34.
(gdb) b GmshMainBatch
Breakpoint 2 at 0x10002fc0: file D:/dev/repos/other/gmsh/src/common/GmshGlobal.cpp, line 486.
(gdb) c
Continuing.

Thread 1 hit Breakpoint 2, GmshMainBatch (argc=1, argv=0x209707c5a90) at D:/dev/repos/other/gmsh/src/common/GmshGlobal.cpp:486
486     {

The GDB User Manual has a section on Starting your Program, which mentions that the starti command “does the equivalent of setting a temporary breakpoint at the first instruction of a program’s execution and then invoking the ‘run’ command.” This is probably closest to what I’ve been looking for.

Building with FLTK

In the midst of the chaos of trying to find the program’s entry point, I read a little bit about FLTK and discovered that it’s the GUI system Gmsh is using. Here’s the new cmake command to build the GUI-enabled Gmsh.

cmake .. -DENABLE_FLTK:BOOL=TRUE -DCMAKE_INSTALL_PREFIX=../install
ninja

Not only is the newly built gmsh.exe binary is a whooping 674MB, it also can’t start:

Unable to start gmsh.exe because libgomp-1.dll is missing

Same error is displayed for libgomp-10.dll when you click OK. Well, let’s try the install target – presumably that should create a usable installation:

$ make install
make: *** No rule to make target 'install'.  Stop.

Turns out there is no makefile in my build folder – I used ninja! As per the ninja manual, this command should list all available targets:

ninja -t targets all

After verifying that there is indeed an install target, run it using ninja:

ninja install

This is not sufficient to address the resulting missing DLL errors – perhaps additional components need to be statically linked into the produced binary. A work-around for now:

cp /mingw64/bin/libgomp-1.dll ../install/bin/
cp /mingw64/bin/libgmp-10.dll ../install/bin/
cp /mingw64/bin/libgcc_s_seh-1.dll ../install/bin/
cp /mingw64/bin/libwinpthread-1.dll ../install/bin/

Running gmesh now outputs the program’s usage info and exits. Still need to try it on some examples to ensure it works. There is also the unresolved question of why the GUI didn’t pop up.

Building using Makefiles

Since I used ninja for everything so far, I decided to use the makefiles generator and see what happens.

cmake .. -G "MSYS Makefiles" -DENABLE_FLTK:BOOL=TRUE -DCMAKE_INSTALL_PREFIX=../install

make install

There is no “Building for Ninja” line at the beginning of the cmake output. This time, the newly built gmsh.exe can run without the other DLLs I manually had to copy. Why doesn’t the GUI show up? Read the cmake output carefully:

-- Could NOT find FLTK (missing: FLTK_LIBRARIES FLTK_INCLUDE_DIR)
$ pacman -Ss fltk
...
mingw64/mingw-w64-x86_64-fltk 1.3.7-2
    C++ user interface toolkit (mingw-w64)
...

$ pacman -S --noconfirm --needed mingw64/mingw-w64-x86_64-fltk

Now running cmake finds FLTK:

-- Found FLTK: D:/dev/Software/msys64/mingw64/lib/libfltk_images.a;D:/dev/Software/msys64/mingw64/lib/libfltk_gl.a;opengl32;D:/dev/Software/msys64/mingw64/lib/libfltk.a
-- Found Fltk

And that’s it! Launching Gmsh from the install folder now launches the GUI application.

Outstanding Questions

Why does using the Makefiles generator produce a build that doesn’t require additional DLLs?


Thermal Oxidation

One of the key lessons from reading about oxidation was that Si has a key advantage over other semiconductors – it oxidizes much more readily thereby simplifying the development of insulation. I was looking up videos on the Deal-Grove oxidation model law when I stumbled into these videos by Chris Mack from a microfabrication course at the University of Texas at Austin using the same Microfabrication book I’m reading! It’s amazing how much free content there is out there.


Categories: Complexity Theory

Information Theory Bootcamp

I just started going through the Communication Complexity of Majority paper. I have not had any explicit study of information theory so I found it immensely helpful that there was a reference to this excellent series on Information Theory in Computational Complexity from the Simons Institute linked to here for reference.

Update: 2022-07-23 – A talk was uploaded specifically about the Communication Complexity of Majority Paper:


Categories: CMake, Elmer

Building the Elmer Install Folder

My post on How to Build Elmer on Windows has a succinct list of instructions but when I first built the Elmer source code (on Windows), I was unsure how to run the binaries. Running ElmerGUI, for example, failed because qt5.dll could not be found. This post details the process I used to figure out how to create a usable Elmer installation.

I started by going through the generated Makefile. It contained targets like install, install/local, and install/strip. I started with install/local, fearing that perhaps these targets would attempt to install the binaries into program files.

Installing only the local directory...
-- Install configuration: "RelWithDebInfo"
-- Installing: C:/dev/repos/fem/install/bin/libopenblas.dll.a
CMake Error at cmake_install.cmake:45 (file):
  file INSTALL cannot find "C:/dev/repos/fem/elmerfem/../bundle_msys2/bin":
  No error.


make: *** [Makefile:142: install/local] Error 1

The error at cmake_install.cmake:45 is from ElmerCPack.cmake. I did not even know about the existence of the CPack tool. Git blame points to commit b9914082 as the source of the failing command. The strange thing about that commit is that there is no mention of what is supposed to create the bundle folders (despite the callout that the change “Relies on selected bundled files selected prior to installation”).

A workaround I tried was to use this define when running cmake: CPACK_BUNDLE_EXTRA_WINDOWS_DLLS:BOOL=FALSE. That avoided the build error but did not result in a usable installation. ElmerGUI’s windows_bundle.cmake needs this to be set to TRUE to package the Qt5 binaries into the install folder. Strangely enough, ElmerGUILogger’s windows_bundle.cmake does not have this logic for Qt5. This is likely because ElmerGUI would already have installed the right files into the bin folder but this looks like a bug.

Another work-around I tried was to manually create the folders expected by the build. The install target then succeeded but the necessary binaries were not copied to the install folder.

mkdir -p bundle_msys2/bin
mkdir -p bundle_qt5/bin
mkdir -p platforms

This is when I dig around and find that only ElmerGUILogger and ElmerClips include windows_bundle.cmake. Hmm… the latter looks promising but doesn’t look up to date either since it requires Qt4. More exploring of the Makefile – the package target looks interesting but fails because NSIS is not installed.

...
[ 97%] Built target ElmerGUI_autogen
[100%] Built target ElmerGUI
Run CPack packaging tool...
CPack Error: Cannot find NSIS compiler makensis: likely it is not installed, or not in your PATH
CPack Error: Could not read NSIS registry value. This is usually caused by NSIS not being installed. Please install NSIS from http://nsis.sourceforge.net
CPack Error: Cannot initialize the generator NSIS
make: *** [Makefile:71: package] Error 1

I wonder if we couldn’t just use NSIS for the MSYS environment:

$ pacman -Ss nsis
...
mingw64/mingw-w64-x86_64-nsis 3.06.1-1
    Windows installer development tool (mingw-w64)
mingw64/mingw-w64-x86_64-nsis-nsisunz 1.0-2
    NSIS plugin which allows you to extract files from ZIP archives (mingw-w64)
...

$ pacman -S mingw64/mingw-w64-x86_64-nsis

Now we can create an Elmer installer by running make package. Unfortunately, that turns out to be insufficient. My next idea is to compare the binaries from the installed. This turned out to be easier when using ls -R1 to output only the file names and in 1 column only. Some obvious differences are that the build in Program Files has a bin folder containing the Qt and vtk binaries (as well as a stripped gfortran).

Qt5Core.dll
Qt5Gui.dll
Qt5OpenGL.dll
Qt5PrintSupport.dll
Qt5Script.dll
Qt5Svg.dll
Qt5Widgets.dll
Qt5Xml.dll
...
libvtkChartsCore-8.2.dll
libvtkChartsCorePython38D-8.2.dll
libvtkCommonColor-8.2.dll
libvtkCommonColorPython38D-8.2.dll
libvtkCommonComputationalGeometry-8.2.dll
libvtkCommonComputationalGeometryPython38D-8.2.dll
libvtkCommonCore-8.2.dll
libvtkCommonCorePython38D-8.2.dll
libvtkCommonDataModel-8.2.dll

The Qt binaries certainly look like the output of windows_bundle.cmake (found this time by a search for “vtk”) but it’s still not clear how this file would be included in the build. I’m using VSCode to search for “windows_bundle” and only 2 of the 3 references in the codebase were showing up (on my desktop). Looking for “ElmerGUILogger” then revealed yet another reference. Such a waste of time! Not cool VSCode, not cool. It’s included in ElmerGUI/CMakeLists.txt. So I probably only need to define WIN32. But why does the WIN32 code run if I add some statements to that IF block?

Some searching (TODO: put bing searches here) leads to indications that there might be an error in CMake where WIN32 is not defined. Seeing signs that MSYS can be in Cywgin? Trying to get to the bottom of why WIN32 is not respected by CMake, I review ElmerGUI/CMakeLists.txt again. It adds the netgen subdirectory. Interestingly, ElmerGUI/netgen/README points out that install\lib\ElmerGUI\ngcore\libng.a is the unix library and that the win32 extension should be .lib. Biggest sign I’ve seen so far that something is really off. At this point, I remember seeing a .a file in the install folder – and that seemed strange for a lib folder since I expected a DLL. This hypothesis fails though because the working Elmer installation also has the file “C:\Program Files\Elmer 9.0-Release\lib\ElmerGUI\ngcore\libng.a“.

The sure way to verify that the WIN32 include is working is to introduce an error into windows_bundle.cmake, e.g. by change the first IF into the unknown IF2. Even better, notice that the “Qt5 Windows packaging” message is correctly displayed. Perhaps the FIND_FILE command should have a REQUIRED option now that it is supported. Adding that doesn’t fail so reexamine the INSTALL command. Since windows_bundle.cmake uses a relative path for the DESTINATION, it is interpreted relative to the value of the CMAKE_INSTALL_PREFIX variable.

At this point, I take a step back and search for cmake install component. My suspision is that there is something about the elmergui COMPONENT specified in the INSTALL command. I discover from Understanding the CMake `COMPONENT` keyword in the `install` command – Code – CMake Discourse that cmake --install is a thing. It seems to do the same things. Unfortunately, it doesn’t copy the files I need either.

How about zooming into the windows_bundle.cmake file and outputting the list of files installed after the install command. The new message says the files were installed. However, they aren’t in the install folder! I need an explanation for this behavior. So let’s open Process Explorer and see which paths are actually used. These requests show up using the Qt5 path filter:

These files exist on disk (despite the Result column in process explorer having the value INVALID DEVICE REQUEST)! For a better understanding of what is happening, I change the bin path used by the install command to dbgcmake since there are multiple bin folders (under install and also in the MinGW installation). So such path shows up in Process Explorer when using a path filter for dbgcmake. This means I shouldn’t be expecting this files to be written by cmake at this point. In fact, running grep -Rin dbgcmake shows that build/ElmerGUI/cmake_install.cmake now contains this snippet (thereby verifying that windows_bundle.cmake is used to generate cmake_install.cmake).

if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xelmerguix" OR NOT CMAKE_INSTALL_COMPONENT)
  file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/dbgcmake" TYPE FILE FILES
    "D:/dev/Software/msys64/mingw64/bin/Qt5Core.dll"
    "D:/dev/Software/msys64/mingw64/bin/Qt5Gui.dll"
    "D:/dev/Software/msys64/mingw64/bin/Qt5OpenGL.dll"
    "D:/dev/Software/msys64/mingw64/bin/Qt5Script.dll"
    "D:/dev/Software/msys64/mingw64/bin/Qt5Xml.dll"
    "D:/dev/Software/msys64/mingw64/bin/Qt5Svg.dll"
    "D:/dev/Software/msys64/mingw64/bin/Qt5Widgets.dll"
    "D:/dev/Software/msys64/mingw64/bin/Qt5PrintSupport.dll"
    )
endif()

So back to the question of why windows_bundle.cmake is not invoked by default – let us dig into the CMake sources for clues. Renaming it outputs an error for the include statement meaning the file is being included! Sigh… I end up poking around some CMake sources to see where WIN32 is set anyway.:

At this point, I’m down to simply finding out how to print CMake call stacks to confirm that this file is indeed included. The StackOverflow question about how to trace cmakelists has the big reveal: use the cmake –trace option!

date; time cmake -G "MSYS Makefiles" -DWITH_ELMERGUI:BOOL=TRUE  -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install  -DCMAKE_Fortran_COMPILER=d:/dev/Software/msys64/mingw64/bin/gfortran.exe  -DQWT_INCLUDE_DIR=d:/dev/Software/msys64/mingw64/include/qwt-qt5/  -DWIN32:BOOL=TRUE --trace-expand ../elmerfem > build.txt 2>&1; date;

I immediately notice that the install command of interest is skipped because CPACK_BUNDLE_EXTRA_WINDOWS_DLLS is not set to TRUE! Setting it to FALSE earlier then seeing a build failure gave the impression that it was set to TRUE everywhere (especially given that ElmerCPack.cmake sets it to TRUE) but that happens after windows_bundle.cmake has been evaluated! Here’s the final required command line:

date; time \
cmake -G "MSYS Makefiles" \
 -DWITH_ELMERGUI:BOOL=TRUE \
 -DWITH_MPI:BOOL=FALSE \
 -DCMAKE_INSTALL_PREFIX=../install \
 -DCMAKE_Fortran_COMPILER=d:/dev/Software/msys64/mingw64/bin/gfortran.exe \
 -DQWT_INCLUDE_DIR=d:/dev/Software/msys64/mingw64/include/qwt-qt5/ \
 -DWIN32:BOOL=TRUE \
 -DCPACK_BUNDLE_EXTRA_WINDOWS_DLLS:BOOL=TRUE \
 ../elmerfem

There are lessons there about making assumptions but the biggest takeaway for me is the need for (and existence) of tracing capabilities in CMake. Enabling tracing made it so easy to figure out exactly what was broken – the variable did not have the value I expected and I simply needed to define it! Running make install now results in new errors haha!

The code execution cannot proceed because libgcc_s_seh-1.dll was not found. Reinstalling the program may fix this problem. This error dialog is then followed by others for qwt-qt5.dll, libstdc++-6.dll, and libdouble-conversion.dll respectively. To see which other binaries are required, manually copy these 4 binaries from d:\dev\Software\msys64\mingw64\bin to install/bin. These are the other missing binaries that show up in error dialogs:

libwinpthread-1.dll
libicuin69.dll
libicuuc69.dll
libpcre2-16-0.dll
libharfbuzz-0.dll
libmd4c.dll
libmd4c.dll
libpng16-16.dll
zlib1.dll
libzstd.dll
libfreetype-6.dll
libgraphite2.dll
libintl-8.dll
libglib-2.0-0.dll
libicudt69.dll
libiconv-2.dll
libbz2-1.dll
libbrotlidec.dll
libbrotlicommon.dll
libpcre-1.dll

There are so many missing binaries that I wonder if building the other components might be necessary. I first manually copy them from the bin folder to see if ElmerGUI can load but that now fails with the error This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

The working installation from the downloaded public Elmer installer has a qwindows.dll in the bin/platforms directory. This file exists on my system as D:\dev\Software\msys64\mingw64\share\qt5\plugins\platforms\qwindows.dll. At this point, I’m really wondering how on earth they are gathering all these files. Hmm, maybe they build using their docker image? Didn’t think of seeing how their docker image is set up. One final try to set up the qwindows.dll first and see what happens.

cp /mingw64/share/qt5/plugins/platforms/qwindows.dll ../install/bin/platforms/

Lo and behold! ElmerGUI loads successfully! Whether it actually works… well, I will revisit that after I learn how to use Elmer/ElmerGUI :). Actually, turns out ElmerSolver.exe doesn’t start. Here is the fix for the 3 binaries that cause error dialogs:

# binaries required by ElmerSolver
cp /mingw64/bin/libgfortran-5.dll ../install/bin/
cp /mingw64/bin/libopenblas.dll ../install/bin/
cp /mingw64/bin/libquadmath-0.dll ../install/bin/

The final set of commands to deploy these binaries is therefore:

# binaries required by ElmerGUI
cp /mingw64/bin/libgcc_s_seh-1.dll ../install/bin/
cp /mingw64/bin/libdouble-conversion.dll ../install/bin/
cp /mingw64/bin/qwt-qt5.dll ../install/bin/
cp /mingw64/bin/libstdc++-6.dll ../install/bin/
cp /mingw64/bin/libwinpthread-1.dll ../install/bin/
cp /mingw64/bin/libicuin69.dll ../install/bin/
cp /mingw64/bin/libicuuc69.dll ../install/bin/
cp /mingw64/bin/libpcre2-16-0.dll ../install/bin/
cp /mingw64/bin/libharfbuzz-0.dll ../install/bin/
cp /mingw64/bin/libmd4c.dll ../install/bin/
cp /mingw64/bin/libpng16-16.dll ../install/bin/
cp /mingw64/bin/zlib1.dll ../install/bin/
cp /mingw64/bin/libzstd.dll ../install/bin/
cp /mingw64/bin/libfreetype-6.dll ../install/bin/
cp /mingw64/bin/libgraphite2.dll ../install/bin/
cp /mingw64/bin/libintl-8.dll ../install/bin/
cp /mingw64/bin/libglib-2.0-0.dll ../install/bin/
cp /mingw64/bin/libicudt69.dll ../install/bin/
cp /mingw64/bin/libiconv-2.dll ../install/bin/
cp /mingw64/bin/libbz2-1.dll ../install/bin/
cp /mingw64/bin/libbrotlidec.dll ../install/bin/
cp /mingw64/bin/libbrotlicommon.dll ../install/bin/
cp /mingw64/bin/libpcre-1.dll ../install/bin/
cp /mingw64/share/qt5/plugins/platforms/qwindows.dll ../install/bin/platforms/

# binaries required by ElmerSolver
cp /mingw64/bin/libgfortran-5.dll ../install/bin/
cp /mingw64/bin/libopenblas.dll ../install/bin/
cp /mingw64/bin/libquadmath-0.dll ../install/bin/

At this point, ElmerSolver starts up successfully but outputs an error about missing ELMERSOLVER_STARTINFO. This is an error from ElmerSolver.F90 (the Fortran 90 source code). From that code, it looks like the error is because I didn’t specify an input file name and the default file does not exist. This is the same behavior as ElmerSolver.exe from the official Elmer installation.

ELMER SOLVER (v 9.0) STARTED AT: 2022/06/26 21:55:22
ParCommInit:  Initialize #PEs:            1
MAIN:
MAIN: =============================================================
MAIN: ElmerSolver finite element software, Welcome!
MAIN: This program is free software licensed under (L)GPL
MAIN: Copyright 1st April 1995 - , CSC - IT Center for Science Ltd.
MAIN: Webpage http://www.csc.fi/elmer, Email elmeradm@csc.fi
MAIN: Version: 9.0 (Rev: af959fd0, Compiled: 2022-06-26)
MAIN:  Running one task without MPI parallelization.
MAIN:  Running with just one thread per task.
MAIN: =============================================================
ERROR:: ElmerSolver: Unable to find ELMERSOLVER_STARTINFO, can not execute.
STOP 1

Reviewing Docker Files

I was wondering after all this if there was a Windows docker file that had all these steps already baked in. However, the docker directory has only Ubuntu dockerfiles. Perhaps I could create a Windows docker file if I could figure out these dependencies.

Binaries Required by ElmerSolver

The above deployment instructions starts with the binaries required by ElmerGUI but ElmerSolver is the crucial component (since Elmer can be used with the GUI). Here are the binaries grouped such that the ElmerGUI binaries can be excluded if desired.

# binaries required by ElmerSolver
cp /mingw64/bin/libgfortran-5.dll ../install/bin/
cp /mingw64/bin/libgcc_s_seh-1.dll ../install/bin/
cp /mingw64/bin/libopenblas.dll ../install/bin/
cp /mingw64/bin/libquadmath-0.dll ../install/bin/
cp /mingw64/bin/libwinpthread-1.dll ../install/bin/

# binaries required by Mesh2D
cp /mingw64/bin/libstdc++-6.dll ../install/bin/

# binaries required by ElmerGUI
cp /mingw64/bin/qwt-qt5.dll ../install/bin/
cp /mingw64/bin/libdouble-conversion.dll ../install/bin/
cp /mingw64/bin/libicuin69.dll ../install/bin/
cp /mingw64/bin/libicuuc69.dll ../install/bin/
cp /mingw64/bin/libpcre2-16-0.dll ../install/bin/
cp /mingw64/bin/libharfbuzz-0.dll ../install/bin/
cp /mingw64/bin/libmd4c.dll ../install/bin/
cp /mingw64/bin/libpng16-16.dll ../install/bin/
cp /mingw64/bin/zlib1.dll ../install/bin/
cp /mingw64/bin/libzstd.dll ../install/bin/
cp /mingw64/bin/libicudt69.dll ../install/bin/
cp /mingw64/bin/libfreetype-6.dll ../install/bin/
cp /mingw64/bin/libglib-2.0-0.dll ../install/bin/
cp /mingw64/bin/libgraphite2.dll ../install/bin/
cp /mingw64/bin/libintl-8.dll ../install/bin/
cp /mingw64/bin/libbz2-1.dll ../install/bin/
cp /mingw64/bin/libbrotlidec.dll ../install/bin/
cp /mingw64/bin/libpcre-1.dll ../install/bin/
cp /mingw64/bin/libiconv-2.dll ../install/bin/
cp /mingw64/bin/libbrotlicommon.dll ../install/bin/

cp /mingw64/share/qt5/plugins/platforms/qwindows.dll ../install/bin/platforms/

Outstanding Issues

Deploying the above binaries manually gives a locally runnable build. Unfortunately, it does not fix the build created by CPack when you run make install – that build will not have any of these binaries/dependencies.


Categories: Material Science

Crystalline vs Amorphous Materials

I was reading about diffusion coefficients for common dopants when the diffusivity of Boron in crystalline Si was compared to that in amorphous Si. Decided to dig into the differences between the crystalline and amorphous materials. These are the resources I used.

Fertig’s video piqued my curiosity about how we determine these structures, hence his other crystallography video on x-ray diffraction. It introduces Bragg’s law.


How to Build Elmer on Windows

As of this post, neither the build instructions on Elmer’s webpage nor the Elmer GitHub repo include instructions for how to build Elmer on Windows. Here is a succinct set of instructions (discovered in the previous post, which detailed the stumbling around that led me a solution).

  1. Clone the Elmer source code.
cd \repos
mkdir fem
cd fem
git clone git://www.github.com/ElmerCSC/elmerfem 
  1. Install MSYS as explained on the MSYS2 website
  2. Run “MSYS MinGW 64-bit” from the Start menu
  3. Run the pacman commands documented on the MSYS2 website (verify that these are still current).
pacman -Syu
pacman -Syu
pacman -S --needed base-devel mingw-w64-x86_64-toolchain
  1. Install the dependencies required for Elmer. NSIS is required to create a Windows installer for Elmer.
pacman -S mingw64/mingw-w64-x86_64-cmake
pacman -S mingw64/mingw-w64-x86_64-openblas
pacman -S mingw64/mingw-w64-x86_64-qt5
pacman -S mingw64/mingw-w64-x86_64-qwt-qt5
pacman -S mingw64/mingw-w64-x86_64-nsis
  1. Switch to the parent directory of the elmer repo using cd /repos/fem. Note that the elmer repo directory will have siblings such as build and install, so the separate parent directory (fem in this example) simplifies the directory organization.
  2. Create the required directories and switch to the build directory.
# create folders required for building a local install
mkdir -p bundle_msys2/bin
mkdir -p bundle_qt5/bin
mkdir -p platforms

mkdir build
cd build
  1. Deploy the prerequisite binaries for Elmer (Solver, Mesh2D, and GUI):
mkdir -p ../install/bin/platforms/

# binaries required by ElmerSolver
cp /mingw64/bin/libgfortran-5.dll ../install/bin/
cp /mingw64/bin/libgcc_s_seh-1.dll ../install/bin/
cp /mingw64/bin/libopenblas.dll ../install/bin/
cp /mingw64/bin/libquadmath-0.dll ../install/bin/
cp /mingw64/bin/libwinpthread-1.dll ../install/bin/

# binaries required by Mesh2D
cp /mingw64/bin/libstdc++-6.dll ../install/bin/

# binaries required by ElmerGUI
cp /mingw64/bin/qwt-qt5.dll ../install/bin/
cp /mingw64/bin/libdouble-conversion.dll ../install/bin/
cp /mingw64/bin/libicuin69.dll ../install/bin/
cp /mingw64/bin/libicuuc69.dll ../install/bin/
cp /mingw64/bin/libpcre2-16-0.dll ../install/bin/
cp /mingw64/bin/libharfbuzz-0.dll ../install/bin/
cp /mingw64/bin/libmd4c.dll ../install/bin/
cp /mingw64/bin/libpng16-16.dll ../install/bin/
cp /mingw64/bin/zlib1.dll ../install/bin/
cp /mingw64/bin/libzstd.dll ../install/bin/
cp /mingw64/bin/libicudt69.dll ../install/bin/
cp /mingw64/bin/libfreetype-6.dll ../install/bin/
cp /mingw64/bin/libglib-2.0-0.dll ../install/bin/
cp /mingw64/bin/libgraphite2.dll ../install/bin/
cp /mingw64/bin/libintl-8.dll ../install/bin/
cp /mingw64/bin/libbz2-1.dll ../install/bin/
cp /mingw64/bin/libbrotlidec.dll ../install/bin/
cp /mingw64/bin/libpcre-1.dll ../install/bin/
cp /mingw64/bin/libiconv-2.dll ../install/bin/
cp /mingw64/bin/libbrotlicommon.dll ../install/bin/

cp /mingw64/share/qt5/plugins/platforms/qwindows.dll ../install/bin/platforms/
  1. Build Elmer. When cmake completes, a message will be displayed confirming that generation is done and that build files have been written to the build/ directory. Run make to start compiling the source code or make install to compile the sources then create a local installation in the install/ directory. Note that there are some folders (created using mkdir -p below) that don’t appear to be used in a local build but the build still expects them to exist. You can also specify a debug build by adding the -DCMAKE_BUILD_TYPE=Debug define.
cmake -G "MSYS Makefiles" \
 -DWITH_ELMERGUI:BOOL=TRUE \
 -DWITH_MPI:BOOL=FALSE \
 -DCMAKE_INSTALL_PREFIX=../install \
 -DCMAKE_Fortran_COMPILER=c:/dev/msys64/mingw64/bin/gfortran.exe \
 -DQWT_INCLUDE_DIR=c:/dev/msys64/mingw64/include/qwt-qt5/ \
 -DWIN32:BOOL=TRUE \
 -DCPACK_BUNDLE_EXTRA_WINDOWS_DLLS:BOOL=TRUE \
 ../elmerfem

make install
  1. To create a Windows installer (using NSIS), run the package target.
make package

Diffusion

Diffusion is a key step in wafer processing for microprocessor manufacturing. Fick’s laws are therefore an important component in understanding diffusion. Fortunately, there are great resources online for an overview of Fick’s law. I started with the Khan Academy video on Fick’s law of diffusion (embedded below). It was informative but did not go into the level of detail I had hoped for.

Some digging around led to a series of lectures from the Mechanical Engineering’s Fertig Research Group at the University of Wyoming. This video on the mathematics of diffusion (Fick’s 1st law) was the level of detail I was hoping for and was therefore a good supplement to the Khan Academy diffusion overview.

And here’s the video on Fick’s 2nd law (again showing how to derive it and some brief comments about PDEs). I wonder if there is some accessible visualization that could be done of various solutions to the diffusion PDE.


Investigating how to Build Elmer on Windows

The instructions for building the Elmer source code are really simple! I decided to try them on Windows. The Developer Command Prompt is necessary for cmake (as far as I can tell). Note that C, C++, and Fortran compilers are required for building Elmer.

cd \dev\repos
mkdir fem
git clone git://www.github.com/ElmerCSC/elmerfem 
mkdir build
cd build
cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install ../elmerfem

I discovered that a Fortran compiler is required when I got this error on my first build attempt:

-- Building for: Visual Studio 17 2022
-- The Fortran compiler identification is unknown
-- The C compiler identification is MSVC 19.32.31326.0
-- The CXX compiler identification is MSVC 19.32.31326.0
CMake Error at CMakeLists.txt:34 (PROJECT):
  No CMAKE_Fortran_COMPILER could be found.

Line 34 of CMakeLists.txtPROJECT(Elmer Fortran C CXX) – uses the PROJECT cmake command to set the project name to “Elmer” and specify the programming languages required, hence the build failure above.

Installing a Fortran Compiler – GFortran?

GFortran looks like the only free Fortran compiler out there so I grabbed the compiler from Fortran, C, C++ for Windows (equation.com) as recommended by Installing GFortran – (fortran-lang.org). The newly installed Fortran compiler was not automatically detected by CMake. Based on the discussion at c++ – Error: No CMAKE_Fortran_COMPILER could be found for Visual Studio 2019 Fortran support – Stack Overflow, I made this change to CMakeLists.txt to pick up the GFortran compiler:

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,6 +21,8 @@ if(APPLE)
   # option(HUNTER_ENABLED "Enable Hunter package manager support" OFF)
   # set (CMAKE_GENERATOR "Unix Makefiles" CACHE INTERNAL "" FORCE)
   # set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
+else()
+  set(CMAKE_Fortran_COMPILER "C:/dev/software/gcc/bin/gfortran.exe")
 endif()

Unfortunately, that wasn’t sufficient to address the build failure. Interestingly, someone else ran into this exact same issue at windows – The MinGW gfortran compiler is not able to compile a simple test program – Stack Overflow. Sad times though when StackOverflow does not have an answer! Their solution for specifying a custom compiler is much cleaner – simply define the CMake variable when invoking cmake!

cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=C:/dev/software/gcc/bin/gfortran.exe ../elmerfem

Searching for the error message “The Fortran compiler identification is unknown (bing.com)” reveals an existing GitHub issue issue Cannot build using cmake with gfortran on Windows — the Fortran compiler identification is unknown · Issue #328 · fortran-lang/stdlib. Someone mentioned that the MinGW compiler worked fine.

Installing a Fortran Compiler – MinGW

Via Cygwin

The MinGW-w64 downloads looked promising. Since I already had Cygwin installed, I installed the GFortran package. The path to the GFortran compiler can be retrieved using the Cygwin command cygpath -w `which gfortran` and passed to CMake. That still didn’t work.

Installing gcc-fortran
setup-x86_64.exe q -P gcc-fortran

cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=C:/dev/cygwin64/bin/gfortran.exe ../elmerfem

At least that showed the mingw Fortran compiler package name mingw64-x86_64-gcc-fortran. Interestingly, that package is marked already installed!

Via MSYS2

Since Cygwin didn’t simply work, I decided to try installing MSYS2 (before resorting to uninstalling the Cygwin gcc-fortran package). The Fortran compiler is installed by MSYS2. Once setup completes, CMake also fails when using the MinGW Fortran compiler!

cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe ../elmerfem

Debugging the Fortran Detection Failure

Since none of the compilers work, let’s take a closer look at the error:

$ cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=C:/dev/software/gcc/bin/gfortran.exe ../elmerfem
-- The Fortran compiler identification is unknown
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - failed
-- Check for working Fortran compiler: C:/dev/software/gcc/bin/gfortran.exe
-- Check for working Fortran compiler: C:/dev/software/gcc/bin/gfortran.exe - broken
CMake Error at C:/Program Files/Microsoft Visual Studio/2022/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.22/Modules/CMakeTestFortranCompiler.cmake:61 (message):
  The Fortran compiler

    "C:/dev/software/gcc/bin/gfortran.exe"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: D:/dev/repos/fem/build/CMakeFiles/CMakeTmp

    Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Preview/Common7/IDE/devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTC_4528a &&
    Microsoft Visual Studio 2022 Version 17.3.0 Preview 1.0 [...].
    Copyright (C) Microsoft Corp. All rights reserved.

    The operation could not be completed. The parameter is incorrect.

    Use:
    devenv  [solutionfile | projectfile | folder | anyfile.ext]  [switches]
...

To get a sense of what could be going wrong, I opened the folder containing the temporary project CMake is trying to build. Its contents are deleted before CMake terminates. However, the build was slow enough for me to copy all the files into another temp folder to repro this failure. Running the devenv.com command above fails with the same error.

Interestingly, loading the solution in Visual Studio results in an error because one of the projects cannot be loaded! However, that project file has a .vfproj extension (which seems specific to the Intel Fortran compiler, e.g. as described at Cannot open vfproj file in visual studio 2017 – Intel Communities).

Looks like it’s the CMakeTestFortranCompiler.cmake file that is generating Intel Fortran projects. The first check that file is:

if(CMAKE_Fortran_COMPILER_FORCED)
  # The compiler configuration was forced by the user.
  # Assume the user has configured all compiler information.
  set(CMAKE_Fortran_COMPILER_WORKS TRUE)
  return()
endif()

The CMAKE_Fortran_COMPILER_FORCED define can be used to bail out of the custom configuration so define it when invoking cmake:

cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE ../elmerfem

We now get a new error! Finally making some progress!

cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE ../elmerfem
-- The Fortran compiler identification is unknown
CMake Deprecation Warning at cmake/Modules/FindMKL.cmake:2 (CMAKE_MINIMUM_REQUIRED):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.
Call Stack (most recent call first):
  CMakeLists.txt:308 (FIND_PACKAGE)


-- ------------------------------------------------
-- Looking for Fortran sgemm
-- Looking for Fortran sgemm - not found
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Found Threads: TRUE
CMake Error at C:/Program Files/Microsoft Visual Studio/2022/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find BLAS (missing: BLAS_LIBRARIES)
Call Stack (most recent call first):
  C:/Program Files/Microsoft Visual Studio/2022/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
  C:/Program Files/Microsoft Visual Studio/2022/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.22/Modules/FindBLAS.cmake:1337 (find_package_handle_standard_args)
  CMakeLists.txt:433 (FIND_PACKAGE)


-- Configuring incomplete, errors occurred!
See also "D:/dev/repos/fem/build/CMakeFiles/CMakeOutput.log".
See also "D:/dev/repos/fem/build/CMakeFiles/CMakeError.log".

This error is from the FindBLAS module (see FindBLAS source code I’ve linked to in the error log above). It should be able to find BLAS as per this question Can CMake FindBLAS find OpenBLAS? – Stack Overflow.

  1. https://duckduckgo.com/?q=gfortran+blas
  2. fortran – Error in linking gfortran to LAPACK and BLAS – Stack Overflow

Installing BLAS

Searching for “pacman blas” leads to fortran – Using BLAS, LAPACK, and ARPACK with MSYS2 – Stack Overflow which points out that you can search for packages using pacman -Ss. The -S flag stands for sync. Use pacman -Sh to see the package sync options. See Package Management – MSYS2 for more details.

# Search for BLAS packages
pacman -Ss blas

# Install mingw BLAS package
pacman -S mingw64/mingw-w64-x86_64-openblas

# Install LAPACK
pacman -S mingw64/mingw-w64-x86_64-lapack

The output should look like this when complete:

$ pacman -S mingw64/mingw-w64-x86_64-openblas
resolving dependencies...
looking for conflicting packages...

Packages (1) mingw-w64-x86_64-openblas-0.3.20-3

Total Download Size:    11.76 MiB
Total Installed Size:  103.67 MiB

:: Proceed with installation? [Y/n] y
:: Retrieving packages...
 mingw-w64-x86_64-openblas-0.3.20-3-any                                                                                                 11.8 MiB  2.26 MiB/s 00:05 [#####...#####] 100%
(1/1) checking keys in keyring             [#####...#####] 100%
(1/1) checking package integrity           [#####...#####] 100%
(1/1) loading package files                [#####...#####] 100%
(1/1) checking for file conflicts          [#####...#####] 100%
(1/1) checking available disk space        [#####...#####] 100%
:: Processing package changes...
(1/1) installing mingw-w64-x86_64-openblas [#####...#####] 100%
Set the environment variable OPENBLAS_NUM_THREADS to the
number of threads to use.resolving dependencies...

This doesn’t address the errors. A search for the exact error message “Could NOT find BLAS (missing: BLAS_LIBRARIES)” reveals a useful GitHub discussion at find_package(BLAS) failed with CMake · Issue #2440 · mxe/mxe. So BLAS_LIBRARIES can simply be defined at the command line!

cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe  -DBLAS_LIBRARIES=D:/dev/Software/msys64/mingw64/lib ../elmerfem

We now get a new error about LAPACK_LIBRARIES and define it as well!

cmake -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE -DBLAS_LIBRARIES=D:/dev/Software/msys64/mingw64/lib -DLAPACK_LIBRARIES=D:/dev/Software/msys64/mingw64/lib ../elmerfem

This finally gets us past the missing package issues and on to more Fortran compiler errors!

-- Found LAPACK: D:/dev/Software/msys64/mingw64/lib
-- Checking whether D:/dev/Software/msys64/mingw64/bin/gfortran.exe supports PROCEDURE POINTER
-- Checking whether D:/dev/Software/msys64/mingw64/bin/gfortran.exe supports PROCEDURE POINTER -- no
CMake Error at CMakeLists.txt:477 (MESSAGE):
  Fortran compiler does not seem to support the PROCEDURE statement.

Support for PROCEDURE Statements

CMakeLists.txt:475 is this line INCLUDE(testProcedurePointer). The included script tests the Fortran compiler but does not explain why the test fails. To see the details, append the string : ${OUTPUT} to the end of the string “Checking whether ${CMAKE_Fortran_COMPILER} supports PROCEDURE POINTER — no” (just before the closing quote). The error message now contains additional information – the same error from earlier! Opening the solution in Visual Studio confirms that yet another unsupported .vfproj has been generated.

Change Dir: D:/dev/repos/fem/build/CMakeFiles/CMakeTmp

Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Preview/Common7/IDE/devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTC_77a33 &&
Microsoft Visual Studio 2022 Version 17.3.0 Preview 1.0 [...].
Copyright (C) Microsoft Corp. All rights reserved.

The operation could not be completed. The parameter is incorrect.

Use:
devenv  [solutionfile | projectfile | folder | anyfile.ext]  [switches]

<Updated VS, unfortunately changing the CMake version>. This is the CMakeLists.txt generated for the solution:

cmake_minimum_required(VERSION 3.22.22022201.0)
set(CMAKE_MODULE_PATH "D:/dev/repos/fem/elmerfem/cmake/Modules;C:/Program Files/Microsoft Visual Studio/2022/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.22/Modules")
cmake_policy(SET CMP0091 OLD)
cmake_policy(SET CMP0126 OLD)
project(CMAKE_TRY_COMPILE Fortran)
set(CMAKE_VERBOSE_MAKEFILE 1)
set(CMAKE_Fortran_FLAGS "")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COMPILE_DEFINITIONS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EXE_LINKER_FLAGS}")
include_directories(${INCLUDE_DIRECTORIES})
set(CMAKE_SUPPRESS_REGENERATION 1)
link_directories(${LINK_DIRECTORIES})
cmake_policy(SET CMP0065 OLD)
cmake_policy(SET CMP0083 OLD)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "D:/dev/repos/fem/build/CMakeFiles/CMakeTmp")
add_executable(cmTC_b909d "D:/dev/repos/fem/build/CMakeFiles/CMakeTmp/testFortranProcedurePointer.f90")
target_link_libraries(cmTC_b909d ${LINK_LIBRARIES})

The cmake project command names the generated project CMAKE_TRY_COMPILE and specifies that the Fortran programming language is needed to build the project. At this point, it looks like a question of how the project is generated. Searching the cmake sources for “.vfproj” leads to the documentation at Help/variable/CMAKE_MAKE_PROGRAM.rst · v3.22.0 · CMake. Turns out this is simply the public documentation at CMAKE_MAKE_PROGRAM — CMake 3.23.2 Documentation. Finally get to the generators docs at cmake-generators(7) — CMake 3.22.5.

If the Visual Studio generator is not appropriate, then which one is? Since I’m using MSYS2, I wonder if the MSYS generator is better suited to this build task. Come to think of it, I saw some discussion of makefile generators, e.g. in Cannot build using cmake with gfortran on Windows — the Fortran compiler identification is unknown · Issue #328 · fortran-lang/stdlib. Sure enough, the cmake options docs say -G is how you choose the generator:

cmake -G "MinGW Makefiles" -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE -DBLAS_LIBRARIES=D:/dev/Software/msys64/mingw64/lib -DLAPACK_LIBRARIES=D:/dev/Software/msys64/mingw64/lib ../elmerfem

That does not work though (in my developer command prompt)

CMake Error: CMake was unable to find a build program corresponding to "MinGW Makefiles".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.
CMake Error: CMake was unable to find a build program corresponding to "MinGW Makefiles".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!

Looks like I need to try this process in MSYS2.

Custom Generator in MSYS

Running which cmake in MSYS did not find cmake so here’s the version I installed.

$ pacman -Ss cmake
...
mingw64/mingw-w64-x86_64-cmake 3.23.2-1
    A cross-platform open-source make system (mingw-w64)
...
$ pacman -S mingw64/mingw-w64-x86_64-cmake

This doesn’t result in being able to run cmake.exe (even though it exists on disk in D:\dev\Software\msys64\mingw64\bin). Time to hit the docs again: msys2 cmake – Search (bing.com) -> Using CMake in MSYS2 – MSYS2. No red flags there… How about a search for the exact error message: msys bash: cmake: command not found – Search (bing.com) -> c++ – CMake is not found when running through make – Stack Overflow. Aha! The answer there about launching MSYS2 using mingw32.exe leads me to inquire about how I’m launching MSYS2. Turns out I’m launching using the last shortcut below (which launches “D:\dev\Software\msys64\msys2_shell.cmd -msys“) instead of MinGW x64.lnk (which launches “D:\dev\Software\msys64\msys2_shell.cmd -mingw64“). Sure enough, which cmake now shows /mingw64/bin/cmake.

 Directory of C:\Users\USERNAME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\MSYS2 64bit

MSYS2 MinGW Clang x64.lnk
MSYS2 MinGW UCRT x64.lnk
MSYS2 MinGW x64.lnk
MSYS2 MinGW x86.lnk
MSYS2 MSYS.lnk

Custom Generator in MinGW

Retrying the command line now makes progress! Notice the Fortran compiler is successfully detected (and the GNU C++ compiler is also selected).

$ cmake -G "MinGW Makefiles" -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE -DBLAS_LIBRARIES=D:/dev/Software/msys64/mingw64/lib -DLAPACK_LIBRARIES=D:/dev/Software/msys64/mingw64/lib ../elmerfem
-- The Fortran compiler identification is GNU 12.1.0
-- The C compiler identification is GNU 12.1.0
-- The CXX compiler identification is GNU 12.1.0
...

The build fails but things are very promising now. The error is because Qt is missing:

--   Building ElmerGUI
-- ------------------------------------------------
CMake Deprecation Warning at ElmerGUI/CMakeLists.txt:1 (CMAKE_MINIMUM_REQUIRED):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


CMake Warning at ElmerGUI/CMakeLists.txt:19 (find_package):
  By not providing "FindQt5.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "Qt5", but
  CMake did not find one.

  Could not find a package configuration file provided by "Qt5" with any of
  the following names:

    Qt5Config.cmake
    qt5-config.cmake

  Add the installation prefix of "Qt5" to CMAKE_PREFIX_PATH or set "Qt5_DIR"
  to a directory containing one of the above files.  If "Qt5" provides a
  separate development package or SDK, be sure it has been installed.


-- ------------------------------------------------
CMake Error at D:/dev/Software/msys64/mingw64/share/cmake/Modules/FindQt4.cmake:1314 (message):
  Found unsuitable Qt version "" from NOTFOUND, this code requires Qt 4.x
Call Stack (most recent call first):
  ElmerGUI/CMakeLists.txt:42 (FIND_PACKAGE)

Installing Qt5 does not address the build failure. The new error message:

--   Building ElmerGUI
-- ------------------------------------------------
CMake Deprecation Warning at ElmerGUI/CMakeLists.txt:1 (CMAKE_MINIMUM_REQUIRED):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


-- ------------------------------------------------
-- Qt5 Windows packaging
--   [ElmerGUI] Qt5:               1
--   [ElmerGUI] Qt5 Libraries: Qt5::OpenGL Qt5::Xml Qt5::Script Qt5::Gui Qt5::Core
-- ------------------------------------------------
CMake Warning (dev) at D:/dev/Software/msys64/mingw64/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:438 (message):
  The package name passed to `find_package_handle_standard_args` (OpenGL)
  does not match the name of the calling package (Qwt).  This can lead to
  problems in calling code that expects `find_package` result variables
  (e.g., `_FOUND`) to follow a certain pattern.
Call Stack (most recent call first):
  D:/dev/Software/msys64/mingw64/share/cmake/Modules/FindOpenGL.cmake:443 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  ElmerGUI/cmake/Modules/FindQwt.cmake:10 (INCLUDE)
  ElmerGUI/CMakeLists.txt:61 (FIND_PACKAGE)
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Found OpenGL: opengl32
CMake Warning (dev) at D:/dev/Software/msys64/mingw64/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:438 (message):
  The package name passed to `find_package_handle_standard_args` (Qt3) does
  not match the name of the calling package (Qwt).  This can lead to problems
  in calling code that expects `find_package` result variables (e.g.,
  `_FOUND`) to follow a certain pattern.
Call Stack (most recent call first):
  D:/dev/Software/msys64/mingw64/share/cmake/Modules/FindQt3.cmake:213 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  D:/dev/Software/msys64/mingw64/share/cmake/Modules/FindQt.cmake:160 (include)
  ElmerGUI/cmake/Modules/FindQwt.cmake:11 (INCLUDE)
  ElmerGUI/CMakeLists.txt:61 (FIND_PACKAGE)
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Could NOT find Qt3 (missing: QT_QT_LIBRARY QT_INCLUDE_DIR)
CMake was unable to find desired Qt version: 3. Set advanced values QT_QMAKE_EXECUTABLE and QT3_QGLOBAL_H_FILE.
--   [ElmerGUI] Qwt:             FALSE
--   [ElmerGUI] QWT_LIBRARY:     QWT_LIBRARY-NOTFOUND
--   [ElmerGUI] QWT_INCLUDE_DIR: QWT_INCLUDE_DIR-NOTFOUND
-- ------------------------------------------------
CMake Warning (dev) at D:/dev/Software/msys64/mingw64/lib/cmake/Qt5Core/Qt5CoreMacros.cmake:44 (message):
  qt5_use_modules is not part of the official API, and might be removed in Qt
  6.
Call Stack (most recent call first):
  D:/dev/Software/msys64/mingw64/lib/cmake/Qt5Core/Qt5CoreMacros.cmake:431 (_qt5_warn_deprecated)
  ElmerGUI/Application/CMakeLists.txt:216 (QT5_USE_MODULES)
This warning is for project developers.  Use -Wno-dev to suppress it.

-- ------------------------------------------------
--   BLAS library:   D:/dev/Software/msys64/mingw64/lib
--   LAPACK library: D:/dev/Software/msys64/mingw64/lib
-- ------------------------------------------------
--   Fortran compiler:        D:/dev/Software/msys64/mingw64/bin/gfortran.exe
--   Fortran flags:            -fallow-argument-mismatch -O2 -g -DNDEBUG
-- ------------------------------------------------
--   C compiler:              D:/dev/Software/msys64/mingw64/bin/cc.exe
--   C flags:                  -O2 -g -DNDEBUG
-- ------------------------------------------------
--   CXX compiler:            D:/dev/Software/msys64/mingw64/bin/c++.exe
--   CXX flags:                -O2 -g -DNDEBUG
-- ------------------------------------------------
-- ------------------------------------------------
--   Package filename: elmerfem-9.0--20220612_Windows-AMD64
--   Patch version: 9.0-
CMake Error at cpack/ElmerCPack.cmake:99 (INSTALL):
  INSTALL FILES given directory "D:/dev/Software/msys64/mingw64/lib" to
  install.
Call Stack (most recent call first):
  CMakeLists.txt:660 (INCLUDE)


-- Configuring incomplete, errors occurred!
See also "D:/dev/repos/fem/build/CMakeFiles/CMakeOutput.log".
See also "D:/dev/repos/fem/build/CMakeFiles/CMakeError.log".

Does this need Qt3? The ElmerGUI documentation says Qt4 (4.8 or higher). FindQt.cmake:160 (in bold above) appears to indicate that only Qt versions 3 and 4 are supported in MinGW. The mix of warnings and “could not find” makes it hard to know exactly what is wrong. The last error, for example, appears to be about the installation files directory. So is there anything wrong with Qt? I’ll assume not.

The cmake docs on installing files doesn’t point to anything peculiar in this scenario but this is a hint that my LAPACK_LIBRARIES variable is most likely wrong. Let’s drop it altogether:

# Clean up old make files
# rm -fr *

cmake -G "MinGW Makefiles" -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE -DBLAS_LIBRARIES=D:/dev/Software/msys64/mingw64/lib ../elmerfem

The build still fails but right before the error, notice the LAPACK library now has a DLL instead of a directory (below)!

-- ------------------------------------------------
--   BLAS library:   D:/dev/Software/msys64/mingw64/lib
--   LAPACK library: D:/dev/Software/msys64/mingw64/lib/libopenblas.dll.a;D:/dev/Software/msys64/mingw64/lib
-- ------------------------------------------------
--   Fortran compiler:        D:/dev/Software/msys64/mingw64/bin/gfortran.exe
--   Fortran flags:            -fallow-argument-mismatch -O2 -g -DNDEBUG
-- ------------------------------------------------
--   C compiler:              D:/dev/Software/msys64/mingw64/bin/cc.exe
--   C flags:                  -O2 -g -DNDEBUG
-- ------------------------------------------------
--   CXX compiler:            D:/dev/Software/msys64/mingw64/bin/c++.exe
--   CXX flags:                -O2 -g -DNDEBUG
-- ------------------------------------------------
-- ------------------------------------------------
--   Package filename: elmerfem-9.0--20220612_Windows-AMD64
--   Patch version: 9.0-
CMake Error at cpack/ElmerCPack.cmake:99 (INSTALL):
  INSTALL FILES given directory "D:/dev/Software/msys64/mingw64/lib" to
  install.

So now it makes sense to drop the BLAS_LIBRARIES definition as well!

# Clean up old make files
# rm -fr *

cmake -G "MinGW Makefiles" -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE ../elmerfem

This build step now succeeds as indicated by the selection of libopenblas.dll.a as the BLAS and LAPACK library.

-- ------------------------------------------------
--   BLAS library:   D:/dev/Software/msys64/mingw64/lib/libopenblas.dll.a
--   LAPACK library: D:/dev/Software/msys64/mingw64/lib/libopenblas.dll.a
-- ------------------------------------------------
--   Fortran compiler:        D:/dev/Software/msys64/mingw64/bin/gfortran.exe
--   Fortran flags:            -fallow-argument-mismatch -O2 -g -DNDEBUG
-- ------------------------------------------------
--   C compiler:              D:/dev/Software/msys64/mingw64/bin/cc.exe
--   C flags:                  -O2 -g -DNDEBUG
-- ------------------------------------------------
--   CXX compiler:            D:/dev/Software/msys64/mingw64/bin/c++.exe
--   CXX flags:                -O2 -g -DNDEBUG
-- ------------------------------------------------
-- ------------------------------------------------
--   Package filename: elmerfem-9.0--20220612_Windows-AMD64
--   Patch version: 9.0-
-- Configuring done
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
QWT_INCLUDE_DIR (ADVANCED)
   used as include directory in directory D:/dev/repos/fem/elmerfem/ElmerGUI/Application
   ...
   used as include directory in directory D:/dev/repos/fem/elmerfem/ElmerGUI/Application
QWT_LIBRARY (ADVANCED)
    linked by target "ElmerGUI" in directory D:/dev/repos/fem/elmerfem/ElmerGUI/Application
...

Looks like I now need to define QWT_INCLUDE_DIR and QWT_LIBRARY. Hmm, I don’t think I even installed QWT.

$ pacman -S mingw64/mingw-w64-x86_64-qwt-qt5
resolving dependencies...
looking for conflicting packages...

Packages (1) mingw-w64-x86_64-qwt-qt5-6.2.0-5

Total Download Size:    29.17 MiB
Total Installed Size:  175.53 MiB

:: Proceed with installation? [Y/n] y
:: Retrieving packages...
 mingw-w64-x86_64-qwt-qt5-6.2.0-5-any                                                                                  29.2 MiB  1136 KiB/s 00:26 [###...###] 100%
(1/1) checking keys in keyring                                                                                                                    [###...###] 100%
(1/1) checking package integrity                                                                                                                  [###...###] 100%
(1/1) loading package files                                                                                                                       [###...###] 100%
(1/1) checking for file conflicts                                                                                                                 [###...###] 100%
(1/1) checking available disk space                                                                                                               [###...###] 100%
:: Processing package changes...
(1/1) installing mingw-w64-x86_64-qwt-qt5                                                                                                         [#########################################################################################] 100%
Optional dependencies for mingw-w64-x86_64-qwt-qt5
    mingw-w64-x86_64-qt5-tools [installed]

Now that QWT is installed, we can set the include directory as follows:

cmake -G "MinGW Makefiles" -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE -DQWT_INCLUDE_DIR=D:/dev/Software/msys64/mingw64/include/qwt-qt5/ ../elmerfem

CMake finally succeeds! The output ends with these lines:

-- Generating done
-- Build files have been written to: D:/dev/repos/fem/build

The generated Makefile has targets such as ElmerGUI, elmersolver, AdvectionDiffusion, FluxSolver, etc. The strange thing is that it has a line that sets SHELL = cmd.exe and so a Windows command prompt is launched when you run make.

#==================================================================
# Target rules for targets named ElmerGUI

# Build rule for target.
ElmerGUI: cmake_check_build_system
	$(MAKE) $(MAKESILENT) -f CMakeFiles\Makefile2 ElmerGUI
.PHONY : ElmerGUI

# fast build rule for target.
ElmerGUI/fast:
	$(MAKE) $(MAKESILENT) -f ElmerGUI\Application\CMakeFiles\ElmerGUI.dir\build.make ElmerGUI/Application/CMakeFiles/ElmerGUI.dir/build
.PHONY : ElmerGUI/fast

Some digging around via mingw cmake shell at DuckDuckGo and I’m reading that makefiles from the MinGW Makefiles generator are for use with mingw32-make under a Windows command prompt. Looks like I need the MSYS Makefiles generator.

cmake -G "MSYS Makefiles" -DWITH_ELMERGUI:BOOL=TRUE -DWITH_MPI:BOOL=FALSE -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_Fortran_COMPILER=D:/dev/Software/msys64/mingw64/bin/gfortran.exe -DCMAKE_Fortran_COMPILER_FORCED:BOOL=TRUE -DQWT_INCLUDE_DIR=D:/dev/Software/msys64/mingw64/include/qwt-qt5/ ../elmerfem

Now we see the expected SHELL = /bin/sh and running make actually causes code to start building! What a journey! I will write another post with simplified instructions for how to build Elmer (on Windows).

$ make
[  0%] Building C object matc/src/CMakeFiles/matc.dir/c3d.c.obj
[  0%] Building C object matc/src/CMakeFiles/matc.dir/clip.c.obj
[  0%] Building C object matc/src/CMakeFiles/matc.dir/dri_ps.c.obj
[  0%] Building C object matc/src/CMakeFiles/matc.dir/eig.c.obj
...

Categories: Material Science

Intro to Finite Element Software via Elmer

After learning about Czoralski crystal growth last month, I saw a mention of simulating this growth process and realized that this simulation would be a great candidate for a high performance computing project. A search for such code on GitHub.com revealed arvedes’ simple example for transient Czochralski growth simulation with Elmer. I’d never heard of this program before but it is open source and on GitHub as the elmerfem repo! Since I am a total newbie to finite element analysis, I found a video to introduce me to the field.

As for Elmer, there is a decent (as far as I can tell) set of webinars on YouTube ranging from an Introduction to Elmer to how to use Elmer in various scientific applications. Looks like a promising place to begin exploring this tool to see what it can do and how it has been used.