I am currently working on a project which requires C++20 (g++ v11) features and CMake. The project tree is similar to the following one:
- Top level
- src
- IO
- IO.cpp
- CMakeLists.txt
- main.cpp
- CMakeLists.txt
CMake compiles IO module without any problem but It generates gcm.cache folder in a following way:
- build
- Some other CMake files and folders
- bin
- lib
- src
- IO
- gcm.cache
- IO.gcm
Therefore, g++ can not find gcm.cache folder and gives me this error:
IO: error: failed to read compiled module: No such file or directory
IO: note: compiled module file is 'gcm.cache/IO.gcm'
IO: note: imports must be built before being imported
IO: fatal error: returning to the gate for a mechanical issue
I would be grateful if anyone tell me that there is a way to specify gcm.cache locations using CMake or force CMake to search gcm files recursively or tell it to create a top level gcm.cache and store everything inside of it. I can not find any answer on anywhere since C++20 documentations are terrible. Thanks in advance...
I have experienced the exact same issue, and without actually discovering a solution have found a workaround. Complete code found here.
In short, I create a symbolic link such that subprojects are all using the gcm.cache/ directory located in the root directory of the project. Create a symlink like so:
ln -fs ../gcm.cache gcm.cache
This is the directory tree of the project:
.
├── engine
│ ├── core
│ │ └── types.cpp
│ ├── engine.cpp
│ ├── gcm.cache -> ../gcm.cache
│ ├── Makefile
│ └── memory
├── gcm.cache
├── init.sh
├── Makefile
└── testgame
├── gamelib.cpp
├── gcm.cache -> ../gcm.cache
├── Makefile
└── test.cpp
So when gcc builds the engine and testgame projects it actually uses the gcm.cache/ from the root directory. Until something better comes along this is my go-to method.
Related
I have a C++ project with submodule another_repo:
.
├── CMakeLists.txt
├── ext
│ └── another_repo
│ └── CMakeLists.txt
├── include
└── src
I would like to build only part of another_repo. That said, I need a new, customized CMakeLists.txt to build another_repo, instead of using its original one ./ext/another_repo/CMakeLists.txt.
But how can I do this in the root directory ./CMakeLists.txt?
If you want to build only a part of another_repo then just create a new target which only build the part you want.
For e.g, another_repo has following files:
another_repo/
│── a.cpp
│── b.cpp
│── c.cpp
And you want to build only a.cpp and b.cpp (assuming they don't depend on c.cpp).
In you root directory CMakeLists.txt:
...
set(ANOTHER ext/another_repo)
add_library(part_of_another_repo ${ANOTHER}/a.cpp ${ANOTHER}/b.cpp)
#or add_executable() if it is an executable
...
I have a given project structure
.
├── CMakeLists.txt
├── lib
│ ├── lodepng
│ │ ├── CMakeLists.txt
│ │ └── src
│ │ ├── lodepng.cpp
│ │ └── lodepng.h
│ └── pixel_reader
│ ├── CMakeLists.txt
│ └── src
│ ├── hello.cpp
│ └── hello.h
├── main.cpp
With the following CMakeLists
./CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(pov_system VERSION 1.0)
add_subdirectory(lib/lodepng)
add_subdirectory(lib/pixel_reader)
add_executable(pov_system main.cpp)
target_link_libraries(pixel_reader PRIVATE lodepng)
target_link_libraries(pov_system PRIVATE pixel_reader)
./lodepng/CMakeLists.txt
add_library(
lodepng
src/lodepng.cpp
src/lodepng.h
)
target_include_directories(lodepng PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
./pixel_reader/CMakeLists.txt
add_library(
pixel_reader SHARED
src/hello.cpp
src/hello.h
)
target_include_directories(pixel_reader PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
As one can see, I try to link the 'lodepng' library to the 'pixel_reader' library and include the 'lodepng.h' to the 'hello.h' file.
But at the moment I get the following error while trying to build the project.
[build] <path-to-project>/pov_system/lib/pixel_reader/src/hello.h:2:10: fatal error: lodepng.h: No such file or directory
[build] 2 | #include "lodepng.h"
[build] | ^~~~~~~~~~~
[build] compilation terminated.
Question
Why is my code not finding the 'lodepng.h' file or (and even more important) is it a good practice to link from one library to another?
Maybe two really simple questions, but just started to dive into the world of CMake, Compiling, etc... and I really appreciate your help.
Why is my code not finding the 'lodepng.h' file or (and even more important)
Because you probably didn't give it correct path. One way to fix that would be to give the exact path in hello.h
#include "../../lodepng/src/lodepng.h
Second way is to use target_include_directories:
target_include_directories(pixel_reader PUBLIC "../../lodepng/src/")
is it a good practice to link from one library to another?
It depends on your project. If library A requires library B, then yes, it is okay in my opinion.
More importantly, you are creating the target in the wrong place i.e., in the root CMakeLists file. It must be done in the directory in which target is created.
./pixel_reader/CMakeLists.txt
# create target
add_library(
pixel_reader SHARED
src/hello.cpp
src/hello.h
)
target_link_libraries(pixel_reader PRIVATE lodepng) #link library where target is created
target_include_directories(pixel_reader PUBLIC "../../lodepng/src/")
target_include_directories(pixel_reader PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
Your pixel_reader library target possibly needs lodepng.h header to compile, because it depends on it.
something like
target_include_directories(pixel_reader PUBLIC "PATH_TO_LODE_PNG_HEADER_DIRECTORY")
could solve this problem.
I have for some time had some problems incorporating modern cmake into a project I've been working fr some while and seem to be stuck on how i should define the the individual CMakeLists, and the top-level CMakeList.
My project structure is pretty simple.
├── build
└── src
├── include
│ ├── database
│ │ ├── database.cpp
│ │ └── database.h
│ ├── match
│ │ ├── match.h
│ │ └── mathc.cpp
│ ├── record
│ │ ├── lib
│ │ ├── record.cpp
│ │ └── record.h
│ └── spectogram
│ ├── spectogram.cpp
│ └── spectrogram.h
└── main.cpp
main.cpp are linked to all the includes, and some of the includes should know the presence of other includes, meaning, I should be able to include match.h in
database.h. Some third-party libs are also going to be used, in this case I am using portaudio, download and installed using externalproject_add, which should only be visible for the include which holds the library, in this case record, should only see this.
But how I should define the individual CMakeList, is currently unknown.
I've scouted the net for a proper way of setting this up, but cannot seem to find one that I understand.
How do i define the CMakeLists for this project, and how do i make sure that the includes, are visible for the Main.cpp and the includes files that need them, and how do I make third-party-libraries visible only for the includes that it is being used for.
CMakeLists example structure tried:
CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
project(soundcloud)
#add_subdirectory(src/database)
#add_subdirectory(src/match)
#add_subdirectory(src/record)
add_subdirectory(src/include/spectogram)
add_executable(cmakeDemo src/main.cpp)
SET_TARGET_PROPERTIES(cmakeDemo PROPERTIES LINKER_LANGUAGE Cxx)
target_link_libraries(cmakeDemo spectogram)
#target_link_libraries(cmakeDemo database match record spectogram)
src/include/database/CMakeLists.txt
add_library(spectogram STATIC .)
target_include_directories(spectogram PUBLIC .)
getting error message:
CMake Error: Error required internal CMake variable not set, cmake may not be built correctly.
Missing variable is:
CMAKE_Cxx_LINK_EXECUTABLE
CMake Error: Cannot determine link language for target "spectogram".
CMake Error: CMake can not determine linker language for target: spectogram
You can use the PRIVATE property of target_include_directories. When PRIVATE, it means that the include directories will be available to the sources of the target. When PUBLIC, it will also be available to whomever links to the target.
If I were writing this in a single CMakeLists.txt, I'd do this:
cmake_minimum_required(VERSION 3.0)
add_library(database STATIC src/include/database.cpp)
target_include_directories(database PUBLIC src/include/database)
################
add_library(match STATIC src/include/mathc.cpp)
target_include_directories(match PUBLIC src/include/match)
################
include(ExternalProject)
ExternalProject_Add(portAudio ${SomeCommands})
add_library(record STATIC src/include/record.cpp)
target_include_directories(record PUBLIC src/include/record) # When cmakeDemo links to this, it'll get these includes
target_include_directories(record PRIVATE src/include/record/lib) # When cmakeDemo links to this, it won't get these includes
target_link_libraries(record portAudio)
#################
add_library(spectogram STATIC src/include/spectogram.cpp)
target_include_directories(spectogram PUBLIC src/include/spectogram)
##################
add_executable(cmakeDemo src/main.cpp)
target_link_libraries(cmakeDemo database match record spectogram)
If I were to do this with distributed CMakeLists.txt, I'd split the files where the ###### lines are, fix the paths, and use add_subdirectory() to include the sub-directories from higher-level cmake files.
First, you don't link to includes, you just "include" them during compilation.
Some people put one CMakeList.txt into every directory that contains a fairly independent compilation unit.
Some people just use one big one at the the top.
Having just one CMakeList.txt file makes it easier to start, but if the project gets huge, things get messy.
For every compilation unit, you can specify the include directories with target_include_directories
Would anyone be able to post a simple example of how to compile code which uses libfreenect2? After installing the library, the following structure is created in my home directory:
→ tree freenect2
freenect2
├── include
│ └── libfreenect2
│ ├── config.h
│ ├── export.h
│ ├── frame_listener.hpp
│ ├── frame_listener_impl.h
│ ├── libfreenect2.hpp
│ ├── logger.h
│ ├── packet_pipeline.h
│ └── registration.h
└── lib
├── cmake
│ └── freenect2
│ └── freenect2Config.cmake
├── libfreenect2.so -> libfreenect2.so.0.2
├── libfreenect2.so.0.2 -> libfreenect2.so.0.2.0
├── libfreenect2.so.0.2.0
└── pkgconfig
└── freenect2.pc
I attempted to compile with the .pc file using a line similar to this found on the pkg-config wikipedia page:
gcc -o test test.c $(pkg-config --libs --cflags libpng)
But came with up with this error:
./test: error while loading shared libraries: libfreenect2.so.0.2: cannot open shared object file: No such file or directory
Obviously, I messed up the compilation process somewhere, but I'm not sure where to look since this is error occurs on runtime and not at compile time. There's also a .cmake file created with the library install, which I'm sure would lead to a more robust and proper solution, but I'm not entirely sure how to use that and haven't been able to find a simple guide showing how to do so. Any links to beginner-friendly documentation are also appreciated. In the documentation for libfreenect2, it says to use this line when compiling cmake -Dfreenect2_DIR=$HOME/freenect2/lib/cmake/freenect2 -- is this something that I'd have to use when making the library or when making my application?
Another tangentially related question, would it be better to move the /include and /lib directories to /usr/local/include and /usr/local/lib respectively? I believe that would "install" the library system-wide, but I imagine there's some reason that libfreenect2 doesn't do it automatically and I'm not sure what that is.
Well, I just use cmake with a CMakeLists.txt file that I create. Do like this:
Create a CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project("My Project")
set(CMAKE_CXX_FLAGS "-std=c++11")
find_package(freenect2 REQUIRED)
include_directories("/usr/include/libusb-1.0/")
INCLUDE_DIRECTORIES(
${freenect2_INCLUDE_DIR}
)
add_executable(main ./main.cpp)
target_link_libraries(main ${freenect2_LIBRARIES})
In this file, I assume we want to compile the main.cpp file that uses libfreenect2. So, in your local directory create a build folder, using the terminal:
mkdir build && cd build
Then, run the command in the terminal:
cmake -Dfreenect2_DIR=$HOME/freenect2/lib/cmake/freenect2 .. && make
this should create main executable in the build folder. Please, note that this cmake command specifies the freenect2 directory. In this case I assume it was placed in the /home directory.
However, I understand that having to type that long cmake command or search for it on the terminal history may be boring for some people. So, it is possible to embed the command like this:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project("My Project")
set(CMAKE_CXX_FLAGS "-std=c++11")
# Set cmake prefix path to enable cmake to find freenect2
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{HOME}/freenect2/lib/cmake/freenect2)
find_package(freenect2 REQUIRED)
include_directories("/usr/include/libusb-1.0/")
INCLUDE_DIRECTORIES(
${freenect2_INCLUDE_DIR}
)
add_executable(main ./main.cpp)
target_link_libraries(main ${freenect2_LIBRARIES})
After, just run this in the terminal:
mkdir build && cd build && cmake .. & make
This answer was my source for this second way of compiling the code.
Hope this helps!
I have instaled Eclipse form repository in Debian it is:
Version: 3.8.1 Build id: debbuild
I create project on platform with MIPS arch. Ofcorse I have works toolchain, and I tested him, evrything it it ok.
To my project I whant tu add Library DBus 1.6.8, this library was also cross compile, so I have got shared library libdbus-1.so.3.7.2 for MIPS in hide direcytory dbus-1.6.8/dbus/.libs. And n direcytory /dbus-1.6.8/dbus can find all header file
dbus-1.6.8/dbus$ tree
.
├── dbus-address.c
├── dbus-address.h
├── dbus-arch-deps.h
├── dbus-arch-deps.h.in
├── dbus-auth.c
├── dbus-auth.h
├── dbus-auth-script.c
├── dbus-auth-script.h
├── dbus-auth-util.c
├── dbus-bus.c
├── dbus-bus.h
├── dbus-connection.c
├── dbus-connection.h
├── dbus-connection-internal.h
├── dbus-credentials.c
├── dbus-credentials.h
├── dbus-credentials-util.c
├── dbus-dataslot.c
├── dbus-dataslot.h
├── dbus-errors.c
├── dbus-errors.h
├── dbus-file.c
├── dbus-file.h
├── dbus-file-unix.c
├── dbus-file-win.c
├── dbus.h
├── dbus-hash.c
├── dbus-hash.h
.....
.....
.....
.....
Now I whant to add this Cross Compiled library to my project in Eclipse. Yes ofcorse I have read a few topic in this forum, I try difrent method but all time I got some error like
mipsel-linux-gcc -O3 -Wall -c -fmessage-length=0 -MMD -MP
-MF"src/dbus-1.6.8/tools/dbus-cleanup-sockets.d" -MT"src/dbus-1.6.8/tools/dbus-cleanup-sockets.d" -o "src/dbus-1.6.8/tools/dbus-cleanup-sockets.o"
"../src/dbus-1.6.8/tools/dbus-cleanup-sockets.c"
../src/dbus-1.6.8/tools/dbus-cleanup-sockets.c:25:20: fatal error:
config.h: No have file or direcytory compilation terminated.
Now I have add below things
I moved whole direcytory dbus-1.6.8 to direcytory with project
In
Project -> Propoerites -> C/C++ General -> Path & Symbols
I add to tab INCLUDE :
/path/form/my/system/MyProject/src/dbus-1.6.8/dbus
And to tab LIBRARIES :
/path/form/my/system/MyProjectsrc/dbus-1.6.8/dbus/libs
And I gets still above error:
------------------------------EDIT----------------------------
I have something changed. I also give error but I feel that I'm more closer solve this problem.
In the:
Properities -> C/C++ Build -> Settings
In Tab Tool Settings in Cross G++ Linker with Libraries I additioned
Window Libraries (-l)
dbus-l
Window Library search path (-L)
/my/home/direcytory/Pulpit/dbus_demo/lib/dbus-1.6.8/dbus/.libs
And I get error
Description Resource Path Location Type final link failed:
Nonrepresentable section on output Jakis C/C++ Problem
Description Resource Path Location Type Jakis: hidden symbol `stat' in
/home/****/buildroot-eglibc-gcc464/usr/bin/../mipsel-buildroot-linux-gnu/sysroot/usr/lib/libc_nonshared.a(stat.oS)
is referenced by DSO Jakis C/C++ Problem
and Console output
mipsel-linux-g++
-L/home/.../Pulpit/dbus_demo/lib/dbus-1.6.8/dbus/.libs -o "Jakis" ./src/communicatorapi.o ./src/dbus.o ./src/filemanager.o ./src/main.o
./src/mediator.o ./src/observer.o ./src/program.o -ldbus-1
/home/.../buildroot-eglibc-gcc464/usr/bin/../lib/gcc/mipsel-buildroot-linux-gnu/4.6.4/../../../../mipsel-buildroot-linux-gnu/bin/ld:
warning: libc.so.0, needed by
/home/.../Pulpit/dbus_demo/lib/dbus-1.6.8/dbus/.libs/libdbus-1.so,
not found (try using -rpath or -rpath-link)
/home/.../buildroot-eglibc-gcc464/usr/bin/../lib/gcc/mipsel-buildroot-linux-gnu/4.6.4/../../../../mipsel-buildroot-linux-gnu/bin/ld:
Jakis: hidden symbol `stat' in
/home/..../buildroot-eglibc-gcc464/usr/bin/../mipsel-buildroot-linux-gnu/sysroot/usr/lib/libc_nonshared.a(stat.oS)
is referenced by DSO
/home/...../buildroot-eglibc-gcc464/usr/bin/../lib/gcc/mipsel-buildroot-linux-gnu/4.6.4/../../../../mipsel-buildroot-linux-gnu/bin/ld:
final link failed: Nonrepresentable section on output makefile:45:
polecenia dla obiektu 'Jakis' nie powiodły się