» »

[C++] Struktura projekta in dodajanje eksterne knjižnice

[C++] Struktura projekta in dodajanje eksterne knjižnice

i33a ::

Pozdravljeni,
izdelujem program v jeziku C++. Poleg moje kode potrebujem še hitro key-value podatkovno bazo (Odločil sem se za RocksDB).
Vso (mojo) kodo imam sedaj v enem direktoriju v različnih datotekah in zraven Makefile.
Sedaj bi rad uporabil RocksDB v moji kodi. Ker bi rad imel vse skupaj narejeno na način, da moj repozitorij lahko samo kloniram in compileam, vem da moram RocksDB kodo dodati v moj repozitorij.
Ne vem pa kam naj dodam (želel bi si imeli direktorij "dependencies")? Poleg tega ravno tako ne vem kaj naj dodam v moj Makefile, da bom lahko buildal oboje skupaj in se bo uspešno linkalo.

Hvala za pomoč in nasvete!

kow ::

RocksDB uporablja zlib, torej so imeli enak problem kot ti.

Zimonem ::

Narediš naprimer lib podirektorij
In ga referiraš z LDFLAGS v makefiletu. Ampak to je bolj za privat projekte.

i33a ::

Hvala obema za odgovor.

Vendar še vedno ne razumem kaj moram narediti.

@kow
Kaj je ta zlib? Ga lahko kako uporabim, da rešim moj problem?

@Zimonem
Ustvaril sem lib poddirektorij. Kaj vse moram kopirati tja? + Kaj so te LDFLAGS?
Projekt je bolj privat narave (sicer bo na githubu objavljena koda).. jih pa najbrž ne bo več kot 5 buildalo projekta.

kow ::

zlib je knjiznica za kompresijo, kar ni pomembno. Moja poanta je bila, da si lahko pogledas njihov makefile kako so oni resili enak problem (tudi oni so uporabili 3rd party knjiznice) kot ga imas ti. Ampak po zacetnem napisanem in dodatnih vprasanjih bo to prevelik zalogaj zate, vsaj zaenkrat.

Torej, prvo vprasanje je, ce imas rocksdb knjiznico downloadano/zbuildano oz. ce sploh razumes, kaj so include fajli, kaj staticna/dinamicna knjiznica ipd.

i33a ::

@kow
Aha, razumem zdaj (glede zlib).
Sem tudi našel, da v makefile-u downloadajo in buildajo knjižnico (link). Meni bi bilo za moje potrebe čisto uredu, če imam kopijo trenutne verzije RocksDB znotraj mojega repozitorija (kot ima recimo bitcoin v svojem repozitoriju tudi leveldb kodo).
Problem je le, ker imajo ti projekti veliko nekih knjižnic in zakomplicirane builde in se iz njih ne znajdem najboljše.

Recimo, da imam rocksdb knjižnico v lib poddirektoriju in jo zbuildam (make static_lib). Sedaj imam RocksDB executable datoteke in vse potrebno za uporabo.
V Readme piše, da je public interface (torej interface s katerim lahko uporavlja moja aplikacija) v /include/rocksdb.
Tu je kup header file-ov ki jih bom (po potrebi vključil) v mojo kodo.

Torej v kodo dodam npr. `#include "lib/include/rocksdb/c.h"`?

Statična knjižnica se linka s kodo v času prevajanja, dinamična pa v run-time.

kow ::

Moras lociti med izvorno kodo knjiznice in pa zbuildano executable kodo (knjiznico).

Jaz v startu ne bi kompliciral in bi samo enkrat zbuildal rocksDB staticno (kloniral njihov repo in pognal static library build), ter komital knjiznico ter headerje v svoj repozitorij.
Je v casu zacetnega razvoja potrebno syncati svojo aplikacijo z zadnjo verzijo rocksDB? Domnevam, da ni potrebe.

Zgodovina sprememb…

  • spremenil: kow ()

mn ::

Sicer ne vem kaj delaš in posledično ne vem kaj je najboljša rešitev zate.

Ena rešitev bi lahko bila tudi Conan. To je package manager za C++. Tako imaš v svojem repozitoriju tudi "recept" kako pridobiti rocksdb z interneta. Seveda pa potrebuješ conan na tisti mašini instaliran.

Potem si poglej še git submodules če ti reši tvoj problem:

https://git-scm.com/book/en/v2/Git-Tool...

Skoraj najboljša pa je verjetno ta, ki jo predlaa "kow" nad mano, torej zbildaj library, ter dodaj headerje in binarije v repository. To sicer ni "the right way" kako se dela stvari, ampak če je to nek hobi projekt bo čisto OK.

kow ::

mn je izjavil:

Sicer ne vem kaj delaš in posledično ne vem kaj je najboljša rešitev zate.

To. Pri razvoju programske opreme NI genericnega pravilnega pristopa, ampak je vse odvisno od konteksta.
Napisi kaj vec o projektu/teamu/cilju ipd, ce hoces cim boljse nasvete.

Zimonem ::

Če imaš zadevo na githubu kot os projekt. Ne prilagaj predkompajliranih knjižnic. Poglej si automake,configure, make. Bo trajalo nekaj časa. Ampak ostane znanje kako zastaviti os projekt. Slepo zaupanje v predkompajlirane knjižnice ne obstaja.
Za referenco pa vzameš lahko rocksdb example.

i33a ::

Hvala za predloge.

Najbrž bo za moj primer res najbolj uporabno, da kloniram in zbuildam rocksDB v mojem repozitoriju.
Conan bom pa pogledal bolj iz firbca :)
Git submodule mi bo pa najbrž tudi zelo prav prišel. Hvala!

Če commitam zbuildan static library v repozitorij to najbrž pomeni, da na drugi mašini (z npr. drugačno arhitekturo) ne bo delovalo ane?
V tem primeru bi raje dodal v repozitorij samo source kodo in dodal navodila za buildanje: 1.) Zbuildaj RocksDB 2.) Zbuildaj moj projekt

Gre se za nek projekt, kjer imamo velike količine podatkov in jih parsam v C++ ter shranjujem v Key-Value podatkovno bazo.
Nato bomo pa iz te baze (zaenkrat ne potrebujemo sprotnega vstavljanja novih podatkov) s pomočjo programa naredili neke analize itd.
Na projektu delam zaenkrat sam, se mi pa kasneje pridružita še eden ali dva sodelavca.
Verzija RocksDB niti ni tako pomembna (lahko ostane na trenutni skozi cel razvoj & mogoče tudi še dlje).

i33a ::

Če si za zgled vzamem rocksdv example in povedano zgoraj, si strukturo predstavljam nekako tako:

Datoteke:
MojProgram1.cpp
MojProgram1.hpp
MojProgram2.cpp
MojProgram2.hpp
makefile
lib/rocksdb (cel repozitorij)

Potem pa recimo v MojProgram.cpp

...
#include <lib/rocksdb/c.h>
...

int main()
{
 // USE RocksDB
}



V navodilih za build pa:
1.) cd lib && make static_lib
2.) cd .. && make

Sem pravilno razumel?

mn ::

OK, sklepam da tole ni hobi projekt.

Kako bi se jaz lotil / se lotevam.

Struktura datotek:
myproj/readme.md
myproj/CMakeLists.txt
myproj/src/MojProgram1.cpp
myproj/src/MojProgram1.hpp
myproj/src/MojProgram2.cpp
myproj/src/MojProgram2.hpp

myproj direktorij gre na git.

V nek ločen direktorij izven te potegni dol rocksDB in ga zbildaj. Proces dokumentiram v readme.md znotraj mojega projekta (myproj).

V "CMakeLists.txt" dodam include in binary direktorije od rocksDB. Glej, target_include_directories in target_link_libraries.

Potem s CMake narediš makefile in z makefilom binary. Ne makefile, ne binary ne gredo na git. V Readme.md dokumentiraš vse kar bo naslednji človek potreboval, da naredi build iz nule.

kow ::

i33a je izjavil:

Hvala!

Če commitam zbuildan static library v repozitorij to najbrž pomeni, da na drugi mašini (z npr. drugačno arhitekturo) ne bo delovalo ane?
V tem primeru bi raje dodal v repozitorij samo source kodo in dodal navodila za buildanje: 1.) Zbuildaj RocksDB 2.) Zbuildaj moj projekt


Drzi. Ce bos zbuildal linux x86_64, ne bo delalo na linuxih arm, ali pa windows/mac masini. Katere platforme targetiras na kratki rok?

i33a ::

Targetiram predvsem linux x86_64. Bilo pa bi super, če bi delalo tudi na mac mašinah.

kow ::

Na mac-ih nimam izkusenj. Sprasujem, ker je zgoraj omenil cmake, pa ce ne bos buildal windows se lahko uporabi verjetno izognes. Domnevam, da lahko uporabis linux toolchain. Ne vem pa zagotovo.

Zgodovina sprememb…

  • spremenil: kow ()

i33a ::

Res hvala vsem za pomoč! :)
Problema sicer še nisem uspel čisto rešiti.

Za test sem naredil tako:
Program.cpp
lib/rocksdb(cel repozitorij)

RocksDB sem uspešno zbuildal z `make static_lib`.

Nato pa sem po vzoru iz primerov na repozitoriju (link) includal recimo db.h
Zaradi strukture direktorijev torej:
#include "lib/rocksdb/include/rocksdb/db.h"


Ko pa sem pognal ukaz: `make program` pa mi prevajalnik javi sledečo napako:
g++     Program.cpp   -o Program
In file included from Program.cpp:10:
lib/rocksdb/include/rocksdb/db.h:18:10: fatal error: rocksdb/iterator.h: No such file or directory
   18 | #include "rocksdb/iterator.h"
      |          ^~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [<builtin>: Program] Error 1


Mi kdo zna pomagati?
Izgleda, da prevajalnik "želi", da bi bile vse poti navadene na nov način al kako?

Zimonem ::

V makefile imaš definirano -I..lib/rocksdb/include ??

i33a ::

program: program.o 
	g++ -std=c++17 program.o -o program

program.o: Program.cpp
	g++ -c -std=c++17 Program.cpp

Trenutno imamo to v makefile.
Kako moram includati rocksdv/include, da bo compiler imel vse datoteke?

Randomness ::

Namesto tega
#include "lib/rocksdb/include/rocksdb/db.h"
imej tako:
#include "rocksdb/db.h"

Potem pa prevajaj tako, kot je predlagal že Zimonem. Torej:
g++ -c -std=c++17 -I../lib/rocksdb/include ...

Zimonem ::

Predvsem se pa muči osnov vsaj make-a.
Še bolje pa celega toolchaina. Development mašine so ponavadi precej razsute zadeve, s kupom beta Ali nightly build knjižnic, programov ...
In kolaboracija brez ustreznega build-debug-release okolja zna biti nočna mora.
Boš sicer za osnove porabil , kak teden, ampak to se pozneje hitro vrne.

Najdi kak projekt na githubu , ki je na tvojo vižo in začni tam.

kow ::

Zimonem je izjavil:

Predvsem se pa muči osnov vsaj make-a.


To ni bil typo, a? :)

Ja, se splaca investirati cas.

i33a ::

Hvala vsem za pomoč. En dober tutorial od make-a, če bo kdo bral in bo rabil :)

Program se mi zdaj prevede, če dodam include.
Problem pa še vedno ni čisto rešen, saj se že pri enostavnem primeru it Githuba.
npr:
DB* db;
  Options options;
  // Optimize RocksDB. This is the easiest way to get RocksDB to perform well
  options.IncreaseParallelism();
  options.OptimizeLevelStyleCompaction();
  // create the DB if it's not already present
  options.create_if_missing = true;

  // open DB
  Status s = DB::Open(options, kDBPath, &db);
  assert(s.ok());


Prevajalnik vrže ven s sledečo napako:

g++ -c -std=c++17 -I ./lib/rocksdb/include/  Program.cpp -o program.o
g++ -std=c++17  program.o -o program
/usr/bin/ld: program.o: in function `main':
Program.cpp:(.text+0x66): undefined reference to `rocksdb::DBOptions::IncreaseParallelism(int)'
/usr/bin/ld: Program.cpp:(.text+0x80): undefined reference to `rocksdb::ColumnFamilyOptions::OptimizeLevelStyleCompaction(unsigned long)'
/usr/bin/ld: Program.cpp:(.text+0xae): undefined reference to `rocksdb::DB::Open(rocksdb::Options const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rocksdb::DB**)'
/usr/bin/ld: program.o: in function `rocksdb::Options::Options()':
Program.cpp:(.text._ZN7rocksdb7OptionsC2Ev[_ZN7rocksdb7OptionsC5Ev]+0x19): undefined reference to `rocksdb::DBOptions::DBOptions()'
/usr/bin/ld: Program.cpp:(.text._ZN7rocksdb7OptionsC2Ev[_ZN7rocksdb7OptionsC5Ev]+0x2b): undefined reference to `rocksdb::ColumnFamilyOptions::ColumnFamilyOptions()'
collect2: error: ld returned 1 exit status
make: *** [makefile:2: program] Error 1


Morda kdo ve kje je težava? Moram dodati še kakšen folder v include g++ ali je kje drugje problem?

i33a ::

V kolikor pa dodam v makefile še ./lib/rocksdb/librockdb.a
g++ -std=c++17  program.o ./lib/rocksdb/librocksdb.a  -o program

Pa dobim napako tipa:
usr/include/c++/9/thread:130: undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
make: *** [makefile:2: program] Error 1

DamijanD ::

Randomness ::

Naučiti se boš moral brati (in razumeti) ozozorila/napake.

undefined reference to `pthread_create' pomeni, da linker (ld) ne najde simbola (v tem primeru funkcije) pthread_create. Povedati ti želi, da moraš linkati tudi knjižnico libpthread. Pri prevajanju oz. linkanju (povezovanju se mi zdi, da je po slovensko), moraš torej podati opcijo -lpthread

i33a ::

Hvala vsem! :)
Sem rešil težave, sedaj pa naprej na učenje novih stvari:)

kow ::

Verjetno se splaca investirati nekaj casa v razumevanje kaj naredi: preprocessor, compilanje, linkanje.
Torej ZELO natancno razumeti kaj pomeni VSAKA beseda v error message-ih. Nobene potrebe ni bilo, da si prilepil izvorno kodo, ker je vse jasno iz errorja.

Zimonem ::

Pričakovat na slo-tech , da bo kdo zapakiral projekt v nekaj s čimer lahko kaj narediš je iluzorno. Vse je blazno skrivnostno in kriptično. Še pri Excelu. Potem pa namesto da bi čas za razlago ali vsaj izdelavo rešitve, vlagaš v vlečenje informacije iz ljudi.

Invictus ::

Raje vlagaj čas v RTFM in Google...
"Life is hard; it's even harder when you're stupid."

http://goo.gl/2YuS2x

Zimonem ::

Pri vsem skupaj smo prišli vbtemi nekako do te stopnje, kjer še Shellac nismo izrabili. Kaj šele kar make ponuja.
Pa akoravno je sam po sebi že v letih in se to kaže na vseh koncih, je še vedno standardno orodje, katerega praktično moraš poznat, če ne delaš zgolj prek idejev.

Zgodovina sprememb…

  • spremenilo: Zimonem ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[c++] auto

Oddelek: Programiranje
6765 (607) killa bee
»

Makefile in c++

Oddelek: Programiranje
253063 (2103) Looooooka
»

c++ vstavljanje knjižnice v kodo

Oddelek: Programiranje
161614 (1273) SasoS
»

program za programiranje v C in C++ ???

Oddelek: Programiranje
162989 (2757) jlpktnst
»

Mandrake 8.0 linux in c++

Oddelek: Programiranje
13980 (854) Senitel

Več podobnih tem