Unable to generate a shared library using cmake - c++

I was trying to generate a shared library for my project using cmake, unfortunately I got this error
Undefined symbols for architecture x86_64:
"_SDL_Init", referenced from:
_main in main.cpp.o
"_SDL_Quit", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
If I'm building a static library it works. This is my cmake file :
cmake_minimum_required(VERSION 3.4.1)
project(yanthra_console VERSION 0.1 DESCRIPTION "A 3d Game Engine.")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fexceptions")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING "Build type selections" FORCE)
set(THIRD_PARTY_DIR "../../third-party")
set(MAIN_SOURCE_DIR "../main/src")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/out)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib )
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
include_directories(${THIRD_PARTY_DIR}/SDL/include)
file(GLOB_RECURSE CPP_HEADERS ${MAIN_SOURCE_DIR}/*.hpp)
file(GLOB_RECURSE CPP_SOURCES ${MAIN_SOURCE_DIR}/*.cpp)
add_library(
yanthra
SHARED
${CPP_HEADERS}
${CPP_SOURCES}
)
add_executable(
yanthra_console
${CPP_HEADERS}
${CPP_SOURCES}
)
set_target_properties(
yanthra_console
PROPERTIES
LINK_FLAGS
"-F../Frameworks -framework SDL2 -framework OpenGL"
)
target_link_libraries(yanthra_console PRIVATE yanthra)
I was able to create a static library with executable.Im using Mulit Configuration to build the project.

Looks like a symbol visibility issue.
By default on clang/gcc symbols are hidden.
There is a cppcon talk that talks about this:
https://www.youtube.com/watch?v=m0DwB4OvDXk&list=PL4s9OdsBXD7aXhgqibbEzf8zAM5eiiENs&index=9
Basically either this library doesn't support being built as a shared library.
Or you need to enable that functionality somehow.
Or just force symbol visibility on.

Related

gl3w - Static Linking Fails

I'm trying to build gl3w from source and link it automatically in my C++ project using CMake. I've added gl3w as a git submodule and have the following in CMakeLists.txt:
# GL3W
set(gl3w_dir "${CMAKE_CURRENT_SOURCE_DIR}/gl3w")
set(gl3w_inc "${gl3w_dir}/include")
set(gl3w_src "${gl3w_dir}/src/gl3w.c")
if (EXISTS ${gl3w_src})
message(STATUS "Found gl3w source files")
else()
execute_process(COMMAND python3 gl3w_gen.py WORKING_DIRECTORY "${gl3w_dir}") # use python or python3
if (NOT EXISTS ${gl3w_src})
message(FATAL_ERROR "Could not generate gl3w source files")
endif()
endif()
add_library(gl3w STATIC "${gl3w_src}")
target_include_directories(gl3w PUBLIC "${gl3w_inc}")
target_link_libraries(main gl3w)
However, this doesn't seem to be working. I get the following error upon building:
[build] Undefined symbols for architecture x86_64:
[build] "_gl3wProcs", referenced from:
[build] _main in main.cpp.o
[build] ld: symbol(s) not found for architecture x86_64
If I instead link gl3w dynamically rather than statically in CMakeLists.txt, I somehow don't get this error - but running the compiled executable results in a segfault.
It turns out that I wasn't calling gl3wInit(); in main, causing my code to segfault whenever it came across calls to OpenGL functions. Now static linking works just fine!

VkPipelineInfoEXT does not exist

I was recently following a tutorial for Vulkan called vkguide.dev.
I was on Chapter 1 part 2 called Vulkan Intialization Code(https://vkguide.dev/docs/chapter-1/vulkan_init_code/), this tutorial uses a bootstrap library to intialize Vulkan(https://github.com/charles-lunarg/vk-bootstrap/).
However when I use the library
in the VKBootstrapDispatch.h file, on line 2318 clang/cmake are complaining about VkPipelineInfoEXT not being a valid type. It suggests VkPipelineInfoKHR however when I switch the type, my code says that there are undefined symbols for arm64 and all of these functions relate to the library.
I couldn't find anything about this online, so it would be great if you could help. I'll attach some screenshots.
The errors are:
VkPipelineInfoEXT does not exist
VkPipelineInfoKHR works but then it says vulkan functions are undefined symbols.
This is what is says when I use KHR instead of EXT
_vkDestroyDevice", referenced from:
VulkanEngine::Cleanup() in VkEngine.cpp.o
"_vkDestroyImageView", referenced from:
VulkanEngine::Cleanup() in VkEngine.cpp.o
"_vkDestroyInstance", referenced from:
VulkanEngine::Cleanup() in VkEngine.cpp.o
"_vkDestroySurfaceKHR", referenced from:
VulkanEngine::Cleanup() in VkEngine.cpp.o
"_vkDestroySwapchainKHR", referenced from:
VulkanEngine::Cleanup() in VkEngine.cpp.o
ld: symbol(s) not found for architecture arm64
CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY) CMAKE_SOURCE_DIR}/build/debu
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "-std=c++17 -O3")
project(Vulkan-Raytracing-Project)
add_executable(Vulkan-Raytracing
${CMAKE_SOURCE_DIR}/src/main.cpp
${CMAKE_SOURCE_DIR}/src/VkEngine.cpp
${CMAKE_SOURCE_DIR}/lib/vkbootstrap/VkBootstrap.cpp
)
find_package(SDL2 REQUIRED)
find_package(Vulkan REQUIRED)
message(STATUS "Found SDL2")
message(STATUS "Found Vulkan")
# target_link_libraries(Vulkan-Raytracing PUBLIC SDL2 ${CMAKE_DL_LIBS})
target_link_libraries(Vulkan-Raytracing ${SDL2_LIBRARIES} $ {VULKAN_LIBRARIES})
# target_link_directories(Vulkan-Raytracing PUBLIC "${CMAKE_SOURCE_DIR}/lib/SDL")
# target_link_libraries(Vulkan-Raytracing PUBLIC libSDL2maind.a)
# target_link_libraries(Vulkan-Raytracing ${CMAKE_SOURCE_DIR}/lib/SDL/libSDL2maind.a)
target_include_directories(Vulkan-Raytracing PRIVATE
${SDL2_INCLUDE_DIRS}
${VULKAN_INCLUDE_DIRS}
"${CMAKE_SOURCE_DIR}/include"
"${CMAKE_SOURCE_DIR}/src"
"/Users/nick/VulkanSDK/1.3.211.0/macOS/include"
)
Sorry for answering my own question, but it turns out that Vulkan was not getting linked properly, and I included the .dylib that came with the sdk and the build worked.

Apple Mach-O Linker error with Allegro5 and Xcode with CMake

I'm trying to set up a project project in Xcode with allegro. I installed allegro5 using homebrew. My CMakeLists.txt is as below:
set(SOURCE_FILES "main.cpp")
add_executable(core ${SOURCE_FILES})
if(WIN32)
# TODO.
else(APPLE)
set(ALLEGRO_INCLUDE "/usr/local/include")
set(ALLEGRO_LIB "/usr/local/lib")
set(ALLEGRO_DYLIB, "/usr/local/lib/*.dylib")
set(ALLEGRO_LINK_FLAGS "-lallegro -lallegro_main")
endif()
include_directories(${ALLEGRO_INCLUDE})
link_directories(${ALLEGRO_LIB})
file(GLOB LIBRARIES ${ALLEGRO_DYLIB})
target_link_libraries(core ${LIBRARIES} ${ALLEGRO_LINK_FLAGS})
However, I keep getting the error: ld: library not found for -lallegro
EDIT:
Edited CMakeLists.txt file:
set(SOURCE_FILES "main.cpp")
add_executable(core ${SOURCE_FILES})
if(WIN32)
# TODO.
else(APPLE)
set(ALLEGRO_INCLUDE "/usr/local/include")
set(ALLEGRO_LIB "/usr/local/lib")
set(ALLEGRO_DYLIB, "/usr/local/lib/*.dylib")
endif()
include_directories(${ALLEGRO_INCLUDE})
link_directories(${ALLEGRO_LIB})
file(GLOB LIBRARIES ${ALLEGRO_DYLIB})
target_link_libraries(core ${LIBRARIES} ${ALLEGRO_DYLIB})
And now I'm getting the error:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
(maybe you meant: __al_mangled_main)
ld: symbol(s) not found for architecture x86_64
You misunderstood target_link_libraries, you don't set the link flags here, but you indicate the list of libraries you want to target, so that would be:
target_link_libraries(core ${LIBRARIES} ${ALLEGRO_DYLIB})
Otherwise you will get flags like -l-lallegro.

cmake build .so library

My CMakeLists.txt is here.
cmake_minimum_required(VERSION 3.9)
project(iemoji-lab)
set(CMAKE_CXX_STANDARD 14)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
add_executable(
util
src/util/util.cpp
)
target_link_libraries(
util
avformat
)
After I build, I got util executable file. As you see, I have to link util with avformat which is in ffmepg.
Now I want to build a .so file named libiemoji.
I have already tried like this.
cmake_minimum_required(VERSION 3.9)
project(iemoji-lab)
set(CMAKE_CXX_STANDARD 14)
add_library(
libiemoji
SHARED
src/util/util.cpp
)
But I got error.
Undefined symbols for architecture x86_64:
"_av_register_all", referenced from:
GetFrameCount(char const*) in util.cpp.o
"_avformat_alloc_context", referenced from:
GetFrameCount(char const*) in util.cpp.o
"_avformat_close_input", referenced from:
GetFrameCount(char const*) in util.cpp.o
"_avformat_free_context", referenced from:
GetFrameCount(char const*) in util.cpp.o
"_avformat_open_input", referenced from:
GetFrameCount(char const*) in util.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
gmake[2]: * [CMakeFiles/libiemoji.dir/build.make:95: liblibiemoji.dylib] Error 1
gmake[1]: * [CMakeFiles/Makefile2:68: CMakeFiles/libiemoji.dir/all] Error 2
gmake: *** [Makefile:84: all] Error 2
So how can generate .so library?
EDIT
After #Mario point, I got solution for no error.
cmake_minimum_required(VERSION 3.9)
project(iemoji-lab)
set(CMAKE_CXX_STANDARD 14)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
add_library(
iemoji
SHARED
src/util/util.cpp
)
target_link_libraries(
iemoji
avformat
)
Now I got a file libiemoji.dyib. I am confused by it because I want to generate a file with extension .so.
You've got everything right, you just forgot linking the library as well. Copy target_link_libraries() and you should be fine.
The sub-project should link libraries, similar to executable project; because of dependencies; you can look at CMake tutorial

Undefined symbols for architecture x86_64 (libdialog.a) on Mac 10.13.3

I'm working on a C++ program which makes use of the dialog library (http://invisible-island.net/dialog/), which is written in C. I've been able to successfully compile and link my application against it on Linux with the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.8)
project(zerus)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Lua REQUIRED)
find_package(Curses REQUIRED)
find_package(Threads REQUIRED)
add_executable(${PROJECT_NAME} main.cpp headers/Utilities.h source/Utilities.cpp headers/config/lua/LuaConfiguration.h source/config/lua/LuaConfiguration.cpp headers/config/PlatformProcessConfiguration.h source/config/PlatformProcessConfiguration.cpp headers/config/PlatformConfiguration.h source/config/PlatformConfiguration.cpp headers/config/PlatformServiceConfiguration.h source/TmuxSessionManager.cpp headers/TmuxSessionManager.h source/PlatformOvermind.cpp headers/PlatformOvermind.h headers/ProcessStartResult.h headers/dialogs/DialogMainMenu.h source/dialogs/DialogMainMenu.cpp source/dialogs/ModdedDialog.cpp headers/dialogs/ModdedDialog.h source/dialogs/DialogServicesChecklist.cpp headers/dialogs/DialogServicesChecklist.h source/ui/UIManager.cpp headers/ui/UIManager.h headers/dialogs/DialogRegionsChecklist.h source/dialogs/DialogRegionsChecklist.cpp source/dialogs/DialogResolveDependenciesYesNo.cpp headers/dialogs/DialogResolveDependenciesYesNo.h source/dialogs/DialogProcessesChecklist.cpp headers/dialogs/DialogProcessesChecklist.h)
target_link_libraries(${PROJECT_NAME} lua curl dialog Threads::Threads)
However, when I try to build the same project on Mac, it compiles but the linker fails with:
Undefined symbols for architecture x86_64:
"_COLOR_PAIRS", referenced from:
_dlg_print_text in libdialog.a(util.o)
_dlg_color_setup in libdialog.a(util.o)
_dlg_color_pair in libdialog.a(util.o)
"_COLS", referenced from:
_dlg_put_backtitle in libdialog.a(util.o)
_dlg_clear in libdialog.a(util.o)
_init_dialog in libdialog.a(util.o)
_dlg_auto_size in libdialog.a(util.o)
_dlg_auto_sizefile in libdialog.a(util.o)
_dlg_ctl_size in libdialog.a(util.o)
_dlg_box_x_ordinate in libdialog.a(util.o)
...
"_LINES", referenced from:
_dlg_clear in libdialog.a(util.o)
_init_dialog in libdialog.a(util.o)
_dlg_print_scrolled in libdialog.a(util.o)
_dlg_auto_size in libdialog.a(util.o)
_dlg_auto_sizefile in libdialog.a(util.o)
_dlg_ctl_size in libdialog.a(util.o)
_dlg_calc_listh in libdialog.a(util.o)
...
"__nc_wacs", referenced from:
_dlg_draw_arrows2 in libdialog.a(arrows.o)
_dlg_draw_scrollbar in libdialog.a(arrows.o)
"_acs_map", referenced from:
_dlg_put_backtitle in libdialog.a(util.o)
_dlg_boxchar in libdialog.a(util.o)
_dlg_print_scrolled in libdialog.a(util.o)
_dlg_draw_box2 in libdialog.a(util.o)
_dlg_asciibox in libdialog.a(util.o)
_dlg_draw_bottom_box2 in libdialog.a(util.o)
_dlg_draw_arrows2 in libdialog.a(arrows.o)
...
"_beep", referenced from:
_dialog_yesno in libdialog.a(yesno.o)
_dlg_beeping in libdialog.a(util.o)
_dlg_checklist in libdialog.a(checklist.o)
_dlg_menu in libdialog.a(menubox.o)
_dlg_edit_string in libdialog.a(inputstr.o)
_mouse_wgetch in libdialog.a(mousewget.o)
_dialog_textbox in libdialog.a(textbox.o)
...
(maybe you meant: _dlg_beeping)
"_cbreak", referenced from:
_init_dialog in libdialog.a(util.o)
...etc.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've tried several approaches to fix this including:
using extern "C" {} to include the dialog header (didn't use on Linux and everything linked correctly).
Changing build file to the following to ensure that CMake was finding the library correctly (and it was).
CMakeLists.txt:
cmake_minimum_required(VERSION 3.8)
project(zerus)
MESSAGE( STATUS "CMAKE_LIBRARY_PATH: " ${CMAKE_LIBRARY_PATH} )
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Lua REQUIRED)
find_package(Curses REQUIRED)
find_package(Threads REQUIRED)
find_library(DIALOG_LIB dialog)
message(DIALOG_LIB=${DIALOG_LIB})
add_executable(${PROJECT_NAME} <source files>)
target_link_libraries(${PROJECT_NAME} ${DIALOG_LIB} lua curl Threads::Threads)
Output during CMake's build verified that it was finding the library:
DIALOG_LIB=/usr/local/lib/libdialog.a
Verifying that the static library created using make/make install-full on the Mac was for the correct architecture:
lipo -info /usr/local/lib/libdialog.a
input file /usr/local/lib/libdialog.a is not a fat file
Non-fat file: /usr/local/lib/libdialog.a is architecture: x86_64
Verifying that the object files inside the static library matched the architecture
I'm not sure where to go from here. I get that the linker can't find the symbols, but it seems to be finding the library which includes those symbols. Is this related to the toolchain on Mac and if so, how can it be fixed?