I'm working on some basic OpenGL program and want to use CMake for building it.
There are couple of dependencies like glfw, glad, imgui etc...
Currently I have it in a very draft state where everything is just under the sources directory:
./
|____CMakeLists.txt
|____build/
|____include/
| |____KHR/
| |____GLFW/
| |____...
|____lib/
| |____libglfw3.a
| |____...
|____src/
| |____main.cpp
| |____...
| |____vendor/
| | |____imgui/
| | |____glad/
| | |____stb_image/
My CMake config is something like this:
include_directories(${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/src/vendor)
add_executable(${PROJECT_NAME}
src/main.cpp
src/vendor/glad/glad.c src/vendor/glad/glad.h
src/vendor/imgui/...
...
)
target_link_libraries(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/lib/libglfw3.a)
It all works, but now I want to bring some structure into it.
Mainly I want to have only my code under src.
I hope I'm not going into "XY problem" but I believe my file structure should be like:
./
|____CMakeLists.txt
|____build/
|____include/
|____lib/
|____glad/
| |____CMakeLists.txt
| |____...
|____imgui/
| |____CMakeLists.txt
| |____...
|____...
|____myproject/
| |____CMakeLists.txt
| |____src/
| | |____main.cpp
| | |____...
So that I'll have separate CMake configs for building glad, imgui etc., and then using them to build myproject.
Unfortunately, I'm struggling with understanding CMake documentation. Should I use INTERFACE targets for dependencies? Or how can I tell CMake that imgui must use specific GLFW location?
My main aim is to build myproject. For that I have to also build dependencies. Some dependencies are using other dependencies which I use. For example: I use GLFW and imgui also uses it. Ideally I'd like to be able to have only one place for that. In my case I have it under include and lib in the root of file structure.
Can anyone please share some ideas what could be the CMake config for such case?
What are the best practices?
I'm starting to explore Conan package management. So far including dependencies present on the conan center has been trivial, but now I'm struggling including other local dependencies.
Suppose I have the following project structure:
|----Project_A
| |
| |-src
| | |...
| |
| |-CMakeLists.txt
| |-conanfile.txt
|
|----Project_B
| |
| |-src
| | |...
| |
| |-CMakeLists.txt
I want Project_A to have Project_B as dependency. Project_B is already generating static libraries when built.
Is there a way using Conan to add that project as dependency? Meaning that it will build Project_B using the provided CMakeLists file and add it as dependency for Project_A?
Thanks in advance!
I have the following directory structure:
Project
|
|-CMakeLists.txt
Library
|
|-LibProjectA
| |-CMakeLists.txt
| |-src
| |-SomeHeader0.h
|-LibProjectB
| |-CMakeLists.txt
| |-src
| |-SomeHeader1.h
|-LibProjectC
|-CMakeLists.txt
|-src
|-SomeHeader2.h
OpenSourceProject
|
|-CMakeLists.txt
|-src
|-SomeOpenSourceHeader.h
Wherein Project includes the statically linked library LibProjectA in the Library directory. LibProjectA depends on LibProjectB. LibProjectB depends on LibProjectC. LibProjectA, LibProjectB, and LibProjectC all utilize the OpenSourceProject and LibProjectC specifically requires access to SomeOpenSourceHeader.h.
Whenever I perform an add_subdirectory on LibProjectC, I am forced to provide a precise path specifying where SomeOpenSourceHeader.h is. Even if this is in the CMakeLists.txt within the top level Project directory. Is there some way that by merely performing an add_subdirectory on the CMakeLists.txt in the OpenSourceProject, the path can be provided such that files therein can automatically be recognized elsewhere in the code and that the target project doesn't need to have any knowledge about the open source library used at a much lower level.
All libraries are statically linked.
At the early stage of our development, we have created micro-repositories, to be able to deeply modify repositories while minimizing interference with each other's work.
Now that we have a fairly stable version of our codebase, we want to merge some of the micro-repositories into a monorepo. That will ease the users' experience while building from source, as well as the deployment phase.
All our micro-repositories are built with CMake, and each of them obviously defines a project(). They also have 'internal' dependencies: some of the micro-repositories is built first and then used by the others with find_package().
RepoA
|-- CMakeLists.txt
| project(RepoA)
RepoB
|-- CMakeLists.txt
| project(RepoB)
| find_package(RepoA)
RepoC
|-- CMakeLists.txt
| project(RepoC)
| find_package(RepoA)
| find_package(RepoB)
While migrating them into a monorepo, the first option that came to my mind is moving each of them into a subdirectory, then adding add_subdirectory() to the root CMakeLists.txt file to build them. In the first instance, I would define a global project by using project() in the root CMakeLists.txt file, and I would also keep the project() definition in subdirectories.
Monorepo/
|-- CMakeLists.txt
| project(Monorepo)
| add_subdirectory(RepoA)
| add_subdirectory(RepoB)
| add_subdirectory(RepoC)
|-- RepoA/
|-- CMakeLists.txt
| project(RepoA)
|-- RepoB/
|-- CMakeLists.txt
| project(RepoB)
| find_package(RepoA)
|-- RepoC/
|-- CMakeLists.txt
| project(RepoC)
| find_package(RepoA)
| find_package(RepoB)
Now the question is: is that a good choice? Would you advise having a global project and multiple sub-projects, all of them defined through the use of the CMake project() command? Are there better strategies?
And also, would this strategy have drawbacks?
Many thanks for your kind help!
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
My source file pane is quickly growing (in terms of the number of files in my project) and it is getting a bit cumbersome to quickly locate the specific source file I need to access at any given time. I'm using Embarcadero's C++Builder, but I have encountered this issue in other C++ IDEs as well.
In Java, I often utilize packages for creating logical divisions of my source code, especially when dealing with a large number of source files in a single project. While this, of course, isn't the only purpose of Java packages, they are very handy in this regard.
Does anyone have any ideas on how I can achieve similar functionality in C++? Should I separate my source into physical folders? Does C++Builder offer some kind of virtual folder/grouping functionality that I'm just not seeing? Any ideas are appreciated and thank you.
I generally recommend not to use (only) the IDE or the language syntax for organizing your source code. For one, you tie yourself to the environment: well organized in the IDE, unorganized on file, and then comes the day when you might want to use a different environment...
Because of this, I usually use all three ways of organizing my source at the same time: I separate my source into functional modules, i.e. related classes. Each module gets its own namespace, physical folder, and IDE folder. (In my case, using CMake and source_group() to generate IDE project files if needed -- personally preferring the command line, Vim, and "make".)
Hence, whether I look at the project from within the IDE, from the command line, or from a compiler log, foo/some_class.hpp is foo/some_class.cpp is foo::some_class, minimizing confusion all around.
Actually, my currently preferred setup further subdivides each module directory into <project>/<module>/<class>.hpp or <project>/<module>/src/<class>.hpp depending on whether the class is used outside its own module or not, <project>/<module>/src/<class>.cpp, and <project>/<module>/test/<class>_tu.cpp. Namespace is <project>::<module>::<class>, of course.
project
|-- foo
| |-- some_class.hpp
| |-- src
| | |-- internal_class.hpp
| | |-- internal_class.cpp
| | `-- some_class.cpp
| `-- test
| |-- internal_class_tu.cpp
| `-- some_class_tu.cpp
|-- bar
| |-- ...
The idea here is that the "external" interface of each module (foo) is documented by the headers in that subfolder, with implementation details and tests "hidden" in the respective subfolders.
But in the end, it very much depends -- on your taste, on that of your co-developers, and the scope of your project.
This is how I roll:
PROJECT_NAME
|-- build // This is DVCS ignored but has all the built intermediates and final binaries
| |-- release // These are the different build profiles
| |-- debug
| |-- profile
| `-- coverage
|-- bin // For binary source code
| `-- hello_world
| |-- doc
| |-- inc
| |-- src
| |-- tests
| `-- build_script // Builds binary into the build folder
|-- include // Public headers for the library
| `-- these
| `-- folders
| `-- represent
| `-- namespaces
| `-- my_awesome_class.hpp
|-- lib // library source code
| |-- these
| | `-- folders
| | `-- represent
| | `-- namespaces
| | |-- inc // Private headers
| | | `-- my_private_class.hpp // internal class
| | |-- src // Source code for this namespace
| | | |-- posix
| | | | `-- my_awesome_class.cpp // posix specific source code
| | | |-- nt
| | | | `-- my_awesome_class.cpp // nt specific source code
| | | |-- my_private_class.cpp // non-visibile class
| | | `-- my_awesome_class.cpp // cross platform source code
| | |-- tests // Unit tests
| | | `-- my_awesome_class.cpp // builds a test executable for the library
| | `-- doc // Documentation for this namespace
| | `-- namespace.dox
| `-- build_script // Builds binary into the build folder
|-- doc // Documentation files
| |-- main_page.dox
| `-- namespace.dox
`-- build_script // Builds the source code into the build folder
This represents the these::folders::represent::namespaces::MyAwesomeClass class which has posix and NT specific source code (as well as generic source code) plus there is a private these::folders::represent::namespaces::MyPrivateClass that is used internally in the library, the headers are not public and the visibility of the class symbols are hidden.
This has scaled very well and provides easy locating of files.
I make projects in order to keep all my files easily accesible. It is the easiest way to organize, along with clear class/file names.