2013-09-26 5 views
2

Я на Ubuntu 13.04 64-битный, и я пытаюсь создать программу «Hello world» в PETSc, используя CMake.Проблемы при связывании программы PETSc при использовании CMake

У меня есть следующие программы solve1.c (по мотивам ex1.c из примеров PETSc), который решает простую систему линейных уравнений:

/* minimal example of solving a linear equation system in petsc 
    (in serial) */ 
/* based on http://www.mcs.anl.gov/petsc/petsc-current/src/ksp/ksp/examples/tutorials/ex1.c.html */ 
#include <petscksp.h> 
#define SIZE 3 
int main(int argc,char **argv) { 
    Vec x,b; /* approx solution, rhs */ 
    Mat A;  /* linear system matrix */ 
    KSP ksp; /* linear solver context */ 
    PC pc;  /* preconditioner context */ 
    int size; 
    PetscInt col[3],i; 
    PetscScalar temp[SIZE]; 

    PetscInitialize(&argc,&argv,PETSC_NULL,PETSC_NULL); 
    MPI_Comm_size(PETSC_COMM_WORLD,&size); 
    if(size!=1) PetscPrintf(PETSC_COMM_WORLD,"warning, %d threads\n",size); 
    /* create vectors */ 
    VecCreate(PETSC_COMM_WORLD,&x); 
    VecSetSizes(x,PETSC_DECIDE,SIZE); 
    VecSetFromOptions(x); 
    VecDuplicate(x,&b); 
    temp[0]=14.5; temp[1]=54; temp[2]=0.423; 
    for(i=0;i<3;i++) VecSetValues(b,1,&i,&temp[i],INSERT_VALUES); 
    /* need to assemble after setting values! do necessary 
     message passing etc to propagate matrix to all ranks */ 
    VecAssemblyBegin(b); 
    VecAssemblyEnd(b); 
    /* create matrix */ 
    MatCreate(PETSC_COMM_WORLD,&A); 
    MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,SIZE,SIZE); 
    MatSetFromOptions(A); 
    MatSetUp(A); 
    temp[0]=1; temp[1]=1; temp[2]=1; 
    col[0]=0; col[1]=1; col[2]=2; 
    for(i=0;i<3;i++) { 
     MatSetValues(A,1,&i,3,col,temp,INSERT_VALUES); 
     temp[i]=0; 
    } 
    /* need to assemble matrix for the same reasons as above */ 
    MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); 
    MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); 
    /* linear solver context! */ 
    KSPCreate(PETSC_COMM_WORLD,&ksp); 
    /* operator is A matrix, also set matrix for preconditioning here */ 
    KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN); 
    /* get pc context from ksp context */ 
    KSPGetPC(ksp,&pc); 
    /* set preconditioner type */ 
    PCSetType(pc,PCJACOBI); 
    KSPSetTolerances(ksp,1e-6,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); 
    KSPSetFromOptions(ksp); 
    /* solve! */ 
    KSPSolve(ksp,b,x); 
    /* display everything */ 
    MatView(A,PETSC_VIEWER_STDOUT_WORLD); 
    VecView(b,PETSC_VIEWER_STDOUT_WORLD); 
    VecView(x,PETSC_VIEWER_STDOUT_WORLD); 
    KSPView(ksp,PETSC_VIEWER_STDOUT_WORLD); 
    /* get rid of everything */ 
    KSPDestroy(&ksp); 
    VecDestroy(&x); 
    VecDestroy(&b); 
    PetscFinalize(); 
    return 0; 
} 

Это моя попытка создать CMakeLists.txt (на основе различных PETSc учебники и проекты, найденные в сети):

CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 

PROJECT(helloworld) 

SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-modules") 

FIND_PACKAGE(PETSc REQUIRED) 

INCLUDE_DIRECTORIES(${PETSC_INCLUDES}) 
ADD_DEFINITIONS(${PETSC_DEFINITIONS}) 

ADD_EXECUTABLE(solve1 solve1.c) 

TARGET_LINK_LIBRARIES(solve1 ${PETSC_LIBRARIES}) 

Кроме того, у меня есть каталог cmake-modules где у меня есть файлы CorrectWindowsPaths.cmake, FindPETSc.cmake, FindPackageMultipass.cmake и ResolveCompilerPaths.cmake, которые я получил от https://github.com/jedbrown/cmake-modules (в соответствии с рекомендациями PETSc FAQ).

Я строю проект на этом пути (изначально стоял в корневом каталоге моего проекта, который /home/ruben/hello):

mkdir build 
cd build 
cmake .. 
make 

К сожалению, команды замыкающих завершается с ошибкой компоновщика. Вот выход из CMake (который хорошо выглядит):

-- The C compiler identification is GNU 4.8.1 
-- The CXX compiler identification is GNU 4.8.1 
-- Check for working C compiler: /usr/bin/cc 
-- Check for working C compiler: /usr/bin/cc -- works 
-- Detecting C compiler ABI info 
-- Detecting C compiler ABI info - done 
-- Check for working CXX compiler: /usr/bin/c++ 
-- Check for working CXX compiler: /usr/bin/c++ -- works 
-- Detecting CXX compiler ABI info 
-- Detecting CXX compiler ABI info - done 
-- petsc_lib_dir /home/ruben/petsc-3.4.2/arch-linux2-c-debug/lib 
-- Recognized PETSc install with single library for all packages 
-- Performing Test MULTIPASS_TEST_1_petsc_works_minimal 
-- Performing Test MULTIPASS_TEST_1_petsc_works_minimal - Success 
-- Minimal PETSc includes and libraries work. This probably means we are building with shared libs. 
-- Found PETSc: /home/ruben/petsc-3.4.2/arch-linux2-c-debug/include;/home/ruben/petsc-3.4.2/include 
-- Configuring done 
-- Generating done 
-- Build files have been written to: /home/ruben/hello/build 

Вот выход из make VERBOSE=1 (что не очень хорошо):

/usr/bin/cmake -H/home/ruben/hello -B/home/ruben/hello/build --check-build-system CMakeFiles/Makefile.cmake 0 
/usr/bin/cmake -E cmake_progress_start /home/ruben/hello/build/CMakeFiles /home/ruben/hello/build/CMakeFiles/progress.marks 
make -f CMakeFiles/Makefile2 all 
make[1]: Entering directory `/home/ruben/hello/build' 
make -f CMakeFiles/solve1.dir/build.make CMakeFiles/solve1.dir/depend 
make[2]: Entering directory `/home/ruben/hello/build' 
cd /home/ruben/hello/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/ruben/hello /home/ruben/hello /home/ruben/hello/build /home/ruben/hello/build /home/ruben/hello/build/CMakeFiles/solve1.dir/DependInfo.cmake --color= 
Dependee "/home/ruben/hello/build/CMakeFiles/solve1.dir/DependInfo.cmake" is newer than depender "/home/ruben/hello/build/CMakeFiles/solve1.dir/depend.internal". 
Dependee "/home/ruben/hello/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/ruben/hello/build/CMakeFiles/solve1.dir/depend.internal". 
Scanning dependencies of target solve1 
make[2]: Leaving directory `/home/ruben/hello/build' 
make -f CMakeFiles/solve1.dir/build.make CMakeFiles/solve1.dir/build 
make[2]: Entering directory `/home/ruben/hello/build' 
/usr/bin/cmake -E cmake_progress_report /home/ruben/hello/build/CMakeFiles 1 
[100%] Building C object CMakeFiles/solve1.dir/solve1.c.o 
/usr/bin/cc -D__INSDIR__="" -I/home/ruben/petsc-3.4.2/arch-linux2-c-debug/include -I/home/ruben/petsc-3.4.2/include -o CMakeFiles/solve1.dir/solve1.c.o -c /home/ruben/hello/solve1.c 
Linking C executable solve1 
/usr/bin/cmake -E cmake_link_script CMakeFiles/solve1.dir/link.txt --verbose=1 
/usr/bin/cc  CMakeFiles/solve1.dir/solve1.c.o -o solve1 -rdynamic /home/ruben/petsc-3.4.2/arch-linux2-c-debug/lib/libpetsc.so -Wl,-rpath,/home/ruben/petsc-3.4.2/arch-linux2-c-debug/lib 
/usr/bin/ld: CMakeFiles/solve1.dir/solve1.c.o: undefined reference to symbol 'MPI_Comm_size' 
/usr/bin/ld: note: 'MPI_Comm_size' is defined in DSO /home/ruben/petsc-3.4.2/arch-linux2-c-debug/lib/libmpich.so.10 so try adding it to the linker command line 
/home/ruben/petsc-3.4.2/arch-linux2-c-debug/lib/libmpich.so.10: could not read symbols: Invalid operation 
collect2: error: ld returned 1 exit status 
make[2]: *** [solve1] Error 1 
make[2]: Leaving directory `/home/ruben/hello/build' 
make[1]: *** [CMakeFiles/solve1.dir/all] Error 2 
make[1]: Leaving directory `/home/ruben/hello/build' 
make: *** [all] Error 2 

PETSc FAQ рекомендует смотреть на CMakeLists.txt из проекта Dohp. К сожалению, я обнаружил, что этот файл CMake трудно понять (Dohp не является особенно маленьким примером и имеет дополнительные зависимости, отличные от PETSc), и я не смог использовать этот файл для исправления ошибки компоновщика.

Мой вопрос: Что случилось с моим CMakeLists.txt и как его исправить? (Или, в случае, если мой файл CMake прав: какие еще ошибки я сделал?)

Дополнительная информация: Я использую PETSc 3.4.2 (установлен в /home/ruben/petsc-3.4.2/, установлен с MPI, который я хотите использовать), CMake 2.8.10.1, gcc 4.8.1, все на Ubuntu 13.04 64-бит на Intel i7-3930k. Я могу скомпилировать и запустить вышеуказанную программу с помощью обычного make-файла, и я могу скомпилировать и запустить все примеры PETSc, которые я пробовал до сих пор.

+0

Мне удалось найти решение, поэтому я написал ответ. В соответствии с FAQ, отвечая на мой вопрос, кажется, все в порядке, и если не будет лучшего ответа в течение нескольких дней, я собираюсь отметить его как принятый. –

ответ

2

Причина ошибки в том, что вызывается неправильный компилятор. Из вывода make (с VERBOSE включено) видно, что вместо MPI-совместимого компилятора вызывается /usr/bin/cc (mpicc)

Способ исправить это, чтобы сообщить CMake, какой компилятор использовать. Обновленные инструкции по сборке заключаются в следующем:

mkdir build 
cd build 
cmake -D CMAKE_C_COMPILER=${PETSC_DIR}/${PETSC_ARCH}/bin/mpicc .. 
make 

(Если бы это был проект C++, правильная переменная CMake для установки будет CMAKE_CXX_COMPILER.)

Для последующего сборки в том же дереве сборки в CMake линии выше может быть заменен на cmake .., так как путь компилятора теперь сохраняется в файлах конфигурации для этого дерева сборки.

Смежные вопросы