ไดเร็กทอรีเอาต์พุต / สร้าง CMake


116

ฉันค่อนข้างใหม่สำหรับ CMake และอ่านบทแนะนำเกี่ยวกับวิธีการใช้งานและเขียนสคริปต์ CMake ที่ซับซ้อน 50 บรรทัดเพื่อสร้างโปรแกรมสำหรับคอมไพเลอร์ 3 ตัว นี่อาจเป็นการสรุปความรู้ทั้งหมดของฉันใน CMake

ตอนนี้ปัญหาของฉันคือฉันมีซอร์สโค้ดซึ่งมีโฟลเดอร์ที่ฉันไม่ต้องการสัมผัส / ยุ่งกับเมื่อฉันสร้างโปรแกรม ฉันต้องการให้ CMake และmakeเอาท์พุตไฟล์และโฟลเดอร์ทั้งหมดเข้ามา../Compile/ดังนั้นฉันจึงเปลี่ยนตัวแปรสองสามตัวในสคริปต์ CMake ของฉันสำหรับสิ่งนั้นและมันก็ใช้ได้ในบางครั้งเมื่อฉันทำสิ่งนี้บนแล็ปท็อปของฉัน:

Compile$ cmake ../src
Compile$ make

โดยที่ฉันมีผลลัพธ์ที่สะอาดในโฟลเดอร์ที่ฉันอยู่ตอนนี้ซึ่งเป็นสิ่งที่ฉันกำลังมองหา

ตอนนี้ฉันย้ายไปที่คอมพิวเตอร์เครื่องอื่นและคอมไพล์ CMake 2.8.11.2 ใหม่และฉันเกือบจะกลับไปที่สี่เหลี่ยมจัตุรัส! มันมักจะรวบรวมสิ่งนั้นไว้ในsrcโฟลเดอร์ที่ฉันCMakeLists.txtอยู่

ส่วนที่ฉันเลือกไดเร็กทอรีในสคริปต์ CMake ของฉันคือ:

set(dir ${CMAKE_CURRENT_SOURCE_DIR}/../Compile/)
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dir})
set(CMAKE_BUILD_FILES_DIRECTORY ${dir})
set(CMAKE_BUILD_DIRECTORY ${dir})
set(CMAKE_BINARY_DIR  ${dir})
SET(EXECUTABLE_OUTPUT_PATH ${dir})
SET(LIBRARY_OUTPUT_PATH ${dir}lib)
SET(CMAKE_CACHEFILE_DIR ${dir})

และตอนนี้มันมักจะลงท้ายด้วย:

-- Build files have been written to: /.../src

ฉันพลาดอะไรไปรึเปล่า?


4
ไม่จำเป็นต้องตั้งค่าตัวแปรทั้งหมดที่คุณตั้งไว้ CMake ตั้งค่าเป็นค่าเริ่มต้นที่สมเหตุสมผล คุณควรแน่นอนไม่ได้ปรับเปลี่ยนหรือCMAKE_BINARY_DIR CMAKE_CACHEFILE_DIRจะเกิดอะไรขึ้นถ้าคุณลบการset()โทรเหล่านี้ออกทั้งหมดและทำcd Compile; rm -rf *; cmake ../srcอย่างไร
Angew ไม่ภูมิใจอีกต่อไปเมื่อ

5
โดยทั่วไปตราบใดที่คุณอยู่นอกไดเร็กทอรีต้นทางเมื่อเรียกใช้ CMake มันจะไม่แก้ไขไดเร็กทอรีต้นทางเว้นแต่ CMakeList ของคุณจะบอกอย่างชัดเจน
Angew ไม่ภูมิใจอีกต่อไปเมื่อ

@Angew ขอบคุณสำหรับเคล็ดลับซึ่งน่าประหลาดใจมาก! ฉันลบบรรทัดเหล่านั้นออกทั้งหมดและใช้ cmake ../src และมันก็ใช้งานได้เหมือนมีเสน่ห์! นี่เป็นเรื่องที่น่าแปลกใจมากเพราะฉันเคยลองมาก่อนตอนที่ฉันเรียน CMake ครั้งแรก แต่มันไม่ได้ กรุณาใส่คำตอบของคุณในการตอบกลับอย่างเป็นทางการเพื่อให้คุณมีเครื่องหมายถูกไขมันใหญ่ :)
นักฟิสิกส์ควอนตัม

1
สิ่งที่ช่วยฉันได้คือคำพูดของ @Adam Bowen ที่ว่า "คุณไม่สามารถสร้างงานสร้างนอกแหล่งสำหรับไดเร็กทอรีต้นทางที่มีการสร้างในซอร์สได้"
Aur Saraf

คำตอบ:


60

ไม่จำเป็นต้องตั้งค่าตัวแปรทั้งหมดที่คุณตั้งไว้ CMake ตั้งค่าเป็นค่าเริ่มต้นที่สมเหตุสมผล คุณควรแน่นอนไม่ได้ปรับเปลี่ยนหรือCMAKE_BINARY_DIR CMAKE_CACHEFILE_DIRถือว่าสิ่งเหล่านี้เป็นแบบอ่านอย่างเดียว

ก่อนอื่นให้ลบไฟล์แคชที่มีปัญหาออกจากไดเร็กทอรี src:

cd src
rm CMakeCache.txt
cd ..

จากนั้นลบ set()คำสั่งและทำ:

cd Compile
rm -rf *
cmake ../src

ตราบใดที่คุณอยู่นอกไดเร็กทอรีต้นทางเมื่อเรียกใช้ CMake จะไม่แก้ไขไดเร็กทอรีต้นทางเว้นแต่ CMakeList ของคุณจะแจ้งให้ทราบอย่างชัดเจน

เมื่อคุณใช้งานได้แล้วคุณสามารถดูว่า CMake วางสิ่งต่าง ๆ ไว้ที่ใดโดยค่าเริ่มต้นและเฉพาะในกรณีที่คุณไม่พอใจกับตำแหน่งเริ่มต้น (เช่นค่าเริ่มต้นEXECUTABLE_OUTPUT_PATH) ให้แก้ไขเฉพาะที่ที่คุณต้องการ และพยายามที่จะแสดงให้พวกเขาเทียบกับCMAKE_BINARY_DIR, CMAKE_CURRENT_BINARY_DIR, PROJECT_BINARY_DIRฯลฯ

หากคุณดูเอกสาร CMake คุณจะเห็นตัวแปรที่แบ่งออกเป็นส่วนความหมาย ยกเว้นในกรณีที่พิเศษมากคุณควรปฏิบัติต่อสิ่งที่ระบุไว้ใน "ตัวแปรที่ให้ข้อมูล" เป็นแบบอ่านอย่างเดียวภายใน CMakeLists


2
ฉันเริ่มใช้ cmake กับ builds ในไดเร็กทอรี src ... เทคนิคนี้ล้มเหลวในตอนแรก เมื่อฉันลบไฟล์ / แคช cmake build ทั้งหมดในไดเร็กทอรี src เทคนิคนี้ใช้ได้ผล ขอบคุณ!
Avi Tevet

18
rm -rf *บางทีมันอาจจะดีกว่าที่จะไม่แนะนำให้ใช้ มันไม่สวยเลยถ้าcd Compileล้มเหลว ...
โรมัน

2
@ โรมันฉันพิจารณาตัวอย่างบรรทัดคำสั่งดังกล่าวรหัสหลอกค่อนข้างมาก มันละเอียดน้อยกว่าและแน่นอนกว่าการพิมพ์ "ป้อนไดเรกทอรีCompileลบทุกอย่างที่นั่นแล้วเรียกใช้ CMake ด้วยพา ธ ไปยัง dir ต้นทาง" ฉันถือว่าสามัญสำนึกพื้นฐานและวิจารณญาณเป็นส่วนหนึ่งของผู้อ่าน
Angew ไม่ภูมิใจใน SO

@AviTevet: ฉันคิดว่านี่เป็นคำตอบที่ถูกต้อง หากมีไฟล์แคช cmake จากการเรียกใช้ cmake ก่อนหน้านี้ภายในไดเร็กทอรีต้นทางคุณจะไม่ได้รับ cmake เพื่อเลือกไดเร็กทอรีอื่นสำหรับไฟล์ที่สร้างขึ้นเว้นแต่คุณจะลบไฟล์เก่าทั้งหมดออกจากไดเร็กทอรีต้นทาง พฤติกรรมที่ไม่ดีโดย CMake ในความคิดของฉัน ทำไมคุณไม่เขียนคำตอบอื่น
Jo So

113

ดูเหมือนคุณต้องการจากแหล่งที่มาของการสร้าง มีสองวิธีที่คุณสามารถสร้างงานสร้างนอกซอร์สได้

  1. ทำในสิ่งที่คุณกำลังทำวิ่ง

    cd /path/to/my/build/folder
    cmake /path/to/my/source/folder

    ซึ่งจะทำให้ CMake เพื่อสร้างสร้างต้นไม้ใน/path/to/my/build/folderสำหรับแหล่งต้นไม้/path/to/my/source/folderใน

    เมื่อคุณสร้างแล้ว cmake จะจำว่าโฟลเดอร์ต้นทางอยู่ที่ไหน - ดังนั้นคุณสามารถเรียกใช้ cmake บนโครงสร้างการสร้างใหม่ด้วย

    cmake /path/to/my/build/folder

    หรือแม้กระทั่ง

    cmake .

    หากไดเร็กทอรีปัจจุบันของคุณเป็นโฟลเดอร์บิลด์แล้ว

  2. สำหรับ CMake 3.13 หรือใหม่กว่าให้ใช้ตัวเลือกเหล่านี้เพื่อตั้งค่าซอร์สและสร้างโฟลเดอร์

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
  3. สำหรับ CMake รุ่นเก่าให้ใช้ตัวเลือกที่ไม่มีเอกสารเพื่อตั้งค่าซอร์สและสร้างโฟลเดอร์ :

    cmake -B/path/to/my/build/folder -H/path/to/my/source/folder

    ซึ่งจะทำสิ่งเดียวกับ (1) แต่ไม่ต้องพึ่งพาไดเร็กทอรีการทำงานปัจจุบัน

CMake ทำให้ทั้งหมดของผลในการสร้างต้นไม้โดยค่าเริ่มต้นดังนั้นถ้าคุณกำลังใช้อย่างกว้างขวาง${CMAKE_SOURCE_DIR}หรือ${CMAKE_CURRENT_SOURCE_DIR}ในแฟ้ม CMake ของคุณก็ไม่ควรจะจับคุณแหล่งต้นไม้

สิ่งที่ใหญ่ที่สุดที่อาจผิดพลาดคือถ้าคุณเคยสร้างโครงสร้างการสร้างในแผนผังแหล่งที่มาของคุณก่อนหน้านี้ (เช่นคุณมีการสร้างแหล่งที่มา ) เมื่อคุณทำสิ่งนี้เสร็จแล้วส่วนที่สองของ (1) ด้านบนจะเริ่มขึ้นและ cmake จะไม่ทำการเปลี่ยนแปลงใด ๆ กับแหล่งที่มาหรือสถานที่สร้าง ดังนั้นคุณจะไม่สามารถสร้างสร้างออกจากแหล่งสำหรับไดเรกทอรีต้นทางที่มีการสร้างในแหล่งที่มา คุณสามารถแก้ไขปัญหานี้ได้ค่อนข้างง่ายโดยการลบ (อย่างน้อยที่สุด)CMakeCache.txtออกจากไดเร็กทอรีต้นทาง มีไฟล์อื่น ๆ อีกสองสามไฟล์ (ส่วนใหญ่อยู่ในCMakeFilesไดเร็กทอรี) ที่ CMake สร้างขึ้นซึ่งคุณควรลบออกเช่นกัน แต่สิ่งเหล่านี้จะไม่ทำให้ cmake ปฏิบัติกับแผนผังต้นทางเป็นโครงสร้างแบบ

เนื่องจากบิวด์นอกซอร์สมักเป็นที่ต้องการมากกว่าบิวด์อินซอร์สคุณอาจต้องการปรับเปลี่ยน cmake ของคุณเพื่อต้องการบิวด์นอกซอร์ส:

# Ensures that we do an out of source build

MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${CMAKE_BINARY_DIR}" insource)
     GET_FILENAME_COMPONENT(PARENTDIR ${CMAKE_SOURCE_DIR} PATH)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${PARENTDIR}" insourcesubdir)
    IF(insource OR insourcesubdir)
        MESSAGE(FATAL_ERROR "${MSG}")
    ENDIF(insource OR insourcesubdir)
ENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)

MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
    "${CMAKE_PROJECT_NAME} requires an out of source build."
)

MacroOutOfSourceBuildแมโครข้างต้นมาจากโมดูลที่ใช้เรียกกันว่า มีแหล่งข้อมูลมากมายสำหรับMacroOutOfSourceBuild.cmakeใน google แต่ฉันไม่สามารถหาต้นฉบับได้และสั้นพอที่จะรวมไว้ที่นี่อย่างครบถ้วน

น่าเสียดายที่ cmake มักจะเขียนไฟล์ไม่กี่ไฟล์ตามเวลาที่เรียกใช้มาโครดังนั้นแม้ว่ามันจะหยุดคุณจากการสร้างงานจริง แต่คุณก็ยังต้องลบCMakeCache.txtและCMakeFilesและ

คุณอาจพบว่ามีประโยชน์ในการกำหนดเส้นทางที่ไบนารีไลบรารีที่ใช้ร่วมกันและแบบสแตติกเขียนถึง - ในกรณีนี้ดูว่าฉันจะสร้างเอาต์พุต cmake ใน dir 'bin' ได้อย่างไร (ข้อจำกัดความรับผิดชอบฉันมีคำตอบที่ได้รับการโหวตสูงสุดสำหรับคำถามนั้น ... แต่นั่นเป็นวิธีที่ฉันรู้)


จริงๆแล้วตัวเลือกในการตั้งค่าโฟลเดอร์ต้นทาง-Sไม่ใช่-H
smac89

@ smac89 ขอบคุณ! ดูเหมือนว่าพวกเขาบันทึกไว้ใน 3.13 - ฉันได้อัปเดตคำตอบเพื่อให้สอดคล้องกับ CMake สมัยใหม่
Adam Bowen

8

เปลี่ยนความคิดเห็นของฉันให้เป็นคำตอบ:

ในกรณีที่ใครทำในสิ่งที่ฉันทำซึ่งเริ่มต้นด้วยการวางไฟล์บิลด์ทั้งหมดในไดเร็กทอรีต้นทาง:

cd src
cmake .

CMake จะใส่พวงของการสร้างไฟล์และแฟ้มแคช (กCMakeCache.txt, CMakeFiles, cmake_install.cmakeฯลฯ ) ในsrc dir

ในการเปลี่ยนเป็นการสร้างนอกซอร์สฉันต้องลบไฟล์เหล่านั้นทั้งหมด จากนั้นฉันสามารถทำสิ่งที่ @Angew แนะนำในคำตอบของเขา:

mkdir -p src/build
cd src/build
cmake ..

7

ในขณะที่CMake Wiki :

CMAKE_BINARY_DIR หากคุณกำลังสร้างในแหล่งที่มาซึ่งจะเหมือนกับ CMAKE_SOURCE_DIR มิฉะนั้นจะเป็นไดเรกทอรีระดับบนสุดของโครงสร้างโครงสร้างของคุณ

เปรียบเทียบตัวแปรทั้งสองนี้เพื่อตรวจสอบว่าบิวด์นอกซอร์สเริ่มทำงานหรือไม่


6

คุณไม่ควรใช้ชื่อ dir บิวด์โค้ดแบบฮาร์ดโค้ดในสคริปต์ของคุณดังนั้นจึง../Compileต้องเปลี่ยนบรรทัดด้วย

เป็นเพราะควรขึ้นอยู่กับผู้ใช้ว่าจะรวบรวมที่ไหน

แทนที่จะใช้ตัวแปรที่กำหนดไว้ล่วงหน้า: http://www.cmake.org/Wiki/CMake_Useful_Variables (ค้นหาCMAKE_BINARY_DIRและCMAKE_CURRENT_BINARY_DIR)


2
นี่คือสิ่งที่ฉันกำลังมองหา - CMAKE_CURRENT_BINARY_DIRโดยทั่วไปจะบอกเกี่ยวกับเส้นทางการสร้างไบนารีในปัจจุบัน อาจใช้สำหรับการตั้งค่าการสร้าง libs / bin ที่ขึ้นต่อกัน
กระซิก
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.