2017-01-23 78 views
0

我有一個C++ cmake的項目編譯速度。在這個項目中,我構建了一個例子,其中我需要使用另一個項目,稱之爲Foo。該Foo項目不提供cmake構建系統。相反,它有一個預製的Makefile.custom.in。爲了構建使用Foo的功能的可執行文件,需要將該makefile複製到他的項目中,並對其進行修改(通常設置SOURCES變量和一些編譯器標誌)。基本上,這個Makefile最終擁有可執行文件的源代碼以及Foo項目的所有源文件。您最終不會使用Foo作爲庫。現在CMake的:當包括外部生成

,這是一個設計,我不喜歡,但對這個問題的緣故,讓我們說,我們堅持下去。

要創建我的例子我的CMake的構建裏面我加了一個自定義的目標:

CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Makefile.custom.in Makefile.custom) 

ADD_CUSTOM_TARGET(my_target COMMAND $(MAKE) -f Makefile.custom 
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 

這工作。我可以指定一些變量給cmake,這個變量在CONFIGURE_FILE的調用中得到解決,我最終得到了一個Makefile.custom。然後,從構建目錄調用make my_target,我可以構建可執行文件。我甚至可以將其與

SET_TARGET_PROPERTIES(my_target PROPERTIES EXCLUDE_FROM_ALL FALSE) 

甜添加到all目標(我節省打字make my_target的努力)。但是,cmake似乎將單個作業分配給自定義目標,這會減慢我的編譯時間(Foo源文件夾包含幾十個cpp文件)。最重要的是,make clean目標不會轉發到自定義生成文件。我最終不得不添加另一個目標:

ADD_CUSTOM_TARGET(really-clean COMMAND "$(MAKE)" clean 
        COMMAND "$(MAKE)" -f Makefile.custom clean 
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 

,不像my_targetall,我不能在clean目標包括:(可以嗎?)。

現在,我知道一個更清潔的解決方案是有Foo項目建設成爲一個外部項目,然後鏈接到它。然而,我被'推薦'使用他們的Makefile.custom.in生成文件,修改我需要的幾行(添加我的源代碼,指定編譯器標誌以及其他一些小修改)。所以,不管如何幹淨整潔的這種設計模式是,我的問題是:

  • 有沒有辦法告訴cmake的,使應使用大於1點的工作更使得目標my_target什麼時候?
  • 是有一個更清潔的方式,包括在cmake的項目預先存在的makefile文件?請注意,我不希望(不能?)使用Foo作爲庫(並鏈接它)。我想(需要?)將它與我的可執行文件一起使用不是由cmake生成的makefile編譯(好吧,通過解析一些變量,cmake可以幫助一點,通過CONFIGURE_FILE,但就是這樣)。

注:我知道ExternalProject的(如還建議在this答案),但我認爲這不是正是我需要在這裏(因爲它會建立Foo,然後用它作爲一個庫)。另外,我的項目和Foo都是專門用C++編寫的(根本不確定這件事)。

我希望這個問題是有道理的(不管醜/煩人/不盡人意設計結果會怎樣)。

編輯:我使用cmake版本3.5.2

+0

如果構建時間很重要,請考慮切換到忍者。這對你的情況也有幫助。 – usr1234567

+0

我想過忍者。我沒有使用它,因爲我可能會也可能不會在某些時候包含一些fortran代碼,並且據我所知,cmake的忍者生成器不支持fortran(但我承認我沒有在一段時間內檢查更新) 。 – bartgol

+0

您使用哪個版本的CMake? – fedepad

回答

1

首先,因爲你定義自己的目標,你可以分配更多內核的構建過程目標my_target,直接在裏面CMakeLists.txt
您可以包含Cmake模塊ProcessCount以確定機器中的內核數量,然後將其用於並行構建。

include(ProcessorCount) 
ProcessorCount(N) 
if(NOT N EQUAL 0) 
    # given that cores != 0 you could modify 
    # math(EXPR N "${N}+1") # modify (increment/decrement) N at your will, in this case, just incrementing N by one 
    set(JOBS_IN_PARALLEL -j${N}) 
endif(NOT N EQUAL 0) 

,當你定義自定義目標有類似如下:

ADD_CUSTOM_TARGET(my_target 
        COMMAND ${CMAKE_MAKE_PROGRAM} ${JOBS_IN_PARALLEL} -f Makefile.custom 
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 

順便說一下,我不認爲有需要,你還包括COMMAND選自S CMAKE_BUILD_TOOL在你的目標。
我相信,而不是修改爲上面的線,你可以調用

make -j8 my_target 

,它可能不修改CMakeLists.txt開始8個作業(只是一個例子),但我不能保證這個工程已經定義的命令你的方式,只是嘗試,如果這足夠了。
對於第二點,我現在無法想象「更清潔」的方式。

+0

謝謝!你的意思是我應該直接寫'make'而不是使用'$ {CMAKE_MAKE_PROGRAM}'?我認爲使用cmake變量會使構建系統變得更加便攜,不是嗎? – bartgol

+0

這是兩回事。在CMakeLists.txt中使用'$ {CMAKE_MAKE_PROGRAM}',你應該保持這種狀態。在命令行中使用命令'make my_target'來觸發自定義目標的構建。 – fedepad