如何搭建android源代碼repo倉庫

来源:https://www.cnblogs.com/aosp/archive/2022/07/05/16445394.html
-Advertisement-
Play Games

如何搭建android源代碼repo倉庫 . 版本: v0.3 作者:河東西望 日期:2022-7-5 . 如果你的開發是基於AOSP源碼來建倉,那麼搭建repo伺服器和部署自己的repo倉庫就是非常必要的工作了。 現實中很多公司都是直接把AOSP源代碼放在一個git倉庫中來管理,這樣做沒什麼毛病。 ...


如何搭建android源代碼repo倉庫


目錄


.
版本: v0.3
作者:河東西望
日期:2022-7-5
.

如果你的開發是基於AOSP源碼來建倉,那麼搭建repo伺服器和部署自己的repo倉庫就是非常必要的工作了。

現實中很多公司都是直接把AOSP源代碼放在一個git倉庫中來管理,這樣做沒什麼毛病。但是如果開發團隊人數較多,會存在一些明顯的弊端:

  1. AOSP源代碼一般的大小是20GB,編譯之後達到40GB以上。每次同步會很耗費時間。
  2. AOSP源代碼文件數量將近70W個,單個倉庫的文件索引會很龐大,每次檢索非常耗時。
  3. AOSP和晶元平臺廠商(例如qcom、mtk、rockchip等)的原始代碼倉庫,一般是以repo倉庫結構提供的,而不是單個git倉庫。改變倉庫結構之後,人工維護的工作量比較大。

AOSP源代碼結構複雜龐大,除了本身的代碼模塊之外,還集成了五六百個第三方倉庫,這些倉庫也會在不停的更新迭代。AOSP維護整個代碼倉庫框架就需要保持足夠的靈活性,於是就引進了repo腳本來批量管理git倉庫。AOSP的源代碼切分的git倉庫數量多達六七百多個。

如果我們想要跟上游平臺倉庫保持一致的倉庫結構,很方便快捷的同步代碼,而我們自己也能靈活的管理本地的擴展倉庫,就需要搭建部署自己的repo倉庫了。

在實際的團隊開發實踐中,代碼管理框架一般是gerrit+repo的組合形式。gerrit的安裝部署和許可權管理等不是本文檔的內容,請讀者搜索網路材料來安裝部署。本文檔的主要內容包括:

  1. 說明repo倉庫的管理策略。
  2. 如何建立清單倉庫。
  3. 如何批量切分git倉庫。
  4. repo倉庫的操作使用。

本文檔的伺服器操作系統是ubuntu18.04。

1 repo是如何管理倉庫的?

1.1 repo如何工作的?

新的操作系統安裝包中已經包含了repo命令程式,可以直接通過下麵的命令安裝:

sudo apt-get install repo

# 查看repo版本
repo --version

<repo not installed>
repo launcher version 2.17
       (from /usr/local/bin/repo)
git 2.34.1
Python 3.10.4 (main, Apr  2 2022, 09:04:19) [GCC 11.2.0]
OS Linux 5.15.0-39-generic (#42-Ubuntu SMP Thu Jun 9 23:42:32 UTC 2022)
CPU x86_64 (x86_64)
Bug reports: https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue

安裝完畢,我們可以看到安裝的實際上是一個repo的引導器。它還不是完整的管理工具。

通過cat命令查看一下repo文件,實際上是一個python3腳本.

which repo
/usr/local/bin/repo

cat /usr/local/bin/repo
........

客戶端在同步倉庫時一般用到的幾個命令序列:

# 初始化倉庫
repo init -u ....
# 檢出代碼
repo sync -j16
# 建立本地分支
repo start <BRANCH> --all
# 批量執行git命令
repo forall -c `GIT COMMAND`

我們以清華大學官網的AOSP代碼為例,操作一下repo的倉庫同步。

# 設置一下REPO_URL。
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'

mkdir -p ~/aosp
cd aosp

# 初始化倉庫
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest
Downloading Repo source from https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/
remote: Enumerating objects: 7372, done.
remote: Counting objects: 100% (7372/7372), done.
remote: Compressing objects: 100% (3935/3935), done.
remote: Total 7372 (delta 4765), reused 5577 (delta 3363)
接收對象中: 100% (7372/7372), 3.27 MiB | 3.58 MiB/s, 完成.
處理 delta 中: 100% (4765/4765), 完成.

... A new version of repo (2.21) is available.
... You should upgrade soon:
    cp /home/xxx/Documents/aosp/.repo/repo/repo /usr/local/bin/repo

Downloading manifest from https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest
remote: Enumerating objects: 98793, done.
remote: Counting objects: 100% (98793/98793), done.
remote: Compressing objects: 100% (39423/39423), done.
remote: Total 98793 (delta 38918), reused 98123 (delta 38532)
接收對象中: 100% (98793/98793), 25.23 MiB | 2.40 MiB/s, 完成.
處理 delta 中: 100% (38918/38918), 完成.

Your identity is: xxx <[email protected]>
If you want to change this, please re-run 'repo init' with --config-name

Testing colorized output (for 'repo diff', 'repo status'):
  black    red      green    yellow   blue     magenta   cyan     white 
  bold     dim      ul       reverse 
Enable color display in this user account (y/N)? y

repo has been initialized in /home/xxx/Documents/aosp/
If this is not the directory in which you want to initialize repo, please run:
   rm -r /home/yl/Documents/aosp//.repo
and try again.

repo init命令執行完畢,實際上就是下載了一個.repo目錄下(repo命令版本過時,可以根據提示更新一下,也可以不用更新)。

我們看一下repo目錄內容:

repo
├── manifests        // 清單倉庫
│   ├── .git -> ../manifests.git/
│   ├── default.xml  // 真正的倉庫清單文件
│   ├── GLOBAL-PREUPLOAD.cfg
│   └── OWNERS
├── manifests.git    // 清單倉庫git配置信息
│   ├── branches
│   ├── config
│   ├── description
│   ├── FETCH_HEAD
│   ├── HEAD
│   ├── hooks
│   ├── index
│   ├── info
│   ├── logs
│   ├── objects
│   ├── packed-refs
│   └── refs
├── manifest.xml     // 清單文件,內容包含default.xml文件
└── repo             // repo工具腳本
    ├── color.py
    ├── command.py
    ├── git_trace2_event_log.py
    ├── hooks
    ├── hooks.py
    ├── repo
    ├── .........
    └── wrapper.py

repo init幹了這幾件事情:

  1. 下載repo工具倉庫,其中包含了python腳本。在.repo/repo目錄下。
  2. 下載了manifests清單倉庫,在目錄.repo/manifests下,軟鏈接包含了.repo/manifests.git目錄。
  3. 下載了一個倉庫清單文件manifests.xml,其中包含default.xml。

repo批量管理倉庫的內容就在default.xml中。我們看一下文件內容:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>

  <remote  name="aosp"
           fetch=".."
           review="https://android-review.googlesource.com/" />
  <default revision="master"
           remote="aosp"
           sync-j="4" />

  <manifest-server url="http://android-smartsync.corp.google.com/android.googlesource.com/manifestserver" />

  <superproject name="platform/superproject" remote="aosp"/>
  <contactinfo bugurl="go/repo-bug" />

  <project path="build/make" name="platform/build" groups="pdk" >
    <linkfile src="CleanSpec.mk" dest="build/CleanSpec.mk" />
    <linkfile src="buildspec.mk.default" dest="build/buildspec.mk.default" />
    <linkfile src="core" dest="build/core" />
    <linkfile src="envsetup.sh" dest="build/envsetup.sh" />
    <linkfile src="target" dest="build/target" />
    <linkfile src="tools" dest="build/tools" />
  </project>
  <project path="build/bazel" name="platform/build/bazel" groups="pdk" >
    <linkfile src="bazel.WORKSPACE" dest="WORKSPACE" />
    <linkfile src="bazel.sh" dest="tools/bazel" />
    <linkfile src="bazel.BUILD" dest="BUILD" />
  </project>
  <project path="build/bazel_common_rules" name="platform/build/bazel_common_rules" groups="pdk" />
  <project path="build/blueprint" name="platform/build/blueprint" groups="pdk,tradefed" />
  <project path="build/pesto" name="platform/build/pesto" groups="pdk" />
  <project path="build/soong" name="platform/build/soong" groups="pdk,tradefed" >
    <linkfile src="root.bp" dest="Android.bp" />
    <linkfile src="bootstrap.bash" dest="bootstrap.bash" />
  </project>
  <project path="art" name="platform/art" groups="pdk" />
  <project path="bionic" name="platform/bionic" groups="pdk" />
  <project path="bootable/recovery" name="platform/bootable/recovery" groups="pdk" />
  <project path="bootable/libbootloader" name="platform/bootable/libbootloader" groups="vts,pdk" />
  <project path="device/common" name="device/common" groups="pdk-cw-fs,pdk" />
  <project path="device/generic/arm64" name="device/generic/arm64" groups="pdk" />
  <project path="device/generic/armv7-a-neon" name="device/generic/armv7-a-neon" groups="pdk" />
  <project path="device/generic/art" name="device/generic/art" groups="pdk" />
  ......
  <repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload" />

  <!--
    Merge marker to make it easier for git to merge AOSP-only manifest
    changes to a custom manifest.  Please keep this marker here and
    refrain from making changes on or below it.
  -->
</manifest>  

這個XML文件的語法,不是本文檔的內容。簡單說明一下幾個關鍵的:

remote: 遠程服務端repo倉庫名稱
project: 每個項目的git倉庫
path: 客戶端git倉庫路徑
name: 服務端git倉庫名稱
revision: 分支名稱或者commit id
linkfile: 軟鏈接文件,src和dest表示源和目的。
copyfile: 文件拷貝,src和dest表示源和目的。
groups: 分組。

概括一下repo批量管理倉庫的方式:

  1. repo init命令下載工具腳本倉庫和清單倉庫。
  2. repo sync命令根據清單文件中的配置,下載遠程倉庫二進位文件。
  3. repo start檢出分支。

所以,repo倉庫的管理核心就在manifest.git,而起關鍵作用的配置文件就是倉庫清單文件xxx.xml,有多少個項目倉庫,就有對應的xml清單文件。

1.2 搭建repo服務需要做哪些事情?

接著就是關鍵問題:搭建repo伺服器我們要做哪些事情?

簡而言之:

  1. 部署通用的工具倉庫git-repo.git。
  2. 部署自己的清單倉庫manifests.git。
  3. 編寫清單文件manifests.xml
  4. 批量創建工程子倉庫和上傳源代碼。

2 部署工具倉庫git-repo.git

實際上,如果你的網路鏈接可以鏈接到外網的話,工具倉庫git-repo.git是不需要搭建部署的。

只需要通過REPO_URL這個環境變數來指定URL就可以自動拉取git-repo.git倉庫。

export REPO_URL=https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/

常用的URL有這些:

## google地址,需要梯子。
https://gerrit.googlesource.com/git-repo

## 清華大學開源軟體鏡像站
https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/

## 其他可以自己網上搜索...

但是現實中,很多公司的外網是受限的,無法訪問。這個時候就需要考慮搭建自己的工具倉庫git-repo.git了。

這個倉庫的搭建很簡單,就是一個普通的git倉庫,但是涉及到GPG簽名的問題就比較複雜。這個過程不是本文檔的內容,可以搜索互聯網上的文檔資料。

3 部署清單倉庫manifests.git

部署清單倉庫的方式,跟普通的git倉庫沒有什麼差別。關鍵問題在:

  1. 清單倉庫如何管理多個項目倉庫?
  2. 如何編寫清單文件manifests.xml?

3.1 如何設計清單倉庫及分支?

3.1.1 需要幾個倉庫?

從伺服器的角度來看,你的伺服器上肯定會管理多個項目倉庫(例如qcom8953,qcom8916,mtk6219,mtk2226,rk3399,rk3358等等),那我們管理這些倉庫的方式可能有:

  1. 整個伺服器只建立一份manifests.git倉庫,每個倉庫下的不同的xml文件管理不同的項目倉庫。例如qcom8953.xml,rk3399.xml等。
  2. 每個項目倉庫建立一個對應的清單倉庫,例如manifests-qcom8953.git、manifests-rk3399.git等,其中放置各項目倉庫的清單文件xml。

這兩種方式都可以,取決於你的代碼管理策略。我一般在整個伺服器上使用一個manifests.git倉庫,通過不同的xml文件來管理所有的項目倉庫。伺服器端項目倉庫的目錄結構設計如下:
aosp
├── manifests.git // 清單倉庫
│   ├── qcom8953.xml
│   ├── rk3399.xml
│   ├── rk3358.xml
│   └── mtk6226.xml
├── qcom/qcom8953 // 項目倉庫
├── rockchip/rk3399 // 項目倉庫
├── rockchip/rk3358 // 項目倉庫
└── mtk/mtk6226 // 項目倉庫

3.1.2 需要幾個分支?

清單倉庫本身就是一個普通的git倉庫,他也是有分支的。同一個配置文件,例如qcom8953.xml,他也可以切分出不同的分支,來管理不同的項目倉庫版本。

清單倉庫的分支,跟項目倉庫的分支沒有直接的關聯關係。但是在實踐操作中,我們一般會在清單倉庫中建立項目倉庫對應的分支,方便管理映射。例如qcom8953項目倉庫,它有4個分支master、develop、test和release,那麼我們的manifests.git也可以建立四個分支,跟項目倉庫對應起來。

我這裡建立兩個分支:master和release。後面會按照這兩個分支來操作。

我們先看一下repo init命令的常用參數:

repo init --help
Usage: repo init [options] [-u] url

Options:

  Manifest options:
    -u URL, --manifest-url=URL
                        manifest repository location
    -b REVISION, --manifest-branch=REVISION
                        manifest branch or revision (use HEAD for default)
    -m NAME.xml, --manifest-name=NAME.xml
                        initial manifest file

  repo Version options:
    --repo-url=URL      repo repository location ($REPO_URL)
    --repo-rev=REV      repo branch or revision ($REPO_REV)
    --no-repo-verify    do not verify repo source code

  Other options:
    --config-name       Always prompt for name/e-mail

一般來說,-b的預設值是master,-m的預設值是manifests.xml。如果我們想要使用不同的預設的清單文件,就需要在編寫服務端清單文件和repo init參數時需要配合使用。

我這裡全部使用預設值。在aosp源碼的mannifests.xml中則體現在這幾個項上:

  <remote  name="aosp"
           fetch=".."
           review="https://android-review.googlesource.com/" />
  <default revision="master"     ## 遠程預設分支
           remote="aosp"         ## 遠程預設倉庫,就是remote標簽中的name="aosp"
           sync-j="4" />

3.2 如何編寫清單文件?

編寫清單文件,肯定不可能全部手寫,需要拿到一份原始的manifests.xml文件。這份文件需要你從你的源頭代碼repo倉庫中獲取是最好的。

我這裡就以qcom的AOSP源碼為例,修改出我自己的倉庫qcom8953.xml。

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
    <!--
        remote: 伺服器遠程倉庫的信息。
        name: 遠程manifest倉庫名稱,一般預設為origin
        fetch: 倉庫url。如果設置為"."(註意是一個點), 就表示在repo init -u url中配置。
        review: 評審系統網址。如果提交代碼,就會進入這個評審系統。
    -->
    <remote name="origin"  fetch="." review="gerrit.your_domain.com" />
        <!--
          default: 這個repo倉庫的預設屬性。
          revision: 預設的工程代碼倉庫分支,可以修改這裡來指向不同的分支。
          remote:   遠程倉庫的名稱。這裡跟<remote>標簽是對應的,當然還可以指向其他倉庫的remote。
        -->
        <default revision="master" remote="origin"/>

        <!--
            project: 每個倉庫就是一個project
            path: 客戶端同步到本地後的路徑名稱。
            name: 伺服器端git倉庫名稱,註意帶了路徑。
        -->
        <project path="build" name="build"  />
        <project path="device" name="device"  />
        <project path="frameworks/base" name="frameworks/base" />
        <!--        
            重要說明:
            這裡的build目錄和其下的三個子目錄:blueprint, kati, soong是嵌套的git倉庫結構!
            這種嵌套的git倉庫。有一個非常重要的控制文件:.gitignore.
            父級目錄那種一定存在一個.gitignore文件,其中包含了嵌套的子級倉庫路徑。
        -->
        <project path="build" name="build">
            <!-- copyfile: 將build/core/root.mk拷貝為Makefile。其中帶有相對路徑 -->
            <copyfile src="core/root.mk" dst="Makefile" />
        </project>
        <project path="build/blueprint" name="build/blueprint" />
        <project path="build/kati" name="build/kati" />
        <project path="build/soong" name="build/soong">
            <!-- linkfile: 建立一個軟鏈接Android.bp指向build/soong/root.bp -->
            <linkfile src="root.bp" dest="Android.bp" />
            <linkfile src="bootstrap.bash" dest="bootstrap.bash" />
         </project>
         <!-- 更多倉庫信息 ...... -->
</manifest>

3.3 創建清單倉庫manifests.git

創建清單倉庫可以有兩種方式:

  1. gerrit系統的web頁面創建。這種方式適合創建少量的倉庫,簡單快捷。
  2. gerrit命令創建。這種方式適合批量創建大量的倉庫,特別是AOSP倉庫。

第一種方式比較簡單,在WEB頁面上操作就可以,沒有什麼特別的。

重點介紹第二種命令行方式。

ssh -p 29418 <USERNAME>@<GERRIT_IP_ADDRESS> gerrit create-project aosp/manifests.git

創建完畢,在gerrit頁面上也可以看到這個manifests.git倉庫。管理員可以在頁面上創建兩個分支:master,release。

客戶端按照正常的git操作操作:

## 克隆代碼
git clone .../manifests.git
## 提交清單文件qcom8953.xml
git add qcom8953.xml
git commit -m "add qcom8953.xml"
git push

這樣我們就建立了一個manifests.git倉庫,並上傳了一個清單文件qcom8953.xml。

下一步就是如何創建項目倉庫了。

4 批量創建工程子倉庫

初始工程倉庫的源代碼,最好來自平臺廠商提供的帶了.repo和.git的完整repo倉庫,然後我們看看如何將這個倉庫移植到我們自己的內部倉庫。

一般的操作步驟:

  1. gerrit命令批量創建服務端空倉庫。
  2. 預處理本地repo倉庫。
  3. 批量上傳源代碼。

4.1 批量創建服務端空倉庫

批量創建子倉庫只能通過gerrit命令行來進行。

ssh -p 29418 <USERNAME>@<GERRIT_IP_ADDRESS> gerrit create-project aosp/qcom8953/xxx.git

這裡我們需要知道的qcom8953倉庫的所有倉庫名字,然後通過腳本來批量創建,有兩種方式:

  1. 從xml腳本中提取倉庫名稱。
  2. 從原始源代碼倉庫的.repo/manifets.git中的project.list文件中直接獲取。
    不管哪種方式,都需要人工核對一下最終的倉庫數量和名稱是一致的。

我們最終需要一個倉庫列表文件:project.list。文件內容如下:

qcom/qcom8953/art
qcom/qcom8953/bionic
qcom/qcom8953/bootable/bootloader/edk2
qcom/qcom8953/bootable/recovery
qcom/qcom8953/build/blueprint
qcom/qcom8953/build/kati
qcom/qcom8953/build
qcom/qcom8953/build/soong
qcom/qcom8953/cts
qcom/qcom8953/dalvik
qcom/qcom8953/developers/build
qcom/qcom8953/developers/demos/JustForUs
qcom/qcom8953/developers/samples/android
qcom/qcom8953/development
qcom/qcom8953/device/common
qcom/qcom8953/device/generic/arm64
qcom/qcom8953/device/generic/armv7-a-neon
......

接下來我們可以使用下列命令來批量創建服務端空倉庫:

# 參數說明
# --empty-commit: 強制參數, 必須添加; 
# -p YOUR-projects: 你的gerrit許可權倉庫。根據你的gerrit許可權名稱來確定。
# 其他參數就不要再添加了,畫蛇添足以後,多出很多問題。
# 註意遠程倉庫名稱前需要帶path首碼(qcom/qcom8953),防止伺服器端倉庫路徑混亂。

cat project.list | xargs -I {}  ssh -p 29418 [email protected] gerrit create-project "{}" --empty-commit -p YOUR-projects

創建完畢,在gerrit頁面上就看到了幾百個git倉庫。

4.2 預處理本地repo代碼

在上傳本地repo倉庫之前,需要做幾個預處理動作:

  1. 刪除本地工程中的.repo目錄。
  2. 核對本地倉庫.repo/manifests.git/xxxx.xml清單文件,根據文件內容刪除掉本地代碼中的copyfile和linkfile的源。
  3. 修改本地每個倉庫的git remote url路徑。這裡你需要自己編寫腳本來批量完成。
git remote set-url origin ssh://[email protected]:29418/xxx

4.3 上傳分支和代碼

倉庫預處理完畢,你需要一一上傳各倉庫的指定的分支和代碼到伺服器倉庫。
這裡是通用的操作, 你也需要自己編寫腳本進行上傳同步:

git checkout master
git push origin master:master
git push -- tags

當然,上傳之後,你最好在第三方測試驗證一下,是不是有些.gitignore或者某些嵌套倉庫存在問題,需要手工進行修複。

5 repo倉庫使用簡述

repo倉庫搭建完畢,對客戶端來說,使用操作並不麻煩,使用常用的repo命令和git命令即可完成代碼提交。

# 初始化倉庫
repo init -u <remote manifests url> -n <manifests branch> -m <manifest NAME.xml>
# 檢出代碼
repo sync -j16
# 建立本地分支
repo start <BRANCH> --all
# 批量執行git命令
repo forall -c `GIT COMMAND`

單個倉庫的代碼提交合併:

git add xxx
git commit -m "xxxx"
git push HEAD:refs/for/BRANCH

初次提交時可能會報告no change id的小錯誤,百度搜索一下,很容易修複的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 Ubuntu20.04伺服器版安裝 下載地址:https://ubuntu.com/download/desktop 一、語言選擇:English(按Done確認,Done按鈕在安裝視窗的最下麵) 二、Installer update avail ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 OneForAll是一款功能強大的子域收集工具 我安裝到了kali git clone https://gitee.com/shmilylty/OneForAll.git git clone https://github.com/shmilylt ...
  • 本文會介紹如何安裝和部署ClickHouse,官方推薦的幾種安裝模式,以及安裝之後如何啟動,ClickHouse集群如何配置等。 簡單來說,ClickHouse的搭建流程如下: 環境檢查,環境依賴安裝 在對應的服務上下載安裝Click House 配置config.xml和user.xml,如果搭建 ...
  • mysql拆分字元串作為查詢條件 有個群友問一個問題 這表的ancestors列存放的是所有的祖先節點,以,分隔 例如我查詢dept_id為103的所有祖先節點,現在我只有一個dept_id該怎麼查 然後我去網上找到這樣一個神奇的sql,改改表名就成了下麵的這樣 SELECT substring_i ...
  • 在如今的業務場景下,高可用性要求越來越高,核心業務跨可用區已然成為標配。騰訊雲資料庫高級工程師劉家文結合騰訊雲資料庫的內核實戰經驗,給大家分享Redis是如何實現多可用區,內容包含Redis主從版、集群版原生架構,騰訊雲Redis集群模式主從版、多AZ架構實現以及多AZ關鍵技術點,具體可分為以下四個 ...
  • 本文主要介紹無損壓縮圖片的概要流程和原理,以及lepton無損壓縮在前期調研中遇到的問題。 ...
  • 安卓往系統中添加日程提醒,吭比較多。 首先有個需求(仿製 ios 日曆),為什麼仿製ios呢?這個得問產品了,我只是一個搬磚的程式員 (*´艸`) 捂嘴 大致有日期,時間,重覆設置,自定義重覆設置,位置提醒設置 跟系統日曆的設置類似,畢竟需要同步到系統,所以設置上面保持規範,都是設置好日期時間,然後 ...
  • 實現APP首頁tabbar滾動吸頂功能 首頁代碼: WillPopScope( child: Scaffold( backgroundColor: Colors.white, appBar: PreferredSize( preferredSize: Size(double.infinity, 0. ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...