亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 操作系統 > 正文

CMake Helloworld 02:更實用一些的Hello World CMake 例子

2024-06-28 13:24:04
字體:
來源:轉載
供稿:網友
CMake Helloworld 02:更實用一些的Hello World CMake 例子

References:

Ref 1. CMake PRactice – Cjacker;Ref 2.Looking for a 'cmake clean' command to clear up cmake output;

我們將采用out-of-source外部構建,約定的構建目錄是工程目錄下的build目錄。

本小節的任務是讓前面的Hello World更像一個工程,我們需要作的是:

  • 為工程添加一個子目錄src,用來放置工程源代碼;
  • 添加一個子目錄doc,用來放置這個工程的文檔hello.txt
  • 在工程目錄添加文本文件COPYRIGHT, README;
  • 在工程目錄添加一個runhello.sh腳本,用來調用hello二進制
  • 將構建后的目標文件放入構建目錄的bin子目錄;
  • 最終安裝這些文件:將hello二進制與runhello.sh安裝至/usr/bin,將doc目錄的內容以及COPYRIGHT/README安裝到/usr/share/doc/cmake/t2,

1,準備工作:

在/home/ccj/CMakeDemo/目錄下建立t2目錄。將t1工程的main.c和CMakeLists.txt拷貝到t2目錄中。

2,添加子目錄src:

mkdir src

mv main.c src

現在的工程看起來是這個樣子:

上一節我們提到,需要為任何子目錄建立一個CMakeLists.txt,

進入子目錄src,編寫CMakeLists.txt如下:

# t2/src/CMakeLists.txt

ADD_EXECUTABLE(hello main.c)

將t2工程的CMakeLists.txt修改為:

# t2/CMakeLists.txt

PROJECT(HELLO)

ADD_SUBDIRECTORY(src bin)

然后建立build目錄,進入build目錄進行外部編譯。

cmake ..

make

結果如下:

構建完成后,你會發現生成的目標文件hello位于build/bin目錄中:

語法解釋:

ADD_SUBDIRECTORY指令:

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

這個指令用于向當前工程添加存放源文件的子目錄,并可以指定中間二進制和目標二進制存放的位置。EXCLUDE_FROM_ALL參數的含義是將這個目錄從編譯過程中排除,比如,工程的example,可能就需要工程構建完成后,再進入example目錄單獨進行構建(當然,你也可以通過定義依賴來解決此類問題)。

上面的例子定義了將src子目錄加入工程,并指定編譯輸出(包含編譯中間結果)路徑為bin目錄。如果不進行bin目錄的指定,那么編譯結果(包括中間結果)都將存放在build/src目錄(即在build下自動創建一個src目錄,這個目錄跟原有的src目錄對應),指定bin目錄后,相當于在編譯時將src重命名為bin,所有的中間結果和目標二進制都將存放在build/bin目錄。

這里需要提一下的是SUBDIRS指令,使用方法是:SUBDIRS(dir1 dir2...),但是這個指令已經不推薦使用。它可以一次添加多個子目錄,并且,即使外部編譯,子目錄體系仍然會被保存。如果我們在上面的例子中將ADD_SUBDIRECTORY (src bin)修改為SUBDIRS(src)。那么在build目錄中將出現一個src目錄,生成的目標代碼hello將存放在src目錄中。

3,換個地方保存目標二進制文件

不論是SUBDIRS還是ADD_SUBDIRECTORY指令(不論是否指定編譯輸出目錄),我們都可以通過SET指令重新定義EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH變量來指定最終的目標二進制的位置(指最終生成的hello或者最終的共享庫,不包含編譯生成的中間文件)

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

在上一個blog中,我們提到了<projectname>_BINARY_DIR和PROJECT_BINARY_DIR變量,它們指的是編譯發生的當前目錄,如果是內部編譯(in-source build), PROJECT_BINARY_DIR =PROJECT_SOURCE_DIR =工程代碼所在目錄,i.e., /home/ccj/CMakeDemo/t2;如果是外部編譯(out-of-source build),PROJECT_BINARY_DIR指的是外部編譯所在目錄,也就是本例中的/home/ccj/CMakeDemo/t2/build目錄。所以,上面兩個指令分別定義了:

可執行二進制的輸出路徑為build/bin,以及庫的輸出路徑為build/lib.

本節我們沒有提到共享庫和靜態庫的構建,所以,你可以不考慮第二條指令。但有個問題,我們應該把這兩條指令寫在工程的CMakeLists.txt里,還是src目錄下的 CMakeLists.txt里呢?把握一個簡單的原則,在哪里ADD_EXECUTABLE 或 ADD_LIBRARY,如果需要改變目標存放路徑,就在哪里加入上述的定義。

在這個例子里,當然就是指 src下的CMakeLists.txt了,即:

# src/CMakeLists.txt

ADD_EXECUTABLE(hello main.cpp)

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/)

Run make之后,會將binary file hello放在 t2/build下,即t2/build/hello

我們可以改變一下目錄, 如下:

# src/CMakeLists.txt

ADD_EXECUTABLE(hello main.cpp)

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

Run make之后,會將binary file hello放在 t2/build/bin下,即t2/build/bin/hello

4,如何安裝。

安裝的需要有兩種,一種是從代碼編譯后直接make install安裝,另一種是打包時的指定目錄安裝。

所以,即使最簡單的手工編寫的Makefile,看起來也是這個樣子的:

DESTDIR=

install:

mkdir -p $(DESTDIR)/usr/bin

install -m 755 hello $(DESTDIR)/usr/bin

(Note: -m 755 表示文件的權限為 -rwxr--r--, 可參考linux的chmod 指令,詳見下圖:

言歸正傳,回到CMake,你可以通過:

make install

將hello直接安裝到/usr/bin目錄,也可以通過make installDESTDIR=/tmp/test ,將其安裝在/tmp/test/usr/bin目錄,打包時這個方式經常被使用。

稍微復雜一點的是還需要定義PREFIX,一般autotools工程,會運行這樣的指令:

./configure --prefix=/usr或者 ./configure --prefix=/usr/local 來指定PREFIX。

比如上面的Makefile就可以改寫成:

DESTDIR=

PREFIX=/usr

install:

mkdir -p $(DESTDIR)/$(PREFIX)/bin

install -m 755 hello $(DESTDIR)/$(PREFIX)/bin

那么我們的HelloWorld應該怎么進行安裝呢?這里需要引入一個新的cmake 中的指令 INSTALL和一個非常有用的變量CMAKE_INSTALL_PREFIX。

CMAKE_INSTALL_PREFIX變量類似于configure腳本的 –prefix,常見的使用方法看起來是這個樣子:

cmake -DCMAKE_INSTALL_PREFIX=/usr .

INSTALL指令用于定義安裝規則,安裝的內容可以包括目標二進制、動態庫、靜態庫以及文件、目錄、腳本等。INSTALL指令包含了各種安裝類型,我們需要一個一個地加以解釋:

1)目標文件的安裝:

INSTALL(TARGETS targets...

[ [ARCHIVE|LIBRARY|RUNTIME]

[DESTINATION <dir>]

[PERMISSIONS permissions...]

[CONFIGURATIONS [Debug|Release|...]]

[COMPONENT <component>]

[OPTIONAL]

] [...])

參數中的TARGETS后面跟的就是我們通過ADD_EXECUTABLE或者ADD_LIBRARY定義的目標文件,可能是可執行二進制、動態庫、靜態庫。目標類型也就相對應的有三種,ARCHIVE特指靜態庫,LIBRARY特指動態庫,RUNTIME特指可執行目標二進制。DESTINATION定義了安裝的路徑,如果路徑以/開頭,那么指的是絕對路徑,這時候CMAKE_INSTALL_PREFIX其實就無效了。如果你希望使用CMAKE_INSTALL_PREFIX 來定義安裝路徑,就要寫成相對路徑,即不要以 “/ ”開頭,那么安裝后的路徑就是:${CMAKE_INSTALL_PREFIX}/<DESTINATION定義的路徑>;

舉個簡單的例子:

INSTALL(TARGETS myrun mylib mystaticlib

RUNTIME DESTINATION bin

LIBRARY DESTINATION lib

ARCHIVE DESTINATION libstatic

)

上面的例子會將:

可執行二進制myrun安裝到${CMAKE_INSTALL_PREFIX}/bin目錄;

動態庫libmylib安裝到${CMAKE_INSTALL_PREFIX}/lib目錄;

靜態庫libmystaticlib安裝到${CMAKE_INSTALL_PREFIX}/libstatic目錄;

特別注意的是你不需要關心TARGETS具體生成的路徑,只需要寫上TARGETS名稱就可以了,即只寫"myrun" "mylib" "mystaticlib",而不用加具體的路徑。

2)普通文件的安裝:

INSTALL(FILES files... DESTINATION <dir>

[PERMISSIONS permissions...]

[CONFIGURATIONS [Debug|Release|...]]

[COMPONENT <component>]

[RENAME <name>] [OPTIONAL])

可用于安裝一般文件,并可以指定訪問權限,文件名是此指令所在路徑下的相對路徑。

如果默認不定義權限PERMISSIONS,安裝后的權限為:

OWNER_WRITE, OWNER_READ, GROUP_READ,和WORLD_READ,即644 (-rw-r--r--)權限。

3)非目標文件的可執行程序安裝(比如腳本之類):

INSTALL(PROGRAMS files... DESTINATION <dir>

[PERMISSIONS permissions...]

[CONFIGURATIONS [Debug|Release|...]]

[COMPONENT <component>]

[RENAME <name>] [OPTIONAL])

跟上面的FILES指令使用方法一樣,唯一的不同是安裝后權限為:

OWNER_EXECUTE, GROUP_EXECUTE, 和WORLD_EXECUTE,即755 (-rwxrw-rw-)權限

4)目錄的安裝:

INSTALL(DIRECTORY dirs... DESTINATION <dir>

[FILE_PERMISSIONS permissions...]

[DIRECTORY_PERMISSIONS permissions...]

[USE_SOURCE_PERMISSIONS]

[CONFIGURATIONS [Debug|Release|...]]

[COMPONENT <component>]

[[PATTERN <pattern> | REGEX <regex>]

[EXCLUDE] [PERMISSIONS permissions...]] [...])

這里主要介紹其中的DIRECTORY、PATTERN以及PERMISSIONS參數。

DIRECTORY后面連接的是所在Source目錄的相對路徑,但務必注意:abc和abc/是有很大區別的。如果目錄名不以/結尾,那么這個目錄將被安裝為目標路徑下的abc;

如果目錄名以/結尾,代表將這個目錄中的內容安裝到目標路徑,但不包括這個目錄本身。

PATTERN用于使用正則表達式進行過濾,PERMISSIONS用于指定PATTERN過濾后的文件權限。

我們來看一個例子:

INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj

PATTERN "CVS" EXCLUDE

PATTERN "scripts/*"

PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ)

這條指令的執行結果是:

將icons目錄安裝到 <prefix>/share/myproj,將scripts/中的內容安裝到<prefix>/share/myproj 不包含目錄名為CVS的目錄,對于scripts/*文件指定權限為 OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ.

安裝時CMAKE腳本的執行:

INSTALL([[SCRIPT <file>] [CODE <code>]] [...])

SCRIPT參數用于在安裝時調用cmake腳本文件(也就是<abc>.cmake文件)

CODE參數用于執行CMAKE指令,必須以雙引號括起來。比如:

INSTALL(CODE "MESSAGE(/"Sample install message./")")

安裝還有幾個被標記為過時的指令,比如INSTALL_FILES等,這些指令已經不再推薦使用,所以,這里就不再贅述了。

下面,我們就來改寫我們的工程文件,讓他來支持各種文件的安裝,并且,我們要使用

CMAKE_INSTALL_PREFIX指令。

5,修改Helloworld支持安裝

在本節開頭我們定義了本節的任務如下:

  • 為工程添加一個子目錄src,用來存儲源代碼;
  • 添加一個子目錄doc,用來存儲這個工程的文檔hello.txt
  • 在工程目錄添加文本文件COPYRIGHT, README;
  • 在工程目錄添加一個runhello.sh腳本,用來調用hello二進制
  • 將構建后的目標文件放入構建目錄的bin子目錄;
  • 最終安裝這些文件:將hello二進制與runhello.sh安裝至/<prefix>/bin,將doc目錄中的hello.txt以及COPYRIGHT/README安裝到/<prefix>/share/doc/cmake/t2,

1)首先我們先添加上訴文件:

  • 添加doc目錄及文件:

cd /backup/cmake/t2

mkdir doc

vimdoc/hello.txt # 隨便填寫一些內容并保存

  • 在工程目錄添加runhello.sh腳本,用來調用hello二進制,所以其內容為:hello
  • 添加工程目錄中的COPYRIGHT和README: touch COPYRIGHT; touch README

2)下面改寫各目錄的CMakeLists.txt文件,以實現以下目標:

將hello二進制與runhello.sh安裝至/<prefix>/bin,將doc目錄中的hello.txt以及COPYRIGHT/README安裝到/<prefix>/share/doc/cmake/t2

  • 安裝COPYRIGHT/README,直接修改主工程文件CMakelists.txt,加入以下指令:

INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake/t2) #將COPYRIGHT/README安裝到/<prefix>/share/doc/cmake/t2

  • 安裝runhello.sh,直接修改主工程文件CMakeLists.txt,加入如下指令:

INSTALL(PROGRAMS runhello.sh DESTINATION bin) # runhello.sh安裝到/<prefix>/bin

  • 安裝hello 可執行文件, 修改t2/src/CMakeLists.txt, 加入如下指令:

INSTALL(TARGETS hello RUNTIME DESTINATION bin) #將hello二進制安裝至/<prefix>/bin

  • 安裝doc中的hello.txt,這里有兩種方式:一是通過在doc目錄建立CMakeLists.txt,并將doc目錄通過ADD_SUBDIRECTORY加入工程來完成。另一種方法是直接在工程目錄通過INSTALL(DIRECTORY …)來完成,前者比較簡單,各位可以根據興趣自己完成,我們來嘗試后者,即在主工程文件CMakeLists.txt做修改。因為hello.txt要安裝到/<prefix>/share/doc/cmake/t2,所以我們不能直接安裝整個doc目錄,這里采用的方式是安裝doc目錄中的內容,也就是使用" doc/ "在工程文件CMakelists.txt中添加:

INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake/t2) #將doc目錄中的hello.txt安裝到/<prefix>/share/doc/cmake/t2

6,嘗試我們修改的結果:

現在進入build目錄進行外部編譯,注意使用CMAKE_INSTALL_PREFIX參數,這里我們

將它安裝到了/tmp/t2/usr目錄:

cmake -DCMAKE_INSTALL_PREFIX=/tmp/t2/usr .. (注: .. 表示build目錄的上一層目錄)

然后運行

make

make install

This result will be shown as below:

讓我們進入/tmp/t2目錄看一下安裝結果:

Now we can run the binary file – hello, in two different directories, and we can get the same results.

此外,我們發現,運行 ./hello 和運行 ./runhello.sh 回得到同一個效果, 因為runhello.sh文件的內容就是"hello", 而且二進制文件hello和runhello.sh 在同一個目錄下,因此可以實現其效果。

如果你要直接安裝到系統,可以使用如下指令:

cmake -DCMAKE_INSTALL_PREFIX=/usr ..

Note: 一個疑問

如果我沒有定義CMAKE_INSTALL_PREFIX會安裝到什么地方?

你可以嘗試以下,cmake ..; make; sudo make install,你會發現CMAKE_INSTALL_PREFIX的默認定義是/usr/local, 如下圖:

7,清理構建結果(See Ref 2)

以下是來自stackoverflow論壇的一個問題:

Question:Just asmake cleandeletes all the files that a makefile has produced, I would like to do the same with CMake. All too often I find myself manually going through directories removing files likecmake_install.cmakeandCMakeCache.txt, and theCMakeFilesfolders.Is there a command likecmake cleanwhich will remove all these files automatically? Ideally this should follow the recursive structure defined within the current directory'sCMakeLists.txtfile.

Best Answer:

8,小結:

本小節主要描述了如何在工程中使用多目錄、各種安裝指令以及CMAKE_INSTALL_PREFIX變量。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久av网站| 欧美在线视频网站| 在线观看日韩www视频免费| 国产在线精品成人一区二区三区| 91av免费观看91av精品在线| 亚洲偷熟乱区亚洲香蕉av| 久久久亚洲影院你懂的| 国产一区二区三区丝袜| 中文字幕亚洲欧美日韩在线不卡| 久久国产精品免费视频| 国产精品久久久91| 亚洲一区二区在线播放| 亚洲午夜精品久久久久久久久久久久| 欧美高清在线视频观看不卡| 97av在线播放| 亚洲一区二区久久久| 成人免费福利在线| 中文字幕日韩av综合精品| 米奇精品一区二区三区在线观看| 97国产精品视频| 色综合久久久888| 国产精品福利在线观看| 国产99久久精品一区二区| 欧美成人午夜免费视在线看片| 青青久久av北条麻妃黑人| 国产福利成人在线| 韩国精品美女www爽爽爽视频| 亚洲一区二区在线| 国产精品电影网站| 亚洲国产精品一区二区久| 欧美午夜影院在线视频| 精品色蜜蜜精品视频在线观看| 日韩黄色高清视频| 91香蕉嫩草影院入口| 亚洲色图35p| 亚洲石原莉奈一区二区在线观看| 日本高清视频精品| 一区二区亚洲精品国产| 欧美激情网站在线观看| 国产日韩欧美日韩大片| 国产欧美日韩精品专区| 久久精视频免费在线久久完整在线看| 成人精品视频久久久久| 97av在线影院| 久久视频在线直播| 亚洲九九九在线观看| 欧美性猛交xxxx乱大交蜜桃| 亚洲经典中文字幕| 国产精品一区二区久久久| 性色av一区二区咪爱| 97免费中文视频在线观看| 91大神在线播放精品| 欧美激情综合亚洲一二区| 亚洲视频精品在线| 日韩欧美高清视频| 欧美日韩国产丝袜美女| 欧美黄色小视频| 欧美在线xxx| 中文字幕日韩免费视频| 自拍偷拍免费精品| 久久久久成人网| 国产在线观看91精品一区| 欧美高清视频在线播放| 日韩成人在线视频网站| 日韩麻豆第一页| 国产亚洲精品激情久久| 8x海外华人永久免费日韩内陆视频| 欧美日韩性生活视频| 久久久久五月天| 欧美激情一级欧美精品| 97热精品视频官网| 亚洲精品一区中文字幕乱码| 亚洲电影在线观看| 日韩欧美成人网| 精品中文字幕乱| 上原亚衣av一区二区三区| 色偷偷88888欧美精品久久久| 中文字幕免费国产精品| 久久久精品在线观看| 国产精品777| 日韩一区视频在线| 91免费人成网站在线观看18| 亚洲国产天堂久久综合网| 久久国产色av| 中文字幕久久精品| 成人伊人精品色xxxx视频| 欧美日韩日本国产| 色中色综合影院手机版在线观看| 国产亚洲福利一区| 欧美视频不卡中文| 超碰97人人做人人爱少妇| 狠狠色狠狠色综合日日五| 国产精品久久久久91| 日韩av在线免费观看一区| 欧美精品性视频| 国产精品电影一区| 欧美精品电影免费在线观看| 精品日本美女福利在线观看| 欧美一级免费看| 国产精品视频区1| 国产午夜精品美女视频明星a级| 亚洲xxxx妇黄裸体| 国产精品爽黄69天堂a| 久久精品国产亚洲精品| 欧美日韩亚洲高清| 亚洲精品福利免费在线观看| 国产精品福利小视频| 中文字幕亚洲图片| 在线精品高清中文字幕| 狠狠爱在线视频一区| 欧美一级片久久久久久久| 中文字幕亚洲欧美日韩在线不卡| 亚洲欧美日韩国产中文专区| 911国产网站尤物在线观看| 亚洲国产精品人人爽夜夜爽| 国产精品久久久久av| 亚洲最大中文字幕| 日韩精品一区二区三区第95| 国产精品日韩精品| 色偷偷av亚洲男人的天堂| 国产欧美一区二区三区久久| 91亚洲精华国产精华| 伊人久久久久久久久久久久久| 中文字幕国产精品| 日韩欧美国产一区二区| 日韩在线观看免费网站| 欧美日韩国产专区| 中文字幕视频在线免费欧美日韩综合在线看| 亚洲精品久久久久久久久| 久久久免费精品视频| 中文字幕亚洲欧美日韩高清| www.99久久热国产日韩欧美.com| 日韩美女免费线视频| 国产精品一区二区久久久| 久久精品国产清自在天天线| 成人精品视频99在线观看免费| 日韩在线视频免费观看高清中文| 日韩成人在线播放| 精品久久久久久久久国产字幕| 欧洲中文字幕国产精品| 日本精品免费观看| 欧美性极品xxxx娇小| 亚洲黄页视频免费观看| 亚洲精品免费网站| 国产性猛交xxxx免费看久久| 亚洲天堂2020| 影音先锋日韩有码| 欧美电影免费观看高清完整| 亚洲国产精品大全| 欧洲精品久久久| 青草青草久热精品视频在线网站| 中国china体内裑精亚洲片| 色综合导航网站| 日本一区二区不卡| 日韩久久午夜影院| 久久国产精品视频| 亚洲一级一级97网| 欧美精品激情blacked18| 97人洗澡人人免费公开视频碰碰碰| 国产精品日本精品| 欧美午夜片欧美片在线观看| 日本成人黄色片| 国模吧一区二区三区| 色噜噜国产精品视频一区二区|