What is the difference between := and += in kernel Makefiles? - makefile

Are := and += same in Linux Kernel Makefiles and could be used interchangeably? If not, then what is the difference between the two ?

As others say, := is assignment.
But there's a fine difference between := and =. In most cases it doesn't matter, but it may make a big difference.
X = $(Y) defines X as a recursive variable, which is something like a C preprocessor macro.
Whenever X is referenced, the value of Y will be used.
The expansion happens when X is expanded. So you can define Y after you've defined X, and it's OK.
X := $(Y) defines X as a simple variable. This is more like a C assignment.
Now, Y is expanded at the time of definition, so changing it later will do nothing.
X += $(Y) appends to X, but keeps its type.
If X was previously defined with =, Y will not be expanded immediately. Same if X was never defined.
If X was previously defined with :=, Y will be expanded immediately.
You can try this exmaple makefile:
X = 1
Y = $(X)
Z := $(X)
X = 2
Y += $(X)
Z += $(X)
X = 3
test:
#echo "Y = $(Y)"
#echo "Z = $(Z)"
It prints
Y = 3 3
Z = 1 2

:= is similar to =, i. e it is an assignment.
+= is a concatenation-and-assignment operator.
Example:
VARIABLE := abc
# here VARIABLE is abc
VARIABLE := def
# VARIABLE is now def only!
VARIABLE_2 = abc
# VARIABLE_2 is now abc
VARIABLE_2 += def
# VARIABLE_2 is abc def

:= is assignment. += is concatenation. See here.

:= clears the previous value of the variable you are assigning to,whereas
+= adds (concatenates) to the variable
For eg, lets say CFLAGS has been set to -Wundef
If we do,
CFLAGS := -Wall
CFLAGS is set to '-Wall' now
If we do,
CFLAGS += -Wall
CFLAGS now becomes '-Wundef -Wall'
It is quite often used in Linux Makefiles.

Related

Disrepancy in results between OpenMP/OpenACC implementation and gcc/PGI compilers

I have a larger Fortran program that I am trying to convert so that the computationally intensive part will run on an NVidia GPU using OpenMP and/or OpenACC. During development I had some issues to understand how variables declared in a module can be used within subroutines that are executed on the GPU (and some of them also on the CPU). Therefore, I created a small example and worked on that, by experimenting and adding the corresponding OpenMP and OpenACC directives. I have included the three files that comprise my example at the end of this message.
Just as I thought that I had understood things and that my example program works, I noticed the following:
I compile the program with gcc 10.2 using the OpenMP directives:
gfortran -O3 -fopenmp -Wall -Wextra test_link.f90 parameters.f90 common_vars.f90 -o test_link
The results are as expected, i.e. all elements of array XMO are 1, of DCP are 2, of IS1 are 3 and of IS2 are 24.
I compile the program with PGI compiler 19.10 community edition using the OpenACC directives:
pgfortran -O4 -acc -ta=tesla,cc35 -Minfo=all,mp,accel -Mcuda=cuda10.0 test_link.f90 common_vars.f90 parameters.f90 -o test_link
The results are the same as above.
I compile the program with gcc 10.2 using the OpenACC directives:
gfortran -O3 -fopenacc -Wall -Wextra test_link.f90 parameters.f90 common_vars.f90 -o test_link
The results for arrays XMO, DCP and IS1 are correct, but all elements of IS2 are 0. It is easy to verify that variable NR has a value of 0 to get this result.
My understanding is that the OpenMP and OpenACC version of my example are equivalent, but I cannot figure out why the OpenACC version works only for the PGI compiler and not for gcc.
If possible, please provide solutions that do not require changes in the code but only in the directives. As I mentioned, my original code is much larger, contains many more module variables and calls many more subroutines in the code to be executed on the GPU. Changes in that code will be much more difficult to do and obviously I would prefer to do that only if really necessary.
Thank you in advance!
The files of my example follow.
File parameters.f90
MODULE PARAMETERS
IMPLICIT NONE
INTEGER, PARAMETER :: MAX_SOURCE_POSITIONS = 100
END MODULE PARAMETERS
File common_vars.f90
MODULE COMMON_VARS
USE PARAMETERS
IMPLICIT NONE
!$OMP DECLARE TARGET TO(NR)
INTEGER :: NR
!$ACC DECLARE COPYIN(NR)
END MODULE COMMON_VARS
File test_link.f90
SUBROUTINE TEST()
USE COMMON_VARS
IMPLICIT NONE
!$OMP DECLARE TARGET
!$ACC ROUTINE SEQ
INTEGER I
I = NR
END SUBROUTINE TEST
PROGRAM TEST_LINK
USE COMMON_VARS
USE PARAMETERS
IMPLICIT NONE
INTERFACE
SUBROUTINE TEST()
!$OMP DECLARE TARGET
!$ACC ROUTINE SEQ
END SUBROUTINE TEST
END INTERFACE
REAL :: XMO(MAX_SOURCE_POSITIONS), DCP(MAX_SOURCE_POSITIONS)
INTEGER :: IS1(MAX_SOURCE_POSITIONS), IS2(MAX_SOURCE_POSITIONS)
INTEGER :: X, Y, Z, MAX_X, MAX_Y, MAX_Z, ISOUR
MAX_X = 3
MAX_Y = 4
MAX_Z = 5
NR = 6
!$OMP TARGET UPDATE TO(NR)
!$OMP TARGET MAP(TOFROM:IS1,IS2,DCP,XMO)
!$OMP TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3)
!$ACC UPDATE DEVICE(NR)
!$ACC PARALLEL LOOP GANG WORKER COLLAPSE(3) INDEPENDENT &
!$ACC COPY(IS1,IS2,DCP,XMO)
DO X = 1, MAX_X
DO Y = 1, MAX_Y
DO Z = 1, MAX_Z
ISOUR = (X - 1)*MAX_Y*MAX_Z + (Y - 1)*MAX_Z + Z
XMO(ISOUR) = 1.0
DCP(ISOUR) = 2.0
IS1(ISOUR) = 3
IS2(ISOUR) = 4 * NR
CALL TEST()
ENDDO ! End of z loop
ENDDO ! End of y loop
ENDDO ! End of x loop
!$ACC END PARALLEL LOOP
!$OMP END TEAMS DISTRIBUTE PARALLEL DO
!$OMP END TARGET
DO X = 1, MAX_X
DO Y = 1, MAX_Y
DO Z = 1, MAX_Z
ISOUR = (X - 1)*MAX_Y*MAX_Z + (Y - 1)*MAX_Z + Z
WRITE(*, *) 'ISOUR = ', ISOUR, 'XMO = ', XMO(ISOUR), 'DCP = ', DCP(ISOUR), 'IS1 = ', IS1(ISOUR), 'IS2 = ', IS2(ISOUR)
ENDDO ! End of z loop
ENDDO ! End of y loop
ENDDO ! End of x loop
END PROGRAM TEST_LINK

Algol: correct syntax leads to problems in compilation?

Here is a relatively simple code for "Evaluation of pi using the Mid-ordinate Rule on a quadrant of circle with radius 2 units."
main.alg
BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;
FOR n BY interval TO upperlimit DO
sumy := 0.0;
FOR p BY 2 TO n+n-1 DO
x := p/n;
y := sqrt(4.0 - x**2);
sumy := sumy + y;
OD
pi := sumy * (2.0 / n);
print((n,pi))
OD
END
I'm getting the following errors:
a68g: syntax error: 1: possibly a missing or erroneous separator nearby.
sh-4.3$ a68g main.alg
13 sumy := sumy + y;
1
a68g: warning: 1: skipped superfluous semi-symbol.
15 pi := sumy * (2.0 / n);
1
a68g: syntax error: 1: possibly a missing or erroneous separator nearby.
Try it live here.
What am I doing wrong? How to correct it?
The short answer:
The following code has your specific problem fixed...
The thing to remember is that a ";" is a "statement separator"... so all "compound statement" should have each statement separated by a ";".. eg consider:
statement; statement; statement # is a valid program #
statement; statement statement; # is not valid #
(statement; statement; statement) # is a valid program #
(statement; statement; statement;) # is not valid #
(statement; statement; statement); # is not valid #
The moral is... separate all statements with a ";" and dont put a ";" after the last statement. (eg before an END, FI, DO, ")" or ESAC)
BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;
FOR n BY interval TO upperlimit DO
sumy := 0.0;
FOR p BY 2 TO n+n-1 DO
x := p/n;
y := sqrt(4.0 - x**2);
sumy := sumy + y
OD;
pi := sumy * (2.0 / n);
print((n,pi))
OD
END
It is interesting to note that you can often use a "," instead of a ";", this tells the compiler you dont care what order the statements are run. It is called a GOMMA. (A contraction of go on and comma)
e.g. The GOMMA should be used sparingly as the compiler is not required to warn you about side effects... for example (in theory)
#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #
INT x:=0;
(x+:=1, x+:=2); # allow the compiler the choice of threading #
PAR(x+:=10, x+:=20); # force statements into different threads #
printf(($"Answer="gl$,x))
What is the Answer? ... it could be 33, but it might also be 21 or 12 etc. depending on your compiler.
In this case the +:= operation is so small and fast that the answer will probably be 33.
The long answer:
The location of the statement separators in languages cause caused grief through the years. For example consider the following FORTRAN code with a missing comma:
DO 999 I=1 1000
PRINT *,I
999 CONTINUE
This bug was found and corrected before the launch of Project Mercury. Urban myth has it that the Mariner Program had a similar bug causing it to crash.
Note that it is often useful to have "Fake" statements, this is used to fulfill syntax/semantic requirements. Python as various examples, eg: "None", "NoneType" and "pass". Algol68 has "VOID", "SKIP" and "~"
To demonstrate the usage of SKIP (or "~").
BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;
FOR n BY interval TO upperlimit DO
sumy := 0.0;
FOR p BY 2 TO n+n-1 DO
x := p/n;
y := sqrt(4.0 - x**2);
sumy := sumy + y; SKIP # insert a "fake statement after the ";" #
OD; # the ";" is still needed #
pi := sumy * (2.0 / n);
print((n,pi))
OD
END
SKIP is often used to permit code to be cleanly commented out:
statement1;
statement2;
SKIP COMMENT
statement3;
statement4 # eg. no ";" on the last statement #
END COMMENT
Without the SKIP the program would not compile.
In the case of Algol68, there is a weird case Yoneda's ambiguity. This ambiguity has haunted numerous programming languages ever since, including Ada and python, and maybe even C...
To find out more go to your university library and read: "A History of ALGOL 68" - by C. H. Lindsey - [Includes a candid reflection of the language design process "Revision by mail", language feature struggles "The Bend" and included/excluded ambiguities (eg Yoneda's ambiguity and incestuous unions)]
In python they tries to side step the "Separator" by making it optional and hiding it with indentation... but the comma ambiguity remained.. eg. spot the syntax/semantic error, and run time error in the following...
print [i for i in ()]
print [i for i in (1)]
print [i for i in (1,2)]
print [i for i in (1,2,3)]
ab="ab etc etc etc"
print "first 2 only: %c,%c"%ab[0:2]
C also suffers a little from "where do I put a semicolon and comma"... the logic is that the ";" need never follow a "}", eg always ";}" but never "};"... It turns out that sometimes you do need ";};"
Then C completely throws a spanner in the works for commas with never ",)" but sometimes "),".
1968's Algol68 does produce an error message for this class of ambiguities. The moral to the story might be: if your compiler does not pick up this kind of ambiguity at compile time, then (just maybe) you should pick another language.
BTW: You can find some sample Algol68 Programs here... And next is your code with the sharp edges removed.
INT lower limit = 10, upper limit = 100, interval = 10;
PROC circle = (REAL x)REAL: sqrt(4 - x**2);
FOR n FROM lower limit BY interval TO upper limit DO
REAL sum y := 0;
FOR p FROM 1 BY 2 TO 2*n DO
REAL x = p/n;
REAL y = circle(x);
sum y +:= y
OD;
REAL pi := sum y * 2 / n;
printf(($g(0)": "g(-real width,real width-2)l$,n,pi))
OD
Compare the code changes to see if you can figure out the effect and what hints they provide... :-)
Or... here is how a standard numerical quadrature program might be coded for sharing. Note the use of passing functions as arguments, in particular there is a concept called Currying here circle(2,) ... where the comma is significant!
INT lower limit = 10, upper limit = 100, interval = 10;
PROC circle = (REAL radius, x)REAL: sqrt(radius**2 - x**2);
PROC mid point integrate = (PROC(REAL)REAL f, REAL lwb, upb, INT num steps)REAL: (
REAL dx := (upb - lwb ) / num steps;
REAL x := lwb + dx/2;
REAL sum y := 0;
FOR p TO num steps DO
REAL y = f(x);
sum y +:= y;
x +:= dx
OD;
sum y * dx
);
FOR num steps FROM lower limit BY interval TO upper limit DO
REAL pi := mid point integrate(circle(2,),0,2,num steps);
printf(($g(0)": "g(-real width,real width-2)l$,num steps,pi))
OD

Using ifeq with multiple options

I want check for a condition in makefile using ifeq, & not sure how to go about:
ifeq ( cond1 = yes || cond2 = yes )
set value x = 1;
else
set value x = 2;
endif
Please suggest the proper way to do it?
In addition to the correct answer given above:if you want to check if x=4 or x=6
ifeq ($(x),$(filter $(x),4 6))
x is either 4 or 6. do whatever you like with it
else
x is neither 4 nor 6
endif
ifeq ($(filter $(cond1) $(cond2),yes),)
x := 2
else
x := 1
endif
Alternate answer is:
ifneq (,$(filter yes,$(cond1) $(cond2)))
x := 1
else
x := 2
endif

Methods don't know about outside variables?

Say I'm writing a division algorithm script:
def current_trace
puts "Counter: #{counter}; r: #{r}; q: #{q}"
end
r = a
q = 0
counter = 0
while r >= d
current_trace
r = r - d
q = q + 1
counter += 1
end
current_trace
I expected that calling current_trace would output the value of counter, r and q. But instead I get:
in current_trace': undefined local variable or methodcounter' for main:Object (NameError)
What's the problem here?
How should I write a method that will output the values of some variables named counter, r, and q, at any given point (preferably without passing arguments to the method)?
In this case, your current_trace method is so simple that it does not worth making it a method. But looking at your code, the reason you did so is probably because it appears more than once. That is the bad part of your code that should be improved. By reconsidering the timing of the conditional and puts, you can avoid calling puts in two different locations.
counter, q, r = 0, 0, a
loop do
puts "Counter: #{counter}; q: #{q}; r: #{r}"
break if r < d
counter += 1
q += 1
r -= d
end
The correct thing is to write your method so it accepts parameters:
def current_trace(c, r, q)
puts "Counter: #{ c }; r: #{ r }; q: #{ q }"
end
Then call it like:
d = 1
r = 5
q = 0
counter = 0
while r >= d
current_trace(counter, r, q)
r = r - d
q = q + 1
counter += 1
end
current_trace(counter, r, q)
Which results in:
Counter: 0; r: 5; q: 0
Counter: 1; r: 4; q: 1
Counter: 2; r: 3; q: 2
Counter: 3; r: 2; q: 3
Counter: 4; r: 1; q: 4
Counter: 5; r: 0; q: 5
(I tweaked your variable names because your code won't work because you don't show where a and d come from, but that's beside the point.)
You can use #instance, $global or CONSTANTs but those are playing games with variable scoping, which can cause problems when you accidentally change them in some method, often because you mistype them or leave off the sigil (#, $) and inadvertently create a local variable that doesn't change the one you want. Having to use #var, or $var at the main level, just to get your code to work, is a pretty good sign you're doing something wrong actually.
I think I figured it out. counter, r and q were (apparently) only local to main's scope. I changed them to the globals $counter, $r and $q, and now I have access to them in my method.
(Realized this here: https://stackoverflow.com/a/9389532/1468130)

Can I avoid "rightward drift" in Haskell?

When I use an imperative language I often write code like
foo (x) {
if (x < 0) return True;
y = getForX(x);
if (y < 0) return True;
return x < y;
}
That is, I check conditions off one by one, breaking out of the block as soon
as possible.
I like this because it keeps the code "flat" and obeys the principle of "end
weight". I consider it to be more readable.
But in Haskell I would have written that as
foo x = do
if x < 0
then return x
else do
y <- getForX x
if y < 0
then return True
else return $ x < y
Which I don't like as much. I could use a monad that allows breaking out, but
since I'm already using a monad I'd have to lift everything, which adds words
I'd like to avoid if I can.
I suppose there's not really a perfect solution to this but does anyone have
any advice?
For your specific question: How about dangling do notation and the usage of logic?
foo x = do
if x < 0 then return x else do
y <- getForX x
return $ y < 0 || x < y
Edit
Combined with what hammar said, you can even get more beautiful code:
foo x | x < 0 = return x
| otherwise = do y <- getForX x
return $ y < 0 || x < y
Using patterns and guards can help a lot:
foo x | x < 0 = return x
foo x = do
y <- getForX x
if y < 0
then return True
else return $ x < y
You can also introduce small helper functions in a where clause. That tends to help readability as well.
foo x | x < 0 = return x
foo x = do
y <- getForX x
return $ bar y
where
bar y | y < 0 = True
| otherwise = x < y
(Or if the code really is as simple as this example, use logic as FUZxxl suggested).
The best way to do this is using guards, but then you need to have the y value first in order to use it in the guard. That needs to be gotten from getForX wich might be tucked away into some monad that you cannot get the value out from except through getForX (for example the IO monad) and then you have to lift the pure function that uses guards into that monad. One way of doing this is by using liftM.
foo x = liftM go (getForX x)
where
go y | x < 0 = True
| y < 0 = True
| otherwise = x < y
Isn't it just
foo x = x < y || y < 0 where y = getForX x
EDIT: As Owen pointed out - getForX is monadic so my code above would not work. The below version probably should:
foo x = do
y <- getForX x
return (x < y || y < 0)

Resources