Having problems setting up a project to keep directory structure with cmake.
Project structure I want to keep:
Project
|-libA
| |-fileA.h
| |-fileA.cpp
| |-CMakeLists.txt
|-include
| |-fileI.h
|-program1
| |-main.cpp
| |-CMakeLists.txt
|-CMakeLists.txt
source code include example:
#include "libA/fileA.h"
This doesn't work. Cmake can't find "libA/fileA.h", it will only work if I create a following directory structure:
Project
|-libA
| |-libA (directory)
| |-fileA.h
| |-fileA.cpp
| |-CMakeLists.txt
|-include
| |-fileI.h
|-program1
| |-main.cpp
| |-CMakeLists.txt
|-CMakeLists.txt
What can I do to keep the project structure as shown in the first example and to keep directory name in source files? (eg #include "libA/fileA.h")
Project cmake:
cmake_minimum_required(VERSION 3.8)
project(A)
include_directories( ${PROJECT_SOURCE_DIR}/include )
add_subdirectory(libA)
add_subdirectory(program1)
libA cmake:
set(LIBA_SRC libA/fileA.cpp)
add_library(libA SHARED ${LIBA_SRC})
Program1 cmake:
set (PROGRAM1_SRC main.cpp)
add_executable (program1 ${PROGRAM_SRC})
target_link_libraries (program1 libA)
target_include_directories (program1 PUBLIC ${PROJECT_SOURCE_DIR}/libA)
If you change the include directory in program1 to
target_include_directories (program1 PUBLIC ${PROJECT_SOURCE_DIR})
it will search from your source directory, so "libA/fileA.h" will find it's target.
Related
to start with, I have the following repo structure.
root
|
|--- blocks
| |
| |---example
| |
| |---example.cpp
| |---CMakeLists.txt
|
|--- interfaces
|
|--- types
|
|-- types1.h
|-- types2.h
|-- CMakeLists.txt
What I would like to do is to only include types1.h in the cmake target of example.cpp. And I would like to include types1.h such that I can include it in example.cpp using its path relative to root (i.e. #include "interfaces/types/types1.h") and I don't want to use include_directories(${CMAKE_SOURCE_DIR}) since that would expose the whole repo to the target.
target_include_directories did not work since it only includes directories but not individual files and I don't want to include a whole directory and expose irrelevant headers in types folder to example.cpp or move types1.h to a dedicated subfolder.
Do you have any suggestions on how to achieve this?
My current solution is as below which gives fatal error: interfaces/types/types1.h: No such file or directory when I compile exampleblock target. (I eased the requirements for start and allowed interface_types target to include types2.h also even though example.cpp doesn't need it)
blocks/example/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
add_library(exampleblock STATIC
example.cpp
)
target_link_libraries(exampleblock INTERFACE
${CMAKE_SOURCE_DIR}/interfaces/types:interface_types
)
interfaces/types/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
add_library(interface_types INTERFACE)
target_include_directories(interface_types INTERFACE .)
I have a project with the below structure. Basically, there are two static libraries: lib_a and lib_b. lib_a uses classes and functions defined in lib_b. There is the main executable, which depends on lib_a (and indirectly on lib_b), and unit tests for lib_a, which also indirectly depend on lib_b.
project
|--CMakeLists.txt
|--static_lib_a
| |--CMakeLists.txt
| |--include
| | \--header_a.h
| \--src
| |--file_a.h
| \--file_a.cpp
|--static_lib_b
| |--CMakeLists.txt
| |--include
| | \--header_b.h
| \--src
| |--file_b.h
| \--file_b.cpp
|--main_exe
| |--CMakeLists.txt
| \--main.cpp
\--unit_test
|--CMakeLists.txt
|--main.cpp
\--test_lib_a.cpp
Since static libraries generally do not link with each other, both main_exe and unit_test need to link lib_a and lib_b. Is there a way to tell CMake that anything that links lib_a also needs to link with lib_b, without specifying this explicitly in main_exe and unit_test? That is, can I express this dependency in static_lib_a/CMakeLists.txt file?
What should be the content of each of the CMakeLists.txt file?
So far I have the following, which produces linking errors (that is, lib_b does not get linked to unit_test):
project/CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(project)
enable_testing()
add_subdirectory(static_lib_a)
add_subdirectory(static_lib_b)
add_subdirectory(main_exe)
add_subdirectory(unit_test)
project/static_lib_a/CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
add_library(lib_a STATIC)
target_sources(lib_a PRIVATE
src/file_a.cpp)
target_include_directories(lib_a
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(lib_a lib_b)
project/static_lib_b/CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
add_library(lib_b STATIC)
target_sources(lib_b PRIVATE
src/file_b.cpp)
target_include_directories(lib_b
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
main_exe/CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
add_executable(main_exe)
target_sources(main_exe PRIVATE main.cpp)
target_link_libraries(main_exe PRIVATE lib_a)
unit_test/CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
include(CTest)
add_executable(unit_test)
target_sources(unit_test PRIVATE
main.cpp
test_lib_a.cpp)
target_link_libraries(unit_test PRIVATE lib_a)
add_test(NAME unit_test COMMAND unit_test)
add_custom_target(run_unit_test ALL
COMMAND ${CMAKE_CTEST_COMMAND} -C debug --output-on-failure
DEPENDS unit_test)
The project has the following structure:
.
|- CMakeList.txt
`- src
|- lib
| |- CMakeList.txt
| `- libA
| |- CMakeList.txt
| |- libA.c
| `- libA.h
`- main
|- CMakeList.txt
`- main.c
and I want to include the libA.h file in main.c using #include "libA.h", but an error occurs when trying to compile fatal error: hello.h: No such file or directory. Can I make cmake add the appropriate include flags and I could write #include "libA.h".
I understand that I can manually add flags like -Ipath/to/src/lib/libA -Ipath/to/src/lib/libB ..., but I would like to automate this process.
Include_directories should solve that for you:
https://cmake.org/cmake/help/v3.0/command/include_directories.html
You can use the built-in PROJECT_SOURCE_DIR CMake variable to access the root source directory of your project. Use this with target_include_directories() to use #include "libA.h" in main.c:
In your src/main/CMakeLists.txt:
add_executable(MyMain main.c)
target_include_directories(MyMain PUBLIC ${PROJECT_SOURCE_DIR}/src/lib/libA)
You want to set your target_include_directories in your libA/CMakeLists.txt. After the target is built with add_library, you want to add the following instruction:
add_library(libA libA.c libA.h)
target_include_directories(libA PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
This instruction will specify that libA and any target that links to it also considers ${CMAKE_CURRENT_SOURCE_DIR} as a path to look for includes. This is known as a library's public header. Ideally, you would want those header files to be in their own subdirectory so you could include them easily to your other projects, without having the libA.c file be in the include directory. For example:
.
|- CMakeList.txt
`- src
|- lib
| |- CMakeList.txt
| `- libA
| |- CMakeList.txt
| |- include
| | `-libA.h
| |- src
| `- libA.c
`- main
|- CMakeList.txt
`- main.c
Solved.
If I create library
add_library(MyLib src/MyLib.cpp include/MyLib.h)
target_include_directories(MyLib PUBLIC include)
then I can write
add_executable(MyExe ${SOURCES} ${HEADERS})
target_link_libraries(MyExe MyLib)
The last line will automatically add the flag '-I/path/to/MyLib/include' when compiling MyExe.
There are numerous similar questions on Stack Overflow, but none come near to answering my question.
I have a C++ library built using CMake:
mylib
| - CMakeLists.txt
| - src/
| | - m.h
| | - m.cpp
| - include/
| | - mylib/
| | | - a.h
| | | - something/
| | | | - some.h
| - cmake/
| - mylibConfig.cmake.in
| - mylibConfigVersion.cmake.in
I then create another library or executable which includes the aforementioned library:
myapp
| - CMakeLists.txt
| - src/
| | - main.cpp
| - include/
| | - myapp/
| | | - b.h
| - libs
| | - mylib
And would like to use mylib within myapp like so. Please take notice how mylib headers are included in a directory like format:
#include <mylib/a.h>
#include <mylib/something/some.h>
mylib should be built when building myapp so that the following works without any other build steps:
$ cd myapp/build
$ cmake ..
$ make
Here is a list of some of the Stack Overflow posts I have reviewed. I have attempted each, and they simply do not work:
CMake: How to build external projects and include their targets
CMake ExternalProject_Add() and FindPackage()
Assuming in the project described, only header files in the mylib/include directory are to be considered public:
The top-level CMakeLists.txt for mylib needs to contain:
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
project(mylib VERSION 0.1 LANGUAGES CXX)
add_library(${MyLibName} ${MyLib_SOURCES})
target_include_directories(${MyLibName}
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
This ensures that projects including mylib will only have access to files in the include/ directory. Files in include/ can be used like #include <myfile.h> and files in include/mylib (the general convention) can be used like #include <mylib/myfile.h>.
The top-level CMakeLists.txt for myapp should include:
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
project(myapp VERSION 0.1 LANGUAGES CXX)
add_subdirectory(libs/mylib)
add_executable(${MyAppName} ${MyApp_SOURCES})
target_link_libraries(${MyAppName} ${MyLibName}
The use of add_subdirectory ensures that mylib will be built before myapp and target_link_libraries adds mylib to the executable.
As mentioned by Tzalumen, make sure you take a look at the CMake tutorials and prefer the use of cmake --build . instead of make.
So, I actually do this in one of my projects.
First, the library needs to be built with ADD_LIBRARY(), but I'm assuming you do that. Something like
ADD_LIBRARY (${MyLibName} ${SOURCES}) in the library's CMakeLists.txt
That adds the library into cmake's list of libraries.
Second, you add the library to your project with
target_link_libraries (${PROJECT_NAME} ${MyLibName}) in the executable's CMakeLists.txt, the same one where you have your add_executable (${PROJECT_NAME} ${SOURCES})
That will set up the dependency chain to force MyLibName to explicitly build before PROJECT_NAME.
I've got a question on cmake project configuration.
The following is my project structure.
trunk
|
|---- mylib
| |
| ---- mylib.h
| ---- mylib.c
| ---- *MYLIB_CMakeList.txt*
|
|---- alib
| |
| ---- alib.h
| ---- alibName.lib
| ---- *ALIB_CMakeList.txt*
|
|
|---- main
| |
| ---- main.cpp
| ---- *MAIN_CMakeList.txt*
|
---- *TOP_CMakeList.txt*
mylib subfolder contains the source code (c) to create my own static library. This code depends on alib.
The main subfolder contains the example code (C++) which uses mylib.
Here is how I've written my CMakeList files:
**TOP_CMakeList.txt**
cmake_minimum_required(VERSION 3.4)
add_subdirectory(mylib)
add_subdirectory(alib)
add_subdirectory(main)
------------------------------------------------------------------------------------------------------------
**MYLIB_CMakeList.txt**
cmake_minimum_required(VERSION 3.4)
project(MyLib C)
if (WIN32)
set(CMAKE_SHARED_LIBRARY_PREFIX "")
endif ()
include_directories(${alib_INCLUDE_DIRS})
add_library(${PROJECT_NAME} STATIC mylib.c)
target_link_libraries(${PROJECT_NAME} alib)
set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR} CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
------------------------------------------------------------------------------------------------------------
**ALIB_CMakeList.txt**
cmake_minimum_required(VERSION 3.4)
project(ALib)
set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR} CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
------------------------------------------------------------------------------------------------------------
**MAIN_CMakeList**
make_minimum_required(VERSION 3.4)
project(Executable CPP)
file(GLOB CPP_FILES *.cpp)
add_definitions(${MyLib_DEFINITIONS})
include_directories(${MyLib_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} ${CPP_FILES})
target_link_libraries(${PROJECT_NAME} MyLib)
With such configuration it doesn't recognize the alib dependency of mylib. In particular (I'm developing under Windows) I get this error:
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/../../../../x86_64-pc-cygwin/bin/ld:
cannot find -lalibName.lib
I can't figure out how to correctly do it. Any suggestions?
Seems that the alib project does not specify any kind of library targets the same way as mylib does:
Try adding this to alibs' CMake file
add_library(${PROJECT_NAME} STATIC <<< alib SOURCES HERE >>>)
Static libraries can't have dependencies(well, they can but they don't drag them with themselves) so there is no point in providing alib in target_link_libraries(...) for another static library. You should provide alib to the add_execuable command directly.
Alternatively, you can build a big static library from both mylib and alib but it will be less elegant and platfrom dependant. For gcc you should look at ar tool.
Remove the add_subdirectory(alib) command, then remove CMake file from the alib subfolder — you don't need it. Then in the cmake file where you have your add_executable command put the following(after the line);
link_directories(../alib)
target_link_libraries(${PROJECT_NAME} alibName.lib)