Reputation: 369
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
Include
build/linux
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
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