如何通过CMake使用MinGW gfortran构建/编译Fortran?

时间:2016-09-27 14:32:38

标签: cmake gfortran mingw-w64 msys2 cmake-gui

我有更多的东西我必须弄清楚CMake而不仅仅是以下问题,但它是第一个也是最简单的一个我仍然无法通过的问题。我已经搜索了互联网,甚至从朋友那里借了“Mastering CMake”这本书,但我仍然遇到了最困难的时刻......关于CMake,Fortran和MinGW的网上存在很多东西,甚至一次两个的组合。但这三者似乎几乎不存在。

我想做的就是(在这一点上)是使用MinGW的gfortran编译器在Windows上使用CMake构建和编译的简单Fortran程序。

......我是一个CMake n00b。

这是我到目前为止一直在使用的方法:

的CMakeLists.txt:

project(cmake_test Fortran)
add_executable(testf test.f90)

test.f90:

      program test
      write(*,*)"hello world"
      endprogram test

我已经获得了MinGW的MSYS2版本,因为这是我最终要编译的代码将在Windows上编译的唯一版本。 (即,当我在MSYS2 shell中使用我自己的Makefile编译它时,它会编译。)

我的Windows路径附加了;C:\msys64\mingw64\bin。 (我也尝试了;C:\msys64\usr\bin,但它抱怨sh.exe在同一目录中,以及其他问题。)

然后我弹出CMake-GUI,加载上面的CMakeLists,点击Configure,指定项目的生成器为“MinGW Makefile”,选择“Use default native compilers”,并得到以下输出:

The Fortran compiler identification is GNU 5.4.0
Check for working Fortran compiler: C:/msys64/mingw64/bin/gfortran.exe
Check for working Fortran compiler: C:/msys64/mingw64/bin/gfortran.exe  -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/mingw64/bin/gfortran.exe supports Fortran 90
Checking whether C:/msys64/mingw64/bin/gfortran.exe supports Fortran 90 -- yes
Configuring done

然后我再次点击配置并获取:

Configuring done

然后生成:

Generating done

在我的构建目录中,有一个Makefile和许多其他文件和目录。

我尝试在MSYS2 shell中运行make,我得到了这个:

myself@COMPUTER MSYS /c/users/myself/desktop/dll_test/with_fortran_cmake/build
$ make
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\users\myself\desktop\dll_test\with_fortran_cmake\build>

最后一行是提示。如果我输入make这样的内容,它似乎再次运行它,它只是在提示符中再次显示提示。如果我按下Ctrl + C,它会杀死它并返回到正常的MSYS2提示符。

所以我无法弄清楚如何实现它,假设我甚至正在做CMake部分。

问题:考虑到我列出的约束,如何让这个示例代码构建/编译/运行?

(我真的宁愿做的,一旦我超越这部分,就是让它与Visual Studio 13一起工作,因为我有一个用CMake构建的C ++项目(主要由我限制的其他人编写)访问问题和帮助)我希望能够调用我的Fortran。一旦我将Fortran放入某个可以通过Visual Studio中的C ++调用的库中,Fortran几乎可以单独留下来作为一个预先构建的库。我知道从VS编辑Fortran实际上并不是很有可能,我对此并不感兴趣。)

以下是生成的 Makefile 的内容(注意我的编辑器在此处复制时用空格替换了标签):

# CMAKE generated file: DO NOT EDIT!
# Generated by "MinGW Makefiles" Generator, CMake Version 3.5

# Default target executed when no arguments are given to make.
default_target: all

.PHONY : default_target

# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:


#=============================================================================
# Special targets provided by cmake.

# Disable implicit rules so canonical targets will work.
.SUFFIXES:


# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =

.SUFFIXES: .hpux_make_needs_suffix_list


# Suppress display of executed commands.
$(VERBOSE).SILENT:


# A target that is always out of date.
cmake_force:

.PHONY : cmake_force

#=============================================================================
# Set environment variables for the build.

SHELL = cmd.exe

# The CMake executable.
CMAKE_COMMAND = "C:\Program Files (x86)\CMake\bin\cmake.exe"

# The command to remove a file.
RM = "C:\Program Files (x86)\CMake\bin\cmake.exe" -E remove -f

# Escaping for special characters.
EQUALS = =

# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = C:\Users\myself\Desktop\dll_test\with_fortran_cmake

# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build

#=============================================================================
# Targets provided globally by CMake.

# Special rule for the target edit_cache
edit_cache:
    @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
    "C:\Program Files (x86)\CMake\bin\cmake-gui.exe" -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache

# Special rule for the target edit_cache
edit_cache/fast: edit_cache

.PHONY : edit_cache/fast

# Special rule for the target rebuild_cache
rebuild_cache:
    @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
    "C:\Program Files (x86)\CMake\bin\cmake.exe" -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache

# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache

.PHONY : rebuild_cache/fast

# The main all target
all: cmake_check_build_system
    $(CMAKE_COMMAND) -E cmake_progress_start C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles\progress.marks
    $(MAKE) -f CMakeFiles\Makefile2 all
    $(CMAKE_COMMAND) -E cmake_progress_start C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles 0
.PHONY : all

# The main clean target
clean:
    $(MAKE) -f CMakeFiles\Makefile2 clean
.PHONY : clean

# The main clean target
clean/fast: clean

.PHONY : clean/fast

# Prepare targets for installation.
preinstall: all
    $(MAKE) -f CMakeFiles\Makefile2 preinstall
.PHONY : preinstall

# Prepare targets for installation.
preinstall/fast:
    $(MAKE) -f CMakeFiles\Makefile2 preinstall
.PHONY : preinstall/fast

# clear depends
depend:
    $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 1
.PHONY : depend

#=============================================================================
# Target rules for targets named testf

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

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

test.obj: test.f90.obj

.PHONY : test.obj

# target to build an object file
test.f90.obj:
    $(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.obj
.PHONY : test.f90.obj

test.i: test.f90.i

.PHONY : test.i

# target to preprocess a source file
test.f90.i:
    $(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.i
.PHONY : test.f90.i

test.s: test.f90.s

.PHONY : test.s

# target to generate assembly for a file
test.f90.s:
    $(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.s
.PHONY : test.f90.s

# Help Target
help:
    @echo The following are some of the valid targets for this Makefile:
    @echo ... all (the default if no target is provided)
    @echo ... clean
    @echo ... depend
    @echo ... testf
    @echo ... edit_cache
    @echo ... rebuild_cache
    @echo ... test.obj
    @echo ... test.i
    @echo ... test.s
.PHONY : help



#=============================================================================
# Special targets to cleanup operation of make.

# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
    $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 0
.PHONY : cmake_check_build_system

版本信息:

  • GNU Fortran(GCC)5.3.0
  • Windows 7企业版
  • Cmake 3.5.2
  • MSYS2 - 我不确定如何找到此版本
  • MinGW - 我不确定如何找到这个
  • 的版本

我在搜索过程中经历了很多不同的在线页面,而且我并没有全神贯注地跟踪它们,但是这一个特别是我一直遇到的,因为它看起来与它非常相关标题,但实际问题和解决方案完全不是:

2 个答案:

答案 0 :(得分:1)

这是一个快速shell会话,展示了我如何使用MSYS2,cmake,make和gfortran构建Fortran程序。您应该尝试运行我所做的相同命令,看看它们是否提供不同的输出然后调查原因。

MSYSTEM变量尤为重要;它取决于你在启动MSYS2时点击的快捷方式。

$ echo $MSYSTEM
MINGW64

$ which cmake
/mingw64/bin/cmake

$ which gfortran
/mingw64/bin/gfortran

$ which make
/usr/bin/make

$ ls
CMakeLists.txt  test.f90

$ cat CMakeLists.txt
project(cmake_test Fortran)
add_executable(testf test.f90)

$ cat test.f90
      program test
      write(*,*)"hello world"
      endprogram test

$ mkdir build && cd build

$ cmake -G"MSYS Makefiles" ..
-- The Fortran compiler identification is GNU 6.2.0
-- Check for working Fortran compiler: D:/msys64/mingw64/bin/gfortran.exe
-- Check for working Fortran compiler: D:/msys64/mingw64/bin/gfortran.exe  -- works
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Checking whether D:/msys64/mingw64/bin/gfortran.exe supports Fortran 90
-- Checking whether D:/msys64/mingw64/bin/gfortran.exe supports Fortran 90 -- yes
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/david/Documents/scraps/test_fortran/build

$ make
Scanning dependencies of target testf
[ 50%] Building Fortran object CMakeFiles/testf.dir/test.f90.obj
[100%] Linking Fortran executable testf.exe
[100%] Built target testf

$ ./testf.exe
 hello world

答案 1 :(得分:0)

编辑:这里有一个有效的解决方案 - 直到最后!

感谢David Grayson对原始问题的评论,我找到了部分解决方案。 “部分”,因为它使用f95而不是gfortran。我发布它是因为它可能适用于其他人,如果我能够弄清楚如何让它与gfortran一起工​​作,我会更新它。

原来问题是一个非常简单的错误:我使用的是“MinGW Makefiles”的“MSYS Makefiles”。

但是当我只更改了它时,当我点击配置时,我在CMake-GUI中得到了以下输出:

CMake Error: CMake was unable to find a build program corresponding to "MSYS 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 "MSYS Makefiles". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
CMake Error: CMAKE_Fortran_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_AR was not found, please set to archive program. Configuring incomplete, errors occurred!

要解决此问题,我再次更改了Windows路径。我一直在使用;C:\msys64\mingw64\bin,因此我将其切换为;C:\msys64\usr\bin

然后工作了(我点击了第二次配置,单击Generate,然后通过make目录中的MSYS2终端运行/build),但正如您在下面的输出中看到的那样,使用f95而不是gfortran:

The Fortran compiler identification is GNU 5.3.0
Check for working Fortran compiler: C:/msys64/usr/bin/f95.exe
Check for working Fortran compiler: C:/msys64/usr/bin/f95.exe  -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/usr/bin/f95.exe supports Fortran 90
Checking whether C:/msys64/usr/bin/f95.exe supports Fortran 90 -- yes
Configuring done

我仍在努力让它使用gfortran,如果我弄明白的话,我会更新这个解决方案。

修改

好的,这显然更像是一个黑客,我相信有更好的解决方案。我将C:\msys64\usr\bin\f95.exe重命名为其他内容(以便MSYS2在找到gfortran之前不会将其视为另一个Fortran编译器)。我还必须清除CMake的缓存并重新启动它。但现在它起作用了:

The Fortran compiler identification is GNU 5.3.0
Check for working Fortran compiler: C:/msys64/usr/bin/gfortran.exe
Check for working Fortran compiler: C:/msys64/usr/bin/gfortran.exe  -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/usr/bin/gfortran.exe supports Fortran 90
Checking whether C:/msys64/usr/bin/gfortran.exe supports Fortran 90 -- yes
Configuring done

努力找出如何以“正确”的方式做到这一点。

修改

好吧,我猜这是更合适的方法,因为我认为它实际上与从那里调用CMake时在命令行上设置环境变量一样。

在CMake-GUI中,我按照前面的说明设置了所有内容,但在第一次单击“配置”之前,我点击了带有小加号的“添加条目”按钮。然后我设置了两个新的缓存条目 - 尽管只有一个是非常必要的:

Name: CMAKE_Fortran_COMPILER
Type: FILEPATH
Value: C:\msys64\usr\bin\gfortran.exe

我还设置了以下内容,但这只是为了验证它是否正确调用了gfortran,正如您将在下面的输出中看到的那样:

Name: CMAKE_VERBOSE_MAKEFILE
Type: BOOL
Value: [True]

然后,在MSYS2终端中运行make,我得到以下内容:

$ make
"/C/Program Files (x86)/CMake/bin/cmake.exe" -H/C/Users/myself/Desktop/dll_test/with_fortran_cmake -B/C/Users/myself/Desktop/dll_test/with_fortran_cmake/build --check-build-system CMakeFiles/Makefile.cmake 0
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_progress_start /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/depend
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_depends "MSYS Makefiles" /C/Users/myself/Desktop/dll_test/with_fortran_cmake /C/Users/myself/Desktop/dll_test/with_fortran_cmake /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles/testf.dir/DependInfo.cmake --color=
Scanning dependencies of target testf
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/requires
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make[2]: Nothing to be done for 'CMakeFiles/testf.dir/requires'.
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/build
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
[ 50%] Building Fortran object CMakeFiles/testf.dir/test.f90.obj
/C/msys64/usr/bin/gfortran.exe     -c /C/Users/myself/Desktop/dll_test/with_fortran_cmake/test.f90 -o CMakeFiles/testf.dir/test.f90.obj
[100%] Linking Fortran executable testf.exe
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E remove -f CMakeFiles/testf.dir/objects.a
/C/msys64/usr/bin/ar.exe cr CMakeFiles/testf.dir/objects.a @CMakeFiles/testf.dir/objects1.rsp
/C/msys64/usr/bin/gfortran.exe     -Wl,--whole-archive CMakeFiles/testf.dir/objects.a -Wl,--no-whole-archive  -o testf.exe -Wl,--out-implib,libtestf.dll.a -Wl,--major-image-version,0,--minor-image-version,0
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
[100%] Built target testf
make[1]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_progress_start /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles 0

结果程序通过MSYS2终端和Windows命令提示符工作。

...现在我需要弄清楚如何在Visual Studio中将这一切与C ++结合在一起。请继续关注更多SO问题! :d