Build only part of a git submodule repository with CMake - c++

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
...

Related

Cmake: How to statically link packages to shared library?

I want to create a .dll library with all its dependencies packed inside the .dll.
However, there seems to be no easy way to achieve that with Cmake. My setup:
cmake_minimum_required(VERSION 3.0.0)
project(Main VERSION 0.1.0)
add_library(Main SHARED Main.cpp)
find_package(libzippp REQUIRED)
target_link_libraries(Main PRIVATE libzippp::libzippp)
This will produce both Main.dll but also libzippp.dll.
I would like to have libzippp.dll packed (statically linked) into Main.dll.
Of course you can't pack one DLL into another. You have to make libzippp a static library in the first place. To do this, build libzippp with BUILD_SHARED_LIBS set to NO at the CMake command line. Then libzippp::libzippp will be a static library when you go to find_package it.
This is easy enough to show steps for:
$ git clone git#github.com:ctabin/libzippp.git
$ cmake -S libzippp -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=NO -DCMAKE_INSTALL_PREFIX=$PWD/local -DLIBZIPPP_BUILD_TESTS=NO
$ cmake --build build --target install
$ tree local
local/
├── include
│   └── libzippp
│   └── libzippp.h
├── lib
│   └── libzippp_static.a
└── share
└── libzippp
├── FindLIBZIP.cmake
├── libzipppConfig.cmake
├── libzipppConfigVersion.cmake
├── libzipppTargets.cmake
└── libzipppTargets-release.cmake

How to specify gcm.cache location using g++ & CMake

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.

How to automaticaly dowload library from github inside lib folder cmake

I want to create my first big project in c++.
And I need to use some library. So I have made this structure
├── CMakeLists.txt
├── README.md
├── src
│   ├── CMakeLists.txt
│   ├── HelloWorld.cpp
│   ├── HelloWorld.h
│   └── main.cpp
├── tst
| ├── CMakeLists.txt
| ├── HelloWorld-test.cpp
| └── main.cpp
└── lib
and I want to automatically download and place the library in the lib folder. In my case, I want to clone googletest int lib folder. So I have tried that in my main project CMakeLists.txt file:
if(UNIX)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib/googletest)
execute_process(
COMMAND git clone "https://github.com/google/googletest.git" googletest
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
add_subdirectory(lib/googletest)
endif(UNIX)
But when I build I have this error :
CMake Error at CMakeLists.txt:17 (add_subdirectory):
add_subdirectory given source "lib/googletest" which is not an existing
directory.
The issue here is that the repository is cloned to the binary directory, but add_subdirectory looks for the directory relative to the source directory.
You need to use add_subdirectory with an absolute path here and pass a build directory. Furthermore add quotes to avoid issues with spaces in the file path.
set(REPO_PARENT "${CMAKE_CURRENT_BINARY_DIR}/lib")
set(REPO_DIR "${REPO_PARENT}/googletest")
set(REPO_BIN_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest_build")
file(MAKE_DIRECTORY ${REPO_DIR})
file(MAKE_DIRECTORY ${REPO_BIN_DIR})
execute_process(
COMMAND git clone "https://github.com/google/googletest.git" googletest
WORKING_DIRECTORY ${REPO_PARENT})
add_subdirectory(${REPO_DIR} ${REPO_BIN_DIR})

cmake target_link_libraries() cannot find renamed lib target by set_target_properties(archive_output_name)

RT~ ps: cmake version 3.9.2
My codebase just like this.
suzanwen#n224-004-133:~/repos/C++/ttt:)$ tree -L 2
.
├── build
│   ├── bin
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── lib
│   ├── Makefile
│   ├── test
│   └── thirdparty
├── build.sh
├── CMakeLists.txt
├── Makefile
├── test
│   ├── CMakeLists.txt
│   └── main.cc
└── thirdparty
├── CMakeLists.txt
├── gflags
└── hellolib
10 directories, 9 files
my thirdparty/hellolib/CMakeLists.txt is
PROJECT(hello)
SET(LIBHELLO_SRC hello.cc)
MESSAGE(STATUS "LIBRARY PATH=" ${LIBRARY_OUTPUT_PATH})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES ARCHIVE_OUTPUT_NAME "hello")
my test/CMakeLists.txt is
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/thirdparty/hellolib
${PROJECT_SOURCE_DIR}/thirdparty/gflags/include)
IF(LIBRARY_OUTPUT_PATH)
LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH})
ENDIF(LIBRARY_OUTPUT_PATH)
ADD_EXECUTABLE(main main.cc)
TARGET_LINK_LIBRARIES(main hello)
# TARGET_LINK_LIBRARIES(main hello_static)
when I build my top-level project, an error occurs like this.
/usr/bin/c++ -rdynamic CMakeFiles/main.dir/main.cc.o -o ../bin/main -L/home/suzanwen/repos/C++/ttt/build/lib -Wl,-rpath,/home/suzanwen/repos/C++/ttt/build/lib -lhello
/usr/bin/ld: cannot find -lhello
But when I comment the line # SET_TARGET_PROPERTIES(hello_static PROPERTIES ARCHIVE_OUTPUT_NAME "hello") and TARGET_LINK_LIBRARIES with hello_static, everything goes fine.
It seems that TARGET_LINK_LIBRARIES cannot find renamed lib target. Could anyone explain it? thanks in advance.
It seems that TARGET_LINK_LIBRARIES cannot find renamed lib target.
Setting ARCHIVE_OUTPUT_NAME property renames not a target, but an output file. So linking with a target still works:
TARGET_LINK_LIBRARIES(main hello_static)
One cannot rename the target once it is created, but it is possible to create ALIAS for a target:
ADD_LIBRARY(hello ALIAS hello_static)
After that it is possible to link with the alias:
TARGET_LINK_LIBRARIES(main hello)

CMake 'no rule to make target' with external library

I am trying link one of my programs to libevent. I am using CMake as build system. My project structure is as follows:
my_project
├── CMakeLists.txt
├── README.md
├── build
│  └── Build stuff
└── software
├── README.md
├── CMakeLists.txt
├── include
├── libraries
│   ├── libevent
│ │   └── CMakeLists.txt
│   └── anotherlibrary
│      └── CMakeLists.txt
├── prog1
│   ├── CMakeLists.txt
├── prog2
│   ├── CMakeLists.txt
└── prog3
└── CMakeLists.txt
CMakeList.txt of prog1 (the one that's needs to be linked to libevent)
cmake_minimum_required(VERSION 2.6)
project (prog1)
file(GLOB prog1
"*.h"
"*.cpp"
)
include_directories("${PROJECT_INCLUDE_DIR}/libevent/include")
add_executable(${PROJECT_NAME} ${prog1})
target_link_libraries(${PROJECT_NAME} event_core)
But when I build the project make can't find the library build by libevent. it searched for: libraries/libevent/lib/libevent_core.a this is the wrong path since libevent builds it libs inside: my_project/build/software/libraries/libevent/lib/libevent_core.a
How do I tell CMake to search there for the library? I already added the following lines to my Cmake file but this wasn't working
link_directories(/my_project/build/software/libraries/libevent/lib/)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/lib)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/bin)
Anyone a suggestion?
I fixed the problem myself by removing the content from the build directory and re running cmake .. inside the build directory.
I think CMake was somehow not aware of the changes I made and by rebuilding the project the problem was fixed.