Plik Makefile i Biblioteki dynamiczne. Linux Ubuntu

Plik Makefile i Biblioteki dynamiczne. Linux Ubuntu
B8
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 4 lata
  • Postów:8
0

Cześć, właśnie uczę się pracować na Linuxie (Ubuntu) i chciałem skompilować program. Napisałem program w C który składa się z trzech plików. Plik główny main.c, nagłówkowy calc.h i plik z obliczeniami calc.c. Chciałbym stworzyć plik makefile, tak żeby pliki calc.h i calc.c kompilowały się do biblioteki dynamicznej która następnie powinna zostać podlinkowana podczas kompilacji pliku main.c. Na razie mój makefile wygląda tak:

Kopiuj
#include <stdio.h>
#include <stdlib.h>
 
#include "calc.h"
#include "calc.c"
 
int main()
{
int pick;
float a,b, result;
 
printf("====Pola Figur====\n");
printf("  \n");
printf("1. Pole prostokata\n");
printf("2. Pole kwadratu\n");
printf("3. Pole trojkata\n");
printf("4. Pole kola\n");
printf("  \n");
printf("Podaj wartosc: \n");
scanf("%d", &pick);
printf("  \n");
switch (pick){
case 1: 
printf("Wybrales pole prostokota. Wzor na pole prostokota to \"P=a*b\"\n");
printf("Podaj dlugosc boku a: ");
scanf("%f", &a);
printf("Podaj dlugosc boku b: ");
scanf("%f", &b);
result=rectangle(a,b);
printf("Pole prostokota wynosi: ");
printf("%f\n", result);
break;
 
case 2: 
printf("Wybrales pole kwadratu. Wzor na pole kwadratu to \"P=a*a\"\n");
printf("Podaj dlugosc boku a: ");
scanf("%f", &a);
result=square(a);
printf("Pole kwadratu wynosi: ");
printf("%f\n", result);
break;
 
case 3: 
printf("Wybrales pole trojkata. Wzor na pole trojkata to \"P=(a*h)/2\"\n");
printf("Podaj dlugosc boku a: ");
scanf("%f", &a);
printf("Podaj wysokosc trojkata: ");
scanf("%f", &b);
result=triangle(a,b);
printf("Pole trojkata wynosi: ");
printf("%f\n", result);
break;
 
case 4: 
printf("Wybrales pole kola. Wzor na pole kola to \"P=Pi*r^2\"\n");
printf("Podaj dlugosc promienia r: ");
scanf("%f", &a);
result=circle(a);
printf("Pole kola wynosi: ");
printf("%f\n", result);
break;
 
default: printf("Nie ma takiej opcji w menu");
}
 
 
return 0;
}

Plik main.c wygląda tak:

Kopiuj
#ifndef CALC_H
#define CALC_H
 
float rectangle(float a, float b);
float square(float a);
float triangle(float a, float b);
float circle(float a);
#endif

a plik calc.c tak:

Kopiuj
#include "calc.h"
#include <math.h>
 
float rectangle(float a, float b)
{
return a*b;
}
float square(float a)
{
return a*a;
}
float triangle(float a, float b)
{
return a*b*0.5;
}
float circle(float a)
{
return a*a*M_PI;
}

Napisałem do tego takiego makefile:

Kopiuj
CC = gcc
  
all: main.o libfigure.so
    $(CC) main.o -Wl,-rpath=. -L. -lfigure -o program 
  
main.o: main.c
    $(CC) main.c -c -o main.o
      
calc.o: calc.c
    $(CC) calc.c -c -o calc.o
     
libfigure.so: calc.o
    $(CC) -shared -fPIC calc.o

Wyskakuje mi taki komunikat: "Makefile:4: recipe for terget 'all' failed
make: *** [all] Error 1

edytowany 1x, ostatnio: kq
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0

Przecież dołączyłeś calc.c za pomocą #include to dołączasz go również poprzez bibliotekę WTF?


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
B8
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 4 lata
  • Postów:8
0

@_13th_Dragon: Ok, ale teraz jak usunełem #include "calc.c" to dalej mam taki sam błąd :(

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0

Najpierw sprawdź czy polecenia się kompilują poprawnie, czyli:
gcc calc.c -c -o calc.o
gcc main.c -c -o main.o
gcc -shared -fPIC calc.o -o libfigure.so
gcc main.o -Wl,-rpath=. -L. -lfigure -o program

nie podoba mi się libfigure && -lfigure


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
B8
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 4 lata
  • Postów:8
0

Storzyłem plik makefile jak powyżej i wyskakuje błąd makefile:1: *** brakujący separator. Stop.

06
Zrób wcięcia tabem
koszalek-opalek
  • Rejestracja:około 9 lat
  • Ostatnio:około 2 lata
0
believer88 napisał(a):

Storzyłem plik makefile jak powyżej i wyskakuje błąd makefile:1: *** brakujący separator. Stop.

Ale zanim stworzysz Makefile (może wstawiłbyś jego kod, bo inaczej nie pomożemy z Twoim brakującym separatorem), zrób to co napisał @_13th_Dragon -- i napisz, czy działa...

PS. Jeśli plik jest taki jak powyżej, to nie będzie działał... :/ Bo @_13th_Dragon nie podał Ci nie Makefile'a lecz polecenia do wykonania -- a to nie to samo...

edytowany 2x, ostatnio: koszalek-opalek
JV
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 miesiące
  • Postów:242
0

$(CC) -c -o main.o - to nie zadziała bo brakuje nazwy z plikiem źródłowym. Możesz usunąć -o, kompilator sam zamieni rozszerzenie .c na .o. Poza tym trzeba stworzyć fałszywy target all bo takiego pliku nigdzie nie tworzysz. To może wyglądać mniej więcej tak:

Kopiuj
.PHONY: all clear
all: main

main: main.o libfigure.so
    $(CC) ...
edytowany 1x, ostatnio: jvoytech
B8
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 4 lata
  • Postów:8
0

@_13th_Dragon: Po wpisaniu dwóch pierwszych poleceń powstały kolejno pliki calc.o i main.o. po trzeciej komendzie dostałem komunikat cannot find -libfigure.so collect2: error: ld returned 1 exit status. Po ostatniej komendzie dostałem komunikat gcc: error: _WI,: Nie ma takiego pliku ani katalogu gcc: error: unrecognized command line option '-rpath=."

B8
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 4 lata
  • Postów:8
0

@jvoytech: czyli mam usunąć moje polecenie all i wpisać to co ty proponujesz?

several
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 6 godzin
1

libfigure.so: calc.o
$(CC) -shared -fPIC calc.o

O nie nie, to pliki .o, które mają składać się na .so muszą być skompilowane z -fPIC. Żeby skompilować to w jednej linijce piszesz coś takiego

Kopiuj
gcc -shared -o libhello.so -fPIC hello.c

Jak chcesz Makefile to będzie jakoś tak

Kopiuj
$(BUILD)/libhello.so: $(OBJ_DIR)/libhello.o
	@$(CXX) -o $@ $^ -shared
	@echo "$<"

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
	@$(CXX) -c -fPIC $^ -o $@ 
	@echo "$<"

EDIT
A budowanie .so nie dodajesz jako zależności w recepcie do aplikacji tylko do all, a w binarce tylko linkujesz, czy w sumie wychodzi jakoś tak

Kopiuj
.PHONY: all

all: $(BUILD)/libhello.so $(BUILD)/program

$(BUILD)/program: $(OBJ_DIR)/main.o
	@$(CXX) -o $@ $^ -L$(BUILD)/ -l:libhello.so -pthread
	@echo "$<"

$(BUILD)/libhello.so: $(OBJ_DIR)/libhello.o
	@$(CXX) -o $@ $^ -shared
	@echo "$<"

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
	@$(CXX) -c -fPIC $^ -o $@ 
	@echo "$<"

Brakuje tylko definicji ścieżek i CXX. Aa, no i main.o zbuduje Ci się z fPIC, ale to to już sobie sam poprawisz.


edytowany 2x, ostatnio: several
JV
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 miesiące
  • Postów:242
1

@believer88:

believer88 napisał(a):

@jvoytech: czyli mam usunąć moje polecenie all i wpisać to co ty proponujesz?

ty budujesz plik wykonywalny program, więc bazowy szkielet wygląda tak:

Kopiuj
.PHONY: all
all: program

program: main.o plik1.o plik2.o ...
    $(CC) -o program main.o plik1.o plik2.o

target all to taki ogólnie przyjęty standard, ale musi on zostać oznaczony .PHONY bo make zakłada, że plik all powstanie w wyniku działania tego przepisu, a tak nie jest.

Post wyżej @several zastosował zmienne automatyczne $@ $^, które zastępują nazwę celu i składników, pozwalając na zwięzłe pisanie Makefile, ale początkującego może trochę przerazić. Jakbym chciał je użyć to wyglądało by to tak:

Kopiuj
program: main.o plik1.o plik2.o ...
    $(CC) -o $@  $^

ponieważ $@ to jest cel działania przepisu, a $^ wszystkie składniki od których zależy "target". $^ stosuje się przede wszystkim w linkerze. Przy kompilacji zazwyczaj potrzebujesz pierwszego składnika (*.c) i możesz zastąpić go $<, np:

Kopiuj
main.o: main.c plik1.h plik2.h ...
    $(CC) -c main.c

zastąpiłbym tym:

Kopiuj
main.o: main.c plik1.h plik2.h ...
    $(CC) -c $<

$< oznacza pierwszy składnik, czyli main.c

Przy bardziej zaawansowanych Makefile nie dodaje się zależności od plików nagłówkowych bo przy dodaniu/odjęciu nagłówka w pliku źródłowym (#include "plik1.h") należałoby zmodyfikować Makefile, a to może szybko stać się źródłem problemów, gdy się o tym zapomni. Do automatyzacji tej czynności uruchamia się kompilator z odpowiednimi parametrami (gcc -MM -MMD), który generuje pliki z zależnościami *.d, które dołącza się w Makefile (include).

edytowany 1x, ostatnio: jvoytech
BG
  • Rejestracja:prawie 6 lat
  • Ostatnio:około 15 godzin
  • Postów:289
1

Jeśli nie musisz sam pisać Makefile, to możesz rozważyć użycie CMake

Do pliku CMakeLists.txt wrzuć coś takiego:

Kopiuj
cmake_minimum_required (VERSION 3.1) 
project (CALC) 

set ( SOURCES main.c )     # można wymienić więcej plików z "głównego" projektu rozdzielając je spacjami
set ( LIB_SOURCES calc.c ) # j.w. jeśli biblioteka ma składać się z wielu plików

add_compile_options( -Wall -Wextra )   # czy co tam lubisz...

add_executable(main ${SOURCES} )
add_library (calc SHARED ${LIB_SOURCES} )

target_link_libraries (main calc)

Potem w katalogu projektu:

Kopiuj
mkdir build
cd build
cmake ..
VERBOSE=1 make

Do polecenia cmake możesz dodać opcję -DCMAKE_BUILD_TYPE=Release albo -DCMAKE_BUILD_TYPE=Debug

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)