Pintu
Pintu

Reputation: 369

CMake Undefined reference when creating executables

I am new to CMake and I am trying to get my project compiling. The project creates a few static libraries and a few executables.

Below is the example of the file structure that I have.

PROJECT

Main CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
SET(CMAKE_CXX_COMPILER "g++")
Project(ort)
SET (CMAKE_CXX_FLAGS " -g -Wall -pThread")

#set the source and header directories location
set(ORT_HEADER_DIRECTORY "../../include") #include folder structure explained above
set(ORT_SOURCE_DIRECTORY "../../src")
set(ORT_BINARY_DIRECTORY "../../lib")  # lib folder to contain all the libraries

set (CMAKE_CURRENT_BINARY_DIR ".")

#Include the library packages
include_directories("/usr/include/wx-2.8")
include_directories("/usr/local/cuda/include") and so on


#set the names of all the projects (for creating the libraries)
SET(PROJECT_NAMES "log" "data" "cc")

foreach(PROJECT_NAME ${PROJECT_NAMES})
     # Create the cmake related files in the out folder so that the libraries can be
     # copied to the lib folder
     add_subdirectory( "{ORT_SOURCE_DIRECTORY}/${PROJECT_NAME}" "${CMAKE_CURRENT_BINARY_DIR}/out/${PROJECT_NAME}"

endforeach(PROJECT_NAME ${PROJECT_NAMES})

#set the names of all the projects (for creating the libraries)
SET(EXECUATALE_PROJECTS "metadata" )

foreach(EXECUATALE_PROJECT ${EXECUATALE_PROJECTS})
     # Create the cmake related files in the out folder so that the libraries can be
     # copied to the lib folder
     add_subdirectory( "{ORT_SOURCE_DIRECTORY}/${EXECUATALE_PROJECT}" "${CMAKE_CURRENT_BINARY_DIR}/out/${EXECUATALE_PROJECT}"

endforeach(EXECUATALE_PROJECT ${EXECUATALE_PROJECTS})

CMakeLists.txt file for log directory (the same logic I have used for cc and data projects)

include_directories(${ORT_HEADER_DIRECTORY})
SET(LOG_SOURCE a.cpp b.cpp c.cpp)
ADD_LIBRARY(log_d ${LOG_SOURCE})
target_link)libraries(log_d cc_d data_d)

metadata CMakeLists.txt file (creating the executable project)

FIND_PACKAGE(wxWidgets)
IF(wxWidgets_FOUND)
        INCLUDE(${wxWidgets_USE_FILE})
ENDIF(wxWidgets_FOUND)

Include_Directories(${wxWidgets_INCLUDE_DIRS})
include_directories(${ORT_HEADER_DIRECTORY})
include_directories("/usr/ort/lib/unixODBC/include")

SET(META_SOURCE meta.cpp data.cpp)

ADD_EXECUTABLE(meta_d ${META_SOURCE })
TARGET_LINK_LIBRARIES(meta_d log_d data_d)

When I just make the project, without the creation of the executables, static files are being generated. But, when I make the whole project (i.e. with the inclusion of the subProject_3 directory) I get undefined reference to a::String which is a function in a.cpp.

Note: All the 3 projects are dependent on each other. For example, in a.cpp, I have #include "b.h" and in b.cpp I have #include "a2.h".

So, I have few questions:

a) How do I resolve the undefined reference issue? Once I have generated the libraries for project 1 and 2, how do I link these to the executable?

b) Should I provide or add any dependencies when I am creating the static libraries? Is this the right way of creating the static libraries (as the projects are inter dependent)? i.e. target_link_libraries(project1 project2 ...) in project 1 and target_link_libraries(project2 project1 ...) in project 2.

c) Every project needs to be compiled with its own compilation setting. Can you please let me know how can I specify the same for every individual project?

ERROR DETAILS:

Liking CXX executable metadata_d ../log/liblog_d.a: file not recognized: File truncated collect2: ld returned 1 exit status

I also get the undefined reference error /home...../metadata/data.cpp 172: undefined reference to xmlSerahNs and so on. collect2: ld returned 1 exit status

Thanks for the help.

Upvotes: 3

Views: 12927

Answers (1)

Fraser
Fraser

Reputation: 78330

How do I resolve the undefined reference issue ? Since, I have generating the libraries for project 1 and 2, how do I link these to the executable.

Just use target_link_libraries again, this time in subProject3's CMakeLists.txt:

target_link_libraries(subProject3 subProject2 subProject1)

Is this the right way of creating the static libraries (as the projects are inter dependent)

Yes. From the docs for target_link_libraries:

The library dependency graph is normally acyclic (a DAG), but in the case of mutually-dependent STATIC libraries CMake allows the graph to contain cycles (strongly connected components). When another target links to one of the libraries CMake repeats the entire connected component. For example, the code

add_library(A STATIC a.c)
add_library(B STATIC b.c)
target_link_libraries(A B)
target_link_libraries(B A)
add_executable(main main.c)
target_link_libraries(main A)

links 'main' to 'A B A B'. (While one repetition is usually sufficient, pathological object file and symbol arrangements can require more. One may handle such cases by manually repeating the component in the last target_link_libraries call. However, if two archives are really so interdependent they should probably be combined into a single archive.)


Every project needs to be compiled with there own compilation setting. Can you please let me know how can I specify the same for every individual project?

In the top-level CMakeLists.txt, before adding the subdirectories, you can set all the flags you need there. (see add_definitions and Properties on Targets for example) They will be adopted by all the subprojects unless specifically changed for a subproject.

Upvotes: 8

Related Questions