Katalog wyjściowy / kompilacji CMake

116

Jestem całkiem nowy w CMake i przeczytałem kilka samouczków o tym, jak go używać, i napisałem kilka skomplikowanych 50 linii skryptu CMake, aby stworzyć program dla 3 różnych kompilatorów. To prawdopodobnie kończy całą moją wiedzę o CMake.

Teraz mój problem polega na tym, że mam kod źródłowy, którego folderu nie chcę dotykać / majstrować podczas tworzenia programu. Chcę, żeby wszystkie CMake i makepliki wyjściowe i foldery trafiały do ​​tego ../Compile/, więc zmieniłem kilka zmiennych w moim skrypcie CMake i działało to przez jakiś czas, kiedy zrobiłem coś takiego na moim laptopie:

Compile$ cmake ../src
Compile$ make

Gdzie z tym miałem czysty wynik w folderze, w którym teraz jestem, co jest dokładnie tym, czego szukam.

Teraz przeniosłem się na inny komputer i ponownie skompilowałem CMake 2.8.11.2 i prawie wracam do punktu wyjścia! Zawsze kompiluje to do srcfolderu, w którym CMakeLists.txtznajduje się my .

Część, w której wybieram katalog w moim skrypcie CMake, jest następująca:

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

A teraz zawsze kończy się na:

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

Czy coś mi brakuje?

Fizyk kwantowy
źródło
4
Nie ma potrzeby ustawiania wszystkich zmiennych, które ustawiasz. CMake ustawia je na rozsądne wartości domyślne. Zdecydowanie nie powinieneś modyfikować CMAKE_BINARY_DIRani CMAKE_CACHEFILE_DIR. Co się stanie, jeśli usuniesz wszystkie te set()połączenia i po prostu to zrobisz cd Compile; rm -rf *; cmake ../src?
Angew nie jest już dumny z SO
5
Zasadniczo, jeśli jesteś poza katalogiem źródłowym podczas uruchamiania CMake, nie zmodyfikuje katalogu źródłowego, chyba że CMakeList wyraźnie mu to nakazuje.
Angew nie jest już dumny z SO
@Angew Dziękuję za wskazówkę, co jest zaskakujące! Usunąłem wszystkie te linie i po prostu użyłem cmake ../src i zadziałało jak urok! Jest to tak zaskakujące, ponieważ próbowałem go wcześniej, kiedy po raz pierwszy uczyłem się CMake i nie działało. Proszę, umieść swoją odpowiedź w oficjalnej odpowiedzi, aby dać ci duży, gruby znacznik :)
The Quantum Physicist
1
To, co mnie uratowało, to uwaga @Adama Bowena, że ​​„nie można utworzyć kompilacji poza źródłem dla katalogu źródłowego z kompilacją w źródle”
Aur Saraf

Odpowiedzi:

60

Nie ma potrzeby ustawiania wszystkich zmiennych, które ustawiasz. CMake ustawia je na rozsądne wartości domyślne. Zdecydowanie nie powinieneś modyfikować CMAKE_BINARY_DIRaniCMAKE_CACHEFILE_DIR . Traktuj je jako tylko do odczytu.

Najpierw usuń istniejący problematyczny plik pamięci podręcznej z katalogu src:

cd src
rm CMakeCache.txt
cd ..

Następnie usuń wszystkie set()polecenia i wykonaj:

cd Compile
rm -rf *
cmake ../src

Dopóki jesteś poza katalogiem źródłowym podczas uruchamiania CMake, nie zmodyfikuje katalogu źródłowego, chyba że CMakeList wyraźnie tego nakazuje.

Gdy już to uruchomisz, możesz sprawdzić, gdzie CMake domyślnie umieszcza rzeczy i tylko jeśli nie jesteś zadowolony z domyślnych lokalizacji (takich jak domyślna wartość EXECUTABLE_OUTPUT_PATH), zmodyfikuj tylko te, których potrzebujesz. I starają się wyrazić je w stosunku do CMAKE_BINARY_DIR, CMAKE_CURRENT_BINARY_DIR, PROJECT_BINARY_DIRitd.

Jeśli spojrzysz na dokumentację CMake, zobaczysz zmienne podzielone na sekcje semantyczne. Z wyjątkiem bardzo szczególnych okoliczności, należy traktować wszystkie te wymienione w sekcji „Zmienne dostarczające informacji” jako tylko do odczytu wewnątrz CMakeLists.

Angew nie jest już dumny z SO
źródło
2
Zacząłem używać cmake z kompilacjami w katalogu src ... ta technika początkowo zawiodła. Po usunięciu wszystkich plików kompilacji / pamięci podręcznych cmake w katalogu src ta technika zadziałała. Dzięki!
Avi Tevet
18
Może lepiej nie radzić używać rm -rf *. Nie jest ładnie, jeśli cd Compilezawiedzie ...
Roman
2
@Roman Takie przykłady linii poleceń uważam za pseudokod. Jest to mniej szczegółowe i dokładniejsze niż wpisanie „wejdź do katalogu Compile, usuń tam wszystko, a następnie uruchom CMake ze ścieżką do katalogu źródłowego”. Zakładam podstawowy zdrowy rozsądek i osąd po części czytelnika.
Angew nie jest już dumny z SO
@AviTevet: Myślę, że to jest poprawna odpowiedź. Jeśli w katalogu źródłowym znajdują się pliki pamięci podręcznej cmake z poprzedniego wywołania cmake, nie otrzymasz polecenia cmake, aby wybrać inny katalog dla wygenerowanych plików, chyba że usuniesz wszystkie stare z katalogu źródłowego. Moim zdaniem dość zepsute zachowanie CMake. Dlaczego nie napiszesz innej odpowiedzi?
Jo So
113

Wygląda na to, że chcesz mieć kompilację poza źródłem . Istnieje kilka sposobów tworzenia kompilacji poza kodem źródłowym.

  1. Rób to, co robiłeś, uciekaj

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

    co spowoduje cmake do generowania drzewa kompilacji w /path/to/my/build/folderna drzewie źródłowym w/path/to/my/source/folder .

    Po utworzeniu cmake pamięta, gdzie jest folder źródłowy - możesz więc ponownie uruchomić cmake na drzewie kompilacji za pomocą

    cmake /path/to/my/build/folder

    lub nawet

    cmake .

    jeśli twój bieżący katalog jest już folderem kompilacji.

  2. W przypadku CMake 3.13 lub nowszego użyj tych opcji, aby ustawić foldery źródłowe i kompilacji

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
  3. W przypadku starszego CMake użyj nieudokumentowanych opcji, aby ustawić foldery źródłowe i kompilacji :

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

    który zrobi dokładnie to samo, co (1), ale bez polegania na bieżącym katalogu roboczym.

CMake domyślnie umieszcza wszystkie swoje dane wyjściowe w drzewie budowania , więc jeśli nie korzystasz zbytnio z plików cmake ${CMAKE_SOURCE_DIR}lub ${CMAKE_CURRENT_SOURCE_DIR}w swoich plikach cmake, nie powinien dotykać twojego drzewa źródłowego .

Największą rzeczą, która może się nie udać, jest to, że wcześniej wygenerowałeś drzewo budowania w swoim drzewie źródłowym (tj. Masz kompilację w źródle ). Gdy to zrobisz, zaczyna się druga część (1) powyżej, a cmake nie wprowadza żadnych zmian w źródle ani lokalizacjach kompilacji. Dlatego nie można utworzyć kompilacji poza źródłem dla katalogu źródłowego z kompilacją w źródle . Możesz to dość łatwo naprawić, usuwając (przynajmniej) CMakeCache.txtz katalogu źródłowego. Istnieje kilka innych plików (głównie w formacieCMakeFiles katalogu), które generuje CMake, które również powinieneś usunąć, ale to nie spowoduje, że cmake będzie traktował drzewo źródłowe jako drzewo budowania.

Ponieważ kompilacje poza źródłem są często bardziej pożądane niż kompilacje w źródle, możesz chcieć zmodyfikować swoje cmake, aby wymagało kompilacji spoza źródła:

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

Powyższe makro pochodzi z powszechnie używanego modułu o nazwie MacroOutOfSourceBuild. W Google jest wiele źródeł, MacroOutOfSourceBuild.cmakeale nie mogę znaleźć oryginału i jest wystarczająco krótki, aby go tu zamieścić w całości.

Niestety cmake zwykle zapisał kilka plików do czasu wywołania makra, więc chociaż uniemożliwi to wykonanie kompilacji, nadal będziesz musiał usunąć CMakeCache.txti CMakeFiles.

Przydatne może być ustawienie ścieżek, w których zapisywane są pliki binarne, biblioteki współdzielone i biblioteki statyczne - w takim przypadku zobacz, jak mogę umieścić dane wyjściowe cmake w katalogu „bin”? (zastrzeżenie, mam najlepszą głosowaną odpowiedź na to pytanie ... ale tak to wiem).

Adam Bowen
źródło
W rzeczywistości opcja ustawienia folderu źródłowego -Snie jest-H
smac89
@ smac89 Dzięki! Wygląda na to, że udokumentowali je w 3.13 - zaktualizowałem odpowiedź, aby odzwierciedlała współczesny CMake.
Adam Bowen
8

Zamieniam mój komentarz w odpowiedź:

Na wypadek, gdyby ktoś zrobił to, co ja, co rozpoczęło się od umieszczenia wszystkich plików kompilacji w katalogu źródłowym:

cd src
cmake .

CUpewnij będzie umieścić kilka plików budować i pliki pamięci podręcznej ( CMakeCache.txt, CMakeFiles, cmake_install.cmakeitp) w srcreż.

Aby zmienić na kompilację poza kodem, musiałem usunąć wszystkie te pliki. Wtedy mógłbym zrobić to, co @Angew zalecił w swojej odpowiedzi:

mkdir -p src/build
cd src/build
cmake ..
Avi Tevet
źródło
7

Od CMake Wiki :

CMAKE_BINARY_DIR, jeśli budujesz w źródle, jest to to samo, co CMAKE_SOURCE_DIR, w przeciwnym razie jest to katalog najwyższego poziomu twojego drzewa kompilacji

Porównaj te dwie zmienne, aby określić, czy została uruchomiona kompilacja poza źródłem

cholera
źródło
6

Nie powinieneś polegać na zakodowanej na stałe nazwie katalogu kompilacji w swoim skrypcie, więc wiersz z ../Compilemusi zostać zmieniony.

To dlatego, że od użytkownika powinno zależeć, gdzie skompilować.

Zamiast tego użyj jednej z predefiniowanych zmiennych: http://www.cmake.org/Wiki/CMake_Useful_Variables (poszukaj CMAKE_BINARY_DIRi CMAKE_CURRENT_BINARY_DIR)

Michał Walenciak
źródło
2
to jest dokładnie to, czego szukałem - CMAKE_CURRENT_BINARY_DIRzazwyczaj mówi o bieżącej ścieżce budowania binarnego. Prawdopodobnie może być użyty do ustawienia zależnych kompilacji libs / bin.
parasrish