# How can I export symbols? (Exporting class-methods)

**URL:** <https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065>\
**Category:** Code\
**Created:** [November 25, 2024, 10:07pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065 "2024-11-25T22:07:51Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![BenEngbers](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/59ef9b/32.png) [@BenEngbers](https://discourse.cmake.org/u/BenEngbers)\
**Post date:** [November 25, 2024, 10:07pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/1 "2024-11-25T22:07:51Z")

</div>

I still consider myself a fairly novice C++ programmer and with CMake I have even less experience.  
In an Eclipse CMake project I have written a shared library for accessing an XML database (BaseX). In the IDE the code compiles without errors to a shared object. In another project I wrote a test program that links to the library. This program compiles with the public API and works as expected.

According to this article ‘[Modern CMake tutorial for C++ library developers](https://medium.com/@pananton/modern-cmake-tutorial-for-c-library-developers-12f3bf57dc87)’, it should be able to package a library. This article provides a template that should make packaging easy ([GitHub - pananton/cpp-lib-template: Template for C++ library built with CMake](https://github.com/pananton/cpp-lib-template)).

- In this template I first replaced all occurrences of `Mylib` and to `MYLIB` to `BasexCpp` respectively `BASEXCPP`.
- The commands `cmake -S . -B Build/Debug --fresh --preset=dev-linux -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_BUILD_TYPE=Debug -G Ninja` and `ninja` (after cd to Build/Debug) result in a shared library with only 1 function (Add) and an executable (`libTest`). This program uses the `Add` function that is provided by the library.

I then added the dependency with Curl in CMakeLists.txt and copied the source code of my library to the directory tree. The new CMakeLists.txt, the public API `BasexCpp.h` and the testfile `main.cpp` are added below.  
Even after adding my sources, the test program works. However, when I uncomment the code in main.cpp, ninja returns this error message:

```
[11/11] Linking CXX executable examples/add/libTest
FAILED: examples/add/libTest 
: && /usr/lib64/ccache/c++ -std=c++20 -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wcast-align -Wcast-qual -Wnull-dereference -Woverloaded-virtual -Wformat=2 -Werror -g examples/add/CMakeFiles/libTest.dir/main.cpp.o -o examples/add/libTest -Wl,-rpath,/home/bengbers/Thuis/CPP_LIB4/Build/Debug libBasexCpp.so.1.0.0 -Llib64 -lcurlpp -L/usr/lib64 -lcurl && :
/usr/bin/ld: examples/add/CMakeFiles/libTest.dir/main.cpp.o: in function `main':
/home/bengbers/Thuis/CPP_LIB4/examples/add/main.cpp:19:(.text+0xf6): undefined reference to `BasexCpp::BasexClient::BasexClient(std:: __cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int const&, std::__ cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: /home/bengbers/Thuis/CPP_LIB4/examples/add/main.cpp:21:(.text+0x154): undefined reference to `BasexCpp::BasexClient::Create(std:: __cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__ cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: /home/bengbers/Thuis/CPP_LIB4/examples/add/main.cpp:24:(.text+0x185): undefined reference to `BasexCpp::BasexClient::~BasexClient()'
/usr/bin/ld: /home/bengbers/Thuis/CPP_LIB4/examples/add/main.cpp:24:(.text+0x1f8): undefined reference to `BasexCpp::BasexClient::~BasexClient()'
collect2: fout: ld gaf exit-status 1 terug
ninja: build stopped: subcommand failed.

```

I don’t know how to interpret the results from the command `readelf -s Build/Debug/libBasexCpp.so > ReadElf.out` but after some googling I learned that `readelf` can be used to inspect the contents from the library.  
This is part of ReadElf.out

```
    9: 0000000000000000 0 FILE LOCAL DEFAULT ABS Add.cpp
    10: 0000000000000000 0 FILE LOCAL DEFAULT ABS Base.cpp
    11: 00000000000451c7 1 OBJECT LOCAL DEFAULT 14 _ZNSt8__detail30[...]
    12: 00000000000451c8 1 OBJECT LOCAL DEFAULT 14 _ZNSt8__detail30[...]
    13: 00000000000451c9 1 OBJECT LOCAL DEFAULT 14 _ZNSt8__detail30[...]
    14: 00000000000451ca 1 OBJECT LOCAL DEFAULT 14 _ZNSt8__detail14[...]
    15: 00000000000451cb 1 OBJECT LOCAL DEFAULT 14 _ZNSt8__detail19[...]
    16: 00000000000451cc 1 OBJECT LOCAL DEFAULT 14 _ZNSt8__detail14[...]
    17: 00000000000451cd 1 OBJECT LOCAL DEFAULT 14 _ZNSt8__detail19[...]

```

I should expect that the lines 11-17 would export the Base-constructor.

Cane someone help me and tell me what I am doing wrong?

Ben

CmakeLists.txt

```auto
cmake_minimum_required(VERSION 3.14)
project(BasexCpp
    VERSION 1.0.0
    DESCRIPTION "Template for C++ library built with CMake"
    LANGUAGES CXX)

#----------------------------------------------------------------------------------------------------------------------
# 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
set(BASEXCPP_SHARED_LIBS 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
#----------------------------------------------------------------------------------------------------------------------

# Search for your dependencies here
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")
else()
  target_link_libraries(${PROJECT_NAME} ${CURLPP_LDFLAGS})
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(public_headers
    include/BasexCpp/export.h
# include/BasexCpp/Add.h
    include/BasexCpp/BasexCpp.h
)

set(sources
    ${public_headers}
    src/Add.cpp

    src/Base.cpp
    src/BasexClient.cpp
    src/BasexSocket.cpp
    src/ClientUtils.cpp
    src/QueryObject.cpp
    src/ResponseObj.cpp
    src/BasexClient.h
    src/BasexSocket.h
    src/ClientUtils.h
    src/QueryObject.h
    src/ResponseObj.h
    )
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}")

    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()

```

BasexCpp.h

# Edit

I have added BASEXCPP\_EXPORT to all the class methods that should be exported.  
Also I added another testfunction (`minus'). `minus`and`add` will be removed in the final library.

```auto
#pragma once

#ifndef BASEXCPP_H_
#define BASEXCPP_H_

#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstddef>
#include <iomanip>
#include <wordexp.h>
#include <iostream>
#include <list>
#include <sys/types.h>
#include <stdlib.h>

typedef std::vector < std::byte > ByteVect;
typedef std::vector < ByteVect> VectOfByteVect;

#include <memory>
class BasexSocket;
typedef std::shared_ptr < BasexSocket > BasexSock_Sptr;
#include <utility>
#include <cassert>
#include <stdexcept>
#include <fstream>
#include <sstream>
#include <array>
#include <regex>
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Exception.hpp>
#include <cstdio>

#ifdef __WIN32__
#include <winsock2.h>
#include <Windows.h>
#else
#include <sys/socket.h>
#include <unistd.h>
#endif

#include <BasexCpp/export.h>

using namespace std;

namespace BasexCpp {

BASEXCPP_EXPORT int add(int a, int b);
BASEXCPP_EXPORT int minus(int a, int b);

class QueryObject;
typedef std::unique_ptr < QueryObject > QueryObj_Uptr;

// 1 ### #include "ClientUtils.h"
BASEXCPP_EXPORT ByteVect getBytes (string const &s);
BASEXCPP_EXPORT string getChar (ByteVect const &b);
BASEXCPP_EXPORT string pathExpander (const string & s, int flags = 0);
BASEXCPP_EXPORT std::ostream & debug_dump (const ByteVect & str, std::ostream & stm = std::cout);
BASEXCPP_EXPORT std::ostream & debug_dump (const string & str, std::ostream & stm = std::cout);

// 2 ### #include "Base.h"
class BASEXCPP_EXPORT Base {
public:
BASEXCPP_EXPORT explicit Base (const string &, const int &, const string &, const string &);
BASEXCPP_EXPORT explicit Base (const string &, const string &, const string &, const string &);
BASEXCPP_EXPORT explicit Base (BasexSock_Sptr socket);
protected:
	BasexSock_Sptr Socket;
};

// 3 ### #include "ResponseObj.h"
class BASEXCPP_EXPORT ResponseObj {
public:
	ResponseObj ();
BASEXCPP_EXPORT explicit ResponseObj (const string &, ByteVect &);
};

// 4 ### #include "QueryObject.h"
class BASEXCPP_EXPORT QueryObject: virtual public Base {
public:
BASEXCPP_EXPORT void Close ();
BASEXCPP_EXPORT void Bind (const string & name, const string & value, const string & type = "");
BASEXCPP_EXPORT void Bind (const string & name, const std::list < string > &valueList, const string & type = "");
BASEXCPP_EXPORT void Bind (const string & name, const std::list < string > &valueList, const std::list < string > &typeList);
BASEXCPP_EXPORT ByteVect Next ();
BASEXCPP_EXPORT bool More ();
BASEXCPP_EXPORT void Exec ();
BASEXCPP_EXPORT void Info ();
BASEXCPP_EXPORT void Options ();
BASEXCPP_EXPORT void Context (const string & value, const string & type = "");
BASEXCPP_EXPORT void Updating ();
BASEXCPP_EXPORT void Full ();

BASEXCPP_EXPORT string getQueryString ();
BASEXCPP_EXPORT string getStatus ();
BASEXCPP_EXPORT ByteVect getResultBytes ();
BASEXCPP_EXPORT ByteVect getResult ();
BASEXCPP_EXPORT string getResultString ();
BASEXCPP_EXPORT string asString (const ByteVect & vect);

	ResponseObj Response;
};

// 5 ### #include "BasexClient.h"
class BASEXCPP_EXPORT BasexClient: virtual public Base {
public:
BASEXCPP_EXPORT explicit BasexClient (const string &, const int &, const string &, const string &);
BASEXCPP_EXPORT explicit BasexClient (const string &, const string &, const string &, const string &);
BASEXCPP_EXPORT virtual ~ BasexClient ();

BASEXCPP_EXPORT void Execute (const string & command);
BASEXCPP_EXPORT void Create (const string & dbName, const string & content = "");
BASEXCPP_EXPORT void Add (const string & path, const string & input);
BASEXCPP_EXPORT void Put (const string & path, const string & input);
BASEXCPP_EXPORT void PutBinary (const string & path, const ByteVect & input);
BASEXCPP_EXPORT QueryObj_Uptr Query (const string & query);
BASEXCPP_EXPORT string getCaller ();
BASEXCPP_EXPORT string getInfo ();
BASEXCPP_EXPORT string getStatus ();
BASEXCPP_EXPORT ByteVect getResultBytes ();
BASEXCPP_EXPORT ByteVect getResult ();
};

}

#endif // BASEXCPP_H_

```

Main.cpp

```auto
#include <BasexCpp/BasexCpp.h>

#include <iostream>

using namespace std;

using namespace BasexCpp;
int main(int, char*[])
{
    // auto sum = BasexCpp::add(3, 1);
    auto sum = add(3, 1);
    std::cout << sum << std::endl;
/*
	string DBHOST("localhost");
	int DBPORT(1984);
	string DBUSERNAME("Test");
	string DBPASSWORD("testBaseX");

	BasexClient Session (DBHOST, DBPORT, DBUSERNAME, DBPASSWORD);

	Session.Create("TestCpp");
*/
    return 0;
}

```

---

<div class="post-metadata">

**Author:** ![retif](https://discourse.cmake.org/user_avatar/discourse.cmake.org/retif/32/1776_2.png) [@retif](https://discourse.cmake.org/u/retif)\
**Post date:** [November 26, 2024, 8:43am UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/2 "2024-11-26T08:43:26Z")

</div>

I don’t see you linking to that library (_should be where you do `add_executable()` with that `main.cpp` source, which you haven’t shared_), so this might be the reason.

---

<div class="post-metadata">

**Author:** ![BenEngbers](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/59ef9b/32.png) [@BenEngbers](https://discourse.cmake.org/u/BenEngbers)\
**Post date:** [November 26, 2024, 10:24am UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/3 "2024-11-26T10:24:37Z")

</div>

The testprogram (main.cpp) resides in a subproject. The function `add` is one of the functions in the library which is build in the main project.

---

<div class="post-metadata">

**Author:** ![retif](https://discourse.cmake.org/user_avatar/discourse.cmake.org/retif/32/1776_2.png) [@retif](https://discourse.cmake.org/u/retif)\
**Post date:** [November 26, 2024, 10:51am UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/4 "2024-11-26T10:51:28Z")

</div>

That does not tell me much, I still don’t see how you linked to the library (_and if you did it at all_).

---

<div class="post-metadata">

**Author:** ![BenEngbers](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/59ef9b/32.png) [@BenEngbers](https://discourse.cmake.org/u/BenEngbers)\
**Post date:** [November 26, 2024, 12:33pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/5 "2024-11-26T12:33:01Z")

</div>

In root/CMakePresets.json I have added the line `"BASEXCPP_BUILD_EXAMPLES":"ON"`.

```auto
**Target in root/CMakeLists.txt**
if(BASEXCPP_BUILD_EXAMPLES)
    add_subdirectory(examples)
endif()

**examples/CMakeLists.txt**
add_subdirectory(add)

**examples/add/CMakeLists.txt**
cmake_minimum_required(VERSION 3.14)
project(libTest LANGUAGES CXX)

include("../../cmake/utils.cmake")
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" is_top_level)

if(is_top_level)
    find_package(BasexCpp REQUIRED)
endif()

set(sources main.cpp)
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources})

add_executable(libTest)
target_sources(libTest PRIVATE ${sources})
target_link_libraries(libTest PRIVATE BasexCpp::BasexCpp)

if(NOT is_top_level)
    win_copy_deps_to_target_dir(libTest BasexCpp::BasexCpp)
endif()

```

The function `add` that is used in `libTest` is defined in he public header `BasexCpp.h` and implemented in the library `libBasexCpp.so` so I am certain that this library is linked.

---

<div class="post-metadata">

**Author:** ![retif](https://discourse.cmake.org/user_avatar/discourse.cmake.org/retif/32/1776_2.png) [@retif](https://discourse.cmake.org/u/retif)\
**Post date:** [November 26, 2024, 1:29pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/6 "2024-11-26T13:29:54Z")

</div>

> ```auto
> target_link_libraries(libTest PRIVATE BasexCpp::BasexCpp)`
> 
> ```

That looks correct (_aside from the executable target name_), but does `BasexCpp::BasexCpp` exist at that point? And is the library’s binary present in the `ninja.build` file among the linking commands?

---

<div class="post-metadata">

**Author:** ![BenEngbers](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/59ef9b/32.png) [@BenEngbers](https://discourse.cmake.org/u/BenEngbers)\
**Post date:** [November 26, 2024, 2:23pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/7 "2024-11-26T14:23:23Z")

</div>

> [@retif](#):
>
> `target\_link\_libraries( **libTest** PRIVATE BasexCpp::BasexCpp)``

- Why is naming the executable `libTest` not correct?

```auto
build examples/add/libTest: CXX_EXECUTABLE_LINKER__libTest_Debug examples/add/CMakeFiles/libTest.dir/main.cpp.o | libBasexCpp.so.1.0.0 || libBasexCpp.so libBasexCpp.so
  FLAGS = -std=c++20 -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wcast-align -Wcast-qual -Wnull-dereference -Woverloaded-virtual -Wformat=2 -Werror -g
  LINK_LIBRARIES = -Wl,-rpath,/home/bengbers/Thuis/CPP_LIB4/Build/Debug libBasexCpp.so.1.0.0 -Llib64 -lcurlpp -L/usr/lib64 -lcurl
  OBJECT_DIR = examples/add/CMakeFiles/libTest.dir
  POST_BUILD = :
  PRE_LINK = :
  TARGET_COMPILE_PDB = examples/add/CMakeFiles/libTest.dir/
  TARGET_FILE = examples/add/libTest
  TARGET_PDB = examples/add/libTest.pdb

```

In `build.ninja` this part is used for linking. As you can see libBasexCpp.so is present.  
`readelf -s Build/Debug/libBasexCpp.so` tells me that all class-files have been touched but as I mentioned earlier, I don’t know how to interpret the output from readelf.

- The library **has to be** present because otherwise the function `add` would not be found.

---

<div class="post-metadata">

**Author:** ![retif](https://discourse.cmake.org/user_avatar/discourse.cmake.org/retif/32/1776_2.png) [@retif](https://discourse.cmake.org/u/retif)\
**Post date:** [November 26, 2024, 2:34pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/8 "2024-11-26T14:34:25Z")

</div>

> Why is naming the executable `libTest` not correct?

Because executable is not a library, is it, so having `lib` in its target name (_and then its binaries_) isn’t quite right, although of course no one can stop you from naming it like that. And in general it isn’t recommended to have `lib` anywhere in the target name of either executable or library.

For the rest, I really can’t tell what is wrong there. Perhaps you could share a minimal project for trying to reproduce the problem.

---

<div class="post-metadata">

**Author:** ![BenEngbers](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/59ef9b/32.png) [@BenEngbers](https://discourse.cmake.org/u/BenEngbers)\
**Post date:** [November 26, 2024, 2:58pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/9 "2024-11-26T14:58:15Z")

</div>

- I’ll give the testfile another name in the release files (whenever I come that far 😏)
- I don’t see how I could make a minimal project. Testing it requires that Basex is installed and that the complete sources are uploaded.
- 

I have been struggling with this particular problem for over a month now. In the meantime, I have solved several small, non-essential problems but the main problem remains the failure to export the symbols.  
On the internet I have seen examples showing that the name of class-methods should also appear in the output of readelf but I cannot find documentation anywhere on how to avoid using only mangled names.

Can this be prevented by using a setting in the gcc compiler or linker?

Ben  
PS. It is unfortunate that I cannot contact either the author of that article or Craig Scott for questions. I assume they could have helped me ages ago. 😮‍💨

---

<div class="post-metadata">

**Author:** ![retif](https://discourse.cmake.org/user_avatar/discourse.cmake.org/retif/32/1776_2.png) [@retif](https://discourse.cmake.org/u/retif)\
**Post date:** [November 26, 2024, 3:12pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/10 "2024-11-26T15:12:33Z")

</div>

> It is unfortunate that I cannot contact […] Craig Scott

You can definitely [contact and pay Craig Scott](https://crascit.com/contact/) to consult you, he is providing these exact services 🙂  
Here is also here on the forum, so he might stumble upon this thread eventually.

> I don’t see how I could make a minimal project

In the original post you said that you “_have written a shared library_”, so you can write another one the same way, just without this “Basex” thing. And then also create a basic executable, which would try to call a method from that library. And then anyone else will be able to try to build that example project on their machines and spot what you might have done wrong in exporting symbols.

---

<div class="post-metadata">

**Author:** ![lukas](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/l/e9a140/32.png) [@lukas](https://discourse.cmake.org/u/lukas)\
**Post date:** [November 29, 2024, 3:54pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/11 "2024-11-29T15:54:57Z")

</div>

What is the content of the file

```auto
include/BasexCpp/export.h

```

in your source tree? Does it correctly define BASEXCPP\_EXPORT?

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)\
**Post date:** [November 29, 2024, 4:27pm UTC](https://discourse.cmake.org/t/how-can-i-export-symbols-exporting-class-methods/13065/12 "2024-11-29T16:27:23Z")

</div>

perhaps you may try my version [Modernize the cmake files a bit by ClausKlein · Pull Request #3 · pananton/cpp-lib-template · GitHub](https://github.com/pananton/cpp-lib-template/pull/3)
