[CMake] Handling library interdependencies
John Drescher
drescherjm at gmail.com
Wed Jun 17 12:10:12 EDT 2009
On Wed, Jun 17, 2009 at 11:53 AM, Mark Lohry<mlohry at gmail.com> wrote:
> Thanks guys, you've helped me to find the real problem :) explicitly linking
> the libraries got rid of a lot of the chaff.
>
> Looks like the core error on linking has to do with just one of the
> libraries. lib1 contains two subdirectories (sublib1 & sublib2) with just a
> handful of files, which are to be built into the lib1 library. These two
> subdirectories have no CMakeLists.txt of their own; lib1/CMakeLists.txt
> explicitly includes their code for compiling to lib1 ( sources list is like
> = src1.cxx sublib1/src2.cxx sublib2/src3.cxx ).
>
> When linking the executables to the library, the build fails, with all the
> errors of the form
>
> "in function (some func in lib1 ) undefined reference to (function in
> sublib1 or sublib2)" or
> "in function (some func in sublib1 or sublib2 )undefined reference to
> (function in sublib1 or sublib2)" or
> "in function (some func in src ) undefined reference to (function in sublib1
> or sublib2)",
>
> despite these subdirectory sources having been compiled and linked into the
> static library. Any thoughts on why these subdirectories wouldn't be linking
> correctly?
>
Using it this way was not automatic for me so I created a variable
which at each each subdirectory gets appended the current library.
Here is an example from my current project:
LungAnalysis/CMakeLists.txt:
PROJECT(LungAnalysis)
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
set (LungAnalysis_VERSION_MAJOR 0)
set (LungAnalysis_VERSION_MINOR 12)
#########################################################################################
option (USE_BZ_AIRWAY_ANALYSIS "Use Bin Zheng's Airway Analysis" ON)
option (USE_SCP_LS "Use Sean Choel Park's Lung Segmentation" ON)
option (USE_JPU_FISSURE "Use Fissure Analysis" ON)
option (DUMP_DICOM_HEADERS "Dump DICOM headers" OFF)
option (DUMP_DEBUG_IMAGES "Dump DEBUG Images" OFF)
option (DUMP_SERIES_DEBUG_INFO "Dump the dicom series debug info." OFF)
option (USE_QTBASICUTILS "Use QTBasicUtils" ON)
option (USE_kwCoreLib "Use kwCoreLib" ON)
option (USE_DEVELOMPENT "Build developement code and test projects" ON)
option (USE_CMD_LINE "Build Lung Analysis with command line support" ON)
option (USE_FILTERS "Build Lung Analysis with filter support" ON)
option (MAKE_DEBUGRELEASE "Add support for building a Release
Target with debug info" ON)
option (USE_LA_BASE_LIB "Add support for laBase library." ON)
option (USE_LA_RESULTS "Add support for results." ON)
option (USE_LA_DOCVIEW "Add support for documents and views." ON)
option (USE_LA_ANALYSIS "Add support for the analysis package." ON)
option (USE_LA_GUI "Add support for the GUI package." ON)
option (USE_LA_DICOM "Add support for the DICOM." ON)
option (USE_ideality "Use the ideality library." ON)
option (USE_lavtkINRIA3D "Use lavtkINRIA3D library." ON)
option (USE_MSVC_PCH "Use precompiled headers in MSVC." ON)
option (DISABLE_OPENGL "Disable opengl. This will disable the
display of images." OFF)
option (DISABLE_RESULT_TIMESTAMPS "Don't save the timetamp in the
filenames for the results" ON)
option (DISABLE_SLICE_THICK_IN_NAME "Don't put the slice thickness in
the document name." ON)
option (PACKAGE_FOR_INSTALL "Package Lung Analysis for installation." OFF)
option (USE_NEGATIVE_SPACING "Force using negative spacing on the Z axis." OFF)
#########################################################################################
set( LUNG_ANALYSIS_SRC ${PROJECT_SOURCE_DIR} )
set( LUNG_ANALYSIS_BINARY ${PROJECT_BINARY_DIR} )
IF (MAKE_DEBUGRELEASE)
SET (CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo" CACHE STRING
"Debug;RelWithDebInfo" FORCE)
SET (RELEASE_BUILD_NAME "RelWithDebInfo")
ELSE(MAKE_DEBUGRELEASE)
SET (CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING
"Debug;Release" FORCE)
SET (RELEASE_BUILD_NAME "Release")
ENDIF (MAKE_DEBUGRELEASE)
#########################################################################################
macro( LA_PCH_SUPPORT ProjectName )
if (MSVC)
if (USE_MSVC_PCH)
set_source_files_properties(${ProjectName}PCH.cxx
PROPERTIES
COMPILE_FLAGS "/Yc${ProjectName}PCH.h"
)
foreach( src_file ${${ProjectName}_SRCS} )
set_source_files_properties(
${src_file}
PROPERTIES
COMPILE_FLAGS "/Yu${ProjectName}PCH.h"
)
endforeach( src_file ${${ProjectName}_SRCS} )
list(APPEND ${ProjectName}_SRCS ${ProjectName}PCH.cxx)
list(APPEND ${ProjectName}_EXT_HDRS ${ProjectName}PCH.h)
endif(USE_MSVC_PCH)
endif (MSVC)
endmacro (LA_PCH_SUPPORT)
#########################################################################################
macro( LA_USE_INTERNAL_LIB TestName LibName )
#example LA_USE_INTERNAL_LIB( USE_FILTERS laFilters )
IF(${TestName})
set(USE_${LibName}_TREE 1)
include(${LUNG_ANALYSIS_BINARY}/Libraries/Internal/${LibName}/${LibName}Config.cmake)
include(${LUNG_ANALYSIS_SRC}/Libraries/Internal/${LibName}/${LibName}USE.cmake)
include_directories(${LUNG_ANALYSIS_BINARY}/Libraries/Internal/${LibName})
ENDIF(${TestName})
endmacro( LA_USE_INTERNAL_LIB )
#########################################################################################
macro( LA_USE_EXTERNAL_LIB TestName LibName )
#example LA_USE_EXTERNAL_LIB( USE_FILTERS laFilters )
IF(${TestName})
set(USE_${LibName}_TREE 1)
include(${LUNG_ANALYSIS_BINARY}/Libraries/External/${LibName}/${LibName}Config.cmake)
include(${LUNG_ANALYSIS_SRC}/Libraries/External/${LibName}/${LibName}USE.cmake)
include_directories(${LUNG_ANALYSIS_BINARY}/Libraries/External/${LibName})
ENDIF(${TestName})
endmacro( LA_USE_EXTERNAL_LIB )
#########################################################################################
IF(USE_NEGATIVE_SPACING)
ADD_DEFINITIONS(-DUSE_NEGATIVE_SPACING)
ENDIF(USE_NEGATIVE_SPACING)
IF(USE_lavtkINRIA3D)
ADD_DEFINITIONS(-DUSE_lavtkINRIA3D)
ENDIF(USE_lavtkINRIA3D)
#########################################################################################
# Note everything above the add_subdirectory(Libraries) will be global to each
# CMakeLists.txt file in the Libraries subdirectories.
#########################################################################################
add_subdirectory(Libraries)
#########################################################################################
IF(DISABLE_OPENGL)
ADD_DEFINITIONS(-DDISABLE_OPENGL)
ENDIF(DISABLE_OPENGL)
IF(DISABLE_RESULT_TIMESTAMPS)
ADD_DEFINITIONS(-DDISABLE_RESULT_TIMESTAMPS)
ENDIF(DISABLE_RESULT_TIMESTAMPS)
IF(DISABLE_SLICE_THICK_IN_NAME)
ADD_DEFINITIONS(-DDISABLE_SLICE_THICK_IN_NAME)
ENDIF(DISABLE_SLICE_THICK_IN_NAME)
IF(WIN32)
#The following command changes \ to / in the Program Files Path so
CMake will not complain
#about bad escape sequences.
IF(CMAKE_SIZEOF_VOID_P MATCHES 4)
string (REPLACE "\\" "/" PGM_FILES $ENV{PROGRAMFILES})
ELSE(CMAKE_SIZEOF_VOID_P MATCHES 4)
# On WIN64 use the 64 bit program files..
string (REPLACE "\\" "/" PGM_FILES $ENV{ProgramW6432})
ENDIF(CMAKE_SIZEOF_VOID_P MATCHES 4)
SET (CMAKE_INSTALL_PREFIX ${PGM_FILES}/UPMC/${CMAKE_PROJECT_NAME}
CACHE STRING "Default Install Path" FORCE)
configure_file (
"${PROJECT_SOURCE_DIR}/install.bat.in"
"${PROJECT_BINARY_DIR}/Batch/install.bat"
)
ENDIF(WIN32)
configure_file (
"${LUNG_ANALYSIS_SRC}/LungAnalysisConfig.h.in"
"${LUNG_ANALYSIS_BINARY}/LungAnalysisConfig.h"
)
INCLUDE_DIRECTORIES(${LUNG_ANALYSIS_BINARY})
IF(WIN32)
SET(CMAKE_CXX_FLAGS "/WL /MP /GR /EHsc" )
SET(CMAKE_EXE_LINKER_FLAGS "/INCREMENTAL:NO /MANIFEST /STACK:10000000 ")
IF(CMAKE_SIZEOF_VOID_P MATCHES 4)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}
/machine:I386 /LARGEADDRESSAWARE")
ELSE(CMAKE_SIZEOF_VOID_P MATCHES 4)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /machine:X64")
ENDIF(CMAKE_SIZEOF_VOID_P MATCHES 4)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE)
ENDIF(WIN32)
IF(DUMP_DICOM_HEADERS)
ADD_DEFINITIONS(-DDUMP_DICOM_HEADERS)
ENDIF(DUMP_DICOM_HEADERS)
IF(DUMP_SERIES_DEBUG_INFO)
ADD_DEFINITIONS(-DDUMP_DICOM_SERIES_DEBUG_INFO)
ENDIF(DUMP_SERIES_DEBUG_INFO)
IF(DUMP_DEBUG_IMAGES)
ADD_DEFINITIONS(-DDUMP_DEBUG_IMAGES_ALWAYS)
ENDIF(DUMP_DEBUG_IMAGES)
ADD_DEFINITIONS(-DNEED_WL_FILTER)
IF(USE_CMD_LINE)
ADD_DEFINITIONS(-DUSE_COMMAND_LINE)
ENDIF(USE_CMD_LINE)
IF(USE_BZ_AIRWAY_ANALYSIS)
option (BZ_AIRWAY_USE_SLICE_ROI_MASK "Airway analysis takes slices
that are cropped to match the Lung_Image_Mask" ON)
IF(BZ_AIRWAY_USE_SLICE_ROI_MASK)
ADD_DEFINITIONS(-DBZ_AIRWAY_USE_SLICE_ROI_MASK)
ENDIF(BZ_AIRWAY_USE_SLICE_ROI_MASK)
FIND_PACKAGE( BZ_Airway REQUIRED )
include(${BZ_AIRWAY_USE_FILE})
ENDIF (USE_BZ_AIRWAY_ANALYSIS)
IF(USE_SCP_LS)
FIND_PACKAGE( SCP_LS REQUIRED )
include(${SCP_LS_USE_FILE})
ENDIF (USE_SCP_LS)
IF(USE_JPU_FISSURE)
FIND_PACKAGE( JPU_Lobe REQUIRED )
include(${JPU_LOBE_USE_FILE})
ENDIF (USE_JPU_FISSURE)
LA_USE_EXTERNAL_LIB( USE_kwCoreLib kwCoreLib )
LA_USE_EXTERNAL_LIB( USE_ideality ideality )
LA_USE_EXTERNAL_LIB( USE_lavtkINRIA3D lavtkINRIA3D )
LA_USE_INTERNAL_LIB( USE_LA_BASE_LIB laBase )
LA_USE_INTERNAL_LIB( USE_FILTERS laFilters )
LA_USE_INTERNAL_LIB( USE_LA_RESULTS laResults )
LA_USE_INTERNAL_LIB( USE_LA_DOCVIEW laDocView )
LA_USE_INTERNAL_LIB( USE_LA_GUI laGUI )
LA_USE_INTERNAL_LIB( USE_LA_DICOM laDICOM )
LA_USE_INTERNAL_LIB( USE_LA_ANALYSIS laAnalysis )
IF(USE_CMD_LINE)
option(DEBUG_CMD_LINE "Debug the command line." OFF)
if(DEBUG_CMD_LINE)
add_definitions(-DDEBUG_CMD_LINE)
endif(DEBUG_CMD_LINE)
set(USE_laBatchProcessing_TREE 1)
include(${LUNG_ANALYSIS_BINARY}/Libraries/Internal/laBatchProcessing/laBatchProcessingConfig.cmake)
include(${LUNG_ANALYSIS_SRC}/Libraries/Internal/laBatchProcessing/laBatchProcessingUSE.cmake)
include_directories(${LUNG_ANALYSIS_BINARY}/Libraries/Internal/laBatchProcessing)
ENDIF(USE_CMD_LINE)
IF(USE_DEVELOMPENT)
add_subdirectory(Development)
ENDIF(USE_DEVELOMPENT)
IF(USE_QTBASICUTILS)
FIND_PACKAGE( QtBasicUtils REQUIRED )
include(${QTBASICUTILS_USE_FILE})
ENDIF (USE_QTBASICUTILS)
IF(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
SET (LIBRARY_OUTPUT_PATH ${LUNG_ANALYSIS_BINARY}/bin CACHE INTERNAL
"Single output directory for building all libraries.")
SET (EXECUTABLE_OUTPUT_PATH ${LUNG_ANALYSIS_BINARY}/bin CACHE INTERNAL
"Single output directory for building all executables.")
FIND_PACKAGE( Qt4 REQUIRED )
set(QT_USE_QTNETWORK true)
INCLUDE( ${QT_USE_FILE} )
FIND_PACKAGE( ITK REQUIRED )
INCLUDE( ${ITK_USE_FILE} )
FIND_PACKAGE( VTK REQUIRED )
INCLUDE( ${VTK_USE_FILE} )
FIND_PACKAGE( Boost REQUIRED )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} )
INCLUDE_DIRECTORIES( ${QT_INCLUDE_DIR} . Include)
#########################################################################################
SET( UPMC_LA_SRCS
./src/main.cxx
./src/mainwindow.cxx
./src/textwidget.cxx
./src/upmcLungApp.cxx
./src/AppSettingsDlg.cxx
./src/laFileMenu.cxx
)
SET( UPMC_LA_MOC_HDR
./Include/mainwindow.h
./Include/textwidget.h
./Include/upmcLungApp.h
./Include/AppSettingsDlg.h
./Include/laFileMenu.h
)
SET( UPMC_LA_HDRS
./Include/ClickedPointEvent.h
./Include/VolumeDataExport.h
./Include/LungAnalysisConstants.h
./Include/sliceOrientation.h
)
#########################################################################################
if (MSVC)
if (USE_MSVC_PCH)
set_source_files_properties(LungAnalysisPCH.cxx
PROPERTIES
COMPILE_FLAGS "/YcLungAnalysisPCH.h"
)
foreach( src_file ${UPMC_LA_SRCS} )
set_source_files_properties(
${src_file}
PROPERTIES
COMPILE_FLAGS "/YuLungAnalysisPCH.h"
)
endforeach( src_file ${UPMC_LA_SRCS} )
list(APPEND UPMC_LA_SRCS LungAnalysisPCH.cxx)
list(APPEND UPMC_LA_HDRS LungAnalysisPCH.h)
endif(USE_MSVC_PCH)
endif (MSVC)
# some .ui files
SET( UPMC_LA_UIS
./rc/AppSettings.ui
)
# and finally an resource file
SET( UPMC_LA_RCS
./rc/LungAnalysis.qrc
)
# this command will generate rules that will run rcc on all files from
UPMC_LA_RCS
# in result UPMC_LA_RC_SRCS variable will contain paths to files produced by rcc
QT4_ADD_RESOURCES( UPMC_LA_RC_SRCS ${UPMC_LA_RCS} )
# and finally this will run moc:
QT4_WRAP_CPP( UPMC_LA_MOC_SRCS ${UPMC_LA_MOC_HDR} )
# this will run uic on .ui files:
QT4_WRAP_UI( UPMC_LA_UI_HDRS ${UPMC_LA_UIS} )
#########################################################################################
LINK_LIBRARIES ( LungAnalysis ${UPMC_EXTERNAL_LIBS} ${QT_LIBRARIES}
ITKCommon ITKBasicFilters
ITKIO QVTK vtkCommon vtkRendering vtkVolumeRendering
)
ADD_EXECUTABLE( LungAnalysis ${UPMC_LA_SRCS} ${UPMC_LA_MOC_SRCS}
${UPMC_LA_HDRS}
${UPMC_LA_MOC_HDR} ${UPMC_LA_RC_SRCS} ${UPMC_LA_UI_HDRS}
)
# The ParaView library dependencies.
SET(LUNG_ANALYSIS_LIBRARY_DEPENDS_FILE
"${LUNG_ANALYSIS_BINARY}/LungAnalysisLibraryDepends.cmake")
EXPORT_LIBRARY_DEPENDENCIES(${LUNG_ANALYSIS_LIBRARY_DEPENDS_FILE})
#########################################################################################
install(TARGETS LungAnalysis
RUNTIME
DESTINATION bin
COMPONENT Applications
)
#########################################################################################
IF(PACKAGE_FOR_INSTALL)
SET(CPACK_PACKAGE_VERSION_MAJOR ${LungAnalysis_VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${LungAnalysis_VERSION_MINOR})
IF(UNIX AND NOT APPLE)
INSTALL(TARGETS HyvesDesktop
DESTINATION bin
)
FOREACH(LIB QtCore QtXml QtTest QtGui QtNetwork QtScript)
INSTALL(FILES
"${QT_LIBRARY_DIR}/lib${LIB}.so.${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}"
RENAME "lib${LIB}.so.${QT_VERSION_MAJOR}"
DESTINATION bin
)
ENDFOREACH(LIB)
ENDIF(UNIX AND NOT APPLE)
IF(WIN32)
SET(CPACK_NSIS_COMPRESSOR "/SOLID lzma")
SET(CPACK_PACKAGE_EXECUTABLES "LungAnalysis" "Lung Analysis")
INSTALL(FILES
"${QT_LIBRARY_DIR}/QtCore${QT_VERSION_MAJOR}.dll"
"${QT_LIBRARY_DIR}/QtXml${QT_VERSION_MAJOR}.dll"
"${QT_LIBRARY_DIR}/QtTest${QT_VERSION_MAJOR}.dll"
"${QT_LIBRARY_DIR}/QtGui${QT_VERSION_MAJOR}.dll"
"${QT_LIBRARY_DIR}/QtNetwork${QT_VERSION_MAJOR}.dll"
"${QT_LIBRARY_DIR}/QtScript${QT_VERSION_MAJOR}.dll"
DESTINATION bin
COMPONENT Applications
)
ENDIF(WIN32)
set(CPACK_COMPONENTS_ALL Applications)
INCLUDE(CPack)
ENDIF(PACKAGE_FOR_INSTALL)
################################################################################################
The LibNameUSE.cmake does the append.
LungAnalysis/Libraries/Internal/laGUI/laGUIUse.cmake:
IF(USE_laGUI_TREE)
set(laGUI_INCLUDE_DIR ${laGUI_TREE_INCLUDE_DIR})
set(laGUI_LIB_DIR ${laGUI_TREE_LIB_DIR})
set(laGUI_LIBRARY ${laGUI_TREE_LIBRARY})
ELSE(USE_laGUI_TREE)
set(laGUI_INCLUDE_DIR ${laGUI_TREE_INCLUDE_DIR})
set(laGUI_LIB_DIR ${laGUI_TREE_LIB_DIR})
set(laGUI_LIBRARY ${laGUI_TREE_LIBRARY})
ENDIF(USE_laGUI_TREE)
INCLUDE_DIRECTORIES( ${laGUI_INCLUDE_DIR} )
LINK_DIRECTORIES( ${laGUI_LIB_DIR} )
ADD_DEFINITIONS(-DUSE_laGUI)
set (UPMC_EXTERNAL_LIBS ${UPMC_EXTERNAL_LIBS} ${laGUI_LIBRARY})
John
More information about the CMake
mailing list