I started with a simple CMakeLists.txt for creating a shared library. After developing working source code in Eclipse, I copied that source code to a new directory, generated a shared library there and then linked the library to a test file. In Eclipse, there were no error messages. However, the test application showed that there was a memory leak somewhere. Since I did not succeed in creating debug information
I then started searching on internet and in doing so I came across this article “Modern CMake tutorial for C++ library developers”.
After I adapted the attached scripts to my application a shared library is now created. But when I try to link it to a test application I get ‘undefined reference to …’ error messages for every call to a public method.
The article does talk about exporting symbols but does not talk about exporting public methods. I have studied the CMake documentation as best I can but have not found any useful information about exporting symbols. This leads me to the following questions:
- Are symbols similar to public methods?
- If so, in what file and in what way should I define those symbols?
I tried the following way in the public header but it doesn’t work.
My CMakeLists.txt and part of the public header are below.
Ben
Public BasexCpp.h
#pragma once
#ifndef BASEXCPP_H
#define BASEXCPP_H
#include <string>
#include <vector>
#include <list>
#include <cstddef>
#include <ostream>
#include <iostream>
#include <sys/socket.h>
#include <BasexCpp/export.h>
typedef
std::vector <
std::vector <
std::byte >>
VectOfByteVect;
typedef
std::vector <
std::byte >
ByteVect;
std::vector < std::byte > getBytes(std::string const &s);
std::string getChar(ByteVect const &b);
std::string pathExpander(const std::string & s, int flags = 0);
std::ostream & debug_dump(const ByteVect & str, std::ostream & stm =
std::cout);
std::ostream & debug_dump(const std::string & str, std::ostream & stm =
std::cout);
namespace BasexCpp {
class BASEXCPP_EXPORT BasexSocket
{
public:
BasexSocket(const std::string, const std::string,
const std::string, const std::string);
~BasexSocket();
BasexSocket(const BasexSocket &) = delete;
BasexSocket & operator=(const BasexSocket &) = delete;
int basex_status(); // moet nog geimplementeerd worden
int get_Socket();
bool wait();
int readSocket(std::string & sockResponseString);
int writeData(const std::string & input);
int writeData(const std::vector < std::byte > &input);
int writeData(const char *input);
int writeByte(unsigned char rawNum);
std::vector < std::byte > decode(const std::vector <
std::byte > &encoded);
};
...
...
CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(BasexCpp
VERSION 1.0.0
DESCRIPTION "Template for C++ library built with CMake"
LANGUAGES CXX)
set(CMAKE_INSTALL_PREFIX)
#----------------------------------------------------------------------------------------------------------------------
# general settings and options
#----------------------------------------------------------------------------------------------------------------------
include(cmake/utils.cmake)
include(GNUInstallDirs)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" is_top_level)
# BASEXCPP_SHARED_LIBS option (undefined by default) can be used to force shared/static build
option(BASEXCPP_SHARED_LIBS "Build BasexCpp shared lib" ON)
option(BASEXCPP_BUILD_TESTS "Build BasexCpp tests" OFF)
option(BASEXCPP_BUILD_EXAMPLES "Build BasexCpp examples" ON)
option(BASEXCPP_BUILD_DOCS "Build BasexCpp documentation" OFF)
option(BASEXCPP_INSTALL "Generate target for installing BasexCpp" ${is_top_level})
set_if_undefined(BASEXCPP_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/BasexCpp" CACHE STRING
"Install path for BasexCpp package-related CMake files")
if(DEFINED BASEXCPP_SHARED_LIBS)
set(BUILD_SHARED_LIBS ${BASEXCPP_SHARED_LIBS})
endif()
if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
set_if_undefined(CMAKE_CXX_VISIBILITY_PRESET hidden)
set_if_undefined(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
add_library(BasexCpp) # initialized below
add_library(BasexCpp::BasexCpp ALIAS BasexCpp)
#----------------------------------------------------------------------------------------------------------------------
# BasexCpp dependencies
#----------------------------------------------------------------------------------------------------------------------
include(FindPkgConfig)
pkg_check_modules(CURLPP REQUIRED curlpp)
include(FindCURL)
find_package(CURL REQUIRED)
if(NOT CURL_FOUND)
message(FATAL_ERROR "Could not find CURL")
endif()
#----------------------------------------------------------------------------------------------------------------------
# BasexCpp sources
#----------------------------------------------------------------------------------------------------------------------
include(GenerateExportHeader)
set(export_file_name "export_shared.h")
if(NOT BUILD_SHARED_LIBS)
set(export_file_name "export_static.h")
endif()
generate_export_header(BasexCpp EXPORT_FILE_NAME include/BasexCpp/${export_file_name})
target_include_directories(BasexCpp PRIVATE src)
set(sources
include/BasexCpp/export.h
include/BasexCpp/BasexCpp.h
include/BasexCpp/export.h
include/BasexCpp/BasexCpp.h
src/Base.cpp
src/BasexClient.cpp
src/BasexSocket.cpp
src/ClientUtils.cpp
src/QueryObject.cpp
src/ResponseObj.cpp)
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources})
#----------------------------------------------------------------------------------------------------------------------
# BasexCpp target
#----------------------------------------------------------------------------------------------------------------------
include(CMakePackageConfigHelpers)
target_sources(BasexCpp PRIVATE ${sources})
target_compile_definitions(BasexCpp PUBLIC "$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:BASEXCPP_STATIC_DEFINE>")
target_include_directories(BasexCpp
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>")
set_target_properties(BasexCpp PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
VERSION ${PROJECT_VERSION})
if(BASEXCPP_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES)
configure_package_config_file(cmake/BasexCpp-config.cmake.in BasexCpp-config.cmake
INSTALL_DESTINATION "${BASEXCPP_INSTALL_CMAKEDIR}")
message("Installeer naar ${BASEXCPP_INSTALL_CMAKEDIR}")
message("Exporteer op basis van ${export_file_name}")
write_basic_package_version_file(BasexCpp-config-version.cmake
COMPATIBILITY SameMajorVersion)
install(TARGETS BasexCpp EXPORT BasexCpp_export
RUNTIME COMPONENT BasexCpp
LIBRARY COMPONENT BasexCpp NAMELINK_COMPONENT BasexCpp-dev
ARCHIVE COMPONENT BasexCpp-dev
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(DIRECTORY include/
TYPE INCLUDE
COMPONENT BasexCpp-dev)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/BasexCpp/${export_file_name}"
COMPONENT BasexCpp-dev
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/BasexCpp")
set(targets_file "BasexCpp-shared-targets.cmake")
if(NOT BUILD_SHARED_LIBS)
set(targets_file "BasexCpp-static-targets.cmake")
endif()
install(EXPORT BasexCpp_export
COMPONENT BasexCpp-dev
FILE "${targets_file}"
DESTINATION "${BASEXCPP_INSTALL_CMAKEDIR}"
NAMESPACE BasexCpp::)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/BasexCpp-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/BasexCpp-config-version.cmake"
COMPONENT BasexCpp-dev
DESTINATION "${BASEXCPP_INSTALL_CMAKEDIR}")
if(MSVC)
set(pdb_file "")
set(pdb_file_destination "")
if(BUILD_SHARED_LIBS)
set(pdb_file "$<TARGET_PDB_FILE:BasexCpp>")
set(pdb_file_destination "${CMAKE_INSTALL_BINDIR}")
else()
# TARGET_PDB_FILE does not work for pdb file generated for static library build, determining it manually
set(pdb_file "$<TARGET_FILE_DIR:BasexCpp>/$<TARGET_FILE_PREFIX:BasexCpp>$<TARGET_FILE_BASE_NAME:BasexCpp>.pdb")
set(pdb_file_destination "${CMAKE_INSTALL_LIBDIR}")
endif()
install(FILES "${pdb_file}"
COMPONENT BasexCpp-dev
CONFIGURATIONS Debug RelWithDebInfo
DESTINATION "${pdb_file_destination}"
OPTIONAL)
endif()
endif()
#----------------------------------------------------------------------------------------------------------------------
# other targets
#----------------------------------------------------------------------------------------------------------------------
if(BASEXCPP_BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
if(BASEXCPP_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if(BASEXCPP_BUILD_DOCS)
find_package(Doxygen REQUIRED)
doxygen_add_docs(docs include)
endif()