3

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

  • SRC

    1. subProject_1
      .cpp (all source files) and CMakeLists.txt 1 for this folder (creating a static library)
    2. subproject_2
      .cpp (all source files) and CMakeLists.txt 2 for this folder (creating a static library)
    3. subproject_3
      .cpp (all source files) and CMakeLists.txt 3 for this folder (creating the executable)
  • Include

    1. subProject_1
      .h (all the header files)
    2. subProject_2
      .h (all the header files)
    3. subProject_3
      .h (all the header files)
  • build/linux

    1. CMakeLists.txt (Main CMakelist file)

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.

Pintu
  • 369
  • 2
  • 6
  • 18

1 Answers1

8

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.

Fraser
  • 74,704
  • 20
  • 238
  • 215
  • Hi Fraser. Thanks for your response. W.r.t target_link_libraries I did something like this: target_link_libraries(subProject3 subProject1 subProject2) But, I am still getting an error libsubProject1.a: file not recognized: File truncated. – Pintu Nov 01 '12 at 19:51
  • In Addition, when I just tried with target_link_libraries(subProject3 subProject_1 subProject_2) I am getting the below error: /usr/bin/ld: cannot find -lsubProject_1 – Pintu Nov 01 '12 at 19:55
  • @Pintu Are you sure you're using the right names throughout? Your example code can't be an exact copy of what you're running since there are a few errors in it. Even your comment above indicates inconsistent naming. It looks like your folders are maybe called e.g. subProject_1 (with underscore) and the targets defined inside maybe `subProject1` (without underscore). If that's the case, you need to specify `subProject1 subProject2` in the `target_link_libraries` command, not `subProject_1 subProject_2`. – Fraser Nov 01 '12 at 22:42
  • Yes, I am using the correct names. I have edited the question description to add more code details. I have provided you the one that I am currently using. Please let me knwo why I am getting the error. – Pintu Nov 07 '12 at 16:51
  • I figured out why I am getting the undefined reference. I forgot to include few static libraries and that caused the problem. Thanks a lot fraser. Totally appreciate your help. – Pintu Nov 07 '12 at 19:05