سؤال

I'm on Ubuntu 13.04 64-bit and I'm attempting to build a "Hello world" program in PETSc using CMake.

I have the following program solve1.c (loosely based on ex1.c from the PETSc examples), which solves a simple system of linear equations:

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

This is my attempt at creating CMakeLists.txt (based on various PETSc tutorials and projects found on the web):

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

In addition, I have a directory cmake-modules where I have the files CorrectWindowsPaths.cmake, FindPETSc.cmake, FindPackageMultipass.cmake and ResolveCompilerPaths.cmake which I have gotten from https://github.com/jedbrown/cmake-modules (as recommended by the PETSc FAQ).

I'm building the project in this way (initially standing in the root directory of my project, which is /home/ruben/hello):

mkdir build
cd build
cmake ..
make

Unfortunately, the make commands fails with a linker error. Here's the output from CMake (which looks good):

-- 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

Here's the output from make VERBOSE=1 (which is not good):

/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

The PETSc FAQ recommends looking at CMakeLists.txt from the Dohp project. Unfortunately, I found this CMake file to be difficult to understand (Dohp is not a particularly small example and it has additional dependencies other than PETSc) and I have not been able to make use of this file to fix my linker error.

My question: What is wrong with my CMakeLists.txt and how can I fix it? (Or, in the case that my CMake file is correct: What other mistake(s) have I done?)

Some additional information: I'm using PETSc 3.4.2 (installed in /home/ruben/petsc-3.4.2/, installed with MPI which I want to use), CMake 2.8.10.1, gcc 4.8.1, all on Ubuntu 13.04 64-bit on an Intel i7-3930k. I am able to compile and run the above program using a regular makefile, and I'm able to compile and run all PETSc examples I've tried so far.

هل كانت مفيدة؟

المحلول

The cause of the error is that the wrong compiler is invoked. From the make output (with VERBOSE on), it can be seen that /usr/bin/cc is called instead of an MPI capable compiler (mpicc)

A way to fix this is to tell CMake which compiler to use. The updated build instructions are as follows:

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

(If this was a C++ project, the correct CMake variable to set would be CMAKE_CXX_COMPILER.)

For subsequent builds in the same build tree, the cmake line above can be replaced with cmake .., as the compiler path is now stored in the config files for this build tree.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top