Linking projects in bazaar - build

I have some projects that need to include the source of another project. All projects are managed by revision control software. In fact, they are for now part of the same local bazaar repository. The desired layout would be something like this:
Repository
MainProject
code.c
more_code.py
OtherProject
SomeData.txt
MainProject2
code.c
OtherProject
SomeData.txt
OtherProject
SomeData.txt
My experience with such tools is lacking. My initial idea was that the OtherProject subfolder of the MainProjects could somehow link to the actual location of the other project with bzr externals. Still, I am curious if this is the right approach?
(If it is the right approach, extra brownie points for actual bzr examples on how to do it)

About the organization, I would recommand one repository for each project.
Root (folder)
MainProject (repo)
code.c
more_code.py
OtherProject (link)
SomeData.txt
MainProject2 (repo)
code.c
OtherProject (link)
SomeData.txt
OtherProject (repo)
SomeData.txt
The link as external is better than copy/paste inside the project. So globally, you are on the good direction !

I believe the bzr-externals plugin would work with your suggested layout, whereas the bzr-scmproj plugin seems to manage a bunch of subdirectories representing different branches as a single branch.
I personally would recommend that you don't embed a copy of or link to OtherProject in the working trees of MainProject and MainProject2 like you've suggested, but rather use a build-time variable to reference OtherProject's location under Repository. But my primary work environment is Windows where I don't have such filesystem features as symbolic links.

Related

How to idiomatically add external library dependencies that use git and CMake to a git and CMake project?

I would like to know how to add external libraries into my project. Is there a standard way of doing so?
The way I do it and that I don't like is:
Have a folder called vendors where I add submodules e.g. boost, openssl...
I build the external libraries (as they come with a cmake to build in general).
I add a premake (I could have used a cmake) to each external library and I configure so I can see the project in VS as well as the cpp and the hpp files.
I don't like this because I do copy the binaries of the external libraries manually, hence if I delete the bin folder I can't build my solution just by clicking build but I have to build the external libraries first using there cmake and then I copy the binaries manually to the bin/ folder of my solution.
Could you please give me a "standard" way I can do this? I feel like there could be better ways by just using to the max the CMake that comes with the external library. Also, I don't like changing the external libs too much, I just want to be able to update them anytime and everything works without me touching stuff.
How can this be done?
One approach is to use CMake's FetchContent functionality.
The FetchContent module allows specifying Git repositories of CMake projects to fetch at configure time. The default setting assumes that that repository has a CMakeLists.txt file at the repo's root directory. It clones the repo to a default (but configurable) location, and then just calls add_subdirectory() on the cloned directory.
You can read about how to use it in the reference documentation, and you can read about how that approach compares with some other CMake-supported approaches for using dependencies in the official Using Dependencies Guide. Do brace yourself when reading the reference docs, though. They're not designed to be like a beginner-friendly tutorial, and since FetchContent is built upon another module called ExternalProject, some of the docs for FetchContent just point you to go read sections from the ExternalProject docs. Be prepared to do a bit of digging.
Here's a basic example I used in a project at one point.
include(FetchContent)
FetchContent_Declare(
range-v3
GIT_REPOSITORY git#github.com:ericniebler/range-v3.git
GIT_TAG "0.12.0" # https://github.com/ericniebler/range-v3/releases
GIT_SHALLOW TRUE
GIT_PROGRESS ON
SYSTEM
)
# more `FetchContent_Declare`s (if any). They should all be declared
# before any calls to FetchContent_Make_available (see docs for why).
FetchContent_MakeAvailable(range-v3)
# more `FetchContent_MakeAvailable`s (if any).
FetchContent in some ways is designed to be a little bit "low level". It has a lot of machinery and customization points. If your project is super simple, you might find it useful to try out a CMake-external wrapper module called "CPM" (CMake Package Manager) that attempts to cater to sensible defaults for more common, simple use-cases.
If you use FetchContent or CPM, be aware that since they eventually just call add_subdirectory, you might need to take some steps to avoid naming conflicts of target names and CMake variable names between your CMake configs and the CMake configs of the dependencies you pull in. For more info, see How can I avoid clashes with targets "imported" with FetchContent_MakeAvailable?.
As others have mentioned, you can also look into using package managers like vcpkg or Conan. I don't know much about those so I can't comment.

How do I scaffold a new C++ project using CMake?

Is there a way to quickly scaffold a basic C++ CMake project using CMake itself? For examples in an empty directory calling cmake new then CMake asks a few questions e.g. project name, lisence and generator. Then CMake generates all the required files and directories, e.g. CMakeLists.txt file, src directory and probably initialize it as Git repository.
I don't know of such features and I don't see a point to add scaffolding into CMake itself. There are free and popular tools specifically for scaffolding purpose, so I suggest you to go to yeoman or slush generators search pages and search for cmake.
You may write a CMake function to create an empty project with a specific layout.
file command helps you to create files and directories.

How to install the C++20 range library from github

I would like to use the range-v3 library in my project, but i don't understand how. The installation description says the following:
This library is header-only. You can get the source code from the
range-v3 repository on github. To compile with Range-v3, just #include
the individual headers you want.
Does that mean I can copy and paste the needed header files and add the filepath to my CMake file? I am a bit confused, because I never included third party library.
Note: please see hythis' answer for a better solution.
Does that mean I can copy and paste the needed header files and add the filepath to my CMake file?
Basically, yes. First git clone to <path_to_range_v3>. Then include these lines into CMakeLists.txt:
add_library(range_v3 INTERFACE IMPORTED)
set_target_properties(range_v3 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES <path_to_range_v3>/include)
target_link_libraries(your_target PUBLIC range_v3)
I'm not sure why Evg suggested what they did, I don't even think in 2019 you were forced to create your own CMake interface with ranges-v3 (see here, the file existed way before hand). Regardless, don't use Evg's solution, ranges-v3 is a good header only library, and in order for a header only library to be good it must provide CMake integration.
Header only libraries do not mean the authors do not provide CMake support, or even avoid CMake themselves. Bad authors do this, as you've probably experienced by having to ask this question in the first place.
To properly integrate with Ranges V3, use a packagemanager (though some package managers screw the process up depending on how their custom CMake files are configured) such as Conan or vcpkg and integrate with their respective CMake solutions, or add the project as a git submodule (though you could git clone it as well) then in your CMakeLists.txt:
add_subdirectory([path to submodules]/range-v3)
...
target_link_libraries(my_target [SCOPE] range-v3::range-v3)
It can be hard to figure out actual targets for libraries if the authors don't spell out how to use their projects in a CMake project, and I don't blame any one making an SO post about it, it's a pain.
Generally if the project has a CMakeLists.txt file, it probably has static-library/sub_directory cmake integration, but some libraries only have install targets, thus are unusable when baked into your source code with out editing their CMakeLists.txt
To check if this is the case, or if you can actually use the targets, if you can't find any CMake documentation about how to use the library (which I couldn't) do the following:
Look inside the CMakeLists.txt file
Find a project alias usually in the form of project_name::project_name. This is how I found range-v3's project alias.
If you can't find alias (via searching for ::), find the actual target name for the library (and try to use this directly), sometimes this isn't exported though (hidden in a sub directory from the top cmake file). OpenCV doesn't use :: for example, and instead each component target is marked with opencv_[component name] but still exported.
If the project has not been configured to be properly used as a submodule and is otherwise meant to be used as a static library, submit an issue or PR to the given repository, this is a bug.

Is there a way to provide a predefined folder structure in SVN?

I am working on several C++ projects on my local computer. They all use some common libs and headers. The file structure is like this:
-bin
-lib
-include
-devel
-project1
-src
-project2
-src
-doc
I am using Eclipse IDE and i set all the relative paths. It compiles the executables to the bin folder and uses libs/includes within the structure. It works fine.
Now I need to import all the projects into an SVN repository so that different people can access and develop codes.
And i wondering if there is a way to have this structure in the SVN server? So when someone checks out a project, he can just start working on it without organising the libs or headers. He will just check out, and all the relative linking will be done.
I am using Eclipse with subclipse plugin.
why u don't use maven? with SVN or GIT it's very good...

CMAKE for modular c++ framework

I'm refactoring a large platform independent c++ framework so that it's libraries and execuables no longer have to be in the same directory (or even repository) and it is proving quite challenging. The framework was currently used only by me and it should now address our whole working group so I have to keep it as modular and as automatized as possible.
My basic structure looks like this
apps/
app1, app2, ...
libs/
core, lib1, lib2, ...
bin:
app1, app2, libcore, liblib1, liblib2, ... (on NIX)
app1.exe, app2.exe, core.dll, lib1.dll, lib2.dll, ... (on Windows)
Apps depend on libs, and all libs depend on the core lib. This all works fine in the same root directory and with the add_subdirectory mechanism.
Project dependencies were handeled by the order in which I was calling add_subdirectory: first libs (core being the first), then apps. Cmake was kind enough to set ${core_SOURCE_IR} to the respective directory and all binaries (libs and apps) were generated in the same directory.
What I need advice with is:
should I move to a find_package based approach (write for each lib and FindLib.cmake file)
how the apps and libs will find each other
where to put the binaries
how to pass along include directories of dependent targets
ExternalProject_Add ?
Thank you
I'd recommend using INSTALL(TARGETS... along with INSTALL(EXPORT...
For full details, run:
cmake --help-command INSTALL
FIND_PACKAGE is generally used to find an external project which is already installed (and which wasn't installed with CMake's INSTALL(EXPORT... command) and ExternalProject_Add is used to download, configure, build and install an external project.
If you use INSTALL(EXPORT... with each of your libs and exes, and then just INCLUDE the installed <target>.cmake in your main CMakeLists.txt, these will become available as proper CMake targets, with their dependencies per configuration already set.
As to where to install these export files - that's up to you, but as long as the path you specify is the same place you use when you INCLUDE the file later, it should work fine.
First, you can add_subdirectory()es in any order without caring about dependencies. CMake handles them when all CMakeLists.txt are parsed.
Second, if you wish any your lib or app to be buildable stand-alone, you certainly should use something like find_package(). It can be find_library() and find_file(lib.h) for simple cases.
In this case after find_package() invocation you will have LIB_INCLUDE_DIRS, LIB_LIBRARY_DIRS, LIB_LIBRARIES variables defined, which can be passed to include_directories(), link_directories() and target_link_libraries() respectively. That's how apps will find libs.
As for where to put binaries - in *NIX it's wide practice to place them into ${CMAKE_INSTALL_PREFIX}/bin.
Please comment on this answer, if there is something unclear for you.