I am working on a chip8 emulator in C and I am using CMake to handle the compilation and linking of libraries in my project.
my working directory looks like this
build >
cmake >
FindSDL2.cmake
library >
SDL2
bin >
include >
lib >
share >
src >
Chip8 >
Chip8.c
Disassembler >
Disassembler.c
Display >
Display.c
main.c
CMakeLists.txt
this is my CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(chip_8 VERSION 0.1.0)
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/library/SDL2/)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
find_package(SDL2 REQUIRED)
add_executable(chip_8 ${CMAKE_SOURCE_DIR}/src/main.c)
target_include_directories(chip_8 PUBLIC ${SDL2_INCLUDE_DIR})
target_link_libraries(chip_8 ${SDL2_LIBRARY})
My display.c requires the SDL2 library. While I could just put all the executables in the add_executable, but that would mean I would also get to include SDL.h in all of the c files, which I don't want I only want to include in the display.h. The above CMakeLists.txt was made when I wanted to add the SDL2 library locally in the project directory, instead of it sitting in the system files of mingw (the bin, include and lib folders of mingw).
How do I change the structure of my project or the CMakeLists.txt so that I can include SDL2 in the display.c in the Display sub-directory
Related
So I am making a C application and I have all the library files .so , .a etc in a ./lib directory in the same directory as my C application.
I am compiling my C application with the -L./lib flag.
But it seems to me that gcc still looks for libraries within /usr/lib /usr/local/lib etc .
Is there a way to force gcc to only look for library files in my ./lib directory?
So if I remove the ./lib folder the application won't compile because it can't find the libraries.
I have a C application using CMake to generate Makefiles on Linux. The application contains .c as well as .proto files. Now I need to genearte .pb-c.c and .pb-c.h using protoc command in the CMakeLists.txt so that when I do cmake . the cmake generates the corresponding .pb-c and .pb-h. The protoc is used as:
execute_process(COMMAND bash -c "${PROTOC_PATH} --c_out=${CMAKE_CURRENT_SOURCE_DIR}/ --proto_path=${PROTO_DIR}/ ${PROTO_DIR}/*.proto")
The problem is that my protoc binary and related .so file is not in /usr/bin and /usr/lib or /usr/local/bin and /usr/local/lib. They are in a directory inside the project - $HOME/project-name/dependencies/bin/protoc and $HOME/project-name/dependencies/lib/libprotobuf.so.12
Due to this I am getting error - error while loading shared libraries: libprotobuf.so.12: cannot open shared object file: No such file or directory
But if I give the command as
execute_process(COMMAND bash -c "protoc--c_out=${CMAKE_CURRENT_SOURCE_DIR}/ --proto_path=${PROTO_DIR}/ ${PROTO_DIR}/*.proto") and run cmake . then it works fine as linker is able to get the .so file from /usr/lib
Mentioned below is a part of my CMakeLists.txt file
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath=${PROTOC_LIB_PATH} -L${PROTOC_LIB_PATH} -lprotobuf")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-rpath=${PROTOC_LIB_PATH} -L${PROTOC_LIB_PATH} -lprotobuf")
execute_process(COMMAND bash -c "${PROTOC_PATH} --c_out=${CMAKE_CURRENT_SOURCE_DIR}/ --proto_path=${PROTO_DIR}/ ${PROTO_DIR}/*.proto")
But it's not working due to aforementioned error.
Also for those who might say it's a duplicate I have looked into and tried the following SO questions:
Turning on linker flags with CMake
I don't understand -Wl,-rpath -Wl,
CMake link to external library
Does cmake have something like target_link_options?
CMAKE RPATH not working - could not find shared object file
https://serverfault.com/q/279068/435497
How to add linker flag for libraries with CMake?
https://serverfault.com/a/926072/435497
If you do not have a special use case, you do not need to call protoc yourself. Let CMake do this for you.
Have a look at: https://cmake.org/cmake/help/v3.16/module/FindProtobuf.html
and Cmake : find protobuf package in custom directory
I found this link which has a script showing how to create a PROTOBUF_GENERATE_C function which can then be used to generate the .pb-c abd .pb-h files.
From the above script I got the idea to make use of find_program which is similar to find_library in a way that it lets you pass the PATHS/PATH option so that CMake looks for the required program in the mentioned path.
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 am writing a Makefile placed in the root directory of my project.
Here is my project directory tree:
project:
Makefile
README
assets/
build/
src/
Actually in Makefile I'm prepending each file with a variable to tell to gcc where find the file:
gcc -c $(SOURCE_DIR)file.c
I'd like to compile .c source files placed in the directory src without change the working directory in the Makefile or prepending the SOURCE_DIR to each file that I have to compile.
Is there any way to do this?
P.S. I've read manual (man gcc) looking for some gcc options. I found that -L or -l could help me, but I didn't understand their usage.
The standard way, like the autotools do, would be write a Makefile in src dir, and then in your main Makefile call that sub Makefile:
programs:
make -C $(SOURCE_DIR) the_program
This case, you can build the program no matter you are in the main directory or in the src directory.
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!