pitchfork
pitchfork copied to clipboard
Question about playing nice with IDEs
After some escapades with getting eclipse to behave nice, while not complicating a simple use-as-subdirectory I ended up with
src
include
CMakelist.txt (1)
test
CMakelist.txt (2)
CMakelist.txt (3)
This would allow depended projects just pointing to (1) as subdirectory, or users just using this subdirectory to get to the lib/public includes quickly. Tests (2) could be similarly standalone, using the installed system libraries instead of the sources.
While (3) is primarily for aiding development and easy integration into IDEs (fitting defaults, incl unit tests).
I started with a similar layout like pitchfork, placing include at the root, but I got somewhat biased against that, as in practice header + sources are tied closer to each other than the remaining categories. for ex:
- common git subtree for history
- generating a public config.h fits more into the src directory (needs information from the build), but is semantically a installable include
- they are typically installed together, so that should be done in one buildscriptfile (that I dont want in the root directory)
What is your question? I don't understand what you're asking. Are you asking if this layout works?
Note the merged header placement. This would look like:
src
my_library (0)
// include files here
// source files here as well
CMakeLists.txt (1)
tests
CMakeLists.txt (2)
CMakeLists.txt (3)
(0) contains all headers and source files. When you install the library, you install all *.hpp files and the build artifacts. Note that CMake can handle installs; you don't need a separate install script, but you can use one.
(3) is the main CMakeLists.txt, which should be viewed as the way to interact with the build system. (1) contains just the commands to set up my_library, (2) contains just the commands to test my_library.
Looking at your descriptions of combining headers and sources, I believe the merged header placement handles that.
My question would be if this layout did consider both use during development and build as dependency.
hierarchical (3) is on top, so you either have to verbosely configure everything (what to build and install) for development, release and use as library/submodule.
Another option would be to break it up and making all sub-directories usable standalone (without the top makefile, and going further without anything not below the directory). If you just want to use the library (headers being part of it), you could directly use the src directory, not the top directory. The top directory would deal with various compiler flags, and use conan for dependencies, while all this is strictly omitted below the src directory (so you could literally copy it over into another project without a mess of compiler settings). Smaller reusable parts, and cleaner structure IMHO, but that would require the include directory below the src directory.
And I would not use "merged headers", public headers would still be in a separate include directory, would be a mess to install otherwise.
This layout does consider both use during development and use as a dependency.
I don't think there's a reasonable benefit to directly using the src/ directory when using a library as a dependency. The top (3) CMakeLists.txt can use conan for dependencies, it can set up compiler flags via add_compile_options and add_link_options, it can have project specific options, etc.
Compile flags are part of the interface of a library; users cannot expect the library to work without it being able to set up flags.
The user can use the root directory with add_subdirectory as one method of using this library as a dependency, and everything would work out fine.
The top (3) CMakeLists.txt should be the entry point for both development and use as a dependency.
If your concern is setting things in top (3) CMakeLists.txt which would affect the user, this can be avoided with the "Modern CMake" style of usage dependencies. No need to modify CMAKE_CXX_FLAGS, etc. You can hide conan or other project-specific settings if the root CMakeLists.txt was included as a subdirectory.
However, I think it would technically follow the pitchfork layout if you kept include/ under the root directory, and in the src/CMakeLists.txt (1), you pointed the include directory up to it:
target_include_directories(my_library
PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/../include"
)
The user could then depend on your library with add_subdirectory(my_library/src). This would mean that the user couldn't copy just the src/ folder into their project, but I don't think the user should expect to be able to do that.
I would not recommend doing this, though.
This layout does consider both use during development and use as a dependency.
I don't think there's a reasonable benefit to directly using the
src/directory when using a library as a dependency. The top (3) CMakeLists.txt can use conan for dependencies, it can set up compiler flags viaadd_compile_optionsandadd_link_options, it can have project specific options, etc. Compile flags are part of the interface of a library; users cannot expect the library to work without it being able to set up flags.
Yes and no. there might be flags that are necessary (C/C++ standard, version + feature macros), but if you think of a library as sourcecode then more than that hurts. As concrete example, take some microprocessors like STM32 (Arm-based microcontrollers), if you want to use a library you would prefer to copy it over or use CMakes "add_subdirectory" to the src directory in the layout I outlined. Reason for that being is that the STM32 family has 100s of variants which differ in compiler parameters (ARM core, FPU, extensions). compiling everything with identical parameters is the only sane way here. I have also project just for some lowlevel startupcode and libraries which further depend on some macros, you cant build this standalone at all so the toplevel CMakeLists.txt is just for the IDE to grab include paths.
This doesnt go against what you say with conan and further configurations, toplevel should be the place to develop and build standalone packages. It should contain everything that's not absolutely crucial to compile the components of the project. Being able to use src standalone would be a testcase for this sort of modularity.
The user can use the root directory with
add_subdirectoryas one method of using this library as a dependency, and everything would work out fine.
not if it contains compiler parameters affecting the ABI, worst of all if you do it on a global level as you state as example. Even with "modern CMake" it might clash (particularly if those are usage requirements for headers), there should be only one toplevel CMakeLists.txt that defines such settings (or a toolchain file, or other "external sources").
Maybe some better example, if you want to convert a multiple of single-library-projects into one with submodules, then you will do exacly that: take out everything not specific to the library and concentrate the rest in the toplevel CMakeLists.txt.
The top (3) CMakeLists.txt should be the entry point for both development and use as a dependency.
If your concern is setting things in top (3) CMakeLists.txt which would affect the user, this can be avoided with the "Modern CMake" style of usage dependencies. No need to modify
CMAKE_CXX_FLAGS, etc. You can hide conan or other project-specific settings if the root CMakeLists.txt was included as a subdirectory.
Still wont help if a subdirectory decides to compile as no-pic and you want to use it in a shared library, or if 2 subdirectories have conflicting usage requirements for their respective headers (which you use both - at the same time). Sure you can build projects where this wont happen, but how would you specify rules that wont happen? If such options aren't allowed at all, then thats a rather simple rule =)
However, I think it would technically follow the pitchfork layout if you kept
include/under the root directory, and in thesrc/CMakeLists.txt(1), you pointed the include directory up to it:target_include_directories(my_library PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include" )The user could then depend on your library with
add_subdirectory(my_library/src). This would mean that the user couldn't copy just thesrc/folder into their project, but I don't think the user should expect to be able to do that.I would not recommend doing this, though.
Its a pedantic approach of never going up or sideways, it helps keeping a hierarchy.
Sorry, if you think that's going nowhere, I am rather keen of solving these issues (project layout) for myself and am looking at approaches and particularly their differences closely. Independent (as much as possible) subprojects in src/libs and tests seem to make alot sense to me, you need a toplevel CMakefile.txt for a distributable/packageable binary (defining consistent compiler options for all sub-folders/projects).