Files exclusion (custom and transient) from build - c++

I have many C++ (Google Test) source files in my Visual Studiosolution and I want to have the possibility to keep only a few for the build (to focus on the problem), but also to come back quick enough (two times by day) to the initial configuration.
We are using, more or less, about three solutions: Visual Studio, CMake and QT (but I could add yet another one). I never used QT, so the other two solutions I see are:
Visual Studio: folders are useless, but I can select files and exclude them from build. But these changes are saved in vcproj so I have to pay attention not to save them on the version control, which is annoying.
CMake: easy change the CMakeLists.txt (comment lines with the sources folders), but I always have the version control problem ... maybe I can configure the excluded files in a custom (user) file. Advantage: I can generate only what I want, more flexible and not so boring like the previous one.
By example, if I do not want the sources in src_2:
file(GLOB_RECURSE SRC_FILES_1
${SOURCE_BASE_DIR}/src_1/*.cpp
${SOURCE_BASE_DIR}/src_1/*.h
)
file(GLOB_RECURSE SRC_FILES_2
${SOURCE_BASE_DIR}/src_2/*.cpp
${SOURCE_BASE_DIR}/src_2/*.h
)
file(GLOB_RECURSE SRC_FILES_3
${SOURCE_BASE_DIR}/src_3/*.cpp
${SOURCE_BASE_DIR}/src_3/*.h
)
add_executable(${PROJECT_TEST_NAME}
${SRC_FILES_1}
# next line is commented
# ${SRC_FILES_2}
${SRC_FILES_3}
)
Is there another solution or a way to improve one of these proposed here?

You can control this with a cmake variable.
option(BUILD_TESTS "builds test cpp files" ON)
This adds an option for your cmake file. It defaults in this case to ON you can change that though. Now lets get on:
if(BUILD_TESTS)
set(TEST_CPP_FILES test1.cpp test2.cpp)
endif(BUILD_TESTS)
add_executabe(foo bar.cpp bar1.cpp $(TEST_CPP_FILES))
Here you define a variable with the source file of your tests (or whatever source files you want to build when the BUILD_TESTS is ON. These then get added to the target. If BUILD_TESTS is off this variable will be empty.
now to change the Value you can run
cmake <...> -DBUILD_TESTS=OFF
Or with ON if you want to turn them back on again. You also can keep the change in version control because it will default to ON and you need to explicitly disable it.
You can also exclude whole subdirectories or targets with this in the if statement if you not just only want to exclude source files.
EDIT:
For your example it could look like this:
if(BUILD_TESTS)
file(GLOB_RECURSE SRC_FILES_2
${SOURCE_BASE_DIR}/src_2/*.cpp
${SOURCE_BASE_DIR}/src_2/*.h
)
endif(BUILD_TESTS)
SRC_FILES_2 should be empty afterwards.

Related

How could I match all subdirectories automatically with cmake

Provided my project is like this:
|--main.cpp
|-A--a1.cpp
| |-a2.cpp
|
|-B--b1.cpp
|-b2.cpp
|--CMakeLists.txt
How could I add all the *.cpp (e.g main.cpp, A/a1.cpp, A/a2.cpp, B/b1.cpp, B/b2.cpp) to a cmake variable SRC ? I hope I could only need one CMakeLists.txt. By the way, what if I need to exclude certain .cpps ?
As mentioned by Alexander, you can use file(GLOB_RECURSE myVar myRegex) to get all the files matching the myRegex into a myVar as a list. In order to exclude some you could play around with the myRegex, or you could filter the list with list(FILTER myVar <INCLUDE|EXCLUDE> REGEX <regular_expression>)
But note that adding another .cpp file to your project will not automatically be added to your target on rebuild. You will need to explicitly reconfigure your project for the changes to be made. Since CMake 3.12 there is also an option CONFIGURE_DEPENDS for file GLOBE and GLOBE_RECURSE, that will do the update on rebuild for you.
Here is the NOTE from CMake documentation:
Note We do not recommend using GLOB to collect a list of source files
from your source tree. If no CMakeLists.txt file changes when a source
is added or removed then the generated build system cannot know when
to ask CMake to regenerate. The CONFIGURE_DEPENDS flag may not work
reliably on all generators, or if a new generator is added in the
future that cannot support it, projects using it will be stuck. Even
if CONFIGURE_DEPENDS works reliably, there is still a cost to perform
the check on every rebuild.
It's what you want:
file(GLOB_RECURSE SRC *.cpp)
For more info: https://cmake.org/cmake/help/v3.0/command/file.html
For excluding you can write function.
Note: But I don't recommend to use 'glob'.
Better use 'set' with list of files.

CMake and VisualStudio: Group files in solution explorer

To finish a long coding session on a project, I wanted to test if my CPP project is compilable on an arrangement of OS'es.
I've been working in Win10 all the time. Compiles fine.
I've tried a Raspberry Pi. Compiles fine.
I re-download a seperate copy of my project to a Win10 client, run cmake-gui, and open the project: My folder structure in the solution explorer all gone.
So I started digging around, and apparently this structure is kept in CMakeLists.txt with the command source_group. So I start adding more source_groupings to my cmake lists, and for some reason my groupings won't take.
Example:
source_group("game\\entitysystem" FILES ${entitysystem_SRC}) // Existing grouping
source_group("game\\entitysystem\\components" FILES ${components_SRC}) // My new grouping
My glob would be this:
file(GLOB components_SRC
"game/components/*.h"
"game/components/*.cpp"
)
file(GLOB entitysystem_SRC
"game/entitysystem/*.h"
"game/entitysystem/*.cpp"
)
I do believe my GLOB's are correct since the new project-clone compiles fine. It's just that every part of the new structure in Visual Studio's Solution Explorer seems lost. Yes, I have cleared Cmake's cache and regenerated the project. Doesn't change it.
Original structure:
Cloned project structure:
Edit:
I did make a mistake in my source_group as in that it should not put components beneath entitysystem, but still, why aren't there any filters created in Visual Studio?
First, make sure you are setting set_property(GLOBAL PROPERTY USE_FOLDERS ON).
Second, it is not recommended to use GLOB to collect a list of source files. From the file(GLOB documentation:
We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
The recommended way to list project files is to add them by hand to CMakeLists.txt.
If you still want to GLOB, it looks like you want to mirror the directory structure in your source tree. You can use a macro such as this every place you define a library or executable to automatically sort them for you:
foreach(FILE ${SRCS})
# Get the directory of the source file
get_filename_component(PARENT_DIR "${FILE}" DIRECTORY)
# Remove common directory prefix to make the group
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" GROUP "${PARENT_DIR}")
# Make sure we are using windows slashes
string(REPLACE "/" "\\" GROUP "${GROUP}")
# Group into "Source Files" and "Header Files"
if ("${FILE}" MATCHES ".*\\.cpp")
set(GROUP "Source Files${GROUP}")
elseif("${FILE}" MATCHES ".*\\.h")
set(GROUP "Header Files${GROUP}")
endif()
source_group("${GROUP}" FILES "${FILE}")
endforeach()

QtCreator CMake project - how to show all project files

I use QtCreator to open CMake project. Some directories apart from CMakeLists.txt contains only headers files *.h and for those directories QtCreator in the project tree view shows only CMakeLists.txt. How to fix that ? I need to see all project files from QtCreator.
Viewing project as a file system is not a solution at all cause your project editor settings for example would not apply.
And I do not like to add headers to executable target, cause they do not actually belong there. You effectively cripple the project file to work nicely with one particular IDE... not good.
The cleaner option IMHO would be:
FILE(GLOB_RECURSE LibFiles "include/*.hpp")
add_custom_target(headers SOURCES ${LibFiles})
As a bonus you get your includes shown in a separate folder.
(borrowed from https://cmake.org/pipermail/cmake/2012-August/051811.html)
I would suggest you switching your project view to File System. This would display a view where you could view any file you want:
You might want to split your project view into two by clicking the second to right button, if you still desire the Projects mode.
You should add header files to the list of your source files: add_executable(${Executable} ${Sources} ${headers})
You can use GLOB_RECURSE if have many header files:
FILE(GLOB_RECURSE INC_ALL "headers/*.h")
include_directories("headers")
add_executable(main "main.cpp" ${INC_ALL})
Don't forget to run CMake again (Build>Run Cmake).
Based on another thread asking the same question, I found a generic solution to the problem, working for all IDE's (at least tested with QtCreator and Visual Studio).
Can be found here : https://github.com/sauter-hq/cmake-ide-support
# \brief adds for the given target a fake executable targets which allows all
# headers and symbols to be shown in IDEs.
# \param target_name Which target properties should be added to the IDE support target.
function(target_add_ide_support target_name)
if (NOT TARGET ${target_name})
message(FATAL_ERROR "No target defined with name ${target_name}, cannot target_add_ide_support it.")
endif()
set (target_for_ide "${target_name}_ide_support")
if (NOT TARGET ${target_for_ide})
file(GLOB_RECURSE target_for_ide_srcs "*.h" "*.hpp" "*.hxx" "*.c" "*.cpp" "*.cxx")
add_executable(${target_for_ide} ${target_for_ide_srcs})
set_target_properties(${target_for_ide} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
endif()
get_target_property(dirs ${target_name} INCLUDE_DIRECTORIES)
target_include_directories(${target_for_ide} PRIVATE ${dirs})
endfunction(target_add_ide_support)
Usage is then for any targets in the CMakeLists, add the following call (can be made in top-most CMakeLists.txt after all add_subdirectory :
include(add_ide_support.cmake)
target_add_ide_support(some-target)
You can try CMakeProjectManager2. Code to display all files already propagated to upstream as a proof of concept. Concept applied but code can't be applied as-is for some reasons. So, simple wait feature in upstream.
There is a closed bug report about this issue: CMake project shows no files.
In that particular case the issue was with the chosen generator, Ninja, which is not well supported by QtCreator.
Please change that to "CodeBlocks - Ninja". Creator needs the CodeBlocks extra generator.
You should see a warning about that when hovering the kit (and the kit should have a warning icon in front of its name).
Using CodeBlocks - Ninja solved it for me too.
Overall, it may help to try up a few generators...

How to organise my files using CMake?

I am having a bit of a problem with CMake regarding the organisation of my code within a solution.
I have for an habit to organise my namespace by creating a directory for each.
For example if I create something like this :
namespace test { namespace blabla { ... } }
I would create a directory test and inside of it a directory blabla, however CMake does not make them appear in my Visual studio or Xcode project.
Is there a trick to get it done ?
Try using the source_group command. After the call to add_executable add source_group statements to structure your project as you wish, e.g.:
source_group("test\\blabla" FILES file1.cpp file2.cpp)
For grouping projects in VS you could use this way in CMake (ver after 2.8.3)
//turn on using solution folders
set_property( GLOBAL PROPERTY USE_FOLDERS ON)
//add test projects under 1 folder 'Test-projects'
FOREACH(TEST ${TESTS_LIST})
add_test(NAME ${TEST} COMMAND $<TARGET_FILE:${TEST}>)
set_tests_properties( ${TEST} PROPERTIES TIMEOUT 1)
set_property(TARGET ${TEST} PROPERTY FOLDER "Test-projects")
ENDFOREACH(TEST)
For Visual Studio: Make sure that all file names are unique. The result of compiling dir/file.cpp will be obj/file.obj. When the compiler compiles otherdir/file.cpp the result will be obj/file.obj - the previous object file will be overwritten. This is the case in VS 2008 and earlier versions, and I suspect it's still the case in VS 2010.
I too organise source code the way you do. I ended up using the following naming scheme: if the path to the source file would be Dir/Subdir/AnotherSubDir/File.cpp, then I'd name the file Dir/Subdir/AnotherSubdir/DirSubdirAnotherSubdirFile.cpp. Ugly? Yes. But it beats a project that won't link, and it's easy to figure out what the file name should be. I guess you could just append a sequence number on the file, but I thought it would be uglier. Also, if you forget to make the file name unique, the error isn't all that obvious to spot. Especially when you're tired, and your fiance/wife is waiting...
The accepted solution does not work for Xcode as of Xcode 6. However, there is a simple workaround:
Delete the references to source files from your Xcode project
(delete them in the sidebar, then pick "Remove Reference").
Add the root folder(s) back, make sure "Create Group" is checked, and select
the desired target(s).
Tada! Now your files should match the folder structure in Finder.

Should I separate CMakeList.txt from source folder?

I'm new to build tool, when I come across Autotool, I have an option to write only one Makefile.am in the top build folder and leave the source folder containing all cpp files clean. I could use VPATH to tell automake to look for the source code inside that folder instead of write /src/ every where. (refer to my old question here: Automake Variables to tidy up Makefile.am)
However It appears to me that CMake have no VPATH to set and some fox around said that It's impossible to do so. So there are two choices:
Create CMakeList.txt in the source folder
Create CMakeList.txt in top build folder and leave the source alone, with a cost that I need to extend "/src" to every source code files.
Which one is more commonly use? I prefer the second because It leave my source code clean from any build-relating-source. In that case is there anyway to get rid of "/src"?
In our company we're using the first option, having a CMakeLists.txt in every subdirectory and building the tree from a root-CMakeLists.txt by using the add_subdirectory command.
This is a modular approach where each subcomponent (think about the project has different parts like boost is split up into system, thread, date_time etc) has its own build-file. If a user wants he is able to just build the subcomponent or to build the whole project.
We're additionally using this as an easy way to include optional subcomponents to the project. The user then can set a Bool value like BUILD_SUBFOO and the add_subdirectory will just be executed, if this Bool is TRUE.
Well-known projects are using this approach too. Here is a link to the root CMakeLists.txt from KDevelop (look at lines 52-62).
I'm quite sure you can do:
FILE(GLOB Source_files src/*.cpp)
which would do exactly what you want.