2

我在 Ubuntu 13.04 64 位上,我正在尝试使用 CMake 在 PETSc 中构建一个“Hello world”程序。

我有以下程序solve1.c(大致基于 PETSc 示例中的 ex1.c),它解决了一个简单的线性方程组:

/* 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})

此外,我有一个目录,其中包含我从https://github.com/jedbrown/cmake-modulescmake-modules获得的文件(由PETSc FAQ推荐)。CorrectWindowsPaths.cmakeFindPETSc.cmakeFindPackageMultipass.cmakeResolveCompilerPaths.cmake

我正在以这种方式构建项目(最初位于我项目的根目录中,即/home/ruben/hello):

mkdir build
cd build
cmake ..
make

不幸的是,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.txtDohp项目中查看。不幸的是,我发现这个 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,全部在 Intel i7-3930k 上的 Ubuntu 13.04 64 位上。我能够使用常规的 makefile 编译和运行上述程序,并且能够编译和运行迄今为止我尝试过的所有 PETSc 示例。

4

1 回答 1

3

错误的原因是调用了错误的编译器。从 make 输出(打开 VERBOSE)可以看出,它/usr/bin/cc被调用而不是支持 MPI 的编译器 (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 ..,因为编译器路径现在存储在此构建树的配置文件中。

于 2013-09-27T12:51:36.050 回答