Here's some simple code to show the problem I am having:
import UIKit
let TEST = true
print(TEST)
#if TEST
print("1. TEST should be true. Value is : ", TEST)
#endif
#if !TEST
print("2. TEST should be false. Value is : ", TEST)
#endif
Regardless of whether TEST is 'true' or 'false', the '#if !TEST' is always executed. The '#if TEST' branch is never executed.
This happens in a Playground and in compiled code.
Xcode 9 Beta 5
You are confusing between TEST the local variable and TEST the compiler flag.
What you have is a local variable named TEST
What you are testing for is the existence of a compiler flag named TEST
To set a compiler flag, go to the target's Build Settings and search for Other Swift Flags, then add -DTEST to your Debug build.
Also, Swift compiler flags are much simpler compared to C compiler flags: a flag either exists or not. You can't associate an int value or anything like that. Consequently, there's no point in getting its value. It's a true/false situation: you know that it exists or not; there's no other value associated with it.
Related
I'm having trouble replicating in Swift the Preprocessor Macro functionality offered by ObjC. I have heard that Swift has no preprocessor, so I'm looking for another way to implement this.
My end goal is to build my project using the command line tools, passing in a custom variable and value, which will be preprocessed and inserted into the code at specific points, before the build takes place.
This is the solution for ObjC:
Use this command to run a test:
xcodebuild \
test \
-scheme TestUserDefinedVariablesObjC \
-destination 'platform=iOS Simulator,name=iPhone 6' \
MY_VAR=42
I use MY_VAR in code like this:
int a = MY_VAR;
(I add MY_VAR to Preprocessor Macros in my target's Build Settings like this: MY_VAR=$(MY_VAR))
As a last resort, I could add pre-action to the scheme's Run phase that substitutes the correct values using sed or something like that, but it's not a great solution.
Are you using different keyset/keyboard? If so check "
example:
Preprocessor Macros in my target's Build Settings
MY_VAR=\"42\"
check " character. Change it with this "
Instead of using SED in a build-phase script, you could use the clang preprocessor.
For example, put this in a file named macro-test.c
#if DEBUG
#define LOG(A) print(A)
#else
#define LOG(A)
#endif
import Foundation
func hello()
{
LOG("Hello, Swift macro!")
let theAnswer = MY_CONST
print("The answer = ", theAnswer)
}
Add a script build phase that runs the clang preprocessor:
#!/bin/sh
if [ $CONFIGURATION == "Debug" ] ;
then
DEBUG="1"
else
DEBUG="0"
fi
MY_CONST=42
clang -E -P -DMY_CONST=$MY_CONST -DOS=$OS -DDEBUG=$DEBUG "${SOURCE_ROOT}/macro-test.c" > "${SOURCE_ROOT}/macro-test.swift"
Add the generated swift file to the Xcode project.
Is there a way to use the native Makefile if-else conditional and also have it respects target-specific variables re-assignments?
Example Makefile:
#!/usr/bin/make
CONFIG = Debug
.PHONY: test printme
test: override CONFIG=Release
test: printme
#echo "Done."
printme:
ifeq "$(CONFIG)" "Debug"
#echo "should be DEBUG -> $(CONFIG)"
else
#echo "should be RELEASE -> $(CONFIG)"
endif
Running make test prints the following output:
should be DEBUG -> Release
Done.
The output I'm looking for is should be RELEASE -> Release how can I achieve that? Do I need to use shell conditionals instead?
This behavior seems logical to me: At the time of parsing the Makefile, CONFIG is defined as Debug. The ifeq conditional uses the value of CONFIG it knows at that time. Therefore it chooses the ifeq branch that outputs "Should be DEBUG".
The target-specific variable is only defined as Release with the target test. Its prerequisite printme also knows the target-specific variable and ouputs Release.
May I suggest that you set variable to make on the command line for the purpose you want. It's not many more characters to write when invoking make but brings all you seem to be willing.
make CONFIG=Release
In a makefile which I have ,I want to assign value to a variable based on a condition.
I have:
CMAKE=cmake ../
I tried doing:
if test condition;
then $(eval CMAKE := $(cmake -DCMAKE_BUILD_TYPE=Release ../));\
fi;
But this does not work.Is there any other way to do this?
P.S The error which is getting reported is :
Syntax error: ";" unexpected
When I removed ";" ,it showed another error :
Syntax error: "fi" unexpected
This kind of "back and forth" between the shell and make is not possible. It's important to understand the relationship between them: make does not implement a shell parser: it just runs the shell for that. All make gets back from the shell is a single exit code that determines whether the command succeeded or not.
Make runs a recipe by first expanding all the variables and functions in the recipe, then passing the resulting command to the shell to be invoked.
Thus it should be clear why your example doesn't work.
Before we can give you good advice we'd need higher-level information about exactly what you're trying to do and why. One way to do what you want is to use $(shell ...) to compute the conditional, all outside of any rule:
ifeq ($(shell test condition && echo true),true)
CMAKE := cmake -DCMAKE_BUILD_TYPE=Release ../
endif
However, this looks pretty strange to me. If you described what you really want to do we can probably give you better help.
ETA:
Based on your description below, the best option is target-specific variables:
CMAKE_BUILD_FLAG = -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE)
debug: CMAKE_BUILD_TYPE = Debug
release: CMAKE_BUILD_TYPE = Release
setup: CMAKE_BUILD_FLAG =
debug release setup: all
all:
cmake $(CMAKE_BUILD_FLAG) ../
Some Makefile contains this -
ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y)
msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
NO_LIBUNWIND := 1
and
whenever I run this make , I get the error message as
warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99
I want to debug this problem - I want to know the values of SOURCE_LIBUNWIND, FLAGS_UNWIND
which are causing this problem - how do I get these values printed on the stdout for debugging purpose ?
GNU make provides several functions that you can use to print the value of a variable: $(error ...), $(warning ...) and $(info ...). The manual mentions them in section 8.12 Functions That Control Make.
Additionally, you can use the command-line parameter -p or --print-data-base to have make print the values of all rules and variables. Redirecting the output to a file and analyzing that might give you a better understanding of why the values are what they are. See section 9.7 Summary of Options for some extra information.
to print value of macro X in the makefile - just add line. ( kind of printf )
$(warning X is $(X))
Reinier and Shraddha have the right answers for the question as asked but I'm not sure that's the right question to have asked.
It would seem to me (based on nothing more than the snippet of makefile posted) that those are more likely to be variables you can set than variables that are already set. That is they would be how you control the location used for locating libunwind.
So if the try-cc call is failing I'd assume that means you either don't have libunwind installed at all or that you have it installed in a non-standard system location and haven't set those variables to tell make about it.
i'm using cs50 appliance.
i've tried to write a new file test.c , found as long as i include int i line, it doesn't generate a new file test, if i remove that line and make again, it can generate test file. then i made changes on the test file, it still output the original file result, no reflect the new changes.
#include <stdio.h>
#include <cs50.h>
int
main (void)
{
printf("Number: \n");
int i = GetInt();
}
it was running properly before though... anyone can help please?
Apparently your default rules for make run the compiler on test.c.
The compiler notices that you are assigning a value to variable i, but you never use that value in any way; it would normally report this as a warning.
Apparently either your compiler or make are configured in such a way that this warning becomes a fatal error to make.
The remedy is to use the variable. It looks as though you need to pick up a book on the C programming language, or follow a course, if that's not what you're doing already.