CMake generated project file to list external source - visual-studio

please consider the following structure:
dev_root/
\__ common/
\__ inc/
\__ src/
\__ CMakeLists.txt
\__ project1/
\__ inc/
\__ src/
\__ CMakeLists.txt
\__ project2/
\__ inc/
\__ src/
\__ CMakeLists.txt
Project1 and Project2 are separated projects.
They both use common code.
I want to list (selectively) some common source files into each project's visual studio project file, so that I could edit them in IDE.
I don't want a standalone library for the common code.
For now I use relative paths, for example, in project1's cmake file:
set(_hdr
inc/proj1.h
../common/inc/common1.h
)
set(_src
src/proj1.cxx
../common/src/common1a.cxx
../common/src/common1b.cxx
)
source_group("common\\inc" FILES
../common/inc/common1.h
)
source_group("common\\src" FILES
../common/src/common1a.cxx
../common/src/common1b.cxx
)
source_group("inc" FILES inc/proj1.h)
source_group("src" FILES src/proj1.cxx)
add_executable( project1 ${_src} ${_hdr} )
This is not flexible - if ever I want to move folders around, all CMakeLists.txt must be reviewed and modified.
Is there a more elegant way to de-couple the dependencies, or what is a better way to deal with common source files?
Any suggestions welcomed.
Thanks a lot.

You may set variable to the path to 'common' folder, and use it for refer to files in it. So, whenever you need to move 'common' folder around, you need to edit only this variable.
CMakeLists.txt:
set(COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common)
project1/CMakeLists.txt:
set(_hdr
inc/proj1.h
${COMMON_DIR}/inc/common1.h
)
set(_src
src/proj1.cxx
${COMMON_DIR}/src/common1a.cxx
${COMMON_DIR}/src/common1b.cxx
)
...

Related

Installing CMake package config files for MacOS frameworks

I created a versioned MacOS framework with CMake and stumbled over the question where to install the package config files sample-config.cmake, sample-config-version.cmake, sample-exports.cmake, sample-exports-release.cmake.
The framework is versioned so the structure is roughly as follows:
<sample.framework>
|-- Headers # link to Versions/Current/Headers
|-- Resources # link to Versions/Current/Resources
+-- Versions
|-- Current # link to B
+-- B
|-- Headers
+-- Resources
|-- CMake
+-- Info.plist
I use CMakes CMakePackageConfigHelpers macros to generate a package config file from a template sample-config.cmake.in with the content
#PACKAGE_INIT#
include("${CMAKE_CURRENT_LIST_DIR}/sample-export.cmake")
CMake does not mention versioned frameworks and recommends to install the files into the directory Resources/CMake.
I did so by calling
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sample-config.cmake"
DESTINATION sample.framework/Resources/CMake
COMPONENT development
)
The generated file looks like this:
####### Expanded from #PACKAGE_INIT# by configure_package_config_file() #######
####### Any changes to this file will be overwritten by the next CMake run ####
####### The input file was sample-config.cmake.in ########
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
macro(set_and_check _var _file)
set(${_var} "${_file}")
if(NOT EXISTS "${_file}")
message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
endif()
endmacro()
macro(check_required_components _NAME)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(NOT ${_NAME}_${comp}_FOUND)
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME}_FOUND FALSE)
endif()
endif()
endforeach()
endmacro()
include("${CMAKE_CURRENT_LIST_DIR}/sample-export.cmake")
Error:
There's a difference in the generated config file whether I install those files to Resources/CMake or to Versions/B/Resources/CMake although both point to the same directory.
When installing via the Resources link to Resources/CMake the call to set PACKAGE_PREFIX_DIR is generated as
`get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)`
but when installing via Versions/B/Resources/CMake it is generated as
`get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../../" ABSOLUTE)`
As a consequence of this the package cannot be found by find_package(sample CONFIG) when installing to Versions/B/Resources/CMake.
Did anybody was facing this error before?
Thanks for any input on this.

Share ExternalProject between multiple projects in CMake

I would like to share an ExternalProject between different CMake projects. Imagine a structure like the following:
prj1
|- CMakeLists.txt
|- ...
prj2
|- CMakeLists.txt
|- ...
lib
|- ext
|- gtest
|- CMakeLists.txt
|- googletest
|_ actual_google_test_files
What I'm trying to obtain is telling CMakeLists.txt to use the gtest in lib/ext/gtest with ExternalProject, without re-building gtest everytime in place for each project.
Ideally, gtest gets built once in its folder and projects just use it. I tried using ExternalProject like explained here (http://kaizou.org/2014/11/gtest-cmake/) and including lib/ext/gtest/CMakeLists.txt in the projects, but gtest gets re-compiled for every user.
tldr: You should try to integrate google_test as "subproject" not as prebuilt and use a "meta" CMakeLists.txt...
Please read https://crascit.com/2015/07/25/cmake-gtest/
CMakeLists.txt.in:
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
CMakeLists.txt:
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download" )
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download" )
# Prevent GoogleTest from overriding our compiler/linker options
# when building with Visual Studio
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This adds
# the following targets: gtest, gtest_main, gmock
# and gmock_main
add_subdirectory("${CMAKE_BINARY_DIR}/googletest-src"
"${CMAKE_BINARY_DIR}/googletest-build")
add_subdirectory(prj1)
add_subdirectory(prj2)

Creating a CMakeLists.txt with header and mains

I have divided my program in 3 folders: build, include, and src.
Build is where I want all the files created from the Makefile to go, include contains a "file.h", and src contains a "file.c" and "main.c".
I have written this in the CMakeLists.txt file:
cmake_minimum_required (VERSION 3.5.1)
project(Listas_interlazadas)
include_directories(${include})
add_executable(ejec
src/main.c
src/listas.c
include/listas.h
)
Nonetheless, I believe I should somehow include the src folder. Also, how do I send all files to the build folder? From the terminal, right?
Thanks.
Your code need some minor reworks.
The command include_directories must point to an valid path
Add header files only in case they are not included in any of your source files
Assume the following structure of your project:
project
+--source
| +--CMakeLists.txt
| +--src
| | +--main.c
| | +--listas.c
| +--include
| +--listas.h
+--build
Reworked CMakeLists.txt
cmake_minimum_required (VERSION 3.5.1)
project(Listas_interlazadas)
include_directories(include)
add_executable(ejec
src/main.c
src/listas.c
)
Back to your questions:
Add the sources: You already inserted the required source files. See add_executable.
Copy sources to build folder: This is not necessary.
To build your project, you have to run cmake and make (or nmake on windows).
Steps:
Open a command shell
Move to the build folder
Run: cmake ../source
Run: make
Some important parts of a CMakeLists.txt

Copy folder into subdirectory in CMake on Windows

I have a CMake project using Makefiles on Windows, with a folder structure that looks like this (the build takes place in build):
project
|- build
|- ...
|- otherfolder
|- stuff
|- more stuff
As a build step (pre- or post doesn't matter), I want to make a copy of project into build (excluding the build folder), like so:
project
|- build
|- ...
|- project
|- otherfolder
|- stuff
|- more stuff
|- otherfolder
|- stuff
|- more stuff
Other options might be acceptable as well, e.g. copying to a temporary directory outside the project root before moving it into place, but CMake seemingly has no builtin support for generating temporary directories.
Things I've tried: xcopy has support for excluding certain files and directories, but refuses to copy even if I explicitly exclude the build folder. cmake -E copy_directory does not (from what I'm able to find) support excluding certain directories.
CMake's file(COPY ... PATTERN build EXCLUDE ... copies successfully, but it runs at CMake configure time and I haven't been able to find a way to make it run at build time.
I might resort to using Python and shutil, but it would be nice if it could be done without additional dependencies, so I'd prefer a batch file solution.
There are several ways for doing selectable directory copiing.
You can use cmake -P for execute cmake script at any time. E.g:
copy_to_build.cmake:
file(COPY . DESTINATION build PATTERN build EXCLUDE)
CMakeLists.txt:
add_custom_command(... COMMAND cmake -P copy_to_build.cmake)
You can prepare list of subdirectories (and files) at configuration stage, and then copy every element of that list using xcopy. This approach uses fact, that everything outside of build directory is not changed. Here iteration is done on configuration stage (by CMake). I am not sure, whether "for" loop works under COMMAND of add_custom_command. If it works, you can use it for iterate over entries in the shell.
CMakeLists.txt:
# List of elements in source directory.
file(GLOB entries RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
# List of commands for pass to `add_custom_command` as is.
# `COMMAND` keyword is included into list.
set(copy_commands)
foreach(entry ${entries})
list(APPEND copy_commands COMMAND xcopy /s /i
${CMAKE_CURRENT_SOURCE_DIR}/${entry} ${CMAKE_CURRENT_SOURCE_DIR}/build/${entry}
endforeach()
add_custom_command(... ${copy_commands})

how to include header files and sources from different project in makefile

I have included a header of another project in my main.cxx file . I want to build my simple program in makefile. Is there a way to do it? Following is the illustration of how files are stored.
Another Project Main Folder
-Folder A
-Folder B
-Include folder
- file.h
Test Folder
-main.cxx

Resources