Hey guys,
I Read about the new cmake FetchContent .
i’d like to use this to clone and checkout a git repository
include(FetchContent)
function(CloneRepository repositoryURL branchName projectName sourceDir)
#Commands are left empty so that we only checkout the source and no not perform any kind of build
message("Starting to clone ${projectName} into ${sourceDir}")
FetchContent_Declare(
"${projectName}"
GIT_REPOSITORY "${repositoryURL}"
SOURCE_DIR "${sourceDir}"
GIT_TAG "origin/${branchName}"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
FetchContent_MakeAvailable(${projectName})
endfunction(CloneRepository)
Now the problem is, I do not want to checkout a specific tag but the latest commit of a specified branch. When running this code the checkout git repo is much bigger than the manually cloned Repo. Also the Upstream Branch does not seam to be set.
Can you help me how to checkout the latest commit of a specified branch?
Git branch name, tag or commit hash. Note that branch names and tags should generally be specified as remote names (i.e. origin/myBranch rather than simply myBranch). This ensures that if the remote end has its tag moved or branch rebased or history rewritten, the local clone will still be updated correctly. In general, however, specifying a commit hash should be preferred for a number of reasons:
If the local clone already has the commit corresponding to the hash, no git fetch needs to be performed to check for changes each time CMake is re-run. This can result in a significant speed up if many external projects are being used.
Using a specific git hash ensures that the main project’s own history is fully traceable to a specific point in the external project’s evolution. If a branch or tag name is used instead, then checking out a specific commit of the main project doesn’t necessarily pin the whole build to a specific point in the life of the external project. The lack of such deterministic behavior makes the main project lose traceability and repeatability.
If GIT_SHALLOW is enabled then GIT_TAG works only with branch names and tags. A commit hash is not allowed.
Hey, does the doc for ExternalProject apply to FetchContent as well? FetchContent docs do not mention git shallow.
I tried CloneRepository("https://github.com/opencv/opencv.git" "origin/master" "opencv" "${CMAKE_CURRENT_LIST_DIR}/../opencv")
However to upstream connection does not seam to be set correctly. Git Bash shows this
=>so despite writing origin/master the upstream branch connection does not seam to be set correctly.
I’m am using latest CMake 3.21.4 generation was done using CMake GUI
(of course you are right using a proper tag is better traceable, but for development purposes I’d like to use the latest of our (internal) shared Lib
cmake_minimum_required (VERSION 3.21.0)
project(parent)
include(FetchContent)
FetchContent_Declare(foobar
GIT_REPOSITORY "https://github.com/opencv/opencv.git"
GIT_TAG "origin/master" # it's much better to use a specific Git revision or Git tag for reproducibility
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../opencv"
)
FetchContent_MakeAvailable(foobar)
add_executable (Test "Test.cpp" "Test.h")
target_link_libraries(Test PRIVATE foobar_target)
even with this there is no connection to the upstream branch. Am I missing something here?
If I’m not mistaken, CMake does check out specific commit, not branch. Why? Because it does not have to. If you need such functionality you probably have to call git commands by yourself.
OpenCV seems to have origin/4.x set as default branch.
So if you clone on command line without further arguments you’ll get origin/4.x and not origin/master.
If you now simply checkout origin/master you end up in headless state, because there is no local master branch.
Please verify with git status for each directory what you are really seeing.
yep it’s like you said. I end up in a headless state. I even tried to omit the GIT_TAG “origin/master” to just checkout the default. But still the heads are detached