Question

I'm using cmake verison 2.8.11.2 to build a project using some external libraries and packages. However since I tried adding the library spglib I have been unable to compile the code. Despite CMake adding the correct .so file the resulting makefile does not correctly link to it.

I use the following CMake code in src/main/CMakeLists.txt to include the spglib .so file:

 ADD_EXECUTABLE(PotFit ${SourceFiles})
 SET_TARGET_PROPERTIES(PotFit PROPERTIES COMPILE_DEFINITIONS "${POTFIT_COMPILE_DEFINITIONS}")
 TARGET_LINK_LIBRARIES(PotFit PotFitLibrary boost_timer boost_system)

 set(CMAKE_PREFIX_PATH [path to]/src/.libs)
 find_library(SPGLIBRARY NAMES spg spglib libsymspg symspg PATHS /home/staffana   /CS/trunk/spglib-1.6.0/src/.libs [path to]/spglib-1.6.0/src)
 target_link_libraries(PotFit "${SPGLIBRARY}")

Which seems to work. I check that CMake actually finds the library using

 message("The value of SPGLibrary is")
 message("${SPGLIBRARY}")

which correctly returns the path to libsymspg.so. However the compiler returns the error

CMakeFiles/PotFit.dir/Main.cpp.o: In function `main':
Main.cpp:(.text.startup+0x11a): undefined reference to `spg_get_spacegroup_type(int)'
collect2: error: ld returned 1 exit status
make[2]: *** [main/PotFit] Error 1
make[1]: *** [main/CMakeFiles/PotFit.dir/all] Error 2
make: *** [all] Error 2
*** Failure: Exit code 2 ***

I make sure that the libsymspg.so does contain this symbol by using

nm libsymspg.so | grep get_spacegroup_type

which returns

0000ad30 T spgdb_get_spacegroup_type
0000c240 T spg_get_spacegroup_type

So between Cmake and linking something is wrong. As far as I know I am using the "normal" way of doing things, so I am not sure where to begin looking for what is causing this problem. I have appended all whole CMakeLists.txt below since that might be useful and I can add the CMakeCache if needed (it's p. long...).

Full Cmake source

src/CMake.txt :

PROJECT(FitPot CXX C Fortran)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

OPTION(USE_OPENMP "Use OpenMP parallelization" "ON")
OPTION(ENABLE_DEBUG_CHECKS "Enable sanity checks in the code." "ON")

# Find and set up Qt4 library.
SET(QT_USE_QTOPENGL FALSE)
SET(QT_USE_QTGUI FALSE)
SET(QT_USE_QTXML TRUE)
SET(QT_USE_QTXMLPATTERNS FALSE)
SET(QT_MIN_VERSION "4.6.0")
# Use the Q_SIGNALS and Q_SLOTS macros to avoid name conflicts with Python.
ADD_DEFINITIONS(-DQT_NO_KEYWORDS)
FIND_PACKAGE(Qt4) 
IF(NOT QT4_FOUND)
    IF(QT4_INSTALLED_VERSION_TOO_OLD)
        MESSAGE(FATAL_ERROR "The installed Qt version ${QTVERSION} is too old, at least version ${QT_MIN_VERSION} is required.")
    ELSE(QT4_INSTALLED_VERSION_TOO_OLD)
        MESSAGE(FATAL_ERROR "The Qt library or the qmake program was not found! Please install Qt manually and specify the path to the 'qmake' program by setting the QT_QMAKE_EXECUTABLE setting in CMake. You need at least version ${QT_MIN_VERSION}.")
    ENDIF(QT4_INSTALLED_VERSION_TOO_OLD)
ENDIF(NOT QT4_FOUND)
INCLUDE(${QT_USE_FILE})

# Find Boost library.
#SET(BOOST_ROOT "/usr/local/boost_1_50_0/") # Might want to use this line, a modified version. !!MODIFYME
FIND_PACKAGE(Boost REQUIRED)
IF(NOT Boost_FOUND)
    MESSAGE(FATAL_ERROR "Boost library not found. Reason: ${Boost_ERROR_REASON}")
ENDIF()

# Modify this line to point to the directory where the boost libraries are. !!MODIFYME
SET(Boost_LIBRARY_DIRS "/usr/local/boost_1_50_0/stage/lib")


LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})

find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()

MESSAGE("boost lib dirs: ${Boost_LIBRARY_DIRS}")
MESSAGE("boost include dirs: ${Boost_INCLUDE_DIRS}")

# Choose compiler flags for Fortran compiler.
GET_FILENAME_COMPONENT(Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME)
IF(Fortran_COMPILER_NAME MATCHES "gfortran")
# gfortran:
SET(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -funroll-all-loops -fno-f2c -O3")
SET(CMAKE_Fortran_FLAGS_DEBUG   "${CMAKE_Fortran_FLAGS_DEBUG} -fno-f2c -O0 -g")
ELSEIF(Fortran_COMPILER_NAME STREQUAL "ifort")
# ifort:
# The '-fltconsistency' flag forces the compiler to "maintain floating point precision";
# replaces -mp option in older ifort versions.
# This is necessary to avoid hangups in the 'dpmeps' function in lbfgs.f on some systems.
SET(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -fltconsistency -f77rtl -O3")
SET(CMAKE_Fortran_FLAGS_DEBUG   "${CMAKE_Fortran_FLAGS_DEBUG} -fltconsistency -f77rtl -O0 -g")
ELSEIF(Fortran_COMPILER_NAME STREQUAL "g77")
# g77:
SET(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -funroll-all-loops -fno-f2c -O3 -m32")
SET(CMAKE_Fortran_FLAGS_DEBUG   "${CMAKE_Fortran_FLAGS_DEBUG} -fno-f2c -O0 -g -m32")
ELSE()
MESSAGE("Unknown Fortran compiler (${Fortran_COMPILER_NAME}), using default flags")
SET(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -O2")
SET(CMAKE_Fortran_FLAGS_DEBUG   "${CMAKE_Fortran_FLAGS_DEBUG} -O0 -g")
ENDIF()

SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS_RELEASE}")

MESSAGE("Fortran flags: ${CMAKE_Fortran_FLAGS}")

# Code files will reference header files relative to the root source directory.
INCLUDE_DIRECTORIES(".")


IF(ENABLE_DEBUG_CHECKS)
    SET(POTFIT_COMPILE_DEFINITIONS "DEBUG_FITPOT")
ENDIF()

# Creates a sub CMakeList.txt in those two subdirectories where source files are defined. 
ADD_SUBDIRECTORY(potfitlib)
ADD_SUBDIRECTORY(main)

MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
MESSAGE("cxx flags: ${CMAKE_CXX_FLAGS}")
MESSAGE("cxx linker flags: ${CMAKE_EXE_LINKER_FLAGS}")
MESSAGE("Library path is : ${CMAKE_LIBRARY_PATH}")

src/potfitlib/CMakeLists.txt

# List of source files that need to be compiled:
SET(SourceFiles
    util/linalg/LinAlg.cpp
    util/Debug.cpp  
    util/Dijkstra.cpp
    job/FitJob.cpp
    job/Fitting.cpp
    job/Validation.cpp
    potentials/Potential.cpp
    potentials/TabulatedEAMPotential.cpp
    potentials/SplineMEAMPotential.cpp
    potentials/LennardJonesPotential.cpp
    potentials/CDIPotential.cpp
    potentials/HarmonicModelFullPhi.cpp
    potentials/HarmonicModel.cpp
    potentials/PairPotential.cpp
    potentials/FourthOrderModel.cpp
    potentials/functions/CubicSpline.cpp
    potentials/functions/GridCubicSpline.cpp
    potentials/functions/Functions.cpp
potentials/fourthOrderHelpers/Bond.cpp
potentials/fourthOrderHelpers/TupleFinder.cpp
potentials/fourthOrderHelpers/SymmetryOperator.cpp
potentials/fourthOrderHelpers/GeneralizedDirection.cpp
potentials/fourthOrderHelpers/ForceTuple.cpp
potentials/fourthOrderHelpers/OldEnergyAndForces.cpp
potentials/fourthOrderHelpers/ForceComputation.cpp
    properties/FitProperty.cpp
    properties/AtomVectorProperty.cpp
    dof/DegreeOfFreedom.cpp
    dof/AtomCoordinatesDOF.cpp
    structures/FitObject.cpp
    structures/StructureGroup.cpp
    structures/AtomicStructure.cpp
    structures/UserStructure.cpp
    structures/NeighborList.cpp
    structures/LatticeStructures.cpp
    minimizer/SplitBregmanFunctionEvaluator.cpp 
    minimizer/Minimizer.cpp
    minimizer/SplitBregmanMinimizer.cpp
    minimizer/MinimizerParameters.cpp
    minimizer/lbfgsb.f
    util/xml/XMLParserUtilities.cpp 
    util/xml/XMLWriterUtilities.cpp 
)

# Include a resource file in the library.
QT4_ADD_RESOURCES(ResourceFiles resources/resources.qrc)

ADD_LIBRARY(PotFitLibrary STATIC ${SourceFiles} ${ResourceFiles})
SET_TARGET_PROPERTIES(PotFitLibrary PROPERTIES COMPILE_DEFINITIONS "${POTFIT_COMPILE_DEFINITIONS}")

# Link with the Qt libraries. 
TARGET_LINK_LIBRARIES(PotFitLibrary ${QT_LIBRARIES})

# Enable OpenMP parallelization when using a GNU C++ compiler.
IF(CMAKE_COMPILER_IS_GNUCXX AND USE_OPENMP)
SET_TARGET_PROPERTIES(PotFitLibrary PROPERTIES COMPILE_FLAGS "-fopenmp")
SET_TARGET_PROPERTIES(PotFitLibrary PROPERTIES LINK_FLAGS "-fopenmp")  
ENDIF(CMAKE_COMPILER_IS_GNUCXX AND USE_OPENMP)

src/main/CMakeLists.txt

 # List of source files that need to be compiled:
SET(SourceFiles
    Main.cpp    
)

INCLUDE_DIRECTORIES([path to]/spglib-1.6.0/src)
INCLUDE_DIRECTORIES([path to]/spglib-1.6.0/src/.libs)
LINK_DIRECTORIES([path to]/spglib-1.6.0/src/.libs )


ADD_EXECUTABLE(PotFit ${SourceFiles})
SET_TARGET_PROPERTIES(PotFit PROPERTIES COMPILE_DEFINITIONS "${POTFIT_COMPILE_DEFINITIONS}")
TARGET_LINK_LIBRARIES(PotFit PotFitLibrary boost_timer boost_system)

set(CMAKE_PREFIX_PATH [path_to]/spglib-1.6.0/src/.libs)
find_library(SPGLIBRARY NAMES spg spglib libsymspg symspg PATHS [path_to]/spglib-1.6.0/src/.libs [path_to]/spglib-1.6.0/src)
target_link_libraries(PotFit "${SPGLIBRARY}")
message("The value of SPGLibrary is")
message("${SPGLIBRARY}")

MESSAGE("Spglib link flags: ${SPGLIB_LINK_FLAGS}")
MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
MESSAGE("cxx flags: ${CMAKE_CXX_FLAGS}")
MESSAGE("cxx linker flags: ${CMAKE_EXE_LINKER_FLAGS}")
MESSAGE("Library path is : ${CMAKE_LIBRARY_PATH}")
Was it helpful?

Solution

Add to the include

extern "C"
{
    #include "symspg.h" // or whatever
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top