CMake çıktı / derleme dizini


116

CMake'de oldukça yeniyim ve nasıl kullanılacağına dair birkaç öğretici okudum ve 3 farklı derleyici için bir program yapmak için karmaşık 50 satırlık CMake betiği yazdım. Bu muhtemelen CMake'deki tüm bilgilerimi tamamlıyor.

Şimdi benim sorunum, programı hazırlarken klasörüne dokunmak / karıştırmak istemediğim bir kaynak kodum olması. Tüm CMake ve makeçıktı dosyalarının ve klasörlerinin içine girmesini istiyorum ../Compile/, bu yüzden CMake betiğimde bunun için birkaç değişkeni değiştirdim ve dizüstü bilgisayarımda böyle bir şey yaptığımda bir süre çalıştı:

Compile$ cmake ../src
Compile$ make

Bununla birlikte, şu anda bulunduğum klasörde temiz bir çıktı elde ettiğim yer, tam olarak aradığım şey bu.

Şimdi başka bir bilgisayara geçtim ve CMake 2.8.11.2'yi yeniden derledim ve neredeyse başa döndüm! Her zaman nesneyi srcbenim konumumun bulunduğu klasörde derler CMakeLists.txt.

CMake betiğimde dizini seçtiğim kısım şudur:

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})

Ve şimdi her zaman şu şekilde bitiyor:

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

Bir şey mi kaçırıyorum?


4
Ayarladığınız tüm değişkenleri ayarlamaya çok az ihtiyaç var. CMake bunları makul varsayılanlara ayarlar. Kesinlikle gerekir değil değiştirmek CMAKE_BINARY_DIRveya CMAKE_CACHEFILE_DIR. Tüm bu set()aramaları kaldırır ve yaparsanız ne olur cd Compile; rm -rf *; cmake ../src?
Angew artık

5
Temel olarak, CMake'yi çalıştırırken kaynak dizinin dışında olduğunuz sürece, CMakeList'iniz açıkça söylemediği sürece kaynak dizini değiştirmez.
Angew artık

@Angew Şaşırtıcı olan ipucu için teşekkür ederim! Tüm bu satırları kaldırdım ve sadece cmake ../src kullandım ve harika çalıştı! Bu çok şaşırtıcı çünkü daha önce CMake'i ilk öğrenirken denedim ve işe yaramadı. Lütfen cevabınızı size büyük bir onay işareti vermek için resmi bir cevaba yazın :)
The Quantum Physicist

1
Beni kurtaran, @Adam Bowen'in "kaynak içi bir yapıya sahip bir kaynak dizin için kaynak dışı bir yapı oluşturamazsınız" yorumuydu
Aur Saraf

Yanıtlar:


60

Ayarladığınız tüm değişkenleri ayarlamaya çok az ihtiyaç var. CMake bunları makul varsayılanlara ayarlar. Kesinlikle gerekir değil değiştirmek CMAKE_BINARY_DIRveya CMAKE_CACHEFILE_DIR. Bunları salt okunur olarak ele alın.

Öncelikle mevcut sorunlu önbellek dosyasını src dizininden kaldırın:

cd src
rm CMakeCache.txt
cd ..

Ardından tüm set()komutları kaldırın ve şunları yapın:

cd Compile
rm -rf *
cmake ../src

CMake'yi çalıştırırken kaynak dizinin dışında olduğunuz sürece, CMakeList'iniz açıkça belirtmedikçe kaynak dizini değiştirmez.

Bunu çalıştırdıktan sonra, CMake'nin şeyleri varsayılan olarak nereye koyduğuna bakabilir ve yalnızca varsayılan konumlardan (varsayılan değeri gibi) memnun değilseniz EXECUTABLE_OUTPUT_PATH, yalnızca ihtiyacınız olanları değiştirebilirsiniz. Ve göreceli onları ifade etmek deneyin CMAKE_BINARY_DIR, CMAKE_CURRENT_BINARY_DIR, PROJECT_BINARY_DIRvb

CMake belgelerine bakarsanız, anlamsal bölümlere ayrılmış değişkenler göreceksiniz. Çok özel durumlar dışında , "Bilgi Sağlayan Değişkenler" altında listelenenlerin tümünü CMakeListleri içinde salt okunur olarak değerlendirmelisiniz.


2
Src dizininde derlemeler ile cmake kullanmaya başladım ... bu teknik başlangıçta başarısız oldu. Src dizinindeki tüm cmake derleme dosyalarını / önbelleklerini sildikten sonra bu teknik çalıştı. Teşekkürler!
Avi Tevet

18
Belki kullanmayı tavsiye etmemek daha iyidir rm -rf *. cd CompileBaşarısız olursa güzel değil ...
Roman

2
@Roman Bu tür komut satırı örneklerini oldukça sözde kod olarak görüyorum. Daha az ayrıntılı ve "dizine girin, Compileoradaki her şeyi silin ve ardından CMake'yi kaynak dizine giden bir yolla çalıştırın." Okuyucunun bir kısmında temel sağduyu ve yargıya varıyorum.
Angew artık SO

@AviTevet: Bunun doğru cevap olduğunu düşünüyorum. Kaynak dizinin içinde önceki bir cmake çağrısından cmake önbellek dosyaları varsa, kaynak dizinden tüm eskileri silmediğiniz sürece, oluşturulan dosyalar için başka bir dizin seçmek için cmake almayacaksınız. Bence CMake'den oldukça bozuk davranış. Neden başka bir cevap yazmıyorsun?
Jo So

113

Kaynak dışı bir derleme istediğiniz gibi görünüyor . Kaynak dışı bir yapı oluşturmanın birkaç yolu vardır.

  1. Yaptığın şeyi yap, koş

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

    hangi cmake bir oluşturmasına neden olur inşa ağacı içinde /path/to/my/build/folderiçin kaynak ağacının içinde /path/to/my/source/folder.

    Bir kez oluşturduğunuzda, cmake kaynak klasörün nerede olduğunu hatırlar - böylece yapı ağacında cmake'ı yeniden çalıştırabilirsiniz.

    cmake /path/to/my/build/folder

    ya da

    cmake .

    mevcut dizininiz zaten yapı klasörü ise.

  2. CMake 3.13 veya üstü için, kaynağı ayarlamak ve klasörler oluşturmak için bu seçenekleri kullanın

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
  3. Daha eski CMake için, kaynağı ayarlamak ve klasörler oluşturmak için bazı belgelenmemiş seçenekleri kullanın :

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

    (1) ile tam olarak aynı şeyi yapacak, ancak mevcut çalışma dizinine güvenmeden.

CKağıt yılında çıkışlarının tüm koyar inşa ağacının sen özgürce kullanıyor bu yüzden sürece, varsayılan olarak ${CMAKE_SOURCE_DIR}veya ${CMAKE_CURRENT_SOURCE_DIR}sizin cmake dosyalarında, bu temas etmemelidir kaynak ağacını .

Yanlış gidebilecek en büyük şey, daha önce kaynak ağacınızda bir yapı ağacı oluşturmuş olmanızdır (yani, bir kaynak derlemesine sahipseniz ). Bunu yaptıktan sonra, yukarıdaki (1) 'in ikinci kısmı devreye girer ve cmake, kaynakta veya inşa konumlarında herhangi bir değişiklik yapmaz. Bu nedenle, bir kaynak içi yapıya sahip bir kaynak dizin için kaynak dışı bir yapı oluşturamazsınız . Bunu CMakeCache.txt, kaynak dizinden (en azından) kaldırarak oldukça kolay bir şekilde düzeltebilirsiniz . CMakeFilesCMake'nin oluşturduğu ve sizin de kaldırmanız gereken birkaç başka dosya (çoğunlukla dizinde) vardır, ancak bunlar cmake'nin kaynak ağacını bir yapı ağacı olarak görmesine neden olmaz.

Kaynak dışı derlemeler genellikle kaynak içi derlemelerden daha cazip olduğundan, cmake'nizi kaynak dışı derlemeler gerektirecek şekilde değiştirmek isteyebilirsiniz:

# 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."
)

Yukarıdaki makro, yaygın olarak kullanılan bir modülden gelir MacroOutOfSourceBuild. MacroOutOfSourceBuild.cmakeGoogle'da çok sayıda kaynak var, ancak orijinalini bulamıyorum ve buraya tam olarak dahil edilecek kadar kısa.

Ne yazık ki cmake, makro çağrıldığında genellikle birkaç dosya yazmıştır, bu nedenle yapıyı fiilen gerçekleştirmenizi engelleyecek olsa da, yine de silmeniz gerekir CMakeCache.txtve CMakeFiles.

İkili dosyaların, paylaşılan ve statik kitaplıkların yazılacağı yolları ayarlamayı yararlı bulabilirsiniz - bu durumda cmake çıktısını bir 'bin' dizinine nasıl yapabilirim? (feragatname, bu soruya en çok oylanan cevaba sahibim ... ama ben bunu böyle biliyorum).


Aslında kaynak klasörü ayarlamaktır -Sdeğil-H
smac89

@ smac89 Teşekkürler! Görünüşe göre bunları 3.13'te belgelemişler - Yanıtı modern CMake'yi yansıtacak şekilde güncelledim.
Adam Bowen

8

Yorumumu bir cevaba dönüştürmek:

Birinin yaptığımı yapması durumunda, tüm yapı dosyalarını kaynak dizine koymakla başlamıştım:

cd src
cmake .

cmake inşa dosya ve önbellek dosyaları (bir demet koyacağız CMakeCache.txt, CMakeFiles, cmake_install.cmakeiçinde, vs) srcdir.

Kaynak dışı bir yapıya geçmek için tüm bu dosyaları kaldırmam gerekti. O zaman @Angew'in cevabında önerdiği şeyi yapabilirdim:

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

7

CMake Wiki itibariyle :

CMAKE_BINARY_DIR eğer kaynak içi derliyorsanız, bu CMAKE_SOURCE_DIR ile aynıdır, aksi takdirde bu, derleme ağacınızın en üst düzey dizini olur

Kaynak dışı derlemenin başlatılıp başlatılmadığını belirlemek için bu iki değişkeni karşılaştırın


6

Betiğinizde sabit kodlanmış bir derleme dizin adına güvenmemelisiniz, bu nedenle ile satırın ../Compiledeğiştirilmesi gerekir.

Çünkü nerede derleneceği kullanıcıya bağlı olmalıdır.

Bunun yerine önceden tanımlanmış değişkenlerden birini kullanın: http://www.cmake.org/Wiki/CMake_Useful_Variables (arayın CMAKE_BINARY_DIRve CMAKE_CURRENT_BINARY_DIR)


2
bu tam olarak aradığım şeydi - CMAKE_CURRENT_BINARY_DIRtipik olarak mevcut ikili yapı yolu hakkında bilgi verirdi. Muhtemelen bağımlı kitaplık / bin yapılarını ayarlamak için kullanılabilir.
parasrish
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.