programing

Git 버전 해시를 C코드로 자동 출력하려면 어떻게 해야 하나요?

prostudy 2022. 8. 27. 08:44
반응형

Git 버전 해시를 C코드로 자동 출력하려면 어떻게 해야 하나요?

Git버전 해시에 접근할 수 있는 C코드를 쉽게 쓸 수 있는 방법이 있나요?

실험실 환경에서 과학 데이터를 수집하기 위해 C로 소프트웨어를 작성했습니다.내 코드는 나중에 분석하기 위해 수집한 데이터를 .yaml 파일에 기록합니다.매일매일 실험이 바뀌어 코드를 수정해야 하는 경우가 많습니다.수정사항을 추적하기 위해 git 저장소를 사용합니다.

Git 리비전 해시를 코멘트로 .yaml 데이터 파일에 포함시키고 싶습니다.이렇게 하면 .yaml 파일을 보고 해당 파일에 표시된 데이터를 생성하기 위해 어떤 코드가 사용되었는지 정확하게 알 수 있습니다.이걸 자동으로 쉽게 할 수 있는 방법이 있나요?

Make-based 빌드를 사용하는 경우 Makefile에 다음 내용을 넣을 수 있습니다.

GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)"

(스위치의 기능에 대해서는, 「man git description」을 참조해 주세요).

다음 내용을 CFLAGS에 추가합니다.

-DVERSION=\"$(GIT_VERSION)\"

그런 다음 프로그램에서 버전을 직접 참조하면 #define인 것처럼 됩니다.

printf("Version: %s\n", VERSION);

기본적으로는 git commit id를 생략하여 출력할 뿐이지만, 옵션으로 다음과 같은 특정 릴리스에 태그를 붙일 수 있습니다.

git tag -a v1.1 -m "Release v1.1"

다음에, 인쇄됩니다.

Version: v1.1-2-g766d

즉, 2는 v1.1을 지나 "766d"로 시작하는 git commit id로 커밋합니다.

트리에 커밋되지 않은 변경 사항이 있는 경우 "-dirty"가 추가됩니다.

인 '의존성 '을 .make clean강제로 버전을 업데이트합니다.하지만 이 문제는 해결할 수 있다.

장점은 단순하고 perl이나 awk와 같은 추가 빌드 종속성이 필요하지 않다는 것입니다.GNU 오토메이크 및 Android NDK 빌드에서 이 방법을 사용해 왔습니다.

로,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.version.c뭇매를 맞다

#include "version.h"
const char * build_date = "2009-11-10 11:09";
const char * build_git_sha = "6b54ea36e92d4907aba8b3fade7f2d58a921b6cd";

다음과 같은 헤더 파일도 있습니다.

#ifndef VERSION_H
#define VERSION_H
extern const char * build_date; /* 2009-11-10 11:09 */
extern const char * build_git_sha; /* 6b54ea36e92d4907aba8b3fade7f2d58a921b6cd */
#endif /* VERSION_H */

헤더 파일과 C 파일은 모두 다음과 같은 Perl 스크립트에 의해 생성됩니다.

my $git_sha = `git rev-parse HEAD`;
$git_sha =~ s/\s+//g;
# This contains all the build variables.
my %build;
$build{date} = make_date_time ();
$build{git_sha} = $git_sha;

hash_to_c_file ("version.c", \%build, "build_");

서 ★★★★hash_to_c_file은 다 합니다.version.c ★★★★★★★★★★★★★★★★★」version.h ★★★★★★★★★★★★★★★★★」make_date_time는 그림과 같이 문자열을 만듭니다.

메인 프로그램에서는 루틴이 있습니다.

#include "version.h"

// The name of this program.
const char * program_name = "magikruiser";
// The version of this program.
const char * version = "0.010";

/* Print an ID stamp for the program. */

static void _program_id_stamp (FILE * output)
{
    fprintf (output, "%s / %s / %s / %s\n",
             program_name, version,
             build_date, build_git_sha);
}

저는 git에 대해 잘 모르기 때문에 더 좋은 방법이 있다면 코멘트 부탁드립니다.

이는 Windows 및 Linux에서 동작하는 CMake 프로젝트를 위한 솔루션으로, 다른 프로그램(스크립트 언어 등)을 설치할 필요가 없습니다.

git 해시는 스크립트에 의해 .h 파일에 기록됩니다.이것은 Linux에서 컴파일 할 때의 bash 스크립트 또는 Windows에서 컴파일 할 때의 Windows 배치 스크립트입니다.CMakeLists의 if-clause.txt는 코드가 컴파일된 플랫폼에 대응하는 스크립트를 실행하기 위해 사용됩니다.

다음 2개의 스크립트를 CMakeLists 와 같은 디렉토리에 저장합니다.txt:

get_syslog_syslog.sh:

#!/bin/bash
hash=$(git describe --dirty --always --tags)
echo "#ifndef GITHASH_H" > include/my_project/githash.h
echo "#define GITHASH_H" >> include/my_project/githash.h
echo "const std::string kGitHash = \"$hash\";" >> include/my_project/githash.h
echo "#endif // GITHASH_H" >> include/my_project/githash.h

get_module_module.module:

@echo off
FOR /F "tokens=* USEBACKQ" %%F IN (`git describe --dirty --always --tags`) DO (
SET var=%%F
)
ECHO #ifndef GITHASH_H > include/my_project/githash.h
ECHO #define GITHASH_H >> include/my_project/githash.h
ECHO const std::string kGitHash = "%var%"; >> include/my_project/githash.h
ECHO #endif // GITHASH_H >> include/my_project/githash.h

CMake Lists에서.txt는 커스텀타깃 "write_time"을 정의하기 위해 선두에 다음 행을 추가합니다.

if(WIN32)
  add_custom_target( write_git_hash
    get_git_hash.cmd
    COMMENT "Call batch script for writing git hash"
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  )
else()
  add_custom_target( write_git_hash
    ./get_git_hash.sh
    COMMENT "Call shell script for writing git hash"
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  )
endif()

프로젝트에 "포함" 폴더를 추가해야 합니다.

project(my_project)
include_directories(include)

실행 파일을 정의한 후 의존관계로 "write_git_hash"를 추가합니다.

add_executable(my_project src/my_cpp_file.cpp)
add_dependencies(my_project write_git_hash)

그러면 프로젝트 빌드 시 githash.h가 생성됩니다.

.h 시키고 githash 파일을 C++ 파일로 만듭니다.#include <my_project/githash.h>할 수 이제 git 해시를 단말기에 인쇄할 수 있습니다.

std::cout << "Software version: " << kGitHash << std::endl;

원하는 대로 할 수도 있어요

njd27의 회답에 근거해, 의존성 스캔이 있는 버전을, 코드가 다른 방법으로 빌드 되었을 때의 디폴트치를 가지는 version.h 파일과 조합해 사용하고 있습니다.version.h를 포함한 모든 파일이 재구축됩니다.

또한 수정 날짜도 별도의 정의로 포함됩니다.

# Get git commit version and date
GIT_VERSION := $(shell git --no-pager describe --tags --always --dirty)
GIT_DATE := $(firstword $(shell git --no-pager show --date=short --format="%ad" --name-only))

# recompile version.h dependants when GIT_VERSION changes, uses temporary file version~
.PHONY: force
version~: force
    @echo '$(GIT_VERSION) $(GIT_DATE)' | cmp -s - $@ || echo '$(GIT_VERSION) $(GIT_DATE)' > $@
version.h: version~
    @touch $@
    @echo Git version $(GIT_VERSION) $(GIT_DATE)

@Kinopiko의 답변과 매우 비슷한 것을 사용하게 되었습니다만, perl이 아닌 awk를 사용했습니다.이는 펄이 아닌 mingw의 특성상 awk가 설치되어 있는 윈도 머신에 고착되어 있는 경우에 유용합니다.이걸 어떻게 하는지 보여줄게.

makefile에는 git, date, awk를 호출하여 c파일을 작성하는 행이 있습니다.

$(MyLibs)/version.c: FORCE 
    $(GIT) rev-parse HEAD | awk ' BEGIN {print "#include \"version.h\""} {print "const char * build_git_sha = \"" $$0"\";"} END {}' > $(MyLibs)/version.c
    date | awk 'BEGIN {} {print "const char * build_git_time = \""$$0"\";"} END {} ' >> $(MyLibs)/version.c 

코드를 컴파일 할 때마다 awk 명령어는 다음과 같은 version.c 파일을 생성합니다.

/* version.c */
#include "version.h"
const char * build_git_sha = "ac5bffc90f0034df9e091a7b3aa12d150df26a0e";
const char * build_git_time = "Thu Dec  3 18:03:58 EST 2009";

다음과 같은 static version.h 파일이 있습니다.

/*version.h*/
#ifndef VERSION_H_
#define VERSION_H_

extern const char * build_git_time;
extern const char * build_git_sha;


#endif /* VERSION_H_ */

이제 내 코드의 나머지 부분은 버전을 포함하는 것만으로 빌드 타임과 git 해시에 액세스할 수 있습니다.h 헤더마지막으로 git에게 버전.c를 무시하도록 지시합니다.gitignore 파일에 행을 추가합니다.이 방법으로는 git이 항상 merge conflicts를 발생시키지 않습니다.이게 도움이 됐으면 좋겠네요!

Makefile 및 Shell을 기반으로 한 또 다른 변형

GIT_COMMIT_FILE=git_commit_filename.h

$(GIT_COMMIT_FILE): phony
    $(eval GIT_COMMIT_SHA=$(shell git describe --abbrev=6 --always 2>/dev/null || echo 'Error'))
    @echo SHA=$(GIT_COMMIT_SHA)
    echo -n "static const char *GIT_COMMIT_SHA = \"$(GIT_COMMIT_SHA)\";" > $(GIT_COMMIT_FILE)

git_commit_commit.h 파일은 static const char *GIT_COMMIT_SHA="를 포함하는 단일 행으로 끝납니다.

https://gist.github.com/larytet/898ec8814dd6b3ceee65532a9916d406 에서

다음 두 가지 작업을 수행할 수 있습니다.

  • Git에서 버전 정보를 파일에 포함시킬 수 있습니다.

    보다 간단한 방법은ident attribute(예를 들어 put)를 의미합니다.

    *.yaml    ident
    

    .gitattributes파일, 및$Id$적절한 장소에서.파일 내용의 SHA-1 식별자(blob id)로 자동 확장됩니다.이것은 NOT 파일버전 또는 마지막 커밋이 아닙니다.

    Git은 분기 전환, 분기 되감기 등에서 변경되지 않은 파일을 건드리지 않기 위해 $Id$ 키워드를 지원합니다.Git이 커밋(버전) 식별자 또는 설명을 파일에 넣기를 원한다면 (ab)를 사용할 수 있습니다.filterclean/smudge 필터를 사용하여 체크아웃 시 키워드($Revision$ 등)를 확장하고 커밋을 위해 정리합니다.

  • Linux 커널이나 Git 자체처럼 빌드 프로세스를 만들 수 있습니다.

    GIT-VERSION-GEN 스크립트와 Git Makefile에서의 그 사용, 또는 예를 들어 이 Makefile이 생성/구성 중에 버전 정보를 포함하는 방법을 보십시오.gitweb/gitweb.cgi파일.

    GIT-VERSION-GEN은 GIT 기술을 사용하여 버전 설명을 생성합니다.프로젝트의 릴리스/마일스톤에 태그(서명 첨부/주석 첨부 태그 사용)를 붙이는 것이 좋습니다.

프로그램은 다음과 같이 전개할 수 있습니다.git describe실행 시 또는 빌드 프로세스의 일부입니다.

제가 이걸 해야 할 때, 저는 태그를 사용합니다.RELEASE_1_23SHA-1을 몰라도 태그의 종류를 결정할 수 있습니다.커밋 후 태그합니다.원하는 대로 프로그램에 태그를 저장할 수 있습니다.

또한 git을 사용하여 과학 코드의 변화를 추적합니다.외부 프로그램은 코드 이동성을 제한하기 때문에 사용하고 싶지 않았습니다(예를 들어 MSVS에서 변경을 원하는 경우).

제 해결책은 계산에는 메인 브랜치만 사용하고 프리프로세서 매크로를 사용하여 빌드 시간을 출력하는 것이었습니다.__DATE__그리고.__TIME__그러면 git log로 확인하고 어떤 버전을 사용하고 있는지 확인할 수 있습니다.참조: http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html

문제를 해결하기 위한 또 다른 우아한 방법은 실행 파일에 git 로그를 포함시키는 것입니다. git 로그로 오브젝트 파일을 만들어 코드에 포함시킵니다.이번에 당신이 사용하는 유일한 외부 프로그램은 objcopy이지만 코딩은 덜 합니다.참조: http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967 및 C++ 프로그램에 데이터 삽입

필요한 것은 다음과 같은 헤더파일을 생성하는 것입니다(예를 들어 cmd행의 에코 사용).

#define GIT_HASH \
"098709a0b098c098d0e"

이를 생성하려면 다음과 같은 방법을 사용합니다.

echo #define GIT_HASH \ > file.h
echo " > file.h
echo git status <whatever cmd to get the hash> > file.h
echo " > file.h

컴파일하려면 따옴표와 백슬래시를 좀 가지고 놀아야 할 수도 있지만, 이해하실 수 있을 겁니다.

원래 커밋에서 memcached에 대해 어떻게 했는지 알 수 있습니다.

기본적으로, 가끔 태그를 붙이고 배달하는 것이make dist또는 이와 유사합니다.

언급URL : https://stackoverflow.com/questions/1704907/how-can-i-get-my-c-code-to-automatically-print-out-its-git-version-hash

반응형