CMake'de dizeler birden çok satıra nasıl bölünür?


98

Genelde projemde, metin dosyalarında 80 satır uzunluğunu aşan satırlar oluşturmama gibi bir politikam var, böylece her türden editörde kolayca düzenlenebilirler (anlaşmayı biliyorsunuz). Ancak CMake ile büyük bir çizgiden kaçınmak için basit bir dizgiyi birden fazla satıra nasıl böleceğimi bilmediğim problemini alıyorum. Şu temel kodu göz önünde bulundurun:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

Zaten 80 hat sınırını aştı. Öyleyse, CMake'deki bir satırı ayrıntıya girmeden birden çok satıra nasıl bölebilirim (çoklu list(APPEND ...)veya benzeri)?

Yanıtlar:


90

CMake 3.0 ve daha yenisi için güncelleme :

ile hat devamı mümkündür \. bkz. cmake-3.0-doc

message("\
This is the first line of a quoted argument. \
In fact it is the only line but since it is long \
the source code uses line continuation.\
")

CMake sürümlerinin kullanılabilirliği:

Debian Wheezy (2013):
2.8.9 Debian Wheezy-backports: 2.8.11
Debian Jessy (2015): 3.0.2
Ubuntu 14.04 (LTS): 2.8.12
Ubuntu 15.04: 3.0.2
Mac OSX: cmake-3 Homebrew aracılığıyla kullanılabilir , Macports ve Fink
Windows: cmake-3 Chocolatey aracılığıyla kullanılabilir


21
CMake 3.0 yaklaşımıyla ilgili sorun, girintiyi göz ardı etmemesidir. Bu, çok satırlı dizelerin kodun geri kalanıyla girintilenemeyeceği anlamına gelir.
void.pointer

@ void.pointer Aynı problemle karşılaştım, çoklu satır ile nasıl girinti yapılacağını buldunuz mu?
user3667089

Ayrıca, girinti kullanmak istiyorsanız ve 80 karakter sınırına bağlıysanız, başka bir yol da şudur: <code> message ("Bu, değişkenin değeridir:" <br> "$ {varValue}") </code>
munsingh

55

CMake 3.0 ve daha yeni

Şu string(CONCAT)komutu kullanın :

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
string(CONCAT MYPROJ_VERSION "${MYPROJ_VERSION_MAJOR}"
                             ".${MYPROJ_VERSION_MINOR}"
                             ".${MYPROJ_VERSION_PATCH}"
                             "-${MYPROJ_VERSION_EXTRA}")

CMake 3.0 ve daha yeni olanı, alıntılanan bağımsız değişkenlerin satır devamını desteklese de, dizenizde bulunan girinti boşluklarını almadan ikinci veya sonraki satırları girintileyemezsiniz.

CMake 2.8 ve üstü

Bir liste kullanabilirsiniz. Listenin her bir öğesi yeni bir satıra yerleştirilebilir:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION_LIST "${MYPROJ_VERSION_MAJOR}"
                        ".${MYPROJ_VERSION_MINOR}"
                        ".${MYPROJ_VERSION_PATCH}"
                        "-${MYPROJ_VERSION_EXTRA}")

Tırnak işaretleri olmadan kullanılan bir liste beyaz boşluk olmadan birleştirilir:

message(STATUS "Version: " ${MYPROJ_VERSION_LIST})
-- Version: 1.0.0-rc1

Gerçekten bir dizeye ihtiyacınız varsa, önce listeyi bir dizeye dönüştürebilirsiniz:

string(REPLACE ";" "" MYPROJ_VERSION "${MYPROJ_VERSION_LIST}")
message(STATUS "Version: ${MYPROJ_VERSION}")
-- Version: 1.0.0-rc1

Orijinal dizelerinizdeki herhangi bir noktalı virgül, liste öğesi ayırıcıları olarak görünecek ve kaldırılacaktır. Kaçmaları gerekir:

set(MY_LIST "Hello World "
            "with a \;semicolon")

1
Çok uzun satırlar için, değişken adından sonra gelen bir satırsonu bu kalıbı daha da iyileştirir (bu örnekte gereksizdir).
sage

Out merakı , o da yerde ters eğik çizgi gereken dizede o çift tırnak tahmin etmek doğru olacaktır ve bu yüzden herhangi bir ters eğik çizgiler ihtiyaç dizede bir karakter olarak görünmesini emin?
Jonathan Leffler

@JonathanLeffler Evet, kaçmaları gerek. Dil kuralları burada: cmake.org/cmake/help/latest/manual/… ama kafa karıştırıcı oluyor. Ayrıca bkz .: stackoverflow.com/a/40728463
Douglas Royds

9

Hala biraz ayrıntılı, ancak 80 karakter sınırı sizi gerçekten rahatsız ediyorsa, o zaman aynı değişkene art arda ekleyebilirsiniz:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION "${MYPROJ_VERSION_MAJOR}.")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_MINOR}.")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_PATCH}-")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_EXTRA}")
message(STATUS "version: ${MYPROJ_VERSION}")

Çıktı verir:

$ cmake  ~/project/tmp
-- version: 1.0.0-rc1
-- Configuring done
-- Generating done
-- Build files have been written to: /home/rsanderson/build/temp

7

CMakeLists.txt dosyalarında veya CMake komut dosyalarında bir dizeyi birden çok satıra bölmenin bir yolu yoktur. Bir dizgenin içine bir satırsonu eklerseniz, dizenin kendisinde gerçek bir satırsonu olacaktır.

# Don't do this, it won't work, MYPROJ_VERSION will contain newline characters:
set(MYPROJ_VERSION "${VERSION_MAJOR}.
  ${VERSION_MINOR}.${VERSION_PATCH}-
  ${VERSION_EXTRA}")

Ancak CMake, bağımsız değişkenleri ayırmak için beyaz boşluk kullanır, bu nedenle, bağımsız değişken ayırıcı olan bir boşluğu, davranışı değiştirmeden istediğiniz yerde yeni satıra değiştirebilirsiniz.

Bu uzun satırı yeniden ifade edebilirsiniz:

set(MYPROJ_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

bu iki kısa satır olarak:

set(MYPROJ_VERSION
  "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

Tamamen eşdeğerdirler.


6

Orijinal sorudaki örnek yalnızca nispeten kısa bir dizeyle ilgilidir. Daha uzun dizeler için (diğer cevaplarda verilen örnekler dahil), parantez argümanı daha iyi olabilir. Belgelerden:

Bir açma aparatı yazılır [sıfır, ardından ya da daha fazla =takip [. Karşılık gelen kapanış parantezi, ]ardından aynı sayıda ve =ardından yazılır ]. Parantezler iç içe geçmiyor. Açma ve kapama braketlerinin diğer uzunluklardaki kapatma braketlerini içermesi için her zaman benzersiz bir uzunluk seçilebilir.

[...]

Örneğin:

message([=[
This is the first line in a bracket argument with bracket length 1.
No \-escape sequences or ${variable} references are evaluated.
This is always one argument even though it contains a ; character.
The text does not end on a closing bracket of length 0 like ]].
It does end in a closing bracket of length 1.
]=])```

Bunu doğru anlarsam, kaynaktaki bir satır sonu da dizede bir satır sonu oluşturacaktır. Örneğin, "uzunluk 1" den sonra bir \ n olacaktır. Bundan kaçınmanın bir yolu var mı?
Lukas Schmelzeisen

Doğru, \ns olacak . Bunu istemiyorsan, parantez argümanlarının çözümün olduğunu düşünmüyorum.
ingomueller.net

BTW, 2.x değil 3.x sürümü için geçerlidir
Maxim Suslov

6

Buradan buraya getirilenler için Bir CMake jeneratör ifadesini birden çok satıra nasıl bölerim? Bazı notlar eklemek istiyorum.

Satır devam yöntemi çalışmaz, CMake boşluk (girinti) ve satır devamı ile yapılmış bir oluşturucu listesini ayrıştıramaz.

Dize (CONCAT) çözümü değerlendirilebilecek bir üretici ifadesi sağlarken, sonuç bir boşluk içeriyorsa değerlendirilen ifade tırnak içine alınacaktır.

Eklenecek her bir seçenek için ayrı bir jeneratör listesi oluşturulmalıdır, bu nedenle aşağıda yaptığım gibi istifleme seçenekleri yapının başarısız olmasına neden olacaktır:

string(CONCAT WARNING_OPTIONS "$<"
    "$<OR:"
        "$<CXX_COMPILER_ID:MSVC>,"
        "$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>"
    ">:"
    "/D_CRT_SECURE_NO_WARNINGS "
">$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Wall -Werror "
">$<"
    "$<CXX_COMPILER_ID:GNU>:"
    "-Wno-multichar -Wno-sign-compare "
">")
add_compile_options(${WARNING_OPTIONS})

Bunun nedeni, sonuçtaki seçeneklerin derleyiciye tırnak içinde iletilmesidir.

/usr/lib64/ccache/c++  -DGTEST_CREATE_SHARED_LIBRARY=1 -Dgtest_EXPORTS -I../ThirdParty/googletest/googletest/include -I../ThirdParty/googletest/googletest -std=c++11 -fno-rtti -fno-exceptions -fPIC    -std=c++11 -fno-rtti -fno-exceptions -Wall -Wshadow -DGTEST_HAS_PTHREAD=1 -fexceptions -Wextra -Wno-unused-parameter -Wno-missing-field-initializers "-Wall -Werror -Wno-multichar -Wno-sign-compare " -fdiagnostics-color -MD -MT ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o -MF ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o.d -o ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o -c ../ThirdParty/googletest/googletest/src/gtest-all.cc
c++: error: unrecognized command line option ‘-Wall -Werror -Wno-multichar -Wno-sign-compare ’

Dize (CONCAT) çözümü kullanılarak temsil edilen uzun oluşturucu ifadelerini değerlendirmek için, her bir oluşturucu ifadesi boşluk içermeyen tek bir seçenek olarak değerlendirilmelidir:

string(CONCAT WALL "$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Wall"
">")
string(CONCAT WERROR "$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Werror"
">")
message(STATUS "Warning Options: " ${WALL} ${WERROR})
add_compile_options(${WALL} ${WERROR})

Bu, yanıtını yayınladığım soruyla ilgisiz olabilir, maalesef yanıtladığım soru yanlış bir şekilde bu sorunun kopyası olarak işaretlendi.

Jeneratör listeleri dizgilerle aynı şekilde ele alınmaz ve ayrıştırılmaz ve bu nedenle, bir jeneratör listesini birden çok satıra bölmek için alınması gereken ek önlemler vardır.


Muhtemelen bu cevabın bir versiyonunu bağlantılı "kopya" üzerine yayınlamak faydalı olacaktır. Karşılaştığım zaman aradığım cevap buydu.
Keith Prussing

3

Kodunuzda iyi bir girinti sağlamak için, sadece yapacak kadar basit

message("These strings " "will all be "
        "concatenated. Don't forget "
        "your trailing spaces!")

Veya doğrudan bir dize oluşturun

string(CONCAT MYSTR "This and " "that "
                    "and me too!")

gibi Douglas'ın cevap kim daha fazla ayrıntı vardır. Ancak bunun temel noktayı özetleyebileceğini düşündüm.

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.