我正在將一個帶有Intel Fortran 2020的Visual Studio 2019專案遷移至CMake
。我正在使用 CMake 3.21 和 CMakePresets 來將生成器設定為 Visual Studio 2019 和 x64bit 架構。
我的最終產品是一個DLL,它建立在多個源檔案上。這些檔案也被組織在檔案夾中。
編譯器被正確找到,一切運行正常,直到我進入鏈接步驟,在那里我得到了未解決的符號錯誤。現在Visual Studio生成了一個名為BuildLog.htm的檔案,其中有一個編譯器運行的所有命令的串列。我恢復了 CMake 生成的檔案,并與 Visual Studio 專案生成的檔案進行了比較。
它是這樣的
它是這樣的
ifort <ze-flags> file1.f90
ifort <some-flags> file2.f90
ifort <some-flags> file3.f90
ifort <some-flags> file4.f90
我注意到的不同之處是,CMake日志的內容是這樣的
。ifort <some-flags> file3.f90
ifort <some-flags> file1.f90
ifort <some-flags> file4.f90
ifort <some-flags> file2.f90
我不確定這里發生了什么,因為我在CMake中以正確的順序生成檔案串列。為什么會出現亂碼呢?
我讀到,這可能是鏈接命令中列出的檔案順序的問題,但我啟動了命令,將物件與 CMake 生成的物件手動鏈接,我得到了同樣的未解決的聯結器錯誤。但是如果我按照正確的順序手動編譯物件,聯結器就不會失敗。
誰能解釋一下為什么 CMake 會對檔案順序做這樣的處理? 為什么Visual Studio不需要我的任何輸入就能獲得正確的順序?我是否在 CMake 中丟失了某些配置選項?
這將是我創建目標的方式
set(APPEND MY_FILE_LIST
file1.f90
file2.f90
file3.f90
file4.f90
)
add_library(MY_LIB SHARED ${MY_FILE_LIST})
鏈接命令是這樣的
link /nologo /subsystem:WINDOWS /DLL /OUT:mylib.dll /IMPLIB:mylib.lib file1.obj file2.obj file3.obj file4.obj
更新:
因此,我試著將 CMake 創建的編譯命令手動排序到與 Visual Studio 輸出的相同順序,結果聯結器失敗了。所以我的猜測是錯誤的存在讓我失敗了。我把編譯器的命令貼出來,它們不太一樣,但我沒有看到問題所在
。Visual Studio編譯器命令
ifort /nologo /O3 /extend_source:132 /warn:none /names:uppercase /iface:stdref /iface:mixed_str_len_arg /libs:dll /threads /c /Qlocation,link," ...ToolsMSVC14.22.27905inHostX64x64" /Qm64 "file1.f90"
ifort /nologo /O3 /heap-arrays0 /extend_source:132 /warn:none /names:uppercase /iface:stdref /iface:mixed_str_len_arg /libs:dll /threads /c /Qlocation,link," ...ToolsMSVC14.22.27905inHostX64x64" /Qm64 "file2.f90"
ifort /nologo /O3 /extend_source:132 /warn:none /names:uppercase /iface:stdref /iface:mixed_str_len_arg /libs:dll /threads /c /extfor:f /Qlocation,link," ...ToolsMSVC14.22.27905inHostX64x64" /Qm64 "file3.f"
ifort /nologo /O3 /heap-arrays0 /extend_source:132 /Qopenmp /warn:none /names:uppercase /iface:stdref /iface:mixed_str_len_arg /libs:dll /threads /c /Qlocation,link," ...ToolsMSVC14.22.27905inHostX64x64" /Qm64 "file4.f90"
CMake編譯器命令
ifort /nologo /O3 /DCMAKE_INTDIR="Release" /Dmylib_EXPORTS /iface:stdref /libs:dll /threads /c /names:uppercase /iface:mixed_str_len_arg /Qlocation,link," ...ToolsMSVC14.22.27905inHostX64x64" /Qm64 "file1.f90"
ifort /nologo /O3 /DCMAKE_INTDIR="Release" /Dmylib_EXPORTS /iface:stdref /libs:dll /threads /c /heap-arrays /Qlocation,link," ...ToolsMSVC14.22.27905inHostX64x64" /Qm64 "file2.f90"
ifort /nologo /O3 /DCMAKE_INTDIR="Release" /Dmylib_EXPORTS /iface:stdref /libs:dll /threads /c /extend-source /f77 /extfor:f /Qlocation,link," ...ToolsMSVC14.22.27905inHostX64x64" /Qm64 "file3.f"
ifort /nologo /O3 /DCMAKE_INTDIR="Release" /Dmylib_EXPORTS /Qopenmp /iface:stdref /libs:dll /threads /c /heap-arrays /Qlocation,link," ...ToolsMSVC14.22.27905inHostX64x64" /Qm64 "file4.f90"
到目前為止,我所嘗試的是:
- 洗掉了/D定義標志 將
- 添加132到
/extend-source。
- 洗掉了/f77 。
libs:dll /threads /c移到/Qlocation,link之前。
更新2:
在仔細檢查標志時,我發現我的一些編譯標志丟失了。
在配置 CMake 時,我設定了用于編譯的全域標志,但有些檔案有特定的編譯標志。
這就是我在CMake中設定標志的方法
set (common_flags "/nologo")
設定(release_flags "/O3")
設定(debug_flags "/debug:full /Od")
設定(external_proc_flags "/names:uppercase /iface:stdref /iface:mixed_str_len_arg")
設定(runtime_flags "/traceback /check:bounds /check:stack")
設定(warning_flags "")
如果(SHOW_WARNINGS)
# 你想要所有的編譯器警告
設定(warning_flags "/stand:f08 /warn:all ${runtime_flags}" )
endif()
設定(my_Fortran_FLAGS_RELEASE "${release_flags} ${external_proc_flags} ${warning_flags}" )
設定(my_Fortran_FLAGS_DEBUG "${debug_flags} ${external_proc_flags} ${warning_flags}" )
set(CMAKE_Fortran_FLAGS "${common_flags}" )
set(CMAKE_Fortran_FLAGS_DEBUG ${my_Fortran_FLAGS_DEBUG})
set(CMAKE_Fortran_FLAGS_RELEASE ${my_Fortran_FLAGS_RELEASE})
set(CMAKE_Fortran_FLAGS_RELEASE ${my_Fortran_FLAGS_RELEASE})
然后在CMake的add_library()命令之后,我為特定的檔案設定了這樣的標志
set_property(SOURCE ${EXTEND_SOURCE_FILES} PROPERTY COMPILE_OPTIONS "/extend-source;/f77")
set_property(SOURCE ${OPENMP_FILES} PROPERTY COMPILE_OPTIONS "/Qopenmp")
set_property(SOURCE ${HEAP_ARRAYS_FILES} PROPERTY COMPILE_OPTIONS "/heap-arrays")
set_property(SOURCE ${OPENMP_PLUS_HEAP_ARRAYS_FILES}屬性COMPILE_OPTIONS "/HEAP-ARRAYS") PROPERTY COMPILE_OPTIONS "/Qopenmp;/heap-arrays")
但是看起來這個最后的編譯選項屬性搞亂了原來的標志,我發現EXTEND_SOURCE_FILES、HEAP_ARRAYS_FILES和OPENMP_PLUS_HEAP_ARRAYS_FILES中的所有檔案都沒有/names:uppercase,這使得鏈接步驟失敗。
uj5u.com熱心網友回復:
我找到了解決我問題的方法。@Tsyvarev給我指出了關于標志的正確方向,原來cmake并沒有像我預期的那樣添加標志。
我需要為目標中的所有檔案設定一些標志,然后為一些特定的檔案設定一些標志。
問題是,在為源檔案設定COMPILE_OPTIONS屬性時,一些全域標志沒有進入編譯命令,特別是缺少的
。 ames:uppercase標志是導致問題的一個標志,但其他一些標志也丟失了。
。這是最終讓它在CMake中作業的配置。
set (common_flags "/nologo")
設定(release_flags "/O3")
設定(debug_flags "/debug:full /Od")
設定(external_proc_flags "/names:uppercase;/iface:stdref;/iface:mixed_str_len_arg")
設定(runtime_flags "/traceback;/check:bounds;/check:stack")
設定(warning_flags "")
如果(SHOW_WARNINGS)
設定(warning_flags "/stand:f08;/warn:all;${runtime_flags}" )
endif()
設定(CMAKE_Fortran_FLAGS_RELEASE ${release_flags})
set(CMAKE_Fortran_FLAGS_DEBUG ${debug_flags})
set(CMAKE_Fortran_FLAGS ${common_flags})
set(my_Fortran_flags "${external_proc_flags};${warning_flags}")
# mylib_sources - 所有源代碼檔案的串列
add_library(mylib SHARED ${mylib_sources})
target_compile_options(mylib PRIVATE ${my_Fortran_flags})
set_property(SOURCE ${EXTEND_SOURCE_FILES}) PROPERTY COMPILE_OPTIONS "/extend-source;/f77;${my_Fortran_flags}")
set_property(SOURCE ${OPENMP_FILES}屬性 PROPERTY COMPILE_OPTIONS "/Qopenmp;${my_Fortran_flags}")
set_property(SOURCE ${HEAP_ARRAYS_FILES}屬性 COMPILE_OPTIONS "/Qopenmp;${my_Fortran_flags}"。PROPERTY COMPILE_OPTIONS "/heap-arrays;${my_Fortran_flags}")
set_property(SOURCE ${OPENMP_PLUS_HEAP_ARRAYS_FILES}屬性COMPILE_OPTIONS "/heap-arrays;${my_Fortran_flags} PROPERTY COMPILE_OPTIONS "/Qopenmp;/heap-arrays;${my_Fortran_flags}" )
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/326364.html
標籤:
