When setting package/lib _SOURCES or per-package/lib flags (CFLAGS, LDFLAGS, LDADD, etc.) conditionally, is it better to conditionally append to the package's flags, e.g.:
bin_PPROGRAMS = mypkg
mypkg_SOURCES = mypkg.c
if OS1
mypkg_SOURCES += os1.c
else
if OS2
mypkg_SOURCES += os2.c
endif
endif
or to conditionally assign variables and concatenate them all into the package's flags (whether populated or null), e.g.:
if OS1
os1_src = os1.c
else
if OS2
os2_src = os2.c
endif
endif
bin_PROGRAMS = mypkg
mypkg_SOURCES = mypkg.c $(os1_src) $(os2_src)
I've seen it both ways and I can see advantages to each. With the former, the actual final action of adding those flags to the package are clear in the conditional, and you haven't crowded the line with variables that don't actually mean anything in a given build. In the latter, what's actually included in the package is consolidated on one line and you don't have unseen appendment happening somewhere else, but you might not really know what's going on in that opaque variable name.
I guess another option is to do something like option 2, but assign the variables with the configure script (configure.ac with AC_SUBST). But I've been keeping my configure scripts purely detecting features available, and choosing which to use in Makefiles.
Does one of them have a technical downside or nasty side-effect?
The differences you observe are largely a matter of style, which is subjective and thus largely off-topic here. But your actual question is pretty objective:
Does one of them have a technical downside or nasty side-effect?
No, none of which I am aware. Either approach will work fine, at least in isolation. A larger context might provides reasons to prefer variations on the second approach, such as re-use of the variables in conjunction with more than one target. That would be more likely the case for preprocessor or link options than for choice of source files, however.
Personally, I would structure the particular case you've presented a bit differently:
if OS1
os_src = os1.c
else
if OS2
os_src = os2.c
endif
endif
bin_PROGRAMS = mypkg
mypkg_SOURCES = mypkg.c $(os_src)
To be sure, this is a matter of style, so take it for whatever it's worth to you. Here, the usage of the variable matches the structure of the condition: OS1 and OS2 are alternatives, so between them they control the value of just one variable. The meaning of that variable is therefore clearer, both at the point where its value is set and at the point it is used.
Multiple variables make more sense for multiple distinct, unrelated conditions.
I would add some more typical patterns:
os1_src = os1.c
os2_src = os2.c
if OS1
myos = os1
endif
if OS2
myos = os12
endif
mypkg_SOURCES = mypkg.c $($(myos)_src)
another:
if OS1
os1 = yes
os2 = no
endif
if OS2
os1 = no
os2 = yes
endif
$(os1)src = os1.c
$(os2)src = os2.c
mypkg_SOURCES = mypkg.c $(yessrc)
Same approach can be used to supply os- or processor- or configuratipn-specific build flags. Often, there are some common settings that are used for more than one module, while other flags are module-specific.
Each approach can be misused and lead to nasty consequences.
The main risk is that some flags or settings for one module will not get reset properly and some settings for another module will 'spill' unintentionally. But also, some module can miss some common flag.
To reduce these risk, try to stick with same technique even if your build contains many modules.
Related
What is the difference between z3.Bool() and z3.FreshBool() functions?
My code in z3 on python fails when I use Bool() (the solver returns unsat when it shouldn't), but works fine when I use FreshBool() (Desired behaviour is observed).
I cannot give out details of the code here, as it is part of an ongoing assignment in a course offered in my college.
Even still, if this information isn't sufficient, I can try and recreate in an unrelated code, to provide you with a better sample to work on.
Thanks
If you use FreshBool() then z3 will create a new variable that does not exist elsewhere in the system. When you use Bool and give it a name, then it will be the same variable if created elsewhere.
To wit, consider:
from z3 import *
# These two are *different* variables even though they have the same name
a = FreshBool("a")
b = FreshBool("a")
s = Solver();
s.add(a != b)
print(s.check())
This will print:
sat
since the variables are different. (And hence can have different values in the model.)
But if you try:
from z3 import *
# These two are the *same* variable, since they have the same name
a = Bool("a")
b = Bool("a")
s = Solver();
s.add(a != b)
print(s.check())
Then you'll get:
unsat
because a and b are the same variable since they have the same name.
Most end-user code should simply use Bool, since this is the usual intended semantics: You refer to different variables with their names when you created them. But when developing libraries, you might want to create a temporary variable that is not the same as any other variable in the system. In these cases, you use FreshBool. Note that in this latter case the string you provide is used as a prefix. If you add print(get_model()) at the end of the first program, it'll print:
sat
[a!0 = True, a!1 = False]
showing the internally created "fresh" names.
z3 also provides similar functions for other types too, such as Int() vs FreshInt(), Real() vs FreshReal() etc.; intended to be used in exactly the same manner.
I have a method that builds a laptop's attributes, but only if the attributes are present within a row that is given to the method:
def build_laptop_attributes desk_id, row, laptop
attributes = {}
attributes[:desk_number] = room_id if laptop && desk_id
attributes[:status] = row[:state].downcase if row[:state]
attributes[:ip_address] = row[:ip_address] if row[:ip_address]
attributes[:model] = row[:model] if row[:model]
attributes
end
Currently, RuboCop is saying that the Metric/AbcSize is too high, and I was wondering if there is an obvious and clean way to assign these attributes?
Style Guides Provide "Best Practices"; Evaluate and Tune When Needed
First of all, RuboCop is advisory. Just because RuboCop complains about something doesn't mean it's wrong in some absolute sense; it just means you ought to expend a little more skull sweat (as you're doing) to see if what you're doing makes sense.
Secondly, you haven't provided a self-contained, executable example. That makes it impossible for SO readers to reliably refactor it, since it can't currently be tested without sample inputs and expected outputs not provided in your original post. You'll need those things yourself to evaluate and refactor your own code, too.
Finally, the ABC Metric looks at assignments, branches, and conditionals. You have five assignments, four conditionals, and what looks liks a method call. Is that a lot? If you haven't tuned Rubocop, the answer is "RuboCop thinks so." Whether or not you agree is up to you and your team.
If you want to try feeding Rubocop, you can do a couple of things that might help reduce the metric:
Refactor the volume and complexity of your assignments. Some possible examples include:
Replace your postfix if-statements with safe navigators (&.) to guard against calling methods on nil.
Extract some of your branching logic and conditionals to methods that "do the right thing", potentially reducing your current method to a single assignment with four method calls. For example:
attributes = { desk_number: location, status: laptop_status, ... }
Replace all your multiple assignments with a deconstructing assignment (although Rubocop often complains about those, too).
Revisit whether you have the right data structure in the first place. Maybe you really just want an OpenStruct, or some other data object.
Your current code seems readable, so is the juice really worth the squeeze? If you decide that RuboCop is misguided in this particular case, and your code works and passes muster in your internal code reviews, then you can tune the metric's sensitivity in your project's .rubocop.yml or disable that particular metric for just that section of your source code.
After reading #Todd A. Jacobs answer, you may want (or not) to write something like this:
def build_laptop_attributes desk_id, row, laptop
desk_number = room_id if laptop && desk_id
{
desk_number: desk_number,
status: row[:state]&.downcase,
ip_address: = row[:ip_address],
model: row[:model]
}.compact
end
This reduces has the advantage of reducing the number of calls to []=, as well as factorizing many ifs in a single compact.
In my opinion, it is more readable because it is more concise and because the emphasis is completely on the correspondence between your keys and values.
Alternative version to reduce the amount of conditionals (assuming you are checking for nil / initialized values):
def build_laptop_attributes desk_id, row, laptop
attributes = {}
attributes[:desk_number] = room_id if laptop && desk_id
attributes[:status] = row[:state]&.downcase
attributes[:ip_address] = row[:ip_address]
attributes[:model] = row[:model]
attributes.compact
end
There is an additional .compact as a cost of removing assignments checks.
In a makefile, what's the difference between writing
define VAR =
...
...
endef
and writing
define VAR
...
...
endef
Notice that the latter is missing the = on the define line. Both are accepted by Gnumake, but they don't appear to exhibit the same behavior (for me, I find that using the latter does what I want it to).
When should you use which form?
There is no difference between them: both create recursive multi-line variable values.
There is ONE difference, though: the former version (with the equals sign) was introduced in GNU make 3.82 (released in 2010). If you're still using a version of GNU make before that, then this statement:
define FOO =
bar
enddef
creates a variable named FOO =, not FOO (which is probably why it doesn't appear to work for you).
The ability to add assignment operators here is really so you can use the other operators, such as :=, ?=, += with multi-line variables, which you didn't used to be able to do.
But the default if no operator is specified is and always has been, to create a normal recursive variable.
I am working on a Jitter which is based on LLVM. I have a real issue with performance. I was reading a lot about this and I know it is a problem in LLVM. However, I am wondering if there are other bottlenecks. Hence, I want to use in my Jitter the same mechanism offers by -time-passes, but saving the result to a specific file. In this way, I can do some simple math like:
real_execution_time = total_time - time_passes
I added the option to the command line, but it does not work:
// Disable branch fold for accurate line numbers.
llvm_argv[arrayIndex++] = "-disable-branch-fold";
llvm_argv[arrayIndex++] = "-stats";
llvm_argv[arrayIndex++] = "-time-passes";
llvm_argv[arrayIndex++] = "-info-output-file";
llvm_argv[arrayIndex++] = "pepe.txt";
cl::ParseCommandLineOptions(arrayIndex, const_cast<char**>(llvm_argv));
Any solution?
Ok, I found the solution. I am publishing the solution because It may be useful for someone else.
Before any exit(code) in your program you must include a call to
llvm::llvm_shutdown();
This call flush the information to the file.
My problem was:
1 - Other threads emitted exit without the mentioned call.
2 - There is a fancy struct llvm::llvm_shutdown_obj with a destructor which call to the mentioned method. I had declared a variable in the main function as follow:
llvm::llvm_shutdown_obj X();
Everybody know that the compiler should call the destructor, but in this case it was no happening. The reason is that the variable was not used, so the compiler removed it.
No variable => No destructor => No flush to the file
I came across lot of flags while reading someone else code,
if (condition1)
var1 = true
else
var1 = false
then later,
if (var1 == true)
// do something.
There are lot of flags like this. I eager to know, is using flags very often in code advisable?
This:
if (condition1)
var1= true;
else
var1 = false;
Is a classic badly written code.
Instead you should write:
var1 = condition1;
And yes, flags are very useful for making the code be more readable and possibly, faster.
It's advisable if condition1 is something quite complicated - like if (A && (B || C) && !D) or contains a lot of overhead (if (somethingTimeConsumingThatWontChange())) then it makes sense to store that result instead of copy-pasting the code.
If condition1 is just a simple comparison then no, I wouldn't use a flag.
This is pretty subjective, and depends on the rest of the code. "Flags" as you call them have their place.
First of all, this code should read like this:
var1 = condition1;
if( var1 )
// No need to compare *true* to *true* when you're looking for *true*
As for the number of flags, there are more elegant ways of branching your code. For instance , when using javascript you can do stuff like this:
var methodName = someFunctionThatReturnsAString();
// assuming you name the method according to what's returned
myObject[ methodName ]();
instead of
if( someFunctionThatReturnsAString === 'myPreferedMethod' ){
myObject.myPreferedMethod();
}else{
myObject.theOtherMethod();
}
If you're using a strongly typed language, polymorphism is your friend. I think the technique is refered to as polymorphic dispatch
I remember this Replace Temp var with Query method from the refactoring book.
I think this refactoring will make the code more readable, but, I agree that it might affect performance when the query method is expensive ... (But, maybe the query method can be put in its own class, and the result can be cached into that class).
This is question is a bit generic. The answer depends on what you want to do and with which language you want it to do. Assuming an OO context than there could be better approaches.
If the condition is the result of some object state than the "flag" should propably be a property of the object itself. If it is a condition of the running application and you have a lot of these things it might could be that you should think about a state pattern/state machine.
Flags are very useful - but give them sensible names, e.g. using "Is" or similar in their names.
For example, compare:
if(Direction) {/* do something */}
if(PowerSetting) {/* do something else */}
with:
if(DirectionIsUp) {/* do something */}
if(PowerIsOn) {/* do something else */}
If it is readable and does the job then there's nothing wrong with it. Just make use of "has" and "is" prefix to make it more readable:
var $isNewRecord;
var $hasUpdated;
if ($isNewRecord)
{
}
if ($hasUpdated)
{
}
Bearing in mind that that code could be more readably written as
var1 = condition1
, this assignment has some useful properties if used well. One use case is to name a complicated calculation without breaking it out into a function:
user_is_on_fire = condition_that_holds_when_user_is_on_fire
That allows one to explain what one is using the condition to mean, which is often not obvious from the bare condition.
If evaluating the condition is expensive (or has side effects), it might also be desirable to store the result locally rather than reevaluate the condition.
Some caveats: Badly named flags will tend to make the code less readable. So will flags that are set far from the place where they are used. Also, the fact that one wants to use flags is a code smell suggesting that one should consider breaking the condition out into a function.
D'A
Call it flags when you work in a pre-OO language. They are useful to parameterize the behaviour of a piece of code.
You'll find the code hard to follow, soon, however. It would be easier reading/changing/maintaining when you abstract away the differences by e.g. providing a reference to the changeable functionality.
In languages where functions are first-class citisens (e.g. Javascript, Haskell, Lisp, ...), this is a breeze.
In OO languages, you can implement some design patterns like Abstract Factory, Strategy/Policy, ...
Too many switches I personally regard as code smell.
That depends on the condition and how many times it's used. Anyway, refactoring into function (preferably caching the result if condition is slow to calculate) might give you a lot more readable code.
Consider for example this:
def checkCondition():
import __builtin__ as cached
try:
return cached.conditionValue
except NameError:
cached.conditionValue = someSlowFunction()
return cached.conditionValue
As for coding style:
if (condition1)
var1= true
else
var1 = false
I hate that kind of code. It should be either simply:
var1 = condition1
or if you want to assure that's result is boolean:
var1 = bool(condition1)
if (var1 == true)
Again. Bad coding style. It's:
if (var1)
What i dont like about flags, is when they are called flags, with no comment whatsoever.
e.g
void foo(...){
bool flag;
//begin some weird looking code
if (something)
[...]
flag = true;
}
They attempt against code redeability. And the poor guy who has to read it months/years after the original programmer is gone, is going to have some hard time trying to understand what the purposse of it originally was.
However, if the flag variable has a representative name, then i think they are ok, as long as used wisely (see other responses).
Yes, that is just silly nonsensical code.
You can simplify all that down to:
if (condition1)
{
// do something
}
Here's my take.
Code using flags:
...
if (dogIsBarking && smellsBad) {
cleanupNeeded = true;
}
doOtherStuff();
... many lines later
if (cleanupNeeded) {
startCleanup();
}
...
Very unclean. The programmer simply happens to code in whatever order his mind tells him to. He just added code at a random place to remind himself that cleanup is needed later on... Why didn't he do this:
...
doOtherStuff();
... many lines later
if (dogIsBarking && smellsBad) {
startCleanup();
}
...
And, following advise from Robert Martin (Clean Code), can refactor logic into more meaningful method:
...
doSomeStuff();
... many lines later
if (dogTookADump()) {
startCleanup();
}
...
boolean dogTookADump() {
return (dogIsBarking && smellsBad);
}
So, I have seen lots and lots of code where simple rules like above could be followed, yet people keep adding complications and flags for no reason! Now, there are legit cases where flags might be needed, but for most cases they are one style that programmers are carrying over from the past.