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?
Related
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 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
I have a static library (.lib file) on Windows platform, I want to know the dependent version of CRT library when the lib is built. I have no source code of the .lib file, any ideas?
thanks in advance,
George
Static libraries don't have those kinds of dependencies. When the library is built it is not linked with the run-time in any way, all it knows about are function declarations in the implementation header files, which don't provide any version information.
However, assuming the library is in MS format, you should be able see what flags the library was built with by opening it in a text editor (make a backup before you do this). You are looking for a line like this:
cl.exe cmd -nologo -MTd -W3 -Gm -GX -ZI -DWIN32 -D_DEBUG (more stuff)
The -MTd flag tells you that the library was compiled with Multi-Threaded Debug support. .