Mi az a 'cmake'?

 ( NevemTeve | 2014. szeptember 3., szerda - 10:05 )

Ez most nem költői kérdés, a mysql fordításához kellene, amihez először őt magát is szeretném lefordítani (persze nem megy, naná). Továbbá szeretném tudni, hogy mi is ez? Mármint nem a marketing szöveget, hanem az effektív információt; úgy értem a leírásokat, hogy ez a 'configure' kiváltója akar lenni, de úgy tűnik (legalábbis abból, hogy a saját fordításhoz önmagát is haszálja), hogy a make feladatát is átveszi, illetve abba is belekavar.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Egy Makefile generátor, a célja ugyanaz, mint az autoconf-automake párosnak, csak egy kicsit újabb, meg szerintem sokkal jobb. CMakeLists.txt fileban van a buildhez szükséges info, ebből gyártódnak a végső Makefileok.
Alap használat pl.:

mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/opt/project ~/source/tree
make
make install

ccmake pedig egy egyszerű kis UI hozzá, ahol a CMake változók állapotait meg tudod nézni.

Köszi!
Eddig az volt a legtöbb, amit elértem a CMake fordításával, hogy összelinkelkelte saját temporális énjét az én LDFLAGS beállításaimmal, de azután a végleges verziót már a saját módján akarta csinálni (mert természetesen ő jobban tudja, hogy hogyan kell AIX-on linkelni, mi én), és persze az előállt program nem futtatható (a -Wl,-blibpath -t volt szíves elrontani, nem volt benne a /usr/local/lib)

Saját magát még sosem fordítottam vele :)

Annyival egészíteném ki, hogy tudtommal az egyetlen meta-project leíró tool, ami támogatja a cross platform és multi target fordítást.

Az ötlet az, hogy leírod a projectedet CMake-ben, és innentől ő legenerálja a megfelelő projectfileokat minden platformra. Legyen az GNU Make alapú gcc, Visual Studio gmake, Visual Studio Solution, vagy amit akarsz, körülbelül minden fordítót és compiler-t ismer. Amit nem, azt Te beleintegrálhatod.

És undorító szintaxist használ.

Ha amúgy valaki CMake expertnek érzi magát, szóljon, mert keresünk kollegát ilyen profillal. Jó fizetés, Írország, fürdőskurvák, eső.

"És undorító szintaxist használ."
De legalább csak egyet, ellentétben az autotools-szal.
Másik nagy előnyének szokták mondani, hogy az autotools nagy része alatt csomó interpretálás után egy bash script fut, ami posix rendszereken se gyors, de windowson borzalmas lassú, a cmake meg egy bináris. Meg állítólag figyelnek a visszafele kompatibilitásra, ellentétben az autotools-szal.
Sajnos nem nagyon ismerem amúgy, de az autotools miatt szívtam elég sokat, annál szerintem bármi jobb.

Annó használtam cmake-t, nekem annyi maradt meg belőle hogy korábban fél órát kellett várnom a forgatásra ha módosítottam 1 fájlt, cmake-el pedig csak azt az 1 fájlt forgatta le újra ami módosult, így kb fél perc volt az újraforgatás. Persze ez debianon volt, de gyanítom itt is ugyanazt fogja tudni (de fixme ha nem).

Mondjuk ezt a sima make is tudja, ha rendesen be van lőve. (ugyebár ha headert módosítasz, az sokmindent magával ránthat persze)

Off: itt van egy hasznos doksi make ügyben: http://aegis.sourceforge.net/auug97.pdf

On: egy újabb nekifutásnál kevesebbre jutottam, mint az előbb, ennél a lépésnél fagy jéggé:

+ /usr/local/src/cmake-3.0.1/Bootstrap.cmk/cmake /usr/local/src/cmake-3.0.1 \
-C/usr/local/src/cmake-3.0.1/Bootstrap.cmk/InitialCacheFlags.cmake \
-GUnix Makefiles -DCMAKE_BOOTSTRAP=1 \
-DCMAKE_VERBOSE_MAKEFILE=1 \
-DCMAKE_USE_SYSTEM_LIBRARY_CURL=1 -DCMAKE_USE_SYSTEM_LIBRARY_EXPAT=1 -DCMAKE_USE_SYSTEM_LIBRARY_ZLIB=1 -DCMAKE_USE_SYSTEM_LIBRARY_BZIP2=1
loading initial cache file /usr/local/src/cmake-3.0.1/Bootstrap.cmk/InitialCacheFlags.cmake

Eddig jutottunk a debuggal:

Source/cmakemain.cxx:317       int res = cm.Run(args, view_only);
CMake Error: Could not create named generator Unix

így kellene tesztelni:

gdb Bootstrap.cmk/cmake
break cmakemain.cxx:317
break cmake.cxx:799
run /usr/local/src/cmake-3.0.1 -C/usr/local/src/cmake-3.0.1/Bootstrap.cmk/InitialCacheFlags.cmake -GUnix Makefiles -DCMAKE_BOOTSTRAP=1 -DCMAKE_VERBOSE_MAKEFILE=1 -DCMAKE_USE_SYSTEM_LIBRARY_CURL=1 -DCMAKE_USE_SYSTEM_LIBRARY_EXPAT=1 -DCMAKE_USE_SYSTEM_LIBRARY_ZLIB=1 -DCMAKE_USE_SYSTEM_LIBRARY_BZIP2=1

1. meglátás: abszolút PATH-névvel futtassuk, ne relatívval:

volt: Bootstrap.cmk/cmake
lett: $(pwd)/Bootstrap.cmk/cmake

Most már elárulhatom, a sok zavaró tényező egyike az volt, hogy a -GUnix Makefiles az igazából -G'Unix Makefiles', vagyis a vidám fiúk szóközt taralmazó fájlnevet bírtak létrehozni. Ezek után azon se csodálkoznék, ha megtudnám, hogy házioltárt emeltek BG tiszteletére, és az előtt szoktak kakast áldozni.

jol elhuzodott a debugging :-)

-------------------------
Roses are red
Violets are blue
Unexpected '}' on line 32

De legalább meglett a hiba! És a kitartás egy új dimenziójával ismerkedhedtünk meg.... :)

+1, néha azon gondolkodom, hogy most vagy ő a nem normális vagy én. :D :D

A jegyzőkönyv kedvéért: lámafalva kis lakói (értsd: a cmake 'bootstrap' scriptjének tudós összeállítói) nem hallottak még a CPPFLAGS-ról, tehát ha a large-file-support-ra vonatkozó opciók sem jutottak el a g++ -hoz. Gáz.

...
export CFLAGS="$CFLAGS $CPPFLAGS"
export CXXFLAGS="$CXXFLAGS $CPPFLAGS"
...
./bootstrap ...

Igazából a CPPFLAGS a C PreProcessor flagjainek a változója. Bár ettől még nem kéne figyelmen kívül hagynia a cmake-nek.

+1

Na, egynapos szenvedés árán rájöttem, hogy ezt a parancsot kellene kivizsgálni, miért esik végetlen ciklusba:

/usr/local/src/cmake-3.0.1/Bootstrap.cmk/cmake \
  /usr/local/src/cmake-3.0.1 \
  -C/usr/local/src/cmake-3.0.1/Bootstrap.cmk\
  /InitialCacheFlags.cmake\
  -G"Unix Makefiles"\
  -DCMAKE_BOOTSTRAP=1\
  -DCMAKE_VERBOSE_MAKEFILE=1\
  -DCMAKE_USE_SYSTEM_LIBRARY_CURL=1\
  -DCMAKE_USE_SYSTEM_LIBRARY_EXPAT=1\
  -DCMAKE_USE_SYSTEM_LIBRARY_ZLIB=1\
  -DCMAKE_USE_SYSTEM_LIBRARY_BZIP2=1

(a gond az volt, hogy a logban úgy látszott, hogy -GUnix Makefile van a parancsban, tehát szétesett a parancs...

truss szerint ilyesmi a vége:

6422708: 24445123: kopen("/usr/local/src/cmake-3.0.1/CMakeFiles/CMakeTmp/CheckIncludeFile.cxx.tmp", O_RDONLY|O_LARGEFILE) = 3
6422708: 24445123: kioctl(3, 22528, 0x00000000, 0x00000000) Err#25 ENOTTY
6422708: 24445123: unlink("/usr/local/src/cmake-3.0.1/CMakeFiles/CMakeTmp/CheckIncludeFile.cxx") = 0
6422708: 24445123: kopen("/usr/local/src/cmake-3.0.1/CMakeFiles/CMakeTmp/CheckIncludeFile.cxx", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) = 4
6422708: 24445123: kioctl(4, 22528, 0x00000000, 0x00000000) Err#25 ENOTTY
6422708: 24445123: kread(3, " # i n c l u d e   < i o".., 4096) = 48
6422708: 24445123: kread(3, "   w a r n i n g ,   i f".., 4048) = 0

Vagyis mintha az end-of-file már egy túl bonyolult jelenség lenne, amit csak végtelen ciklussal lehet elviselhetővé tenni...

Ilyesmit ír a gdb utolsó erejével:

2137      while(fin)
2138        {
2139        fin.read(buffer, bufferSize);
2140        if(fin.gcount())
2141          {
2142          fout.write(buffer, fin.gcount());
2143          }
2144        }

Namostan ez tényleg lehet egy file-másolás, de vajon mi a gond?
Mondjuk egy kicsit korábban egy érdekes komment van:

  // This copy loop is very sensitive on certain platforms with
  // slightly broken stream libraries (like HPUX).  Normally, it is
  // incorrect to not check the error condition on the fin.read()
  // before using the data, but the fin.gcount() will be zero if an
  // error occurred.  Therefore, the loop should be safe everywhere.

(Off: kb 25 éve mondogatom, hogy a C++ egyelőre kiforratlan, experimentális termék, komoly munkára ne használjuk, de figyel rám valaki?! Naná, hogy nem.)

De bakker az eof sok mindennek nevezhető, de hibának nem. Az más kérdés, hogy ha tovább erőltetem azt a rohadt read-et, onnantól már persze hibát kap, persze hogy mi lesz a gcount-ban, arról halvány dunsztom nincs. Mondjuk naívan azt mondanám, hogy akkor is 0, de azt azért nem látom, hogy attól, hogy túlolvastam a fájl végén, a fin mitől válna 0-vá - lévén én fenti részletben nem a fin-gcount, hanem a fin alapú ciklust látok. Szóval vagy én vagyok totál hülye (ez azért nem kizárt), vagy programozó úr rontott el valamit - vagy csak simán félreértem azt a kódrészletet.
Szerk: a 4. lehetőség a megoldás: tényleg 0-vá válik a fin, ha elérte az eof-ot. azannya cxx.

No, nézem tovább, hátha a debugkiíratások elárulnak valamit...
Ez most keményebbnek látszik, mint az eddigiek, például azért, mert nem mindig ugyanaz a hibajelenség, ennél a végtelen ciklusnál jutott már messzebb is...

Úgy látom, olyan van itt, hogy 'make clean', de olyan nincs 'make distclean', és úgy tűnik, egyes generált komponensek túlélik a 'make clean'-t.

Most éppen itt tartunk:

cmCacheManager.cxx:LoadCache függvény olvassa a 'CMakeCache.txt' fájlt, aminek ilyen a vége:

//Test curl_cv_recv
curl_cv_recv:INTERNAL=1
//Test curl_cv_send
curl_cv_send:INTERNAL=1
//Test run_pic_test
run_pic_test:INTERNAL=1

és ebből ilyesmi fakad:

Debug cmCacheManager.LoadCache.264: line='curl_cv_send:INTERNAL=1' line[0]=63
fin.good()=1 fin.eof()=0 (bool)fin=1 fin.gcount=24
Filename=/usr/local/src/cmake-3.0.1/CMakeCache.txt

Debug cmCacheManager.LoadCache.231: line='//Test run_pic_test' line[0]=2f
fin.good()=1 fin.eof()=0 (bool)fin=1 fin.gcount=20
Filename=/usr/local/src/cmake-3.0.1/CMakeCache.txt

Debug cmCacheManager.LoadCache.264: line='run_pic_test:INTERNAL=1' line[0]=72
fin.good()=1 fin.eof()=0 (bool)fin=1 fin.gcount=24
Filename=/usr/local/src/cmake-3.0.1/CMakeCache.txt

Debug cmCacheManager.LoadCache.231: line='' line[0]=00
fin.good()=1 fin.eof()=0 (bool)fin=1 fin.gcount=1
Filename=/usr/local/src/cmake-3.0.1/CMakeCache.txt

Debug cmCacheManager.LoadCache.231: line='' line[0]=00
fin.good()=1 fin.eof()=0 (bool)fin=1 fin.gcount=0
Filename=/usr/local/src/cmake-3.0.1/CMakeCache.txt

Na itt egy tesztprogram, ami nekem nagyon másképp megy linuxon, mint AIX-ben...

http://web.axelero.hu/lzsiga/ifstreamtest.cc

mondhatni AIX-on a második olvasási módszer végtelen ciklust generál, az elsőnél meg az 'iostate' állítása problémás nekem...

Ilyenek vannak nekem telepítve:

libstdc++-4.6.4-1.aix6.1.ppc.rpm
libstdc++-devel-4.6.4-1.aix6.1.ppc.rpm

A jelenség egyforma 32/64 biten, AIX-oslevel=6.1.0.0

while (is) {
getline (is,line);
cout << line << '\n';
}

http://www.cplusplus.com/reference/ios/ios/operator_bool/

Returns whether an error flag is set (either failbit or badbit).
Notice that this function does not return the same as member good, but the opposite of member fail.

Azaz eof esetén, ha olvasási hiba amúgy tulajdonképpen nincs, ez a while elvileg örökké fut. Ennek fényében nekem az meglepő, hogy linuxon nem kapsz végtelen ciklust, de gondolom van rá valami logikus magyarázat.

EOF esetén is kilép (egyébként nem éppen elegáns módszer, bár TurboPascal-ban tényleg így szoktuk: előrször EOF-ellenőrzés, aztán olvasás -- mert ott az EOF-ellenőrzés tartalmazta a bufferbe olvasást)

Magam sem értem egészen, amit most mondani akarok, de azért a jegyzőkönyv kedvéért:

a fordító szerint az 'ifstream' és az 'ios_base' között 280 byte a különbség, a debugger és libstdc++ szerint 224...

Najó, kicsit pontosabban:

compiler (printf)
'is'                                    is at ffffffffffff210
'is._M_filebuf'                         is at ffffffffffff220 [264]
'is._M_filebuf._M_buf_locale'           is at ffffffffffff258 [8]
'is._M_filebuf._M_lock'                 is at ffffffffffff260 [64]
'is._M_filebuf._M_file'                 is at ffffffffffff2a0 [16]
'is._M_filebuf._M_buf'                  is at ffffffffffff2d0 [8]
'(ios_base *)&is'                       is at ffffffffffff328
'is._M_streamstate'                     is at ffffffffffff348

debugger
p/x &is
$1 = 0xffffffffffff210

p/x (ios_base *)&is
warning: RTTI symbol not found for class 'std::basic_ifstream >'
$2 = 0xffffffffffff2f0

(gdb) print sizeof(is._M_filebuf)
$3 = 208

(gdb) p/x &is._M_filebuf._M_buf_locale
$1 = 0xffffffffffff258

(gdb) p &is._M_filebuf._M_lock
$1 = (__c_lock *) 0xffffffffffff260

(gdb) p sizeof (is._M_filebuf._M_lock)
$2 = 4

(gdb) p &is._M_filebuf._M_file
$1 = (struct __basic_file *) 0xffffffffffff268

(gdb) print &is._M_filebuf._M_buf
$1 = (char **) 0xffffffffffff298

(gdb) p/x &is->_M_streambuf_state
warning: RTTI symbol not found for class 'std::basic_ifstream >'
warning: RTTI symbol not found for class 'std::basic_ifstream >'
warning: RTTI symbol not found for class 'std::basic_ifstream >'
$4 = 0xffffffffffff310

ebből a RTTI-t nem értem, de a címek közötti különbség zavar...

Szerk... Szóval a _M_filebuf mérete az egyik komponens szerint 208, a másik szerint 264.

Szerk^2: típusa a ' __filebuf_type', és a 'fstream' nevű hedaer teszi bele a a különböző osztályokba; mégpedig így typedef-eli:

typedef basic_filebuf __filebuf_type;

Szerk^3: hajlok arra, hogy _M_lock-ot is a hiba részesének tekintsem: az egyik komponens szerint 64 byte a mérete, a másik szerint csak 4

Na jó, az előző hozzászólás már teljesen elkopott a sok szerkesztgetéstől, akkor most itt tartunk:

fstream{.nincskiegészítés}:
...
  template
    class basic_filebuf : public basic_streambuf<_CharT, _Traits>
    {

      // Data Members:
      // MT lock inherited from libio or other low-level io library.
      __c_lock                  _M_lock;
...
}

Szerk: az a __c_lock pedig, tisztelettel mondva, ilyen:

typedef __gthread_mutex_t __c_lock;

Viszont a __gthread_mutex_t nem más, mint a 'pthread_mutex_t' és az 'int' valamelyike, fordítási opcióktól függően.

Annyi biztos, hogy a pthread_mutex_t ilyen:

typedef struct {
#ifdef __64BIT__
        long    __mt_word[8];  /* 64 byte*/
#else
        int     __mt_word[13]; /* 52 byte */
#endif /* __64BIT__ */
} pthread_mutex_t;

Szóval, a gond alapvetően ott van, hogy két libstdc++ van, ami a következő négy:

32-bit, pthread-nélkül (__gthread_mutex_t=int)
32-bit, pthread-dal (__gthread_mutex_t=pthread_mutex_t)
64-bit, pthread-nélkül (__gthread_mutex_t=int)
64-bit, pthread-dal (__gthread_mutex_t=pthread_mutex_t)

Namostan olyat én nem tudok csinálni, hogy egy kis ilyen, meg egy kis olyan, azután majd jól összelinkelünk valamit; tehát azt választom, hogy a pthread-ost nevezem ki alapértelmezettnek. (Ezt azzal fejezem ki, hogy a /usr/local/lib -be telepítem.)

(Márcsak azért is, mert én tulajdonképpen a tesztprogramban sem mondtam, hogy -pthread, legfeljebb annyit, hogy -D_THREAD_SAFE (szerk: és ez pont elég is a "gthr-default.h"-nak))

Akkor most 'egész jók' vagyunk, a 'teljesen jóhoz' az kellene, hogy a linkelésnél az én kis rögeszmém érvényesüljön, ne az övé.

Az övé ilyen (dump -H):

0      /usr/local/lib:/opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.6.4/pthread:/opt/freeware/lib/pthread:/opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.6.4:/opt/freeware/lib:/usr/lib:/lib
1                                    libcpotlas.so
2                                    libtrace_opendir.so
3                                    libexpat.so
4                                    libz.so
5                                    libbz2.so
6                                    libcurl.so
7                                    libstdc++.so
8                                    libgcc_s.a          shr.o
9                                    libpthreads.a       shr_comm.o
10                                   libpthreads.a       shr_xpg5.o
11                                   libc.a              shr.o
12                                   librtl.a            shr.o

Az enyémben ilyesmi lenne (egy másik programból idézve):

0      /usr/local/lib:/usr/lib:/lib
1      /usr/local/lib                libcrypto.so.1.0.1
2      /usr/local/lib                libcurl.so.4
3      /usr/local/lib                libgcc_s.a          shr.o
4      /usr/local/lib                libiconv.so.2
5      /usr/local/lib                libidn.so.11
6      /usr/local/lib                libintl.so.8
7      /usr/local/lib                libssl.so.1.0.1
8      /usr/local/lib                libz.so.1
9      /usr/local/lib                libcpotlas.so.1
10     /usr/lib                      libpthread.a        shr_xpg5.o
11     /usr/lib                      libc.a              shr.o

(pathnevek, verziószámok, katonás fegyelem;)

parancsolj:

0      /usr/local/lib:/usr/lib:/lib   
1      /usr/local/lib                libbz2.so.1
2      /usr/local/lib                libcrypto.so.1.0.1
3      /usr/local/lib                libcurl.so.4
4      /usr/local/lib                libexpat.so.1
5      /usr/local/lib                libgcc_s.a          shr.o
6      /usr/local/lib                libiconv.so.2
7      /usr/local/lib                libidn.so.11
8      /usr/local/lib                libintl.so.8
9      /usr/local/lib                libssl.so.1.0.1
10     /usr/local/lib                libstdc++.so.6
11     /usr/local/lib                libz.so.1
12     /usr/local/lib                libcpotlas.so.1
13     /usr/lib                      libpthreads.a       shr_comm.o
14     /usr/lib                      libpthreads.a       shr_xpg5.o
15     /usr/lib                      libc.a              shr.o

Csak úgy kíváncsacsiságból megkérdezném: elképzelhető, hogy a cmake és a libtool kizáró kapcsolatban vannak?