How to add source files in another folder - cmake

I'm using cmake to build my project in C++. Assume I have the following directories on my Source folder
Source
|_Dir1
| |_Class.cpp
| |_Class.hpp
|
|_Dir2
|_Main.cpp
In Dir1 there's a class with its header and implementation files (Class.cpp and Class.hpp).
In Dir2 there's the main application which uses the class in Dir1
What is the good way to tell the CMakeLists in Dir2 to build the executable with Dir1/Class.cpp file?
EDIT: To be more specific, I want to define that the source file for Class.cpp has to be used in Dir1's CMakeLists.txt, and not in Dir2's. Doing it the other way feels plain wrong to me and it's hard to use, so if there's a reason they're enforcing me to do this some clarification on the topic would be nice.
What I'm currently doing is hard-coding the Class.cpp file location in Dir2/CMakeLists.txt but that just doesn't scale when I've got a bunch of classes interacting together.

Supposed you have a single CMakeLists.txt file at the Source directory, you'll create two variables using different file() commands
file(GLOB Dir1_Sources RELATIVE "Dir1" "*.cpp")
file(GLOB Dir2_Sources RELATIVE "Dir2" "*.cpp")
and add both sets generated by the file() commands to your target's source list:
add_executable(MyProgram ${Dir1_Sources} ${Dir2_Sources})
Alternatively you can place a CMakeLists.txt file under Dir1 and Dir2 (Main) looking as follows
Source
|
|_ CMakeLists.txt
| > project(MyProgram)
| > cmake_minimum_required(VERSION 3.8)
| > add_subdirectory("Dir1")
| > add_subdirectory("Dir2")
|
|_ Dir1
| |_ CMakeLists.txt
| > file(GLOB Sources "*.cpp")
| > add_library(Dir1 STATIC ${Sources})
|_ Dir2
|_ CMakeLists.txt
> file(GLOB Sources "*.cpp")
> add_executable(MyProgram ${Sources})
> target_link_libraries(MyProgram Dir1)
to add subdirectories as further (static) libraries linked to your main target.

Related

Cmake add external project?

I'm not entirely sure if externalproject_Add as most of the examples I can find on it is about downloading git etc/but maybe thats it...
Esentially I have :
FolderA // inherited project
> main.cpp
> CMakeList.txt
> libFolder
>someStuff.h
>someStuff.cpp
FolderB // base project
> main.cpp
> CMakeList.txt
> libFolder_Core
>someStuff_Core.h
>someStuff_Core.cpp
I want to "not" have to build static/dynamic/etc lib every time I make a change to project in folderB, I just want to include the CMakeList.txt from that folder in my folderA, FolerB cmake only has something like
set(headers xx.h)
set(source xx.cpp)
set(all ${headers} ${source})
Just looking for a way to say in projectA, cmake,
get_filename_component(libs"${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE)
SET(coreLib ${libs}/someCoreLib/)
add_executable(name, main.cpp ${coreLib})
Is something like that possible?
You can do that easily with mordern CMake using exported target.
In project A:
add_library(projecta a.cpp b.cpp c.cpp)
add_library(projecta::projecta ALIAS projecta)
target_include_directories(projecta PUBLIC ...)
install(TARGETS projecta EXPORT projectaTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
install(
EXPORT projectaTargets
NAMESPACE projecta::
FILE projectaConfig.cmake
DESTINATION lib/cmake/projecta
)
export(
EXPORT projectaTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/projectaConfig.cmake"
)
This will make a target for projecta and export the targets for other project to use them.
If the project A itself has dependencies, consider exporting the targets to a target file, then generate a config file that also find the package of your dependencies. More on that on the It's Time To Do CMake Right blog post.
Simply add the path of your build directory in the CMake module path in the command line: -DCMAKE_PREFIX_PATH=/path/to/projecta/build
Then, in project B:
find_package(projecta REQUIRED)
add_executable(projectb x.cpp y.cpp z.cpp)
# link project b to project a,
# adding include directories and link dependencies
target_link_libraries(projectb PUBLIC projecta::projecta)

CMake: Include directory for local static library

I have a static library in my project, lets call it libcommon, and I am including a header file from this library #include <libcommon/common.h>, not the angular brakets, not upper quotes. How can I configure CMakeLists.txt so that it find the include?
Assume the directory structure is like this:
-- root/
\-- src/
| |-- libcommon/common.h
| \-- main/main.c
\-- CMakeLists.txt
I tried:
include_directories (... src)
and:
include_directories (... ${main_SOURCE_DIR}/src)
but the libcommon/common.h was not found.
I figured it out while writing the question:
Instead of using just include_directories, I had to use target_include_directories:
target_include_directories(main PRIVATE src)
or:
target_include_directories(main PRIVATE ${main_SOURCE_DIR}/src)

CMake: how to create include path to generated include files

I have a project with about 600 directories, containing the source for about a dozen libraries and several dozen programs. Some of the programs depend upon a C++ header file that is generated from a text file.
How do I cleanly tell CMake how to include that path to the generated header file into the include path for those source files which require it?
Or alternatively, how can I force the generated file to be installed into a known location before CMake attempts to compile those programs? (This idea is based on the current Makefile system, which generates the header and installs it into the /include directory where all source files can find it.)
Or is there some other alternative?
-- EDIT: added "toy" example --
This example does not work. I need a way to tell prog1 and prog2 where to find home.h.
My tree:
.
|-- prog1/
| |-- CMakeLists.txt
| `-- prog1.cpp
|-- prog2/
| |-- CMakeLists.txt
| `-- prog2.cpp
`-- share/
`-- dict/
|-- CMakeLists.txt
`-- gen.sh*
In share/dict:
cmake_minimum_required(VERSION 2.8.4)
project(dict)
set(SRC foo.c)
set(HEADERS foo.h home.h)
add_custom_target(home
ALL
DEPENDS ${CMAKE_INSTALL_PREFIX}/include/home.h
)
add_custom_command(
OUTPUT ${CMAKE_INSTALL_PREFIX}/include/home.h
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/gen.sh gen.sh
COMMAND gen.sh ${CMAKE_INSTALL_PREFIX}
)
add_library(dict ${SRC})
install(TARGETS dict DESTINATION lib)
install(FILES ${HEADERS} DESTINATION include)
In prog1 (and similarly in prog2):
cmake_minimum_required(VERSION 2.8.4)
project(prog1)
add_executable(prog1 prog1.cpp)
target_link_libraries(prog1 dict)
install(TARGETS prog1 DESTINATION bin)
After
add_library(dict ${SRC})
add
target_include_directories(dict
# The location of the headers before installation
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
# The location of the headers after installation
$<INSTALL_INTERFACE:include>
)
and read the link I already provided in the comment.
Outputting generated files into out-of-source build directory is an intended way to do it.
Use CMAKE_BINARY_DIR and CMAKE_CURRENT_BINARY_DIR as output prefix and as target_include_directories() argument.

How to set include_directories from a CMakeLists.txt file?

I seem to be having trouble setting the include path (-I) using the include_directories() command in CMake. My project directory is as follows:
Root
| - CMakeLists.txt
| - libs
| - | - CMakeLists.txt
| - | - inc
| - | - | - // lib specific includes
| - | - src
| - | - | - // lib specific sources
| - proj1
| - | - CMakeLists.txt
| - | - inc
| - | - | - // proj1 specific includes
| - | - src
| - | - | - // proj1 specific sources
The root CMakeLists.txt file looks like so:
project(ROOT)
add_subdirectory(libs)
add_subdirectory(proj1)
The CMakeLists.txt file under libs:
project(lib)
add_library(lib STATIC ${lib_hdrs} ${lib_srcs}) // for conciseness, omitted set()
And lastly, the CMakeLists.txt file under proj1:
project(proj1)
include_directories("${ROOT_SOURCE_DIR}/lib/inc") # <- problem line?
add_executable(proj1 ${proj1_srcs})
target_link_libraries(proj1 lib)
The goal is to create the library from the source and header files in libs, then link against the executable generated under proj1. Proj1 has some files that #include stuff in libs include, so I need to add the directories to be used with -I. Based on the documentation, that's what include_directories() is supposed to do. However despite explicitly setting that and following it with a debug message(${INCLUDE_DIRECTORIES}), the INCLUDE_DIRECTORIES variable is an empty string, and no directories are specified for the include path, so my compilation of proj1 fails.
I've also attempted removing the quotes around ${ROOT_SOURCE_DIR}/inc to see if that helped but no luck.
include_directories() populates a directory property called INCLUDE_DIRECTORIES:
http://www.cmake.org/cmake/help/v2.8.12/cmake.html#prop_dir:INCLUDE_DIRECTORIES
Note that CMake 2.8.11 learned the target_include_directories command, which populates the INCLUDE_DIRECTORIES target property.
http://www.cmake.org/cmake/help/v2.8.12/cmake.html#command:target_include_directories
Note also that you can encode the fact that 'to compile against the headers of the lib target, the include directory lib/inc is needed' into the lib target itself by using target_include_directories with the PUBLIC keyword.
add_library(lib STATIC ${lib_hdrs} ${lib_srcs}) # Why do you list the headers?
target_include_directories(lib PUBLIC "${ROOT_SOURCE_DIR}/lib/inc")
Note also I am assuming you don't install the lib library for others to use. In that case you would need to specify different header directories for the build location and for the installed location.
target_include_directories(lib
PUBLIC
# Headers used from source/build location:
"$<BUILD_INTERFACE:${ROOT_SOURCE_DIR}/lib/inc>"
# Headers used from installed location:
"$<INSTALL_INTERFACE:include>"
)
Anyway, that's only important if you are installing lib for others to use.
After the target_include_directories(lib ...) above you don't need the other include_directories() call. The lib target 'tells' proj1 the include directories it needs to use.
See also target_compile_defintions() and target_compile_options().

Moving Headers/Libraries/Executables to specific directories

I've recently started using CMake for one of my multi-platform projects, but I'm having a little trouble figuring out how to do something.
Basically, inside the project I've got multiple libraries and executables, all in their own folders. I would like to place all of the compiled libraries into one directory on build i.e. a lib folder inside the CMake build folder. I would like to do the same things for the executables.
CMake Build Directory
| ----------> bin (where i want the executables to go)
| ----------> lib (where i want the libraries to go)
| ----------> utils (where the libraries are ordinarily compiled)
| ----------> test (where the executables are ordinarily compiled)
There are directories inside utils and apps for all the different libraries and executables I'm making. I have a CMakeLists in the base folder of my source directory which adds all the subdirectories. If anything does not make sense then feel free to ask.
You can also use this:
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
Look at install CMake command.
Here example from that page:
install(TARGETS myExe mySharedLib myStaticLib
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static)
install(TARGETS mySharedLib DESTINATION /some/full/path)
So you can use CMAKE_BINARY_DIR instead /some/full/path
In addition, for includes:
install( FILES ${HEADERS}
DESTINATION inc )
[when set of header files to be installed]
install( DIRECTORY include/${PROJECT_NAME}/
DESTINATION inc)
[when header directory to be installed]
More Info