【CMake】環境變量

目錄

一.環境變量簡單介紹

1.1.示例1——設置與清除

1.2.示例2——全局唯一性和全局可見性

1.3.示例3

1.4.示例4

1.5.示例5


一.環境變量簡單介紹

什么是環境變量?

我們看看官網是怎么說環境變量的:cmake-language(7) — CMake 4.1.1 Documentation

環境變量是操作系統提供給所有運行中程序(進程)的一套全局鍵值對。

CMake 作為一個程序,在啟動時會繼承它所在 shell(如命令行終端)的所有環境變量。

CMake 自己也提供了一套機制來操作這些變量。

它與 CMake 普通變量的核心區別如下:

1. 作用域 (Scope)

  • 全局性環境變量在同一個 CMake 進程內部的作用域是全局的。這意味著一旦你設置或修改了一個環境變量,你可以在同一個 CMake 運行過程中的任何地方(無論是在根目錄的?CMakeLists.txt,還是在深層子目錄的?CMakeLists.txt,或是在任何?.cmake?腳本文件中)訪問到它。

  • 不被緩存環境變量不會被存入 CMake 的緩存(即項目根目錄下的?CMakeCache.txt?文件)。緩存變量可以通過?set(... CACHE ...)?命令被緩存,從而在多次運行?cmake?時保持值不變。環境變量沒有這個特性,每次重新運行?cmake?命令時,環境變量都會重新從外部系統環境中初始化。

2. 引用方式 (References)

  • 你不能像引用普通變量(${MY_VARIABLE})那樣直接引用環境變量。

  • 你必須使用特殊的?$ENV{<變量名>}?語法。這里的?ENV?是一個操作符,它告訴 CMake 你要訪問的是環境變量,而不是普通變量。

  • 示例: 如果你想獲取系統環境變量?PATH?的值,你需要這樣寫:$ENV{PATH}

3. 初始化和修改 (Initialization)

  • 初始值: 當你在終端輸入?cmake ...?命令時,CMake 進程啟動那一刻,它所擁有的環境變量集合就是你的終端 shell 當時的環境變量集合的副本。

  • 修改的局限性: 這是最關鍵的一點。

    • 你可以使用?set(ENV{<變量名>} <值>)?命令來設置或修改一個環境變量。

    • 你也可以使用?unset(ENV{<變量名>})?命令來刪除一個環境變量。

    • 但是,這些修改僅僅發生在當前這個正在運行的 CMake 進程內部!?它會產生以下重要影響:

      • 不影響系統: 它絕對不會改變你操作系統的環境變量,也不會改變你終端 shell 的環境變量。

      • 不回傳: 當 CMake 進程結束時,它對環境變量所做的任何修改都會隨之消失,不會寫回給調用它的父進程(也就是你的終端 shell)。

      • 不影響后續進程: 在 CMake 執行過程中,它可能會啟動其他的子進程(例如調用?execute_process?命令,或者編譯完成后進行構建和測試)。默認情況下,這些子進程啟動時會繼承最初從父 shell 那里獲得的環境變量副本。但是啟動子進程之后,如果父進程又修改了環境變量,那么子進程就看不到修改后的環境變量值(除非使用特定命令,見下一條)。

4. 相關工具 (Tools)

  • cmake -E env: 正因為直接在 CMake 腳本中修改環境變量對后續構建/測試進程無效,CMake 提供了一個命令行工具來解決這個問題。你可以在調用 CMake 時,使用?cmake -E env VAR1=value1 VAR2=value2 <command> ...?來為一個單獨的命令臨時創建一個修改后的環境,然后在這個新環境中運行該命令。這常用于為?build?或?test?階段設置特定的環境。

  • cmake -E environment: 這個命令可以列出當前 CMake 進程所能看到的所有環境變量及其值。它是一個非常有用的調試工具,可以幫你確認環境變量的值是否如你所預期。

使用環境變量

我們可以去官網看看是怎么說的:set — CMake 4.1.1 Documentation

set(ENV{<變量名>} [<值>])

該命令用于將環境變量設置為指定值。此后在當前進程中通過?$ENV{<變量名>}?獲取該環境變量時,將返回新設置的值。

需要注意的是,此命令僅對當前 CMake 進程有效:

  • 不會影響調用 CMake 的父進程的環境;

  • 不會改變整個系統的環境變量設置;

  • 也不會影響后續構建或測試進程的環境。

如果?ENV{<變量名>}?后未提供參數,或?<值>?為空字符串,則該命令將清除該環境變量當前已存在的值。

若在?<值>?后提供了額外參數,這些參數將被忽略。同時,如果檢測到有多余參數存在,CMake 會發出作者警告(author warning)。

1.1.示例1——設置與清除

📂 項目目錄結構

env_demo/
└── CMakeLists.txt

🔹 env_demo/CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(EnvVarDemo)# 1. 設置環境變量
set(ENV{MY_ENV_VAR} "hello world")
message("設置后: $ENV{MY_ENV_VAR}")# 2. 清除方式一:賦空字符串
set(ENV{MY_ENV_VAR} "")
message("清除方式一后: '$ENV{MY_ENV_VAR}'")# 3. 再次設置
set(ENV{MY_ENV_VAR} "hello again")
message("再次設置后: $ENV{MY_ENV_VAR}")# 4. 清除方式二:不給值
set(ENV{MY_ENV_VAR})
message("清除方式二后: '$ENV{MY_ENV_VAR}'")

其實我們可以通過下面這個命令來一鍵搭建出這個目錄結構和文件

mkdir -p env_demo && \
cat > env_demo/CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.15)
project(EnvVarDemo)# 1. 設置環境變量
set(ENV{MY_ENV_VAR} "hello world")
message("設置后: $ENV{MY_ENV_VAR}")# 2. 清除方式一:賦空字符串
set(ENV{MY_ENV_VAR} "")
message("清除方式一后: '$ENV{MY_ENV_VAR}'")# 3. 再次設置
set(ENV{MY_ENV_VAR} "hello again")
message("再次設置后: $ENV{MY_ENV_VAR}")# 4. 清除方式二:不給值
set(ENV{MY_ENV_VAR})
message("清除方式二后: '$ENV{MY_ENV_VAR}'")
EOF

接下來我們就來搭建我們的項目

rm -rf build && mkdir build && cd build && cmake ..

兩種清理方式都是沒有問題的!!

1.2.示例2——全局唯一性和全局可見性

項目結構

demo/
├── CMakeLists.txt              # 頂層
├── subdir/
│   ├── CMakeLists.txt          # 子目錄
│   └── subsubdir/
│       ├── CMakeLists.txt      # 子子目錄
│       └── helper.cmake        # 腳本

頂層 CMakeLists.txt

cmake_minimum_required(VERSION 3.18)
project(GlobalEnvDemo)# 在頂層設置環境變量
set(ENV{MY_VAR} "HelloFromTop")
message(STATUS "頂層看到的 MY_VAR: '$ENV{MY_VAR}'")# 進入子目錄
add_subdirectory(subdir)# 在所有子目錄之后再打印一次,看看是否被修改過
message(STATUS "頂層最后看到的 MY_VAR: '$ENV{MY_VAR}'")

子目錄 subdir/CMakeLists.txt

# 子目錄也能訪問
message(STATUS "子目錄看到的 MY_VAR: '$ENV{MY_VAR}'")# 進入子子目錄
add_subdirectory(subsubdir)

子子目錄 subdir/subsubdir/CMakeLists.txt

# 子子目錄訪問環境變量
message(STATUS "子子目錄看到的 MY_VAR: '$ENV{MY_VAR}'")# 在子子目錄里修改環境變量
set(ENV{MY_VAR} "ModifiedInSubSubDir")
message(STATUS "子子目錄修改后的 MY_VAR: '$ENV{MY_VAR}'")# 引入 helper 腳本
include(helper.cmake)

腳本 subdir/subsubdir/helper.cmake

# helper.cmake 也能看到修改過的值
message(STATUS "helper.cmake 看到的 MY_VAR: '$ENV{MY_VAR}'")

我們可以運行下面這個bash語句來一鍵搭建出這個目錄結構和文件

mkdir -p demo/subdir/subsubdir && \
cat > demo/CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.18)
project(GlobalEnvDemo)# 在頂層設置環境變量
set(ENV{MY_VAR} "HelloFromTop")
message(STATUS "頂層看到的 MY_VAR: '$ENV{MY_VAR}'")# 進入子目錄
add_subdirectory(subdir)# 在所有子目錄之后再打印一次,看看是否被修改過
message(STATUS "頂層最后看到的 MY_VAR: '$ENV{MY_VAR}'")
EOFcat > demo/subdir/CMakeLists.txt <<'EOF'
# 子目錄也能訪問
message(STATUS "子目錄看到的 MY_VAR: '$ENV{MY_VAR}'")# 進入子子目錄
add_subdirectory(subsubdir)
EOFcat > demo/subdir/subsubdir/CMakeLists.txt <<'EOF'
# 子子目錄訪問環境變量
message(STATUS "子子目錄看到的 MY_VAR: '$ENV{MY_VAR}'")# 在子子目錄里修改環境變量
set(ENV{MY_VAR} "ModifiedInSubSubDir")
message(STATUS "子子目錄修改后的 MY_VAR: '$ENV{MY_VAR}'")# 引入 helper 腳本
include(helper.cmake)
EOFcat > demo/subdir/subsubdir/helper.cmake <<'EOF'
# helper.cmake 也能看到修改過的值
message(STATUS "helper.cmake 看到的 MY_VAR: '$ENV{MY_VAR}'")
EOF

現在我們就來構建我們的項目

rm -rf build && mkdir build && cd build && cmake ..


? 這就展示了:

  1. 環境變量在同一個 CMake 進程里是 全局可見的

  2. 子子目錄修改了環境變量之后,頂層 CMakeLists.txt 后續部分也能看到修改后的值

1.3.示例3

初始值: 當你在終端輸入?cmake ...?命令時,CMake 進程啟動那一刻,它所擁有的環境變量集合就是你的終端 shell 當時的環境變量集合的副本。

案例1

在你的 終端 里先設置一個環境變量,例如

export MY_VAR=HelloFromShell

寫一個簡單的 CMakeLists.txt

cmake_minimum_required(VERSION 3.18)
project(InitEnvDemo)# 打印 CMake 啟動時繼承的環境變量
message(STATUS "CMake 看到的 MY_VAR: '$ENV{MY_VAR}'")

運行:

mkdir build && cd build && cmake ..

運行結果

結論

CMake 啟動時,確實拿到了 終端 shell 的環境變量副本

  • 如果你在終端里沒設置 MY_VAR,那 CMake 里就是空。

  • 如果你在運行 cmake .. 之后再修改 shell 的 MY_VAR,CMake 進程是看不到的(因為它只在啟動時復制了一份)。

我們來看看

export MY_VAR=Hello

再次啟動看看

這說明 CMake 每次啟動時都是從當前 shell 環境復制一份副本。


1.4.示例4

我給你寫一個最小例子,演示 CMake 內部修改環境變量不會影響系統或終端 shell

打開終端,先設置一個環境變量:

export MY_VAR=OriginalValue

寫一個簡單的 CMakeLists.txt

cmake_minimum_required(VERSION 3.18)
project(NoSystemImpactDemo)# 打印啟動時 shell 的環境變量
message(STATUS "CMake 啟動時看到的 MY_VAR: '$ENV{MY_VAR}'")# 修改 CMake 內部環境變量
set(ENV{MY_VAR} "ModifiedInCMake")
message(STATUS "CMake 內部修改后的 MY_VAR: '$ENV{MY_VAR}'")

運行 CMake:

rm -rf build && mkdir build && cd build && cmake ..

CMake 內部修改了環境變量set(ENV{MY_VAR} ...)),只對 CMake 進程和它啟動的子進程有效

系統環境或父 shell 完全不受影響,CMake 退出后修改的值消失。

1.5.示例5

我們都說子進程會繼承父進程的環境變量,我們來看看是不是這么一回事。

📂 項目目錄結構

env_demo/
└── CMakeLists.txt

🔹 env_demo/CMakeLists.txt

cmake_minimum_required(VERSION 3.18)
project(MultiChildEnvDemo)# Step 1: CMake 啟動時的環境變量
message(STATUS "CMake 啟動時看到的 MY_VAR: '$ENV{MY_VAR}'")# Step 2: 修改環境變量
set(ENV{MY_VAR} "FirstValue")
message(STATUS "CMake 修改后的 MY_VAR: '$ENV{MY_VAR}'")# Step 3: 啟動第一個子進程
execute_process(COMMAND printenv MY_VAROUTPUT_VARIABLE OUT1OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "第一個子進程看到的 MY_VAR: '${OUT1}'")# Step 4: 再修改環境變量
set(ENV{MY_VAR} "SecondValue")
message(STATUS "CMake 再次修改 MY_VAR: '$ENV{MY_VAR}'")# Step 5: 啟動第二個子進程
execute_process(COMMAND printenv MY_VAROUTPUT_VARIABLE OUT2OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "第二個子進程看到的 MY_VAR: '${OUT2}'")

?運行 CMake:

rm -rf build && mkdir build && cd build && cmake ..

  • 第一次修改"FirstValue"

    • 第一個子進程 繼承了 "FirstValue"

  • 第二次修改"SecondValue"

    • 第二個子進程 繼承了 "SecondValue"

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/96428.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/96428.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/96428.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mysql雜志(十四)——Mysql邏輯架構

Mysql邏輯架構 這個圖相信大家并不陌生&#xff0c;這個就是mysql的邏輯結構圖下面是主包讓AI生成的翻譯后的邏輯結構圖&#xff1a; 我們先來看看各個部分的作用是什么 第一層&#xff1a;客戶端連接層 (Client Layer) 這一層負責處理所有客戶端連接到服務器的請求。責任就…

Git 版本回退與撤銷修改

作為版本控制管理器&#xff0c;Git應當具備版本回退等一系列功能——它的應用場景也很常見&#xff0c;當你在工作區開發時&#xff0c;忽然發現&#xff1a;怎么我這版本寫的代碼還不如上一版本好&#xff1f;這時&#xff0c;版本回退功能就派上用場了。一.版本回退1.概覽首…

學習日記-JS+DOM-day54-9.12

1.javascript基本說明知識點核心內容重點JavaScript基礎控制HTML內容與屬性&#xff0c;實現動態行為&#xff08;如開燈/關燈效果&#xff09;src屬性路徑修正&#xff08;./與../的區別&#xff09;前端三要素HTML&#xff08;內容&#xff09;、CSS&#xff08;樣式&#xf…

使用tree命令導出文件夾/文件的目錄樹( Windows 和 macOS)

你可以在終端&#xff08;命令提示符&#xff09;中使用 tree 命令來清晰直觀地查看和導出文件夾的目錄結構。下面我會詳細告訴你如何在 Windows 和 macOS 上使用它。 &#x1f5a5;? tree 命令基本用法 tree 命令的核心作用是以樹狀圖的形式展示指定路徑下的目錄和文件結構。…

GrapeCity Documents V8.0 Update2 重磅發布:性能飛躍、AI 賦能與文檔處理全流程升級

作為葡萄城旗下服務端文檔組件庫&#xff0c;GrapeCity Documents&#xff08;簡稱"GcDocs"&#xff09;憑借跨平臺、高兼容的優勢&#xff0c;已成為 眾多開發者構建文檔生成、編輯、轉換與管理系統的首選。 近日&#xff0c;GcDocs 迎來 V8.0 Update2 版本更新&am…

水質在線監測系統御控物聯網解決方案

一、行業背景與需求痛點水質安全是飲用水供應、工業生產、生態保護的核心要素。隨著《水污染防治行動計劃》的深入實施&#xff0c;傳統水質監測方式面臨三大挑戰&#xff1a;時效性不足&#xff1a;人工采樣-實驗室分析周期長達24-72小時&#xff0c;難以實時捕捉污染事件&…

【完整源碼+數據集+部署教程】倉庫物品分類檢測圖像分割系統源碼和數據集:改進yolo11-convnextv2

背景意義 研究背景與意義 隨著現代物流和倉儲管理的快速發展&#xff0c;物品分類與檢測技術在提高倉庫運營效率、降低人工成本方面發揮著越來越重要的作用。傳統的物品管理方式往往依賴人工識別和分類&#xff0c;效率低下且容易出錯。為了解決這一問題&#xff0c;基于計算機…

瀏覽器穩定性提升之路:線上崩潰率優化中的 Return 與 CHECK 之爭

一、前言在大型 C 工程&#xff08;例如 Chrome 瀏覽器內核&#xff09;中&#xff0c;開發者經常會遇到這樣的選擇&#xff1a; 到底應該在關鍵點使用 CHECK 直接崩潰&#xff0c;還是使用 return、LOG 記錄錯誤然后繼續執行&#xff1f;這看似只是一個代碼風格問題&#xff0…

【數據結構與算法Trip第3站】雙指針

我們來詳細講解一下算法中非常常用且重要的技巧——雙指針法。 這是一個概念清晰但應用極其廣泛的技術&#xff0c;掌握它能幫助你高效解決許多問題。 一、什么是雙指針法&#xff1f; 核心思想&#xff1a;顧名思義&#xff0c;就是在遍歷對象&#xff08;通常是數組或鏈表&am…

時序數據庫選型指南:基于大數據視角的IoTDB應用優勢分析詳解!

目錄 一、時序數據庫選型的基本原則 1.1 數據特征與需求分析 1.1.1 數據規模與寫入負載 1.1.2 查詢需求 1.1.3 數據保留與歸檔策略 1.1.4 系統擴展性與高可用性 1.2 技術架構與系統性能評估 1.2.1 寫入性能 1.2.2 查詢性能 1.2.3 數據壓縮能力 1.2.4 高可用性與災備…

緩存三大劫攻防戰:穿透、擊穿、雪崩的Java實戰防御體系(三)

第三部分&#xff1a;緩存雪崩——大量key失效引發的“系統性崩潰” 緩存雪崩的本質是“大量緩存key在同一時間失效&#xff0c;或緩存集群整體故障”&#xff0c;導致請求全量穿透至DB&#xff0c;引發“系統性崩潰”。 案例4&#xff1a;電商首頁的“批量過期”災難 故障現場…

解決docker配置了鏡像源但還會拉取官方鏡像源的問題

&#x1f3d3;我們有時候雖然配置了Docker國內鏡像源&#xff0c;但是還是會繞過去請求官方鏡像源&#xff08;docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded&#xff09;&#xff0c;現在我們就來解決一…

R語言水文、水環境模型優化:從最速上升法、嶺分析到貝葉斯優化與異方差處理,涵蓋采樣設計、代理模型與快速率定等

在水利工程、環境治理、生態保護、機械設計與航天航空等現代工業與科學領域&#xff0c;數學模型已成為不可或缺的核心分析、預測與決策工具。然而&#xff0c;隨著系統復雜性的日益增長&#xff0c;模型構建的精確性、參數率定的效率以及不確定性量化的重要性被提到了前所未有…

關于數據采集與處理心得(一)

目前所實踐的經驗告知我&#xff01;1. 別企圖妄想一個腳本解決所有問題要學會對問題分解&#xff0c;編寫多個腳本一步步將問題解決&#xff0c;如果每一個步驟都為了下一個階段的成果打地基&#xff0c;也是非常OK的。同時要盡可能將每一個編寫的腳本都盡到最大的利用率2. 編…

IvorySQL 適配 LoongArch? 龍架構

IvorySQL 社區很高興向您宣布&#xff0c;IvorySQL 已成功適配LoongArch 龍架構&#xff0c;為國產數據庫與國產芯片的深度融合邁出了堅實一步。這一里程碑標志著 IvorySQL 在推動國產化生態建設、賦能信創產業方面取得了重大突破&#xff0c;為用戶提供更高效、穩定、安全的數…

數據庫分庫分表是考慮ShardingSphere 還是Mycat?

http://www.mycat.org.cn/ https://shardingsphere.apache.org/ 這是一個非常核心且優秀的問題。在選擇 ShardingSphere 和 Mycat 之間&#xff0c;對于游戲這種高性能、高復雜度的場景&#xff0c;目前行業內的主流選擇和發展趨勢毫無疑問是 ShardingSphere。 我會為你詳細對…

mysql分庫分表數據量核查問題

場景&#xff1a; 使用分庫分表的業務有時分庫數量幾百甚至上千&#xff0c;當主管需要查詢每個庫中的數據&#xff0c;掌握數據分布情況。要你查看哪些庫中的表數量大于某個量級的給找出來 &#xff0c;你會怎么做。 例子 &#xff1a; mysql庫數量&#xff1a;db_xx_devicein…

python之socket網絡編程

引言 在互聯網時代&#xff0c;網絡編程已經成為開發人員必備的技能之一。無論是Web開發、實時通信還是分布式計算&#xff0c;都離不開網絡編程的支持。Python提供的socket模塊為我們提供了簡潔而強大的接口&#xff0c;可以輕松實現客戶端和服務器之間的通信。 Socket編程是網…

WPF Telerik.Windows.Controls.Data.PropertyGrid 自定義屬性編輯器

1.AI幫忙定義新用戶控件 2.在屬性上添加TelerikEditorAttribute特性 private ObservableCollection<string> _axisOrder;[Display(Description "點位", GroupName "通用", Name "軸&順序", Order 1)][DataMember][TelerikEditorAt…

【超詳細】別再看零散的教程了!一篇搞定Gitee從注冊、配置到代碼上傳與管理(內含避坑指南最佳實踐)

&#x1f525;個人主頁&#xff1a;艾莉絲努力練劍 ?專欄傳送門&#xff1a;《C語言》、《數據結構與算法》、C語言刷題12天IO強訓、LeetCode代碼強化刷題、洛谷刷題、C/C基礎知識知識強化補充、C/C干貨分享&學習過程記錄 &#x1f349;學習方向&#xff1a;C/C方向學習者…