How debug dynamic library in such situation - c++

Well, I am new to CMake.
I have the following file structure
haze_removal
|---build
|---bin
| |--Test
| |--CMakeLists.txt
|---lib
| |--libtools.so
|---include
| |--tools.hpp
|---test
| |--main.cpp
| |--CMakeLists.txt
|---src
| |--tools.cpp
| |--CMakeLists.txt
|---CMakeLists.txt
The libtools.so is builded from ../src/tools.cpp. I build the whole project in ../build using the following cmake command:
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
The Test is build from ../test/main.cpp
I build this project successfully. But when I debug Test using gdb ./Test, I can't skip in the function that from libtools.so.
These are my CMakeLists.txt from different directories.
CMakeLists.txt under haze_removal/
cmake_minimum_required(VERSION 2.8)
project(haze_removal)
# find needed package
find_package(OpenCV REQUIRED)
# library directory
add_subdirectory(src)
# test
add_subdirectory(test)
CMakeLists.txt under ../src/
# generate dynamic library
# add source file, include directories
aux_source_directory(. TOOLS_SRC)
include_directories(${PROJECT_SOURCE_DIR}/include)
# generate
add_library(tools SHARED ${TOOLS_SRC})
# set output directory and lib's name
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
set_target_properties(tools PROPERTIES OUTPUT_NAME "tools")
# link library
target_link_libraries(tools ${OpenCV_LIBS})
CMakeLists.txt under ../test/
# add source file, include directories, link directories
aux_source_directory(. EXE_SRC)
include_directories(${PROJECT_SOURCE_DIR}/include)
link_directories(${PROJECT_SOURCE_DIR}/lib)
# generate
add_executable(Test ${EXE_SRC})
# set output directory
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# link libraries
target_link_libraries(Test ${OpenCV_LIBS} libtools.so)
My question is how I can debug the functions that from libtools.

Well, I find that why I can't step in the dynamic library even though I set CMAKE_BUILD_TYPE=Debug. Because before I set the build model to Debug I used to set CMAKE_BUILD_TYPE=Release. After I change the build model, I didn't delete the files in the build directory.
I don't know whether the above explanation is right or not, but I do solve my problem.
Thx!

Related

Make all files in a folder accessible to all projects (subdirectories)

I have multiple projects (subdirectories) inside my repository. All projects have only one executable file named main.cpp and they all use libraries from the common folder with #include statements. The folder structure looks like this:
root
|
├────common
| ├──── example.h
| ├──── example.cpp
| ├──── *.h # many header files
| └──── *.cpp # many source files
|
├────Project_A
| ├──── CMakeLists.txt
| └──── main.cpp
|
├────Project_B
| ├──── CMakeLists.txt
| └──── main.cpp
|
└──── CMakeLists.txt
This is my attempt at writing the root's CMakeLists.txt
cmake_minimum_required (VERSION 3.8)
project ("root")
file(GLOB_RECURSE CommonLibs ${CMAKE_SOURCE_DIR}/common/*.cpp)
link_libraries(${CommonLibs})
add_subdirectory ("Project_A")
add_subdirectory ("Project_B")
Project_A's CMakeLists.txt
cmake_minimum_required (VERSION 3.8)
add_executable (Project_A "main.cpp")
Project_B's CMakeLists.txt
cmake_minimum_required (VERSION 3.8)
add_executable (Project_B "main.cpp")
However when running any of the projects I get this error:
LNK1107 invalid or corrupt file: cannot read at 0x7AC, file example.h
I don't believe the file is corrupted because before I tried to use link_libraries() in root's CMakeLists.txt I was getting other error:
Unresolved external symbol SomeNamespace::ExampleClass::ExampleClass(bool)
Possible duplicates
Other questions such as this one don't solve my problem because they usually work with a more complex folder structure. Also there are questions that attempt to target only single project like this one, but I have multiple projects.
Can you please provide a concise solution?
Add a CMakeLists.txt to your common/ directory:
root
|
├────common
| ├──── CMakeLists.txt <-------- Add this
| ├──── example.h
....
common/CMakeLists.txt
file(GLOB_RECURSE CommonLibsFiles ${CMAKE_CURRENT_SRC_DIR}/*.cpp)
add_library(CommonLibs ${CommonLibsFiles})
...
root's CMakeLists.txt
...
### NO NEED FOR THESE
file(GLOB_RECURSE CommonLibs ${CMAKE_SOURCE_DIR}/common/*.cpp)
link_libraries(${CommonLibs})
###
add_subdirectory(common) #CommonLibs will now be visible to children directories
...
Now link the libraries as required. For example for project A:
Project_A's CMakeLists.txt
cmake_minimum_required (VERSION 3.8)
add_executable (Project_A "main.cpp")
target_link_libraries(Project_A PRIVATE CommonLibs) #link to common libs here,
All the targets/variables that are created or are visible to parent cmake file, are visible to children. The reverse is not true though. For children to expose their variables to parent, they need to explicitly specify PARENT_SCOPE
The following lines in your top-level CMake do not make much sense:
file(GLOB_RECURSE CommonLibs ${CMAKE_SOURCE_DIR}/common/*.cpp)
link_libraries(${CommonLibs})
The link_libraries() command accepts libraries or library targets, not variables (such as CommonLibs). You can use the CommonLibs variable to define a new library target, then link the library target to your executables using link_libraries():
file(GLOB_RECURSE CommonLibs ${CMAKE_SOURCE_DIR}/common/*.cpp)
# Add this line.
add_library(MyCommonLib SHARED ${CommonLibs})
link_libraries(MyCommonLib)
Please note that the use of link_libraries() in general is discouraged, even in CMake documentation itself. You should prefer linking your MyCommonLib to the specific executables that require it using target_link_libraries.
target_link_libraries(Project_A PRIVATE MyCommonLib)

CMake linking libraries into one single library

I used CMake to compile a framework into three different .lib files, and one .sln file. The project is structured as such
UeiDaqFramework
|-CMakeLists.txt
|-build
| |-Framework_static.sln
| | - other cmake files and stuff
|-UeiDaqCore
| |-CMakeLists.txt
| |-source code for this subproject
|-UeiSimuDriver
| |-CMakeLists.txt
| |-source code for this subproject
|-UeiPDNADriver
| |-CMakeLists.txt
| |-source code for this subproject
|
|-Output
|-UeiDaqCore.lib
|-UeiSimuDriver.lib
|-UeiPDNADriver.lib
My test code require a Framework_static.lib in its include file instead of a .sln file, and I do not know how to combine the three existing .lib files using cmake. I did attempt to follow what this CMake - combine multiple libraries into one answer suggested, by just building all the source files into a single library, but I'm new to CMake, and it did not work. Here is the CmakeLists.txt file at the top directory of my project.
cmake_minimum_required(VERSION 3.13.0 FATAL_ERROR)
set(CMAKE_SYSTEM_VERSION CACHE TYPE INTERNAL FORCE)
project(Framework_static_vc15)
################################################################################
# Set target arch type if empty. Visual studio solution generator provides it.
################################################################################
if(NOT CMAKE_VS_PLATFORM_NAME)
set(CMAKE_VS_PLATFORM_NAME "x64")
endif()
message("${CMAKE_VS_PLATFORM_NAME} architecture in use")
if(NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32"))
message(FATAL_ERROR "${CMAKE_VS_PLATFORM_NAME} arch is not supported!")
endif()
################################################################################
# Global configuration types
################################################################################
set(CMAKE_CONFIGURATION_TYPES
"Debug"
"Release"
CACHE STRING "" FORCE
)
################################################################################
# Global compiler options
################################################################################
if(MSVC)
# remove default flags provided with CMake for MSVC
set(CMAKE_CXX_FLAGS "")
set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_RELEASE "")
endif()
################################################################################
# Global linker options
################################################################################
if(MSVC)
# remove default flags provided with CMake for MSVC
set(CMAKE_EXE_LINKER_FLAGS "")
set(CMAKE_MODULE_LINKER_FLAGS "")
set(CMAKE_SHARED_LINKER_FLAGS "")
set(CMAKE_STATIC_LINKER_FLAGS "")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_DEBUG "${CMAKE_STATIC_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS}")
endif()
################################################################################
# Nuget packages function stub.
################################################################################
function(use_package TARGET PACKAGE VERSION)
message(WARNING "No implementation of use_package. Create yours.")
endfunction()
################################################################################
# Common utils
################################################################################
include(CMake/Utils.cmake)
################################################################################
# Additional Global Settings(add specific info there)
################################################################################
include(CMake/GlobalSettingsInclude.cmake OPTIONAL)
################################################################################
# Use solution folders feature
################################################################################
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
################################################################################
# Sub-projects
################################################################################
add_subdirectory(Source/UeiDaqCore)
add_subdirectory(Source/UeiPDNADriver)
add_subdirectory(Source/UeiSimuDriver)
These CMakeLists.txt files were generated automatically by a generator that takes a visual studio .sln file and converts it to a .txt tree. Heres the link to the converter if anyone is interested. https://cmakeconverter.readthedocs.io/en/develop/intro.html
Im not sure if I need to rewrite Just the top level .txt file, or if I need to rewrite all the CMakeLists.txt files. Any help would be appreciated.
I assume the build of the shared libs is within the subdirectories, because your CMakeLists.txt does not contain any add_library command.
To get a static library containing all sources you have to
Collect all sources
Add command to build the static library
For 1. add the following to every subdir/CMakeLists.txt
set(SOURCES # This creates a list of sources called SOURCES
myFileA.cpp # This adds an item to the list
myFileB.cpp
${SOURCES} # This adds all items of existing list SOURCES to the current list
PARENT_SCOPE # This makes SOURCES visible in the parent CMakeLists.txt
)
For 2. add the static library
add_library(myTestLib_static.c STATIC ${SOURCES})

CMake build problems under Visual Studio

To begin with, I'm new to CMake.
Folder structure
root_project
|─── CMakeLists.txt
|─── build
|─── Project 1
| |─── build
| | |─── Debug
| | └─── Release
| |─── CMakeLists.txt
| |─── source
| | └─── include
| |─── resource
| └─── header
└─── Project 2
|─── build
| |─── Debug
| └─── Release
|─── source
| |─── CMakeLists.txt
| └─── include
|─── resource
└─── header
CMake files
The CMakeLists.txt for the root_project:
# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.8.2 FATAL_ERROR)
# Project's name
project("RootProject X")
IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt.")
ENDIF()
OPTION(BUILD_TESTS "Decides whether the unit tests will be built." ON)
# C/C++ languages required.
enable_language(C)
enable_language(CXX)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Only allow 64bit architecture
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
# 64bit
message(STATUS "Compiling for x86-64 platform. Proceeding...")
ELSEIF(CMAKE_SIZEOF_VOID_P EQUAL 4)
# 32bit
message(FATAL_ERROR "Compiling for x86 platform. This is not supported. Aborting...")
ELSE()
# unidentified architecture
message(FATAL_ERROR "Running on unidentified architecture. This is not supported. Aborting...")
ENDIF()
# Abort when OpenGL is not found
FIND_PACKAGE(OpenGL 4.5 REQUIRED)
IF(NOT VULKAN_FOUND)
message(WARNING "Could not find Vulkan library.")
ENDIF()
# Add the modules
add_subdirectory("Project 1")
add_subdirectory("Project 2")
The CMakeLists for Project 1:
# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.8.2 FATAL_ERROR)
project("Project 1")
# Set the version number of the project here
set(VERSION_MAJOR "0")
set(VERSION_MINOR "1")
set(VERSION_PATCH "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
find_package(OpenGL 4.5 REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sources/third-party-include/)
link_libraries(${OPENGL_gl_LIBRARY})
add_definitions(${OpenGL_DEFINITIONS})
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sources/include/)
# ToDo: Testing
set(HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/sources/include/Engine.h
)
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/source/Engine.cpp
)
source_group(headers FILES ${HEADERS})
source_group(sources FILES ${SOURCES})
if(WIN32)
# currently add_executable for testing purpose
add_executable("Project 1" WIN32
#${HEADERS}
${SOURCES}
)
ELSEIF(UNIX AND NOT APPLE)
add_library("Project 1"
${HEADERS}
${SOURCES}
)
ELSE()
# The system is not supported
message(FATAL_ERROR "System not supported.")
ENDIF()
target_link_libraries(DarkEngine ${OPENGL_gl_LIBRARY})
The CMakeLists for Project 2:
# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.8.2 FATAL_ERROR)
project("Project 2")
# Set the version number of the project here
set(VERSION_MAJOR "0")
set(VERSION_MINOR "1")
set(VERSION_PATCH "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(HEADERS
)
set(SOURCES
)
source_group(headers FILES ${HEADERS})
source_group(sources FILES ${SOURCES})
add_executable("Project 2" WIN32
${HEADERS}
${SOURCES}
)
target_link_libraries("Project 2" "Project 1")
Question/Problem
Note: I am trying to achieve an out-of-source build where Project 1 is an Engine which is used from Project 2.
Commands I run under build of root_project: cmake .. -G "Visual Studio 15 2017 Win64"
Project 2 doesn't link against Project 1
Project 2 doesn't show up in VS 2017
My own header files under /include for Project 1 will be shown in External Dependencies in VS 2017 instead of source
Turning my comment into an answer
You just need to specify sources for your Project 2 target.
I've given you example a try and CMake gives you an configuration error (which is probably why it won't show up/doesn't rewrite the solution/project files, if you add the second project):
CMake Error at CMakeLists.txt:23 (add_executable):
add_executable called with incorrect number of arguments, no sources provided
And yes, if you add e.g. a not yet existing src/main.cpp to SOURCES you will get:
CMake Error at CMakeLists.txt:23 (add_executable):
Cannot find source file:
src/main.cpp
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx
So the workflow in CMake is always to first create the source file and then add to your CMakeLists.txt. With an IDE like VS you could just add a new item to your project (like you would do for non-generated projects) and then add it to your CMakeLists.txt file.
For some of my projects I've created a check_and_create_source() function called inside overwritten add_executable() calls, but using it for some years I can now say there is no real benefit in that approach. You still need to run a ZERO_CHECK build to get the empty files created/before you can start (and you get confused when you mistyped an inclusion for an existing source file).
And I personally don't like the globbing alternative (see Why is cmake file GLOB evil? and CMake/Ninja attempting to compile deleted `.cpp` file)

CMake configure project

I've got a question on cmake project configuration.
The following is my project structure.
trunk
|
|---- mylib
| |
| ---- mylib.h
| ---- mylib.c
| ---- *MYLIB_CMakeList.txt*
|
|---- alib
| |
| ---- alib.h
| ---- alibName.lib
| ---- *ALIB_CMakeList.txt*
|
|
|---- main
| |
| ---- main.cpp
| ---- *MAIN_CMakeList.txt*
|
---- *TOP_CMakeList.txt*
mylib subfolder contains the source code (c) to create my own static library. This code depends on alib.
The main subfolder contains the example code (C++) which uses mylib.
Here is how I've written my CMakeList files:
**TOP_CMakeList.txt**
cmake_minimum_required(VERSION 3.4)
add_subdirectory(mylib)
add_subdirectory(alib)
add_subdirectory(main)
------------------------------------------------------------------------------------------------------------
**MYLIB_CMakeList.txt**
cmake_minimum_required(VERSION 3.4)
project(MyLib C)
if (WIN32)
set(CMAKE_SHARED_LIBRARY_PREFIX "")
endif ()
include_directories(${alib_INCLUDE_DIRS})
add_library(${PROJECT_NAME} STATIC mylib.c)
target_link_libraries(${PROJECT_NAME} alib)
set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR} CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
------------------------------------------------------------------------------------------------------------
**ALIB_CMakeList.txt**
cmake_minimum_required(VERSION 3.4)
project(ALib)
set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR} CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
------------------------------------------------------------------------------------------------------------
**MAIN_CMakeList**
make_minimum_required(VERSION 3.4)
project(Executable CPP)
file(GLOB CPP_FILES *.cpp)
add_definitions(${MyLib_DEFINITIONS})
include_directories(${MyLib_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} ${CPP_FILES})
target_link_libraries(${PROJECT_NAME} MyLib)
With such configuration it doesn't recognize the alib dependency of mylib. In particular (I'm developing under Windows) I get this error:
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/../../../../x86_64-pc-cygwin/bin/ld:
cannot find -lalibName.lib
I can't figure out how to correctly do it. Any suggestions?
Seems that the alib project does not specify any kind of library targets the same way as mylib does:
Try adding this to alibs' CMake file
add_library(${PROJECT_NAME} STATIC <<< alib SOURCES HERE >>>)
Static libraries can't have dependencies(well, they can but they don't drag them with themselves) so there is no point in providing alib in target_link_libraries(...) for another static library. You should provide alib to the add_execuable command directly.
Alternatively, you can build a big static library from both mylib and alib but it will be less elegant and platfrom dependant. For gcc you should look at ar tool.
Remove the add_subdirectory(alib) command, then remove CMake file from the alib subfolder — you don't need it. Then in the cmake file where you have your add_executable command put the following(after the line);
link_directories(../alib)
target_link_libraries(${PROJECT_NAME} alibName.lib)

CMakeLists.txt add subfolder which represents namespace (just for organization)

Consider the following setup:
-project
--src
---CMakeLists.txt
---main.cpp
---Application.cpp
---Application.hpp
---subfolder
----SomeClass.cpp
----SomeClass.hpp
--bin
And consider this CMakeLists.txt
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
# Include directories
INCLUDE_DIRECTORIES("subfolder")
# Executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
Now, as long as I had all my classes in the same folder (src) everything worked perfectly fine.
But now I want to restructure my application a bit. I want to build a folder-hierarchy that represents the namespaces.
Of course in my includes I would then use
#include "subfolder/SomeClass.hpp"
but it doesn't work that way. I had a look at the manpage but there are so many options in CMake and it's often talking about standalone libraries that have their own CMakeLists.txt... I'm not that far yet. I just want to add a subfolder, that's all.
Until now I've used QMake for my C++ projects, but I wanted to dive into CMake now.
Are there any useful tutorials out there? I've found a few, but they they don't cover the basics.
The recommened way is to use a CMakeLists.txt for every subdirectory in existence. If you want to have subdirectories and organize them without having to create multiple CMakeLists.txt files, you can create one in the main directory with those contents:
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
include_directories(src)
file(GLOB_RECURSE SRC_LIST *.c* *.h*)
# Executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
Using aux_source_directory is used mainly for template related things. Also it's common practice to use a toplevel CMakeLists.txt, which includes the further files, has common project settings etc.:
<project>
|
+- CMakeLists.txt
|
+- src/
|
+-- CMakeLists.txt
|
+-- main.cpp
|
…
So this would look like:
CMakeLists.txt (Project dir):
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
include_directories(src) # Add 'src' to include paths
subdirs(src) # Includes the 'src' directory and its cmake file
# ...
Now you can use the include path as expected.
CMakeLists.txt (src dir):
# Better add src files this way:
add_executable(${PROJECT_NAME} main.cpp Application.cpp)
subdirs(subfolder) # TODO: handle subfolder
The subfolder can be added through an additional library target, that is linked to your executable. Usually there's another CMakeLists.txt file in there.
Also make sure your cmake cache is updated; best you recreate it.