【轉載】CMake 兩種變數原理

来源:https://www.cnblogs.com/hdning/archive/2019/11/10/11832383.html
-Advertisement-
Play Games

本文記錄一下 CMake 變數的定義、原理及其使用。CMake 變數包含 Normal Variables、Cache Variables。通過 set 指令可以設置兩種不同的變數。也可以在 CMake 腳本中使用和設置環境變數。set(ENV{ ...


原文地址:https://cslam.cn/archives/c9f565b5.html

摘要:

本文記錄一下 CMake 變數的定義、原理及其使用。CMake 變數包含 Normal Variables、Cache Variables。通過 set 指令可以設置兩種不同的變數。也可以在 CMake 腳本中使用和設置環境變數。set(ENV{<variable>} <value>...),本文重點講述 CMake 腳本語言特有的兩種變數。

正文:

1、兩種變數的定義參考

Normal Variables

通過 set(<variable> <value>... [PARENT_SCOPE])這個命令來設置的變數就是 Normal Variables。例如 set(MY_VAL “666”) ,此時 MY_VAL 變數的值就是 666。

Cache Variables

通過 set(<variable> <value>... CACHE <type> <docstring> [FORCE])這個命令來設置的變數就是 Cache Variables。例如 set(MY_CACHE_VAL "666" CACHE STRING INTERNAL),此時 MY_CACHE_VAL 就是一個 CACHE 變數。

2、兩種變數的作用域原理及使用

1、Normal Variables

​ 作用域屬於整個 CMakeLists.txt 文件,當該文件包含了 add_subdirectory()、include()、macro()、function()語句時,會出現兩種不同的效果。

(1)、包含 add_subdirectory()、function()。(本質是值拷貝)

假設,我們在工程根目錄 CMakeLists.txt 文件中使用 add_subdirectory(src) 包含另一個 src 目錄,在 src 目錄中有另一個 CMakeLists.txt 文件。在終端運行的目錄結構如下:

 

$ tree
.
├── CMakeLists.txt
└── src
    └── CMakeLists.txt

1 directory, 2 files

以根目錄 CMake 文件為父目錄,src 目錄為子目錄,此時子目錄 CMake 文件會拷貝一份父目錄文件的 Normal 變數。需要說明的是,我們在子目錄中如果想要修改父目錄 CMake 文件包含的 Normal 變數。必須通過 set(… PARENT_SCOPE) 的方式。下麵通過例子來說明。

在父 / 根目錄的 CMakeLists.txt 文件內容如下:

cmake_minimum_required(VERSION 3.10)
message("父目錄 CMakeLists.txt 文件")
set(MY_VAL "666")
message("第一次在父目錄 MY_VAL=${MY_VAL}")
add_subdirectory(src) 
message("第二次在父目錄,MY_VAL=${MY_VAL}")

在子目錄 src/CMakeLists.txt 文件內容如下:

cmake_minimum_required(VERSION 3.10)
message("進入子目錄 src/CMakeLists.txt 文件")
message("在子目錄,MY_VAL=${MY_VAL}")
message("退出子目錄")

運行結果:

$ cmake .
父目錄 CMakeLists.txt 文件
第一次在父目錄 MY_VAL=666
進入子目錄 src/CMakeLists.txt 文件
在子目錄,MY_VAL=666
退出子目錄
第二次在父目錄,MY_VAL=666

從結果可以看出,在子目錄 CMake 文件中可以直接使用父目錄定義的 MY_VAL 變數的值 666。當在子目錄 CMake 文件中修改 MY_VAL 變數值,看看在父目錄中 MY_VAL 的值如何變化。下麵僅僅在子目錄 CMake 文件中加入一行代碼 set(MY_VAL "777"), 最後的子目錄 CMake 文件代碼如下:

cmake_minimum_required(VERSION 3.10)
message("進入子目錄 src/CMakeLists.txt 文件")
set(MY_VAL "777") # 剛剛加入的
message("在子目錄,MY_VAL=${MY_VAL}")
message("退出子目錄")

運行結果:

$ cmake .
父目錄 CMakeLists.txt 文件
第一次在父目錄 MY_VAL=666
進入子目錄 src/CMakeLists.txt 文件
在子目錄,MY_VAL=777
退出子目錄
第二次在父目錄,MY_VAL=666

我們發現在 src/CMakeLists.txt 中列印的 MY_VAL 的值是 777,然後退出子目錄回到根目錄後,列印 MY_VAL 的值仍然是 666。這就說明瞭:子目錄的 CMakeLists.txt 文件僅僅是拷貝了一份父目錄的 Normal 變數,即使在子目錄 CMake 文件中修改了 MY_VAL 變數,那也只是子目錄自己的變數,不是父目錄的變數。因為 Normal 變數的作用域就是以 CMakeLists.txt 文件為基本單元。那麼我們如何在子目錄 CMake 文件中修改父目錄 CMake 文件的 Normal 變數呢? 我們需要在子目錄 CMakeLists.txt 文件中設置 MY_VAL 時,加上 PARENT_SCOPE 屬性。即用如下代碼: set(MY_VAL "777" PARENT_SCOPE),子目錄 CMakeLists.txt 文件如下:

cmake_minimum_required(VERSION 3.10)
message("進入子目錄 src/CMakeLists.txt 文件")
set(MY_VAL "777" PARENT_SCOPE) # 修改處
message("在子目錄,MY_VAL=${MY_VAL}")
message("退出子目錄")

運行結果:

$ cmake .
父目錄 CMakeLists.txt 文件
第一次在父目錄 MY_VAL=666
進入子目錄 src/CMakeLists.txt 文件
在子目錄,MY_VAL=666
退出子目錄
第二次在父目錄,MY_VAL=777

可以看出在第二次回到父目錄時,MY_VAL 的值已經變成了 777。同理,對於 function() 最開始的結論也適用。代碼如下:

cmake_minimum_required(VERSION 3.10)
message("父目錄 CMakeLists.txt 文件")
set(MY_VAL "666")

message(
"第一次在父目錄 MY_VAL=${MY_VAL}") # 函數定義 function(xyz test_VAL) # 函數定義處! set(MY_VAL "888" PARENT_SCOPE) message("functions is MY_VAL=${MY_VAL}") endfunction(xyz) xyz(${MY_VAL}) # 調用函數 message("第二次在父目錄,MY_VAL=${MY_VAL}")

運行結果:

父目錄 CMakeLists.txt 文件
第一次在父目錄 MY_VAL=666
functions is MY_VAL=666
第二次在父目錄,MY_VAL=888

可以看出在該函數中使用 MY_VAL 這個變數值,其實就是一份父目錄變數的值拷貝,此時列印值為 666。在 函數中修改值,那麼也是用 set(${MY_VAL} 888 PARENT_SCOPE)。此時,退出函數第二次列印變數值時。該值就是在函數中修改好的值 888。 本質講,對於 function() 而言,剛剛說到的父目錄其實不是嚴格正確的。因為函數定義可以是在其他 .cmake 模塊文件中定義的。也可以在其他 CMakeLists.txt 文件中調用,因此準確的說,這裡的父目錄應該改為『調用函數的地方所屬的 CMakeLists.txt 』,我們做的這個實驗是在根目錄 CMakeLists.txt 文件中定義了函數,又在本文件中使用了。因此之前的說法理解其意思即可。對於 add_subdirectory() 而言,其實也是說調用的地方。下麵的 include()、macro() 例子會涉及到,將 function() 放在一個外部的 .cmake 文件中。那裡也會說明 function() 與 macro() 的不同。

(2)、包含 include()、macro() (本質有點類似 c 中的 #include 預處理含義)

現在在上面的根目錄中加入了一個 cmake_modules 目錄。目錄中有一個 Findtest.cmake 文件。新的目錄結構如下:

$ tree
.
├── CMakeLists.txt
├── cmake_modules
│   └── Findtest.cmake
└── src
    └── CMakeLists.txt

2 directories, 3 files

在根目錄中的 CMakeLists.txt 文件包含的代碼如下:

cmake_minimum_required(VERSION 3.10)
message("父目錄 CMakeLists.txt 文件")
set(MY_VAL "666")
message("第一次在父目錄 MY_VAL=${MY_VAL}")

# 使用 include() 文件的巨集
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules) 
include(Findtest) # 從 CMAKE_MODULE_PATH 包含的路徑中搜索 Findtest.cmake 文件
#test(${MY_VAL}) # 調用巨集
#xyz(${MY_VAL}) # 調用函數

#find_package(test REQUIRED) # 從 CMAKE_MODULE_PATH 包含的路徑中搜索 Findtest.cmake 文件 與 include () 兩者的效果是一樣的!

message("第二次在父目錄,MY_VAL=${MY_VAL}")

message("include test=${test_VAL}") 
#message("macro_val=${macro_val}")

cmake_modules/Findtest.cmake 文件內容如下:

# 該文件定義了一個函數以及一個巨集
message("進入 Findtest.cmake 文件")

set(test_VAL "222") # 驗證根目錄 CMake 文件能夠訪問這個變數
set(MY_VAL "000") # 測試 include() 效果

# 巨集定義
macro(test MY_VA) # 定義一個巨集!
 set(macro_val "1") # 巨集內部定義變數
 message("macro is MY_VAL=${MY_VA}")
 set(MY_VAL "999") # 直接修改的就是調用該巨集所處的文件中的 Normal 變數
endmacro(test)

# 函數定義
function(xyz test_VAL)
 set(MY_VAL "888" PARENT_SCOPE)  # 修改 調用者的 變數
 message("function is MY_VAL=${MY_VAL}")
endfunction(xyz)

運行結果:

$ cmake .
父目錄 CMakeLists.txt 文件
第一次在父目錄 MY_VAL=666
進入 Findtest.cmake 文件
第二次在父目錄,MY_VAL=000
include test=222

從結果可以看出,include() 內部是可以修改調用者 MY_VAL 變數。include() 包含的文件內定義的變數 test_VAL,也可以在調用 include() 的 CMakeLists.txt 文件中直接訪問,同樣的對於 macro() 也適用,在根目錄 CMake 文件中調用巨集,即取消 test(${MY_VAL}) 以及 message(“macro_val=${macro_val}”) 部分的註釋,此時最後輸出結果 :

$ cmake .
父目錄 CMakeLists.txt 文件
第一次在父目錄 MY_VAL=666
進入 Findtest.cmake 文件
macro is MY_VAL=000
第二次在父目錄,MY_VAL=999
include test=222
macro_val=1

可以看出,這次輸出的結果在第二次進入父目錄後,MY_VAL 變數的值就是 999 了。註意到在根目錄中 CMakeLists.txt 中 註釋語句中有一個 find_package() ,這個和 include() 其實都是一樣的結果。

總結:

結合 include() 、macro() 最後結果,能夠得出一個結論:通過 include() 和 macro() 相當於把這兩部分包含的代碼直接加入根目錄 CMakeLists.txt 文件中去執行,相當於他們是一個整體。因此變數直接都是互通的。這就有點像 C/C++ 中的 #include 包含頭文件的預處理過程了。這一點其實與剛開始講的 function() 、add_subdirectory() 完全不同,在函數以及 add_subdirectory() 中,他們本身就是一個不同的作用域範圍,僅僅通過拷貝調用者的 Normal 值 (僅僅在調用 add_subdirectory() / function() 之前的 Normal 變數),如果要修改調用者包含的 Normal 變數,那麼只能通過 set(MY_VAL "某個值" PARENT_SCOPE)註明我們修改的是調用者 Normal 值。雖然在 C/C++ 中,可以通過指針的方式,通過函數可以修改外部變數值,但是在 CMake 腳本語言中 function() 雖然能夠傳入形式參數,但是者本質上就是 C/C++ 中的值拷貝。而不是引用。上面所說的 Normal 變數其實就是一個局部變數。

2、Cache Variables

相當於一個全局變數,我們在同一個 cmake 工程中都可以使用。Cache 變數有以下幾點說明:

  1. Cache 變數 CMAKE_INSTALL_PREFIX 預設值是 /usr/local (可以在生成的 CMakeCache.txt 文件中查看),這時候如果我們 在某個 CMakeLists.txt 中,仍然使用 set(CMAKE_INSTALL_PREFIX “/usr”),那麼此時我們 install 的時候,CMake 以後面的 /usr 作為 CMAKE_INSTALL_PREFIX 的值,這是因為 CMake 規定,有一個與 Cache 變數同名的 Normal 變數出現時,後面使用這個變數的值都是以 Normal 為準,如果沒有同名的 Normal 變數,CMake 才會自動使用 Cache 變數。
  2. 所有的 Cache 變數都會出現在 CMakeCache.txt 文件中。這個文件是我們鍵入 cmake .命令後自動出現的文件。打開這個文件發現,CMake 本身會有一些預設的全局 Cache 變數。例如:CMAKE_INSTALL_PREFIX、CMAKE_BUILD_TYPE、CMAKE_CXX_FLAGSS 等等。可以自行查看。當然,我們自己定義的 Cache 變數也會出現在這個文件中。Cache 變數定義格式為 set(<variable> <value> CACHE STRING INTERNAL)。這裡的 STRING可以替換為 BOOL FILEPATH PATH ,但是要根據前面 value 類型來確定。參考。
  3. 修改 Cache 變數。可以通過 set(<variable> <value> CACHE INSTERNAL FORCE),另一種方式是直接在終端中使用 cmake -D var=value ..來設定預設存在的 CMake Cache 變數。

下麵通過一個例子來說明以上三點:

 

首先看一下目錄樹結構:

$ tree
.
├── CMakeLists.txt
└── src
    └── CMakeLists.txt

1 directory, 2 files

根目錄 CMakeLists.txt 文件內容如下:

cmake_minimum_required(VERSION 3.10)
set(MY_GLOBAL_VAR "666" CACHE STRING INTERNAL )
message("第一次在父目錄 CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
message("第一次在父目錄 MY_GLOBAL_VAR=${MY_GLOBAL_VAR}")
add_subdirectory(src)
message("第二次在父目錄 CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
message("第二次在父目錄 MY_GLOBAL_VAR=${MY_GLOBAL_VAR}")
set(CMAKE_INSTALL_PREFIX "-->usr" )
message("第三次在父目錄 CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")

src/CMakeLists.txt 文件內容如下:

cmake_minimum_required(VERSION 3.10)
message("子目錄,CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
message("子目錄,MY_GLOBAL_VAR=${MY_GLOBAL_VAR}")
set(CMAKE_INSTALL_PREFIX "/usr" CACHE STRING INTERNAL FORCE)
set(MY_GLOBAL_VAR "777" CACHE STRING INTERNAL FORCE )

運行結果:

$ cmake .
第一次在父目錄 CMAKE_INSTALL_PREFIX=/usr/local
第一次在父目錄 MY_GLOBAL_VAR=666
子目錄,CMAKE_INSTALL_PREFIX=/usr/local
子目錄,MY_GLOBAL_VAR=666
第二次在父目錄 CMAKE_INSTALL_PREFIX=/usr
第二次在父目錄 MY_GLOBAL_VAR=777
第三次在父目錄 CMAKE_INSTALL_PREFIX=-->usr

程式說明:首先在根目錄中列印一下當前的 Cache 變數 CMAKE_INSTALL_PREFIX 值,主要看看預設值是什麼,然後在子目錄 src/CMakeLists.txt 中再次列印和修改該 Cache 值,目的是熟悉修改全局 Cache 變數,當返回根目錄 CMakeLists.txt 文件中再次執行第二次列印該 Cache 值時,主要看一看在子目錄中修改後的效果。接著在根目錄中設定一個 CMAKE_INSTALL_PREFIX 的 Normal 同名變數,此時第三次列印 CMAKE_INSTALL_PREFIX 的值,此時是為了證明,當有與 Cache 同名的 Normal 變數出現時,CMake 會優先使用 Normal 屬性的值。通過設定 MY_GLOBAL_VAR 主要是為了說明可以自己設定全局 Cache 變數。最後的結果如上面顯示,當我們再次執行 cmake . 的時候,程式結果如下:

$ cmake .
第一次在父目錄 CMAKE_INSTALL_PREFIX=/usr
第一次在父目錄 MY_GLOBAL_VAR=777
子目錄,CMAKE_INSTALL_PREFIX=/usr
子目錄,MY_GLOBAL_VAR=777
第二次在父目錄 CMAKE_INSTALL_PREFIX=/usr
第二次在父目錄 MY_GLOBAL_VAR=777
第三次在父目錄 CMAKE_INSTALL_PREFIX=-->usr

可以發現第一次在父目錄列印 CMAKE_INSTALL_PREFIX 和 MY_GOLBAL_VAR 時,他們的結果是上次cmake .後生成的值,存儲在 CMakeCache.txt 中,自己可以找到,解決方案就是可以把 CMakeCache.txt 文件刪除,然後在 cmake .我們以後在實際使用時要註意這個坑。對於修改 Cache 變數的另一種方式就是cmake -D CMAKE_INSTALL_PREFIX=/usr。可以自己驗證。這裡說一個重要的點,就是在終端中輸入的 cmake -D var=value . 如果 CMake 中預設有這個 var Cache 變數,那麼此時就是賦值,沒有的話,CMake 就會預設創建了一個全局 Cache 變數然後賦值。(tips: $CACHE{VAR}表示獲取 CACHE 緩存變數的值)。例子如下:(目錄結構同上)

 

根目錄 CMakeLists.txt :

cmake_minimum_required(VERSION 3.10)
set(MY_GLOBAL_VAR "666")
message("第一次在父目錄 MY_GLOBAL_VAR=$CACHE{MY_GLOBAL_VAR}")
add_subdirectory(src)
message("第二次在父目錄局部 MY_GLOBAL_VAR=${MY_GLOBAL_VAR}")
message("第二次在父目錄全局 MY_GLOBAL_VAR=$CACHE{MY_GLOBAL_VAR}")

src/CMakeLists.txt :

cmake_minimum_required(VERSION 3.10)
message("子目錄,MY_GLOBAL_VAR=${MY_GLOBAL_VAR}")
set(MY_GLOBAL_VAR "777" CACHE STRING INTERNAL FORCE )

運行結果:

第一次在父目錄 MY_GLOBAL_VAR=8
子目錄,MY_GLOBAL_VAR=666
第二次在父目錄局部 MY_GLOBAL_VAR=666
第二次在父目錄全局 MY_GLOBAL_VAR=777

有了上面的基礎,相信這個例子很快能看明白。

 

參考:

  1. https://stackoverflow.com/questions/31037882/whats-the-cmake-syntax-to-set-and-use-variables/31044116#31044116
  2. https://stackoverflow.com/questions/3249459/for-the-cmake-include-command-what-is-the-difference-between-a-file-and-a-mod
  3. https://cmake.org/cmake/help/v3.11/command/set.html#set

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

-Advertisement-
Play Games
更多相關文章
  • 一、out參數實例 【實例】求一個數組中的最大值、最小值、總和、平均值 執行代碼輸出結果,如圖所示: 總結: 如果一個方法中,返回多個相同類型的值時候,我們可以考慮返回一個數組。但是返回多個不同類型的值時候,返回數組就不行,那麼這個時候,我們可以考慮用out參數。 out參數就側重於一個方法可以返回 ...
  • 一、作用 用來處理多條件的區間性的判斷。 二、語法 執行過程: 程式首先判斷第一個if所帶的小括弧中的判斷條件,如果條件成立,也就是返回一個true,則執行該if所帶的大括弧中的代碼,執行完成後,立即跳出if else-if結構。 如果第一個if所帶的判斷條件不成立,也就是返回一個false,則繼續 ...
  • 一、簡介 一個 if 語句 後可跟一個可選的 else 語句,else 語句在布爾表達式為假時執行。 二、語法 描述: 執行過程: 程式執行到if處,首先判斷if的小括弧是判斷條件是否成立,如果成立,則返回一個true,則執行if所帶大括弧中的代碼,執行完成後,跳出if-else結構。如果if所帶的 ...
  • 一、簡介 一個 if 語句 由一個布爾表達式後跟一個或多個語句組成。 二、語法 描述: 判斷條件:一般為關係表達式或者布爾類型。 執行過程:程式運行到if處,首先判斷if所帶的小括弧中的判斷條件。如果條件成立返回true,則執行if大括弧的代碼,如果條件成立,也就返回一個false,則跳過if結構, ...
  • 一、簡介 在Random類用於創建隨機數。(當然是偽隨機的。) 二、Random用法 例: 三、方法詳細說明 Random 類中提供的 Next、NextBytes 以及 NextDouble 方法可以生成整數類型、byte 數組類型以及雙精度浮點型的隨機數,詳細說明如下表所示。 Next():每次 ...
  • ASP.NET Core基於策略的授權允許一種更加靈活的方式來創建授權規則 ...
  • 一、進入/etc/bash.bashrc(使用文本編輯器打開) 二、在最後面添加新的環境變數 export PATH=usr/...(路徑):$PATH 三、保存後,打開終端,輸入source ~/.bashrc 四、輸入echo $PATH,可以查看是否已成功添加 ...
  • 此書作者劉遄(Liu Chuán)從事於Linux運維技術行業,並且在2012年獲得紅帽工程師RHCE 6版本證書,在2015年初又分別獲得紅帽工程師RHCE 7版本證書與紅帽架構師認證RHCA頂級證書。 學習是件苦差事: 稻盛和夫先生在《活法》中有段一直激勵著我的話,現在轉送給正在閱讀本書的你: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...