What is the scope of variables in gyp? - chromium

The gyp documentation documents the 'variables' section like this:
'variables': Definitions of variables that can be interpolated and
used in various other parts of the file.
(emphasis mine).
This seems to exclude using the variables in included gyp files, and also exclude the possibility of including other gyp files that set variables.
Is this correct? What is the scope of these variables, and how do you set variables globally?
I see that in Chromium, the build/common.gypi is setting lots of variables, but Chromium also is using a magic gyp_chromium script that is different from plain gyp.

The scope of variables is GYP is very much alike with the scope of local variables in C++. Let's say you define a variable in a variables dictionary FOO. The scope of variables defined in FOO is the dictionary BAR which is parent of FOO. You can use those variables anywhere inside BAR and nowhere outside of it.
how do you set variables globally?
Knowing the described rules it's very easy. Add a variables dictionary to the top-level dictionary of your gyp script and define some variables in it. They will be available anywhere1 in this script.
This seems to exclude using the variables in included gyp files, and
also exclude the possibility of including other gyp files that set
variables.
This is not true. Let's say you include include.gypi into generator.gyp script. If include.gypi has variables section in it's top-level dictionary, those variables would be accessible anywhere in the generator.gyp. Obviously variables defined not in the top-level dictionary would not be accessible.
1 Keep in mind that includes are parsed before the variables expansion. Thus you can not use variables in includes paths.

Related

How can I scope a CMake function so it can't be accessed from outside a file?

I'm trying to write some CMake code in a relatively complex project and I have a module that internally includes another module. The problem is, whenever I include my module, all of the functioned defined in the module it internally includes become available at a global level! This effectively is polluting my global namespace with a bunch of functions I didn't explicitly ask for.
For example:
# CMakeLists.txt
# Include my module
include(MyModule)
# Call a function from my module
my_module_function()
# HERE IS THE PROBLEM -- functions from "AnotherModule" are visible here!
# This call works
another_module_function()
Inside my module:
# MyModule.cmake
# Include another module
# - This other module is written and supported by someone else so I can't modify it
# - No functions from "AnotherModule" will be used outside of "MyModule"
include(AnotherModule)
# Define my function
function(my_module_function)
# Call a function from the other module
another_module_function()
endfunction()
Is there any way inside MyModule.cmake that I can import the functions from AnotherModule.cmake without having them be visible outside of my own module? This other module is written by someone else so I don't have control over it and it includes other functions with very generic names like one called parse_arguments that could potentially cause naming conflicts later on.
Making the functions from AnotherModule.cmake fully invisible outside of MyModule.cmake would be ideal, but even if there were a simple way to just simulate a namespace for the imported functions to be in that would be better than nothing.
In CMake macros and functions has global visibility and nothing can change that.
Often a function, "internal" to some module, is defined with underscore (_) prefix. Such prefix plays the role of a signal to outer code "not to use me". But this is only a convention, CMake doesn't enforce anything about underscore-prefixed names.
If including a module has only immediate effects, that is defines custom commands/targets but does not export functions/macros/variables for outer code, you may consider to wrap it with external project (ExternalProject_Add). An external project is a separate CMake project, and none its CMake things like variables or functions are visible outside it.

CodeNarc ruleset for identifying duplicate global variables in a script

Goal : Ability, to create a custom rule set, such that, if a groovy script file has duplicate global variables defined in a groovy script, it should disallow such variable declartions in a file.
I understand, this is technically a valid declaration, since, this is basically overriding the global variable. There's a architectural faultline in the design of the system, where in we need to disallow such declarations, else these declarations comes out as runtime detonators. (declaring the variable final is not an option,since it would involve, refactoring hundreds of groovy scripts.)
Please advice, how can I add a custom rule set to avoid duplicate global variable definition in a groovy shell script.

Is there an include once command for cmake files?

Does anyone know a simple way to apply the "include once" pattern in CMake files? In C/C++ it used to require a #ifdef / #endif pair in the beginning and end of the header file until #pragma once became common. Of course, it's possible to do the same in CMake, but I thought it'd be nice if it didn't require an explicit conditional statement.
Re-edition: It seems that the return() command should do it. And I'd define a macro like this:
macro(include_once)
if (INCLUDED_${CMAKE_CURRENT_LIST_FILE})
return()
endif()
set(INCLUDED_${CMAKE_CURRENT_LIST_FILE} true)
endmacro()
Use the macro in the beginning of your file, without any arguments. Because it's a macro, the return is from the include command for the file, not from the macro itself.
Notice that the created variable has an odd name, but CMake seems to accept this.
I used to use the logic that others have suggested as the solution. Then I learned that cmake has this functionality built in.
Take a look at the include_guard() command. I believe this will do what you want.
New in version 3.10.
Provides an include guard for the file currently being processed by CMake.
include_guard([DIRECTORY|GLOBAL])
Sets up an include guard for the current CMake file (see the CMAKE_CURRENT_LIST_FILE variable documentation).
CMake will end its processing of the current file at the location of the include_guard() command if the current file has already been processed for the applicable scope (see below). This provides functionality similar to the include guards commonly used in source headers or to the #pragma once directive. If the current file has been processed previously for the applicable scope, the effect is as though return() had been called. Do not call this command from inside a function being defined within the current file.
An optional argument specifying the scope of the guard may be provided. Possible values for the option are:
DIRECTORY
The include guard applies within the current directory and below. The file will only be included once within this directory scope, but may be included again by other files outside of this directory (i.e. a parent directory or another directory not pulled in by add_subdirectory() or include() from the current file or its children).
GLOBAL
The include guard applies globally to the whole build. The current file will only be included once regardless of the scope.
If no arguments given, include_guard has the same scope as a variable, meaning that the include guard effect is isolated by the most recent function scope or current directory if no inner function scopes exist. In this case the command behavior is the same as:
if(__CURRENT_FILE_VAR__)
return()
endif()
set(__CURRENT_FILE_VAR__ TRUE)
The simplest guard pattern against multiple module's inclusion would be
if(<something-which-is-defined-in-your-module>)
return()
endif()
E.g., if your CMake module defines a function foo_func, you may use this guard:
if(COMMAND foo_func)
return()
endif()
Do you actually need a guard?
Depended on things, defined in the module, the module may require protection agains multiple inclusion or not.
In many simple cases a guard is not needed: the module's code will work even when included multiple times.
But in some other cases, wrong protection may break the usage of the proptected module.
A module defines a function or a macro: guard is not needed.
CMake allows to define the functions and macros many times.
A module defines a constant variable: guard is not needed.
Like with function, CMake allows to define the variable many times.
But if you use guard in that case, it should check variable, not a function:
if(foo_var)
return()
endif()
This is because functions have global visibility, but variables have local visibility. That is, if you module will be included into other subtree, the function will be already visible in that subtree, but the variable is not.
A module defines a global variable via set(CACHE): guard is needed only if variable is defined as set(CACHE INTERNAL).
Variables defined via, e.g., set(CACHE STRING) or find_library don't require guards.
A module defines global property: guard is needed.
Note, that if your module uses simple (not CACHE) variable as global, it cannot work in multiple subtrees, so guard should be
if(foo_var)
message(SEND_ERROR "Module <...> cannot be included twice")
endif()

Making the VB compiler warn when I don't declare variables properly

How can I make the VB6 compiler fail when I forget to declare a variable?
This would stop various typing errors (both keyboard and data types) and errors like this when it tries to access something unexpected.
Problems caused by not correctly declaring variables:
Unexplained errors when using an undefined variable, but is in fact pointing to somehting else
Variables having different values at different times, due to spelling mistakes
Trying to access variables outside of their scope appearing to by uninitialised
You should use Option Explicit. This should be put on the first line of every module and form's code section.
You can also configure the VB6 IDE to add this automatically to all new modules by going to Tools > Options > Require Variable Declaration.

changing constants for unit tests

I'm writing some unit tests in cocoa for a data driven application.
I've got a constants header file which defines a whole heap of variables including paths to the databases etc.
I was wondering if it's possible to get all the classes to use a different set of constants which would link to a testing version of the database etc.
I've tried redefining the constants, but it doesn't take effect globally.
You could instead have a structure that contained all of the constants used and pass it into your objects' constructors. Normally that structure will be whatever values are necessary to run but when you're testing, you would instead pass a structure with the fields initialized to test parameters
I'm know absolutely nothing about objective C though, so I'm not sure if this is possible for you.
You can put all your constants into a singleton object that has read only properties for the constants. Then you can mock the constants object and change the constants.