The project structure of my static library is exactly the same as defined in this question and my CMakeList.txt is exactly the same:
cmake_minimum_required (VERSION 2.8)
project (project_name)
add_subdirectory (src)
add_subdirectory (test)
I want to build the test folder after my static library. I have also added add_test() but only problem is my test directory doesn't contain unit tests, but actual test application like following code:
#include <iostream>
main() {
/*
this code uses static library functions in it. There is not Unit Test defined in it.
*/
}
add_test() didn't helped me, and I am still getting a cannot find -ldal error. dal is my static library name, which I have added as target_link_library to my test application.
libdal/src/CMakeList.txt
cmake_minimum_required(VERSION 3.12)
project(dal)
# Flags Variables
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
# Include Directeries
include_directories(${CPP_KAFKA_INC})
include_directories(${CPP_MYSQL_INC})
include_directories(${CPP_ALTIBASE_INC})
include_directories(${AFN_STATE_INC})
include_directories(${AFN_DAL_INC})
include_directories(${AFN_COMMONS_INC})
include_directories(${AFN_CONFIG_INC})
include_directories(${SQL_ODBC_INC})
# Executable Target(s)
file(GLOB SOURCES *.cpp)
add_library(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME}
${AFN_LIB}
"-lafinit_state"
"-luuid"
"-lz"
"-lpthread"
${PQXX_LIB}
${PQ_LIB}
"-lmysqlcppconn"
${libmscpp}
${kafkacpplib}
${rdkafkalib}
${rdkafkacpplib}
afiniti_config $<$<CONFIG:DEBUG>:-lgcov>
)
# Installation
install(CODE "MESSAGE(\"Installing ${PROJECT_NAME} \")")
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
libdal/test/CMakeList.txt
cmake_minimum_required(VERSION 3.12)
project(testdal)
# Flags Variables
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17" )
option(DAL_PUSH_TESTER "enable DAL push tester" ON)
# Include Directeries
include_directories(${CPP_KAFKA_INC})
include_directories(${AFN_DAL_INC})
include_directories(${CPP_MYSQL_INC})
include_directories(${AFN_STATE_INC})
include_directories(${AFN_CONFIG_INC})
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME}
${AFN_LIB}
"-lmysqlcppconn"
"-luuid"
"-lz"
${libmscpp}
"-ldal"
${PQXX_LIB}
${PQ_LIB}
${kafkacpplib}
${rdkafkalib}
${rdkafkacpplib}
"-lafinit_state"
"-luuid"
"-lpthread"
afiniti_config $<$<CONFIG:DEBUG>:-lgcov>
${AFN_LICENSE_LIB} "-laf_license_manager"
)
# Installation
install(CODE "MESSAGE(\"Installing ${PROJECT_NAME} \")")
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin/tests
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
if (DAL_PUSH_TESTER)
add_executable(dal_push_tester dal_push_tester.cpp)
target_link_libraries(dal_push_tester
${AFN_LIB}
"-lmysqlcppconn"
"-luuid"
"-lz"
${libmscpp}
"-ldal"
${PQXX_LIB}
${PQ_LIB}
${kafkacpplib}
${rdkafkalib}
${rdkafkacpplib}
"-lafinit_state"
"-luuid"
"-lpthread"
afiniti_config $<$<CONFIG:DEBUG>:-lgcov>
${AFN_LICENSE_LIB} "-laf_license_manager"
)
# Installation
install(CODE "MESSAGE(\"Installing dal_push_tester \")")
install(TARGETS dal_push_tester
RUNTIME DESTINATION bin/tests
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
endif ()
The issue has been raised a couple times on the site, but there are some other issues with your CMake file that warrant explanation.
The problem is that the linker doesn't know where to find the dal library, because you've only provided "-ldal", without a full path to the library or anything. You can fix this by simply using the CMake library target name (dal) in target_link_libraries() instead, because it was defined earlier in the same CMake invocation.
target_link_libraries(${PROJECT_NAME}
${AFN_LIB}
"-lmysqlcppconn"
"-luuid"
"-lz"
${libmscpp}
dal # <------ Note the change on this line.
${PQXX_LIB}
${PQ_LIB}
${kafkacpplib}
${rdkafkalib}
${rdkafkacpplib}
"-lafinit_state"
"-luuid"
"-lpthread"
afiniti_config $<$<CONFIG:DEBUG>:-lgcov>
${AFN_LICENSE_LIB} "-laf_license_manager"
)
Furthermore, target_link_libraries doesn't need the explicit -l link flag added; it adds this automatically. Also, you should always specify the scoping argument (e.g. PRIVATE, PUBLIC, etc.) for this and other target_* calls. Also, also, you have linked uuid twice, so you can probably remove one of these:
target_link_libraries(${PROJECT_NAME} PRIVATE
${AFN_LIB}
mysqlcppconn
uuid
z
${libmscpp}
dal
${PQXX_LIB}
${PQ_LIB}
${kafkacpplib}
${rdkafkalib}
${rdkafkacpplib}
afinit_state
pthread
afiniti_config $<$<CONFIG:DEBUG>:gcov>
${AFN_LICENSE_LIB} af_license_manager
)
In addition, the manual modification of CMAKE_CXX_FLAGS in this line:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
is highly discouraged. For setting the C++ standard, you should use:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
or one of the other more modern approaches discussed in this question.
I encourage you to browse through some of the content regarding modern CMake practices.
Related
Here is my directory tree
I implemented accident component which have to be a standalone library. Here is CMakeLists.txt for it
set (ACCIDENT accident)
file (GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
file (GLOB HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
add_library (${ACCIDENT} STATIC ${HEADER_FILES} ${SOURCE_FILES})
target_include_directories (${ACCIDENT} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
add_subdirectory (test)
and that works fine. Now I am trying to use that library in note part which should be linked with accident. Especially the accident.hpp file should be visible in my IDE without doing things like this
#include "../../accident/include/accident.hpp"
and the code from accident.cpp should also be accessible. My attempts was similar to this one
set (MUSIC_NOTE music_note)
file (GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
file (GLOB HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
add_library (${MUSIC_NOTE} STATIC ${HEADER_FILES} ${SOURCE_FILES})
target_include_directories (${MUSIC_NOTE}
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../accident/include"
)
target_link_libraries (${MUSIC_NOTE} accident)
add_subdirectory (test)
unfortunately, it does not work - accident.hpp header is not found. Do you know where I am doing a mistake?
EDIT
In response to #Martin's question, here is my top level CMakeLists.txt
cmake_minimum_required (VERSION 3.5)
set (CMAKE_BUILD_TYPE Debug)
set (PROJECT_NAME scales)
project (${PROJECT_NAME} LANGUAGES CXX)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set (CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}" "${CMAKE_MODULE_PATH}")
set (CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}" "${CMAKE_PREFIX_PATH}")
add_subdirectory (src)
add_subdirectory (external)
option (BUILD_TESTS "Build tests" ON)
enable_testing ()
if (BUILD_TESTS)
add_subdirectory (test)
endif ()
# Add google test
include (FetchContent)
FetchContent_Declare (
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
The note directory is in src, and src includes CMakeLists.txt with only one line
add_subdirectory (note)
In this note directory we have the stuff I pasted above Top level CMakeLists.txt in note directory contains
add_subdirectory (accident)
add_subdirectory (note)
EDIT 2
Problem resolved - see Ave Milia comment below. Thanks!
As we figured out in the comment section, the test executable was forgotten to be linked to the relevant static library.
I try to add the library spdlog to a dll (.so file). The spdlog is just a git submodule from the spdlog library. Looking at the documentation, it's recommended to use it as a static library. So i think i have a problem trying to compile it inside a .so file.
To get a clear view of what i'm doing, here is a pic of my system:
My root CMakeLists.txt is :
cmake_minimum_required(VERSION 3.23)
# set the project name
project(Test VERSION "0.1.0" LANGUAGES CXX)
configure_file(config/config.h.in config.h)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3")
# Set location for .so files
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}")
# Set location for executables
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
add_subdirectory(Engine)
list(APPEND EXTRA_LIBS Engine)
add_subdirectory(Game)
target_link_libraries(Test PUBLIC ${EXTRA_LIBS})
target_include_directories(Test PUBLIC
"${PROJECT_BINARY_DIR}"
)
And inside the Engine folder:
message(STATUS "BUILD Engine shared library File")
add_subdirectory(spdlog)
add_library(Engine SHARED Log.cpp Log.h)
target_include_directories(Engine
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(Engine
spdlog
)
target_include_directories(Engine
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/spdlog/include
)
Inside the Game (not relevant at my opinion)
message(STATUS "BUILD .exe File")
# add the executable
add_executable(Test main.cpp)
But currently, if i try to use the spdlog inside my Log file, i have this cryptic error:
[build] /usr/bin/ld: spdlog/libspdlogd.a(spdlog.cpp.o): relocation R_X86_64_TPOFF32 against `_ZGVZN6spdlog7details2os9thread_idEvE3tid' can not be used when making a shared object; recompile with -fPIC
Does anyone have an idea?
Thanks to fabian in the comments, I add
set(CMAKE_POSITION_INDEPENDENT_CODE 1)
Just before adding the spdlog subdirectory and it just works fine.
I am new to C++ and have just started to use Cmake for linking the libraries to my project. I need to use a library:
https://github.com/Gnimuc/FastPD
Fortunately, I managed to build the library using Cmake (in my build there is no *.lib file at all), but I don't know how to link it to my project. I mean that I don't know how to add it to my cmakelists.txt :
(PS. I'm also using two other libraries ITK and VTK; but I can't link the above mentioned library to my project or main.cpp.)
################################################
cmake_minimum_required(VERSION 2.8)
project(My_project)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
if (ITKVtkGlue_LOADED)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
else()
find_package(ItkVtkGlue REQUIRED)
include(${ItkVtkGlue_USE_FILE})
set(Glue ItkVtkGlue)
endif()
add_executable(My_project MACOSX_BUNDLE main.cpp)
target_link_libraries(My_project
${Glue} ${VTK_LIBRARIES} ${ITK_LIBRARIES})
################################################
Thanks in advance for your helps,
Assuming you installed the library and its header files, you can then search for the header files using find_path, and add the found path to the include directories. Then you can search for the library by using find_library, and add the library with the target_link_libraries command.
I tried both shared and static types for creation of the library. In the case of shared, no *.lib file was created, and in the case of static, my project couldn't link to the library. Therefore, in my project's CmakeLists.txt, I decided to add all the *.cpp and headers as libraries and then link them together (as I didn't know the dependency among them!!!), and finally, I linked them to my project. Perhaps it does not make sense but it works; hope it helps you:
CmakeLists.txt
##############################################
cmake_minimum_required(VERSION 2.6)
set(PROJ_NAME PROJECT46)
PROJECT(${PROJ_NAME})
# Prevent compilation in-source
if( ${CMAKE_BINARY_DIR} STREQUAL ${PROJECT_SOURCE_DIR} )
Message( " " )
Message( FATAL_ERROR "Source and build directories are the same.
Create an empty build directory,
change into it and re-invoke cmake")
endif()
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support.
Please use a different C++ compiler.")
endif()
##############################################
## External libraries
##############################################
list( APPEND CMAKE_MODULE_PATH
${PROJECT_SOURCE_DIR}/cmake
)
# Blitz
find_package( Blitz++ REQUIRED )
list( APPEND PROJ_INCLUDE_DIRS
${Blitz++_INCLUDE_DIR}
)
list( APPEND
PROJ_LIB
${Blitz++_LIBRARIES}
)
# ITK and VTK
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
if (ITKVtkGlue_LOADED)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
else()
find_package(ItkVtkGlue REQUIRED)
include(${ItkVtkGlue_USE_FILE})
set(Glue ItkVtkGlue)
endif()
##############################################
# FASTPD
add_library(FASTPD Fast_PD.cpp Fast_PD.h common.h block.h)
add_library(GRAPH graph.h graph.cpp)
add_library(linked LinkedBlockList.h LinkedBlockList.cpp)
add_library(MAXFLOW maxflow.cpp)
include_directories(${PROJ_INCLUDE_DIRS})
add_executable(${PROJ_NAME} main.cpp)
target_link_libraries(linked MAXFLOW)
target_link_libraries(GRAPH linked)
target_link_libraries(FASTPD GRAPH)
target_link_libraries(${PROJ_NAME} FASTPD)
target_link_libraries(${PROJ_NAME}
${PROJ_LIB} ${Glue} ${VTK_LIBRARIES} ${ITK_LIBRARIES}
)
for a project I need to create an executable that includes all the libraries that I used (opencv, cgal) in order to execute it on a computer that has not those libraries. Currently, this is my CMakeLists.txt (I use linux).
cmake_minimum_required(VERSION 2.8)
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -O2")
project( labeling )
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
add_library(OpenCV STATIC IMPORTED)
add_library(CGAL STATIC IMPORTED COMPONENTS Core)
add_library(GMP STATIC IMPORTED)
find_package(OpenCV REQUIRED)
find_package(CGAL QUIET COMPONENTS Core )
find_library(GMP_LIBRARY gmp /usr/lib)
include(src)
include( ${CGAL_USE_FILE} )
include( CGAL_CreateSingleSourceCGALProgram )
set(EXECUTABLE_OUTPUT_PATH ../bin)
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
include_directories( src )
include_directories( ${OpenCV_INCLUDE_DIRS} )
file(GLOB_RECURSE nei_SRC "src/*.cpp")
add_executable( nei_segmentation ${nei_SRC})
target_link_libraries( nei_segmentation ${OpenCV_LIBS} ${GMP_LIBRARY})
In such a way only GMP and some other c++ libraries are included in my executable. My question is: How can I create a makefile in order to automatically including all the libraries in a static manner and creating only a "big" executable that contains all the libraries? Can you help me?
As global CMake settings, add these lines before add_executable, valid for gcc/clang:
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static")
On Modern CMake (3.x+ - target_link_libraries doc), you can apply the flag to specific targets, in this way:
target_link_libraries(your_target_name -static)
If you're using MSVC, you have to set the compiler and linker flags:
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
target_compile_options(your_target_name [PUBLIC|PRIVATE] /MT)
target_link_options(your_target_name [PUBLIC|PRIVATE] /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT)
or alternatively also:
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
and if you are using MFC, you need to specify the flag to 1 see here:
set(CMAKE_MFC_FLAG 1)
Add these lines after add_executable(MyExec "main.c") (for example) :
target_link_libraries(MyExec PUBLIC "-static")
or before: link_libraries("-static")
My program uses giblib and Imlib2 library and it is built with cmake.
It works perfectly in my computer but not in other's.
I guess the reason is I installed every library what my program needs but other's doesn't.
My goal is making standalone program. (don't need to install any other library addtionally)
What should I add in cmake file?
projectDef.cmake source code
file (GLOB PLATFORM RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
X11/[^.]*.cpp
X11/[^.]*.h
X11/[^.]*.cmake
)
SOURCE_GROUP(X11 FILES ${PLATFORM})
add_definitions(
)
set (SOURCES
${SOURCES}
${PLATFORM}
)
add_x11_plugin(${PROJECT_NAME} SOURCES)
target_link_libraries(${PROJECT_NAME}
${PLUGIN_INTERNAL_DEPS}
)
include_directories(/usr/include/giblib)
include_directories(/usr/include/X11)
target_link_libraries(MyProject X11)
target_link_libraries(MyProject Imlib2)
target_link_libraries(MyProject giblib)
CMakeList.txt source code
cmake_minimum_required (VERSION 2.6)
set (CMAKE_BACKWARDS_COMPATIBILITY 2.6)
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static")
Project(${PLUGIN_NAME})
file (GLOB GENERAL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
[^.]*.cpp
[^.]*.h
[^.]*.cmake
)
include_directories(${PLUGIN_INCLUDE_DIRS})
SET_SOURCE_FILES_PROPERTIES(
${GENERATED}
PROPERTIES
GENERATED 1
)
SOURCE_GROUP(Generated FILES
${GENERATED}
)
SET( SOURCES
${GENERAL}
${GENERATED}
)
include_platform()
Try starting with this options in your root CMakeLists.txt:
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
BUILD_SHARED_LIBS is only needed if your project has its own libraries (add_library).
With the -static linker flag, you need static libs for ALL your additional libraries too! One common problem when static linking is to avoid circular dependencies.