Как связать ноутбук с CMake и Visual 2013?
Аннотация: я создал простой пример C++ с использованием lapack. Я не могу скомпилировать его с CMake и Visual Studio 2013 из-за ошибки ссылки.
Конфигурация: Windows 7 64-битная, Visual Studio 12 2013 Win64, компилятор intel64, CMake 3.1.0, Lapack 3.5.0.
Установка Lapack: я построил Lapack 3.5.0 с CMake, используя компиляторы от Intel. Я активировал все опции BUILD_*, кроме BUILD_SHARED_LIBS. Я построил с Visual Studio в режиме выпуска. Я получил два lib-файла в моей директории установки: blas.lib и lapack.lib.
Пример C++: я создал следующий простой пример C++, используя функцию ilaver (предоставив версию lapack).
#include <iostream>
extern "C" { void ilaver_(int* major, int* minor, int* patch); }
int main(int argc, char** argv)
{
int major = 0; int minor = 0; int patch = 0;
ilaver_(&major, &minor, &patch);
std::cout << major << "." << minor << "." << patch << std::endl;
return 0;
}
CMakeLists.txt: я также создал связанный файл CMakeLists:
cmake_minimum_required(VERSION "2.8.9")
project(linklapack)
enable_language(C)
enable_language(CXX)
enable_language(Fortran)
set(LAPACK_LIBDIRS "C:/softs/lapack/3.5.0/64/lib")
set(LAPACK_LIBRARIES lapack)
link_directories(${LAPACK_LIBDIRS})
add_executable(GetLapackVersion ${CMAKE_SOURCE_DIR}/GetLapackVersion.cpp)
target_link_libraries(GetLapackVersion ${LAPACK_LIBRARIES})
install(TARGETS GetLapackVersion DESTINATION ${CMAKE_INSTALL_PREFIX})
Под Linux: работает. (Конечно, путем изменения пути к lib)
Под Windows: я запустил CMake с теми же компиляторами и той же конфигурацией Visual Studio. Я загрузил сгенерированное решение для Visual Studio и создал цель "GetLapackVersion". Тогда я получил следующую ссылку:
2>GetLapackVersion.obj : error LNK2019: unresolved external symbol ilaver_ referenced in function main
2>C:\Users\caduchon\Documents\Christophe\linklapack\BUILD\Release\GetLapackVersion.exe : fatal error LNK1120: 1 unresolved externals
Изменить: команда ссылки в Visual Studio для цели является следующей:
/OUT:"C:\Users\caduchon\Documents\Christophe\linklapack\BUILD\Release\GetLapackVersion.exe" /MANIFEST /NXCOMPAT /PDB:"C:/Users/caduchon/Documents/Christophe/linklapack/BUILD/Release/GetLapackVersion.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "comdlg32.lib" "advapi32.lib" "lapack.lib" /IMPLIB:"C:/Users/caduchon/Documents/Christophe/linklapack/BUILD/Release/GetLapackVersion.lib" /MACHINE:X64 /INCREMENTAL:NO /PGD:"C:\Users\caduchon\Documents\Christophe\linklapack\BUILD\Release\GetLapackVersion.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"GetLapackVersion.dir\Release\GetLapackVersion.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:/softs/lapack/3.5.0/64/lib" /LIBPATH:"C:/softs/lapack/3.5.0/64/lib/Release" /TLBID:1
Я понятия не имею, как решить эту проблему... Заранее спасибо за вашу помощь.
1 ответ
Отвечая на мой собственный вопрос.
Как и ожидал rubenvb, символы не были представлены в библиотеке, как ожидалось. Проблема задокументирована как "Фортран Имя Манглинг". Чтобы определить конфигурацию библиотеки с CMake, я изменил свой тестовый пример следующим образом:
#include <iostream>
#if defined LapackNameManglingUpper
#define ilaver ILAVER
#elif defined LapackNameManglingLower
#define ilaver ilaver
#elif defined LapackNameManglingUBack
#define ilaver ilaver_
#elif defined LapackNameMangling2UBack
#define ilaver ilaver__
#elif defined LapackNameManglingUFront
#define ilaver _ilaver
#endif
extern "C" { void ilaver(int* major, int* minor, int* patch); }
int main(int argc, char** argv)
{
int major = 0; int minor = 0; int patch = 0;
ilaver(&major, &minor, &patch);
std::cout << major << "." << minor << "." << patch << std::endl;
return 0;
}
Затем я могу определить хорошую конфигурацию с помощью CMake, пытаясь скомпилировать код с дополнительным аргументом. -DLapackNameManglingConfig
:
set(NAME_MANGLING_OPTIONS
"NameManglingUpper"
"NameManglingLower"
"NameManglingUBack"
"NameMangling2UBack"
"NameManglingUFront")
set(LAPACK_NAME_MANGLING "")
foreach(NAME_MANGLING_OPTION IN LISTS NAME_MANGLING_OPTIONS)
set(LAPACK_NAME_MANGLING "${NAME_MANGLING_OPTION}")
set(TRY_MANGLING_LIBRARY_DIRS ${Lapack_LIBRARY_DIRS} ${Compiler_LIBRARY_DIRS})
set(TRY_MANGLING_LIBRARIES ${Lapack_LIBRARIES} ${Fortran_LIBRARIES})
try_compile(TRY_MANGLING_OPTION ${CMAKE_BINARY_DIR}/tmpLapack ${CMAKE_MODULES_DIR}/GetLapackVersion.cpp
CMAKE_FLAGS "-DLINK_DIRECTORIES=${TRY_MANGLING_LIBRARY_DIRS}" "-DLINK_LIBRARIES=${TRY_MANGLING_LIBRARIES}"
COMPILE_DEFINITIONS "-DLapack${NAME_MANGLING_OPTION}")
if(TRY_MANGLING_OPTION)
set(LAPACK_NAME_MANGLING "Lapack${NAME_MANGLING_OPTION}")
break()
endif()
endforeach()
if(LAPACK_NAME_MANGLING STREQUAL "")
message(SEND_ERROR "Impossible to detect Fortran name mangling...")
else()
message(STATUS "Lapack: detected Fortran name mangling: ${LAPACK_NAME_MANGLING}")
add_definitions("-D${LAPACK_NAME_MANGLING}")
endif()