Clone Git Repository using new CMake FetchContent Functionality

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)

usage
CloneRepository("https://github.com/opencv/opencv.git" "master" "opencv" "${CMAKE_CURRENT_LIST_DIR}/../opencv")

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?

greets Julian

From the CMake docs

GIT_TAG

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
grafik

=>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 :wink:

for some reason I’m only allowed to add only 1 img per Post.
So here is what i would expect
grafik

FetchContent uses ExternalProject “This module enables populating content at configure time via any method supported by the ExternalProject module.”

Here are some FetchContent tutorials:

https://enccs.github.io/cmake-workshop/fetch-content/

https://eliasdaler.github.io/using-cmake/

Hey I took the example from Using CMake and managing dependencies · Elias Daler's blog
Just added the Source Dir to the example

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?

What do you mean? I copy pasted your code locally and it seemed to pull it down just fine.

The only issues I had was it failed to find python 2.7 on my machine.

  CMake's 'find_host_package(PythonInterp 2.7)' found wrong Python version:

Here is my code for reference:

### Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved. ###
cmake_minimum_required(VERSION 3.21)

include(FetchContent)

project(TEST4)

FetchContent_Declare(opencv
  GIT_REPOSITORY "https://github.com/opencv/opencv.git"
  GIT_TAG "origin/master"
  SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../opencv"
)

FetchContent_MakeAvailable(opencv)

add_executable(foobar)

target_sources(foobar PRIVATE main.cpp)

Hey, thx for your reply :slight_smile:
could you verfiy this
Open the cloned opencv repo with a Git Gui and see if the checkout commit is actually attached to origin

This is the result in my case.

However when I open a shell and type in git clone … I’ll get this.
(see next post. I’m only allowed to post 1 image per post)

This is my expected result from performing a clone operation. Can you observe the same behaviour?

=>this is the expected behaviour

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.

hey. Thx I was afraid you might say that.
Than I will go back execute_process() :frowning:

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 :frowning:

sorry is it just me or does this link not work any more? I get a 404 error

Use my original link, @kadir’s link is broken

https://eliasdaler.github.io/using-cmake/

sorry just to be clear. You all have a detached head when using my snippet correct?
At least that’s what I’m encountering after several tries

Thx for your help so far :slight_smile: