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()
Related
I'm trying to generate Qt help files during build.
.qhp (Qt help project), contains list of HTML files located in /html folder adjacent to .qhp file.
It works fine, if I change .qhp file. But if I change only HTML files the build is not started.
This is part of my CMakeLists.txt:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/help.qch
COMMAND qhelpgenerator ${CMAKE_CURRENT_SOURCE_DIR}/help.qhp -o ${CMAKE_CURRENT_BINARY_DIR}/help.qch
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/help.qhp
)
ADD_CUSTOM_TARGET(${TARGET_NAME}
ALL DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/help.qch
SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/uav_help.qhp
)
Q: How can I add dependencies to HTML files (w/o creating list of them in CMakeLists.txt), if I don't want to add them to the project?
Q2: Are there other ways to organize automatic .qch generation during build?
List these HTML's in DEPENDS of add_custom_command() call too, obviously.
You can also look at KDE's Extra CMake Modules project, which contains ECMAddQch macro.
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()
I made a C++ project on Linux, and I grouped source files in many directories to organize myself.
I was using CMake to compile, with one CMakeFiles.txt on each subdirectory.
srcs
|--folderA
| |--Toto.cpp
| |--Tata.cpp
|
|--folderB
| |--Foo.cpp
| |--Bar.cpp
[...]
Recently, I opened it with Visual Studio 2015, which found every source file, but just put the entire list on the "Source Files" folder of solution explorer.
Source Files
|--Toto.cpp
|--Tata.cpp
|--Foo.cpp
|--Bar.cpp
I plan to have a huge number of files, and it shall be soon difficult to find one.
Is there any way to explicitly tell it to respect the folder hierarchy on solution explorer?
Use the source_group command.
source_group(<name> [FILES <src>...] [REGULAR_EXPRESSION <regex>])
Defines a group into which sources will be placed in project files. This is intended to set up file tabs in Visual Studio. The options are:
FILES
Any source file specified explicitly will be placed in group . Relative paths are interpreted with respect to the current source directory.
REGULAR_EXPRESSION
Any source file whose name matches the regular expression will be placed in group .
#James Adkison is correct; source_group is what you want to use. As of CMake 3.8, the improved source_group command now offers a TREE argument to recursively search your source hierarchy to create source groups to match it. Here is a basic solution for the example you provided:
project(MyProj)
set(MyProj_SOURCES
"folderA/Toto.cpp"
"folderA/Tata.cpp"
"folderB/Foo.cpp"
"folderB/Bar.cpp"
)
add_executable(Main ${MyProj_SOURCES})
# Create the source groups for source tree with root at CMAKE_CURRENT_SOURCE_DIR.
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${MyProj_SOURCES})
I'm setting up cmake for my project and I've set up a testing project for it. When it generates my visual studio 2010 project I want to make it as the project I've had earlier.
it creates a ALL_BUILD and ZERO_CHECK project that I dont want.
it puts the .h files into the External Dependencies folder. I want a Include Files folder where all the .h files goes.
I also want to group some files under different filters. Like in my core lib I want to group all files related to Maths in a folder and all files related to Event management in another.
On the filesystem it puts the project files inside /Lib/src. Probably cause I have it organized that in the code folder, but I dont want that for the project files.
I want to set up different configuration so I have DebugOpenGL, DebugDirectX, ReleaseOpenGL, ReleaseDirectX and then setting a flag USE_OPENGL or USE_DIRECTX for the two types of configurations.
How can I exclude some files when I build on windows and others when I build on linux? Like I have WindowWin.cpp and WindowLinux.cpp.
I've tried what you sugested but cant get it working:
#LibProject/src
FILE(GLOB test0_headers $CMakeTest_SOURCE_DIR/LibProject/inc/test.h)
source_group(include0 FILES ${test0_headers})
FILE(GLOB test0_source ${CMakeTest_SOURCE_DIR}/LibProject/src/test.cpp)
source_group(source0 FILES ${test0_source})
FILE(GLOB test1_headers $CMakeTest_SOURCE_DIR/LibProject/inc/test1.h)
source_group(include1 FILES ${test1_headers})
FILE(GLOB test1_source ${CMakeTest_SOURCE_DIR}/LibProject/src/test1.cpp)
source_group(source1 FILES ${test1_source})
include_directories(${test0_headers} ${test1_headers})
add_library(LibProject ${test0_headers} ${test1_headers} ${test0_source} ${test
1_source})
I kind of got it working now.. only that I want sub folders for headers and source files inside the source group.
set(test_source0 ${CMakeTest_SOURCE_DIR}/LibProject/inc/test.h ${CMakeTest_SOURCE_DIR}/LibProject/src/test.cpp)
source_group(TEST FILES ${test_source0})
set(test_source1 ${CMakeTest_SOURCE_DIR}/LibProject/inc/test2.h ${CMakeTest_SOURCE_DIR}/LibProject/src/test2.cpp)
source_group(TEST2 FILES ${test_source1})
include_directories(${CMakeTest_SOURCE_DIR}/LibProject/inc)
add_library(LibProject ${test_source0} ${test_source1})
Heres my solution :)
set(test_header
${CMakeTest_SOURCE_DIR}/LibProject/inc/test.h)
set(test_source
${CMakeTest_SOURCE_DIR}/LibProject/src/test.cpp)
source_group(TEST\\Headers FILES ${test_header})
source_group(TEST\\Source FILES ${test_source})
set(test2_header
${CMakeTest_SOURCE_DIR}/LibProject/inc/test2.h)
set(test2_source
${CMakeTest_SOURCE_DIR}/LibProject/src/test2.cpp)
source_group(TEST2\\Headers FILES ${test2_header})
source_group(TEST2\\Source FILES ${test2_source})
include_directories(${CMakeTest_SOURCE_DIR}/LibProject/inc)
add_library(LibProject
${test_header}
${test_source}
${test2_header}
${test2_source})
To group files into a folder in Visual Studio you can use:
# Include files
FILE(GLOB all_headers "include/*.h*")
source_group("include" FILES ${all_headers})
# Source files
FILE(GLOB all_srcs "src/*.cpp")
source_group("source" FILES ${all_srcs})
This will put all of your .h files that are located in the include folder to appear in a folder called include in Visual Studio. Same for your cpp files. You can use this technique to make your own structure in CMake, if that is what you want.
For the purposes of ALL_BUILD and ZERO_CHECK read this answer. To disable the generation of ZERO_CHECK use set(CMAKE_SUPPRESS_REGENERATION true).
To select between OpenGL and DirectX and to setup the appropriate folders, you can use the same technique used above but put them inside a
if(${USE_OPENGL})
FILE(GLOB ....)
endif()
I think you get the idea.
I'll answer the ones I know:
The ALL_BUILD and ZERO_CHECK are used to keep your projects in sync with changes to the CMakeFiles. I don't think there's a way to get rid of those.
To get the .h files where you want them, you need to include them as part of the source. I use something like this:
file(GLOB LocalProjectIncludes "${yourheaderdirectory}/*.h")
Then I append ${LocalProjectIncludes} to the source files for the project. CMake will figure out that they're headers; it won't try to build them.
I'm new to CMake and re-learning C++, so I hope these are appropriate questions. I have a project in directory /projects/A and some .h files in /projects/include/open-source-project-1 that the A project depends on.
Sample Hierarchy:
/projects
/CMakeLists.txt
/A
/CMakeLists.txt
/a.cpp
/B
/CMakeLists.txt
/include
/open-source-project-1
/includeMe.h
/open-source-project-2
Do I need to use a cmake include_directories() command? If so, in what CMakeLists.txt file do I need to put it in? (I've tried many variations)
Do I need a different cmake command?
If I put that in the top most level CMakeLists.txt, should that take care of all occurences of #include in the .cpp files for the A project or B project?
Is this a typical setup for a c++ project? Does it seem logical?
Your top-level CMakeLists.txt file is not needed unless all of the projects are directly inter-related somehow or have otherwise unresolvable dependencies. Unrelated projects should not include each other, nor do they need a parent list file.
If A and B are separate projects, ./A/CMakeLists.txt and ./B/CMakeLists.txt should contain at least this line:
include_directories(../include)
Otherwise, if A and B are parts of a larger single project, then it is appropriate to put these lines in the top-level CMakeLists.txt files:
include_directories(include)
add_subdirectory(A)
add_subdirectory(B)
Only for separate projects. One invocation of cmake will create one build tree. One project to a build tree is all you need.
No. Only if the top-level lists file contains an add_subdirectory directive will it affect the other list files.
No, this is atypical.