How to organise my files using CMake? - c++

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.

Related

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()

Files exclusion (custom and transient) from build

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.

Visual Studio 2010 project file filters

I have a complex C/C++ bunch of applications that I'm working on which is supposed to also be platform independent. So far, is UNIX/Windows compatible and it runs fine. However, maintaing this monster on VS2010 is a nightmare. I have the following file structure:
/
sources
lib1
include
...
src
...
lib2
include
...
src
...
app3
include
...
src
...
builders
cmake
...
make
...
VS2010
vs2010.sln
lib1
lib1.vcxproj
lib1.vcxproj.filters
lib2
lib2.vcxproj
lib2.vcxproj.filters
app3
app3.vcxproj
app3.vcxproj.filters
As we can see, because everything is platform independent, I had to completely separate the builders from sources. IMHO, that itself is a very good practice and it should be enforced by everyone :)
Here is the problem now... VS2010 is completely unusable when it comes to organize the include/sources files in filters. You have to do that manually by repeatedly doing "Add -> New Filter" followed by "Add -> Exiting Item". I have a VERY complex folder structure and files in each and every include folder. The task for creating the filters becomes a full day job. On the other hand, I could just drag the whole folder from Explorer onto the project inside VS2010 but it will put all header/source files in there without any filters, rendering it worthless: you can't possible search within 100 files for the right one without having some sort of hierarchy..
Question is:
Is VS2010 having some obscure way of importing a folder AND preserving the folder structure as filters? Looks to me that M$FT people who created VS2010 think that M$FT is the only animal in the jungle and you MUST pollute the sources folder with builders projects so you can leverage "show hiden files" to include them in the project along with the folder structure. That is absurd IMHO...
You are using CMake, so I advise you stick with only this. You can generate makefiles and VS2010 project files with it (at least). For VS, the generated files are a sln and a bunch of vxproj (one for each project in the CMake script).
In CMake file you can group files, using the command source_group. The filters will be automatically generated for vs according to the source groups. I don't know for other IDE like Code::Blocks or NetBeans.
If you want automatic grouping based on file path [Comment request]:
# Glob all sources file inside directory ${DIRECTORY}
file(GLOB_RECURSE TMP_FILES
${DIRECTORY}/*.h
${DIRECTORY}/*.cpp
${DIRECTORY}/*.c
)
foreach(f ${TMP_FILES})
# Get the path of the file relative to ${DIRECTORY},
# then alter it (not compulsory)
file(RELATIVE_PATH SRCGR ${DIRECTORY} ${f})
set(SRCGR "Something/${SRCGR}")
# Extract the folder, ie remove the filename part
string(REGEX REPLACE "(.*)(/[^/]*)$" "\\1" SRCGR ${SRCGR})
# Source_group expects \\ (double antislash), not / (slash)
string(REPLACE / \\ SRCGR ${SRCGR})
source_group("${SRCGR}" FILES ${f})
endforeach()

The right way to structure my c++ project with cmake?

I have been struggling with this for quite a while, and my adventures with cmake have only resulted in hackish solutions that I am pretty sure are not correct.
I created a library that consists of several files, as follows:
-libfolder
-codepart1folder
-CMakeLists.txt
-codepart1.cpp
-codepart1.hpp
-codepart2folder
-codepart3folder
-lib.cpp
-lib.hpp
-CMakeLists.txt
I wrote a CMakeLists file to compile the library (after some experimentation), and I can generate a lib.a file. Now I would like to include this code as a library in other projects, and access it through the interface in lib.hpp. What is the best way to do this, in terms of directory structure, and what I need to put into CMakeLists.txt in my root project?
My current attempt has been to add -libfolder as a subfolder to my current project, and add the commands:
include_directories(${PROJECT_SOURCE_DIR}/libfolder)
link_directories(${PROJECT_BINARY_DIR}/libfolder)
add_subdirectory(libfolder)
target_link_libraries(project lib)
When I run make, the library compiles fine, but when project.cpp compiles, it complains that it cannot find codepart1.hpp (which is included in lib.hpp, included from project.cpp).
I suspect that this is the wrong way about doing this, but I cannot wade through the CMake documentation and find a good tutorial on setting up projects like this. Please help, CMake gurus!
The clean way to import one CMake project into another is via the find_package command. The package declaration is done by using the export command. An advantage of using find_package is that it eliminates the need to hard-code paths to the package's files.
Regarding the missing hpp file, you didn't include codepart1folder, so it's not on the include path.
Ok, so after consulting a coworker of mine who is a CMake guru, it seems CMake does not have support for what I am trying to do, leaving one with 3 options:
Add all of the dependencies to the parent projects CMakeLists.txt - not very clean, but it will get the thing to work. You'll have to do this for every project you add the code to, and go back and fix things if your library changes.
clean up your library headers. This is done through some compiler hackery. The idea is to forward-declare every class, and use only pointers or boost::shared_ptr, and then include the dependencies only in the cpp file. That way you can build the cpp file using all the findpackage stuff, and you get the bonus of being able to use the lib by only including the header and linking to the library.
Look into build systems. Having portable code and fast code compilation with complex dependencies is not a solved problem! From my investigations it turned out to be quite complicated. I ended up adopting my coworkers build system which he created himself in cmake, using things he picked up from Google.
Looking at your post you don't seem to add 'codepart1folder' to the includes anywhere. How are you including codepart1.hpp as:
#include <codepart1.hpp>
#include "codepart1folder/codepart1.hpp"
I don't think there is a standard accepted way to structure cmake projects. I've looked at a bunch of cmake repos and they tend to have differences. Personally I do the following:
-project
CMakeLists.txt
-build
-cmake
OptionalCmakeModule.cmake
-src
-Main
Main.cpp
Main.hpp
-DataStructs
SomeTree.hpp
SomeObject.hpp
-Debug
Debug.hpp
-UI
Window.hpp
Window.cpp
Basically that dumps all the source code into 1 directory, then you perform an out of source build with: 'mkdir build && cd build && cmake .. && make' in the projects root folder.
If you have separate libs as part of your project, then you might want a separate libs directory with another subfolder for your specific lib.
I have some of my repos on: https://github.com/dcbishop/ if you want to look at the CMakeLists.txt files.
The main problems with my project structure are that I use the FILE_GLOB which is apparently the 'wrong' way to do things (if you add files after running 'cmake ..' then they won't be picked up hen you do a 'make'). I haven't figured out what the 'right' way to do it is (from what I can see it involves keeping a separate list of files) I also only use 1 CMakeLists.txt file.
Some projects also choose to separate their cpp and hpp files into separate directories. So you would have an include and src folders (at least for the hpp files that are intended to be used externally). I think that would mainly be for projects that are mainly large libraries. Would also make installing header files much easier.
You are probably missing
include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder)
In such a case you might want to set( CMAKE_INCLUDE_CURRENT_DIR on) to add all folders to the include directory path variable.
Check cmake's output on the command line whether the correct include folders are set or not. Additionally you can always use message() as "print debugging" for cmake variables.
In case of include directories however you need to read the directory property to see what is actually in the include directories.
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("inc_dirs = ${inc_dirs}")
I hope this helps you figuring out what is missing.
Edit
I just saw your comment about added codepart1folder in the libfolder. It is only available in the libfolder's include_directory path and not propagated to the root folder.
Since the include codepart1.hpp is present in the lib.hpp however you need to have it also available in the project path otherwise you will get missing declaration errors when you build your project.

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.