I currently have two C projects on Clion with cmake. One of the projects is named "sharedLibsDemo" and I am trying to create a shared library in this project. In the other project I want to use the library that was created by the "shared" project.
Currently, in the "sharedLibsDemo" project I have the following cmake:
cmake_minimum_required(VERSION 3.7)
project(sharedLibsDemo)
set(CMAKE_C_STANDARD 11)
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}")
set(SOURCE_FILES shared.c shared.h main.c)
add_library(shared SHARED ${SOURCE_FILES})
include(GenerateExportHeader)
GENERATE_EXPORT_HEADER(shared # generates the export header shared_EXPORTS.h automatically
BASE_NAME shared
EXPORT_MACRO_NAME SHARED_EXPORTS
EXPORT_FILE_NAME shared_EXPORTS.h
STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC)
set(EXEC_FILES main.c)
add_executable(myexe ${EXEC_FILES})
target_link_libraries(myexe shared)
However, this cmake only creates the shared_EXPORTS.h, libshared.dll, and libshared.dll.a` files.
I managed to create the .lib file using Mingw itself and put all of these files including the .h file of the source code into one folder and placed the folder in the root folder of the second project in order to use it.
However, I've looked everywhere to find a way to link the library into the second project's executable. The documentation for cmake itself assumes I have a tonne of knowledge which I don't. Is there any list of commands that I can use to finally link my library. I have already tried the generic answer of "use find_package() or target_link_libraries" to no avail.
EDIT 1
The following is the contents of shared.h :
#include "shared_EXPORTS.h"
#ifndef SHAREDLIBSDEMO_LIBRARY_H
#define SHAREDLIBSDEMO_LIBRARY_H
void SHARED_EXPORTS sharedHello(void);
#endif
As per the suggestion of #Shmuel H. I placed the shared.h shared.c and the cmakelist.txt for the shared project into a folder in the project that I want to include the library in. And I used add_subdirectory() and target_link_libraries().
The following is the CMakeLists.txt for the project:
cmake_minimum_required(VERSION 3.7)
project(projectFiles)
set(CMAKE_C_STANDARD 11)
include_directories(src ${maker_INCLUDE_DIR})
set(SOURCE_FILES src/nv_runner/main.c src/FactParser/FactParser.c src/FactParser/FactParser.h src/Utils/Utils.c src/Utils/Utils.h src/nv_runner/main.h)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
find_package(maker REQUIRED)
include_directories(${maker_INCLUDE_DIR})
set(LIBSHARED_LOCATION ${PROJECT_SOURCE_DIR}/libshared)
add_subdirectory(libshared)
include_directories(${LIBSHARED_LOCATION})
add_executable(${PROJECT_NAME} ${SOURCE_FILES} src/FactParser/FactParser.c src/FactParser/FactParser.c src/FactParser/FactParser.h src/nv_runner/main.h)
target_link_libraries(${PROJECT_NAME} ${maker_LIBRARY})
target_link_libraries(${PROJECT_NAME} shared)
At first, I had to remove the SHARED_EXPORTS macro from the sharedHello function and the shared_EXPORTS.h include in shared.h because otherwise it would not recognize the function for use in other files. But when I ran the program I got this result:
Process finished with exit code -1073741515 (0xC0000135)
EDIT 2
Project setup image
In the screenshot, I've taken all the necessary files from the shared project, placed it in a directory in the current project and marked the directory as a Library. The cmake can be seen in the image. With this setup, whenever I run my program, it just crashes with the error seen in the image.
I found out what the issue was. I did not know that the dll had to be in the same folder as the exe, that's why the program was not executing. Once I placed the .dll file inside the exe folder, it worked.
Credit goes to this question for helping me identify the issue: C++ running file with included library failes without compiling error (CMake / CLion)
And I found out that .lib files are only necessary for MSVC compiler. MinGW uses the .dll.a file; replacing .lib. This post lead me to finding this out: Compatibility of *.dll *.a *.lib *.def between VisualStudio and gcc
Please correct me if I'm wrong however. Here is an image of my current project and cmake setup
Related
I created a C application first on windows which uses MagickWand and added imagemagick to it by first installing imagemagick from the official site, then adding the installed static libraries and include folder from the imagemagick installation to my project, and depending on them in CMake. It worked succesfully.
I wanted to do the same on linux: but with different library files (.lib for windows, and .a for linux, since I am linking statically).
I installed imagemagick source code from github, then built the project as documented:
./configure, make, make install.
Then I copied the generated library files and include folder to my project, same as I did on windows:
and this is my CMakeLists.txt, it just adds dependencies to the static magick libraries:
cmake_minimum_required(VERSION 3.23)
project(demo-app)
set(CMAKE_CXX_STANDARD 23)
file(GLOB SOURCE_FILES src/*.c)
add_executable(demo ${SOURCE_FILES})
include_directories(src)
#ImageMagick
# set quantum depth
set(MAGICKCORE_QUANTUM_DEPTH 16)
# IF linux:
if (UNIX)
include_directories(Dependencies/ImageMagick/include)
target_link_directories(demo PRIVATE Dependencies/ImageMagick/lib)
# add MagickWand static library
add_library(MagickWand STATIC IMPORTED)
set_target_properties(MagickWand PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/Dependencies/ImageMagick/lib/libMagickWand-7.Q16.a)
target_link_libraries(demo PRIVATE MagickWand)
# add MagickCore static library
add_library(MagickCore STATIC IMPORTED)
set_target_properties(MagickCore PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/Dependencies/ImageMagick/lib/libMagickCore-7.Q16.a)
target_link_libraries(demo PRIVATE MagickCore)
endif ()
so far so good. Now If I build and run, I get alot of undefined reference errors:
logs
I searched for the missing references, for example: undefined reference to XWithdrawWindow, small google search and I find that this function is part of xlib library, So please don't tell me I should add each of these libraries separately into my CMakeLists.txt.
I really don't understand why is this happening? shouldn't the static libraries contain any other dependencies they need (if this is what's causing the error)?
What am I doing wrong?
Previously, I'm looking for this kind of question but none of them are working as example this thread and this one.
Currently, I'm creating a C library which supposed to outputs a shared library (*.so or *.dll) file and multiple *.h files in a ./include directory. The shared library is successfully built and installed to /usr/local/lib. However, I have no idea how do I tell CMake to copy *.h files to the correct destination as below.
In POSIX: /usr/local/include
In Windows: C:\<Compiler Path>\include
I know I could workaround this by copying those *.h with Python script or using if-else logic on CMake. But at least tell me if there is a feature in CMake for doing that thing. Thanks!
Here's my CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project (
learn_c_library
VERSION 1.0.0
LANGUAGES C
)
# Specify CMake build and output directory
set(CMAKE_BINARY_DIR "${PROJECT_SOURCE_DIR}/.cmake")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/out")
# Use every .c file inside ./src
file(GLOB_RECURSE MY_SOURCE_PATH "src/*")
add_library(
${PROJECT_NAME} SHARED
${MY_SOURCE_PATH}
)
include_directories(
${PROJECT_NAME}
"include/"
)
# Allows "make install" to install shared library
install(TARGETS ${PROJECT_NAME})
This answer improves on your answer:
cmake_minimum_required(VERSION 3.14)
# ...
include(GNUInstallDirs)
install(DIRECTORY "include/"
TYPE INCLUDE
COMPONENT MyProj_Development)
The GNUInstallDirs module provides standard configuration points for customizing a project's install layout. These variables should essentially always be used instead of hardcoding path/directory names.
The TYPE INCLUDE argument to install() was introduced in CMake 3.14 and uses GNUInstallDirs's CMAKE_INSTALL_INCLUDEDIR variable to determine the destination.
Finally, and especially if your project is a library, all your install() rules should be given a COMPONENT argument to allow splitting files between runtime and development packages (and potentially others like documentation and architecture-independent data files).
After days of fiddling CMake, finally I found the solution!
Let's assume you store your public *.h inside ./include directory, then here's the syntax for installing your *.h files to your machine:
install(
DIRECTORY
"include/" # Your global headers location in the project
DESTINATION
include # This is your system's default "include" location
)
I got the solution from here with usr/myproject replaced to be include
I am using dart:ffi to interoperate with some C code in order to use the SDK provided by ZeroTier. I have tried and successfully call out a dummy function from the shared library produced by CMake. This is the CMakeList.txt.
cmake_minimum_required(VERSION 3.4.1)
add_library(
weather
SHARED
../../src/weather.c
)
I have followed the documentation of ZeroTierSDK and the output of the compilation is the .dll and .a files. May I know what is the proper way to link the shared library produced from my .c file with the compiled library (.a / .dll) so that I could use the functions provided by the sdk?
I have tried adding the following lines to the CMakeList.txt.
link_directories ("../../src/libzt.lib")
target_link_libraries(weather ../../src/libzt.lib)
The error that I get was as below, I have confirmed that the lib was located in the same director as my .c file.
C:/Users/DELL/AppData/Local/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: cannot find -l../../src/libzt.lib
I have recently started programming on Clion, and I would like to create a Snake game in C language. I have downloaded all the necessary SDL libraries via Homebrew, and I have copied these files into my Developer/CommandLineTools/usr/ folder. My C compiler is in this folder.
I have tried using CMakeLists.txt but I cannot get it to work properly.
cmake_minimum_required(VERSION 3.17)
project(test)
set(CMAKE_C_STANDARD 99)
INCLUDE(FindPkgConfig)
pkg_check_modules(SDL2 REQUIRED sdl2)
pkg_check_modules(SDL2_IMG REQUIRED sdl2_image)
pkg_check_modules(SDL2_TTF REQUIRED sdl2_ttf)
pkg_check_modules(SDL2_MIXER REQUIRED sdl2_mixer)
find_package(SDL2 REQUIRED)
find_package(SDL2_IMG REQUIRED)
find_package(SDL2_TTF REQUIRED)
find_package(SDL2_MIXER REQUIRED)
add_executable(test ${PROJECT_SOURCE_DIR}/src/main.c)
include_directories(${PROJECT_SOURCE_DIR}/assets)
include_directories(${SDL2_INCLUDE_DIRS}
${SDL2_IMG_INCLUDE_DIRS}
${SDL2_TTF_INCLUDE_DIRS}
${SDL2_MIXER_INCLUDE_DIRS})
link_directories(${SDL2_LIBRARY_DIRS}
${SDL2_IMG_LIBRARY_DIRS}
${SDL2_TTF_LIBRARY_DIRS}
${SDL2_MIXER_LIBRARY_DIRS})
target_link_libraries (test
${SDL2_LIBRARIES}
${SDL2_IMG_LIBRARIES}
${SDL2_TTF_LIBRARIES}
${SDL2_MIXER_LIBRARIES})
I have looked through many similar questions here on stackoverflow but none of them seemed to solve my issue.
If I include the find_package, I get this error message:
Could not find a package configuration file SDL2_IMG and so on. If I leave it out I get this library not found for -lSDL2_image.
sdl2 libraries should download individually. mixer, ttf, etc
I worked with SDL2 on XCode without problem (easy)
Rather then compiler location, I prefer project location.
By the way, I indicate header files as path
I wish these help you.
I have done the following:
Create new c project (Makefile Project with Existing Code)
Added a build variable that my Makefile complained about
Now my source .c file complains about #include files because it does not know where the lib folder is,I tried adding lib folder to library path (DID NOT WORK).
How can I link my project to an external lib folder so that my .c source file can read the .h files needed for the #include?
I added the library path to Paths and Symbols->Includes BUT when I go back to the project it only shows the root folder and nothing inside it. Do I also have to add each individual .so lib file?
Answered here : How do you add libraries to Eclipse CDT? (No such file or directory)
#cyfur01 has the best answer :
What to add depends on what you are trying to include. In the case of
Boost, there are a number of header-only libraries, and there are some
libraries that require linking in static/shared-object libraries
(e.g., serialization). Header-Only Libraries
For header-only libraries, you just need to include the base directory
of all the header files. With gcc, you add the directory using the -I
flag (e.g., -I C:/path/to/boost_52_0). With a managed makefile project
in Eclipse, you can accomplish the same using Properties > C/C++ Build
Settings > Tool Settings > GCC C++ Compiler > Directories Static/Shared-Object Libraries
For static/shared-object libraries, you have to specify two options:
-l --> The name of the library, less the 'lib' prefix and the file suffix (e.g., libboost_serialization.dll -> boost_serialization
-L --> The directory to look for the library file in. This is only needed if the library is on a non-standard path.
As #Chris pointed out, for a managed makefile project, both of these
options can be set through Properties > C/C++ Build > Settings > Tool
Settings > GCC C++ Linker > Libraries
ok so I figured it out:
(1) At the start I had a source.c and a MAKEFILE
(2) Create new c project (Makefile Project with Existing Code)
(3) MAKEFILE complained about a variable so I added it to environment variable
(4) #include files complained so I added external library like so
(a) I located my library path and found that there is a folder before /lib called include
(b) The include folder had a list of header files
(c) So I added the path to the include folder NOT the lib folder under paths and symbols include
WORKED LIKE A CHARM!