C/C++ передача параметра через Makefile

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

C/C++ передача параметра через Makefile

Непрочитанное сообщение Olej » 24 июл 2021, 09:15

Параметры 2-мерного массива определяются через константы периода компиляции, типа такого:

Код: Выделить всё

#define N 4

const int R =32/N,     // бит на уровень
               L = 1<<R;   // число узлов в уровне
...
struct  RtNode{
...
private:
    void* node[N][L];
};
Это не важно что это и откуда ... 32 бит расщепляются на N равных частей, и создаётся массив node[N][L] (например node[4][256], или node[8][16]).
Хотелось бы, чтобы параметр N передавался из командной строки в make и через Makefile переходил в компилируемую единицу, создавая нужные размерности.

P.S. Конечно, можно бы в конструкторе класса RtNode создавать структуру массива node динамически, задавая его параметры в конструкторе, и тогда вообще решать вопрос размерности runtime, в период выполнения, а не компиляции... например, задавая, при необходимости, из командной строки запуска программы.
Но ...
1). это совсем элементарно в C++ (например vector vector void*), но несколько тягомутно в C, как названо в заголовке...
2). это не требуемое усложнение
3). ... да и просто в облом это делать :lol:

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C/C++ передача параметра через Makefile

Непрочитанное сообщение Olej » 24 июл 2021, 09:27

Olej писал(а):
24 июл 2021, 09:15
Хотелось бы, чтобы параметр N передавался из командной строки в make и через Makefile переходил в компилируемую единицу, создавая нужные размерности.
Делаем так:

Код: Выделить всё

#ifdef NUM                 // число уровней (2, 4, 8, 16)
#define N NUM  
#else
#define N 4    
#endif
...
А в Makefile:

Код: Выделить всё

...
%:      %.cc
        $(CXX) $< -D NUM=$(NUM) -o $@
...
Всё ОК, задача собирается под разные размерности!:

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/tree$ env | grep NUM

olej@nvme:~/2021/OWN_TEST.codes/tree$ export NUM=2; make tree++
g++ -Wall -pedantic -std=c++14 tree++.cc -D NUM=2 -o tree++

olej@nvme:~/2021/OWN_TEST.codes/tree$ env | grep NUM
NUM=2

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/tree$ make clean
rm -f tree tree++

olej@nvme:~/2021/OWN_TEST.codes/tree$ export NUM=8; make tree++
g++ -Wall -pedantic -std=c++14 tree++.cc -D NUM=8 -o tree++

olej@nvme:~/2021/OWN_TEST.codes/tree$ env | grep NUM
NUM=8

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C/C++ передача параметра через Makefile

Непрочитанное сообщение Olej » 24 июл 2021, 09:32

Olej писал(а):
24 июл 2021, 09:27
Всё ОК, задача собирается под разные размерности!:
Но тут вылазит новая печалька - если make выполнять без явного указания NUM (дефаултное значение):

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/tree$ unset NUM

olej@nvme:~/2021/OWN_TEST.codes/tree$ env | grep NUM

olej@nvme:~/2021/OWN_TEST.codes/tree$ make clean
rm -f tree tree++

olej@nvme:~/2021/OWN_TEST.codes/tree$ make tree++
g++ -Wall -pedantic -std=c++14 tree++.cc -D NUM= -o tree++
tree++.cc:11:18: error: expected primary-expression before ‘,’ token
   11 | const int R =32/N,     // бит на уровень
      |                  ^
tree++.cc:53:19: error: ‘L’ was not declared in this scope
   53 |     void* node[N][L];
      |                   ^
...

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C/C++ передача параметра через Makefile

Непрочитанное сообщение Olej » 24 июл 2021, 09:37

Olej писал(а):
24 июл 2021, 09:32
Но тут вылазит новая печалька - если make выполнять без явного указания NUM (дефаултное значение):
Или ещё веселее так :lol: :

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/tree$ export NUM=zzz; make tree++
g++ -Wall -pedantic -std=c++14 tree++.cc -D NUM=zzz -o tree++
<command-line>: error: ‘zzz’ was not declared in this scope
tree++.cc:6:11: note: in expansion of macro ‘NUM’
    6 | #define N NUM
      |           ^~~
tree++.cc:11:17: note: in expansion of macro ‘N’
   11 | const int R =32/N,     // бит на уровень
      |                 ^
<command-line>: error: ‘zzz’ was not declared in this scope
tree++.cc:6:11: note: in expansion of macro ‘NUM’
    6 | #define N NUM
      |           ^~~
...
Т.е. нужно бы определить (для периода компиляции):
1). что NUM определено
2). что $NUM имеет значение
3). что это значение числовое (не 'zzz' ;-) )
4). желательно, что это значение >1 и <32 или из набора чисел: 2,4,8,16

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C/C++ передача параметра через Makefile

Непрочитанное сообщение Olej » 24 июл 2021, 09:58

Olej писал(а):
24 июл 2021, 09:37
Т.е. нужно бы определить (для периода компиляции):
И (предположительно) это можно сделать 2-мя совершенно разными способами:
1). проверять наличие переменной окружения NUM shell-командами в Makefile, и если нет передавать дефаултное значение
2). проверять переменную компиляции NUM непосредственно в C/C++ коде: определена ли? присвоено ли ей значение? числовое ли это значение? попадает ли оно в диапазон допустимых?

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C/C++ передача параметра через Makefile

Непрочитанное сообщение Olej » 24 июл 2021, 18:41

Olej писал(а):
24 июл 2021, 09:58
1). проверять наличие переменной окружения NUM shell-командами в Makefile, и если нет передавать дефаултное значение
Как 1-й вариант пригодный для тестирования....

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/tree$ cat Makefile 
TASK = tree tree++
NM = $(shell ./size)

CC += -Wall -pedantic -std=c99
CXX += -Wall -pedantic -std=c++14

all: $(TASK)

%:      %.c
	$(CC) $< -D NUM=$(NM) -o $@

%:      %.cc
	$(CXX) $< -D NUM=$(NM) -o $@

clean:
	rm -f $(TASK)

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/tree$ cat size 
#!/usr/bin/bash

isnumber()        # функция тестирования на числовое значение
{
    /bin/test $1 -eq $1 2>/dev/null
}

if [ -z ${NUM} ]; # значение не определялась
    then 
	NUM=4; 
	echo $NUM;
        exit
fi

if isnumber $NUM;
    then        # число но не нулевое
	if !(($NUM)); 
	    then NUM=4; 
	fi;
    else        # не число
	NUM=4; 
fi

echo $NUM
Всё это понадобилось для изменений размерностей при компиляции здесь: C & C++ : трансляция страниц.
Теперь можно по-быстрому компилировать под разные размерности:

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/tree$ export NUM=2; make clean; make
rm -f tree tree++
cc -Wall -pedantic -std=c99 tree.c -D NUM=2 -o tree
g++ -Wall -pedantic -std=c++14 tree++.cc -D NUM=2 -o tree++

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/tree$ export NUM=16; make clean; make
rm -f tree tree++
cc -Wall -pedantic -std=c99 tree.c -D NUM=16 -o tree
g++ -Wall -pedantic -std=c++14 tree++.cc -D NUM=16 -o tree++

Код: Выделить всё

 
olej@nvme:~/2021/OWN_TEST.codes/tree$ unset NUM; make clean; make
rm -f tree tree++
cc -Wall -pedantic -std=c99 tree.c -D NUM=4 -o tree
g++ -Wall -pedantic -std=c++14 tree++.cc -D NUM=4 -o tree++

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 5 гостей