LFortran Minimum Viable Product (MVP)

We are pleased to announce that we have just released LFortran MVP:

If you have any questions or feedback, we’ll be happy to discuss.

We are looking for new contributors to help us get over the finish line faster. If anybody reading this is interested, please let me know, I am happy to meet over video to explain the details and get you up to speed. There are many opportunities to contribute (semantics, LLVM backend, other backends, C++/Python/Julia interoperability, runtime library implementation, test suite, documentation, etc.).


Do you plan a FreeBSD port? Trying to build it currently requires to pull the whole FreeBSD source to get the LLVM headers. And as base is still at LLVM 10, I’m not even sure it will work. I’ll try it later with a dedicated build jail.

1 Like

Congratulations and thanks. On WSL 2 I am able to install LFortran and run the demo.

On Windows I use Intel Python

Python 3.7.9 (default, Nov  5 2020, 16:54:28) [MSC v.1916 64 bit (AMD64)] :: Intel Corporation on win32
Intel(R) Distribution for Python

so that which conda.exe gives c:\programs\intel\oneapi\intelpython\latest\Scripts\conda.exe
Then the conda create command does not work:

c:\fortran\public_domain\gitlab\mvp_demo>conda create -n mvp_demo -c conda-forge fpm=0.4.0 lfortran=0.14.0
Collecting package metadata (repodata.json): ...working... done
Solving environment: ...working... failed

PackagesNotFoundError: The following packages are not available from current channels:

  - fpm=0.4.0

Current channels:

  - https://conda.anaconda.org/conda-forge/win-64
  - https://conda.anaconda.org/conda-forge/noarch
  - file:///C:/programs/intel/oneapi/conda_channel/win-64
  - file:///C:/programs/intel/oneapi/conda_channel/noarch
  - https://conda.anaconda.org/intel/win-64
  - https://conda.anaconda.org/intel/noarch
  - https://repo.anaconda.com/pkgs/main/win-64
  - https://repo.anaconda.com/pkgs/main/noarch
  - https://repo.anaconda.com/pkgs/r/win-64
  - https://repo.anaconda.com/pkgs/r/noarch
  - https://repo.anaconda.com/pkgs/msys2/win-64
  - https://repo.anaconda.com/pkgs/msys2/noarch

Is anyone able install LFortran with another Python distribution on Windows, for example that of Anaconda?

1 Like

I can confirm that fpm 0.4.0 is not available on conda-forge for Windows.

Try installing WSL2, maybe?

1 Like

I’ll be happy to support FreeBSD officially but I would need some means to test it. To start, simply compile LFortran without LLVM:

wget https://lfortran.github.io/tarballs/release/lfortran-0.14.0.tar.gz
tar xzf lfortran-0.14.0.tar.gz
cd lfortran-0.14.0
cmake -DWITH_LLVM=no .
make -j8

You only need a C++ compiler and cmake. Let me know if this works. If anything fails, either in the build or tests, then let’s fix it.

As a second step, we can get LLVM working also.

As @wyphan said, unfortunately fpm is not available on Windows yet in Conda. So just install lfortran and jupyter using conda, that will work (we test it at our CI), and you can at least test jupyter notebook, or run lfortran from a command line by hand.

Unfortunately lfortran also currently does not work with cmake on Windows (only on Linux and macOS).

Can you try downloading the Windows fpm binary from here: Release Fpm alpha version 0.4.0 · fortran-lang/fpm · GitHub I believe that should work. Then trying it with lfortran installed via Conda?

Indeed we can’t build fpm with the conda-forge Windows toolchains, see Not packaged for Windows · Issue #4 · conda-forge/fpm-feedstock · GitHub for details. The best option for Windows at conda-forge is currently (classic) flang, but this was broken for TOML Fortran last time I checked (Tests fail with flang · Issue #28 · toml-f/toml-f · GitHub).

The alternative is to download the statically linked binary from the release page or if you are using the MSYS2 package manager, install fpm via pacman -S mingw-w64-x86_64-fpm.

1 Like

Build fails on FreeBSD 12:

[ 87%] Linking CXX executable cpptranslate
ld: error: unable to find library -lstdc++fs
c++: error: linker command failed with exit code 1 (use -v to see invocation)
1 Like

That got pretty far!

Yeah, that’s using some C++17 filesystem support. Can you disable it in CMake and comment out the offending lines? That should be doable. We’ll then figure out a workaround for the functionality that we need.

diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt
index 5678d6bb4..8fd56088b 100644
--- a/src/bin/CMakeLists.txt
+++ b/src/bin/CMakeLists.txt
@@ -1,10 +1,6 @@
 add_executable(lfortran lfortran.cpp)
 target_include_directories(lfortran PRIVATE "tpl")
 target_link_libraries(lfortran lfortran_lib)
-    # This is sometimes needed to fix link errors for CLI11
-    target_link_libraries(lfortran stdc++fs)
         # Link statically on Linux with gcc or clang
@@ -134,7 +130,3 @@ endif()
 add_executable(cpptranslate cpptranslate.cpp)
 target_link_libraries(cpptranslate lfortran_lib)
-    # This is sometimes needed to fix link errors for CLI11
-    target_link_libraries(cpptranslate stdc++fs)

gfortran 1.f90 2.f90 will create an executable if the source files comprise a complete program, and other compilers work the same way. For LFortran you must do

lfortran -c 1.f90
lfortran -c 2.f90
lfortran 1.o 2.o

Otherwise you get

$ lfortran 1.f90 2.f90
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
The command 'gcc -o a.out a.out.tmp.o  -L"/home/bingy/miniconda3/envs/mvp_demo/bin/../share/lfortran/lib" -Wl,-rpath,"/home/bingy/miniconda3/envs/mvp_demo/bin/../share/lfortran/lib" -llfortran_runtime -lm' failed.

The codes in 1.f90 and 2.f90 are

module m
subroutine sub()
  print*,"in sub"
end subroutine sub
end module m
program main
  use m
  call sub()
end program main
1 Like

Builds fine now, but I can’t compile without LLVM:

$ lfortran -c test.f
The -c option requires the LLVM backend to be enabled. Recompile with `WITH_LLVM=yes`.
1 Like

Perfect. There are couple options now:

  1. Use the C++ backend
    In LFortran’s git repository:

    lfortran --show-cpp examples/expr2.f90
    lfortran --backend=cpp examples/expr.f90

    The first prints the C++ code and the second option tries to compile it. Currently it requires the Kokkos C++ library for arrays. We can improve this in various ways, such as not using Kokkos optionally, etc.

  2. Using the x86 backend:

    lfortran --backend=x86 examples/expr2.f90

    This backend produces a Linux ELF x86 (32bit) binary. The compilation should succeed for you (as it does for me on macOS), but obviously the binary probably won’t run in FreeBSD. But we can improve it to work if there is interest. The x86 backend is more of a prototype still, so only very simple things work.

  3. Get LLVM working in FreeBSD
    What LLVM versions are available? We currently don’t actually compile with the latest LLVM 12 version, and I think we require LLVM 11. I think it would not be difficult to support several latest LLVM versions. You mentioned the latest LLVM version available is LLVM 10. I think we can support that and test it at our (Linux) CI.

It seems the 3) would be the easiest as we are currently focusing on the LLVM backend the most. Can you try to compile it with the LLVM from FreeBSD and report back? If the issue is just some errors because the LLVM API is tiny bit different, that we can fix for sure using ifdefs and CI tests in Linux.


While we are at this topic: do you know how to best test FreeBSD at our Continuous Integration? We can run any Docker container on Linux (gitlab.com runners), we can run on Windows (AppVeyor) or macOS (using Azure). If there was a way to test on FreeBSD, I’ll add it in and fix things so that they just work. I can see that GitLab CI supports FreeBSD: Install GitLab Runner on FreeBSD | GitLab, so now I just need to get it running somewhere. I found this online service: FreeBSD VMs - Cirrus CI.

Thanks. LFortran works with LLVM 11, so that should work.

I’ll try to figure out a CI solution, because otherwise what would happen is that people fix it, and then we break it again as we develop.

I am actually considering just buying a few computers, installing various systems on them and run a GitLab CI runner on them all the time and use that as part of our CI testing.

There is a FreeBSD solution with Cirrus CI, I used their service in the past to make some checks on FreeBSD. The images do not contain any software by default, means you have to invest some time to get a proper caching setup or you will spend too much time installing GBs of packages.

1 Like

Thanks for the tips. I created an issue for this: CI: add FreeBSD testing (#584) · Issues · lfortran / lfortran · GitLab to keep track of it. If anyone is interested in setting this up, please let us know.

The segfault is due to compiling in the default mode using cmake, which compiles in Release mode, no asserts, etc… You can try these:

cmake \

That should give better error messages and assert statements. If that does not work, just do this:

$ cmake \

That should not segfault anymore.

It may not be necessary to target LLVM 10, as FreeBSD 13 has already moved on to LLVM 11. I’ll try it again with installed LLVM 11 sources once I’ve upgraded from 12 to 13.

1 Like

On this note: would people like if we maintain compatibility with multiple versions of LLVM, and how many?

We could do for example the last three (so today that would be 12, 11, 10).

My experience with LLVM is that they change the API with each release, but the changes are relatively minor, so we can handle it with a preprocessor. One big breaking change is how they handle JIT, we still use an older version that got completely removed in LLVM 12, so we need to rewrite it.

I was thinking simply supporting the latest version at our CI on all platforms, and then add two older versions but only test those on Linux. Otherwise it would slow down especially the Windows builds, and I am hoping to avoid that.

It’s neat that you can define functions and subroutines in an interactive session and then invoke them:

>>> function square(i) result(j)                                                                                       ┐
... integer, intent(in) :: i                                                                                           │
... integer :: j                                                                                                       │
... j = i**2                                                                                                           │
... end function square                                                                                          5,20  ┘
>>> subroutine sub()                                                                                                   ┐
... print*,square(3)                                                                                                   │
... end subroutine sub                                                                                           3,19  ┘
>>> call sub() ! gives 9

It would be nice if you could define a module, but currently you get

>>> module m                                                                                                     1,9   ]
input:2:1 syntax error: end of file is unexpected here