Can I use environment variables or tilde in module.modulemap? - swift

My module.modulemap file looks like this:
module CompanyInternalSDK {
header "~/Company/CompanyInternalSDK.framework/Headers/CompanyInternalSDK.h"
export *
}
However, I get this error:
/Users/username/Path/To/Project/CompanyInternalSDK/module.modulemap:2:12: error: header '~/Company/CompanyInternalSDK.framework/Headers/CompanyInternalSDK.h' not found
header "~/Company/CompanyInternalSDK.framework/Headers/CompanyInternalSDK.h"
^
It compiles just fine when I use the absolute path without the tilde, but since this will be distributed like this to all developers, I want to use the tilde. Is there any way to make this work correctly?
I also tried to use an environment variable in the header string, but that didn't work either:
module CompanyInternalSDK {
header "${HOME}/Company/CompanyInternalSDK.framework/Headers/CompanyInternalSDK.h"
export *
}
/Users/username/Path/To/Project/CompanyInternalSDK/module.modulemap:2:12: error: header '${HOME}/Company/CompanyInternalSDK.framework/Headers/CompanyInternalSDK.h' not found
header "${HOME}/Company/CompanyInternalSDK.framework/Headers/CompanyInternalSDK.h"
^

No, the modulemap syntax does not expand tildes or environment variables. It ultimately just expects to stat the path you gave it, and if no file's there, it'll gripe.
Here's where the header file lookup is kicked off, during lexing of the module map file.
It ultimately passes the path to the SourceManager's FileManager to produce a File object, as here for a header in a framework's Headers/ public header folder.
getFile ultimately ends up calling out to getStatValue, which does a cache lookup.
The FileSystemStatCache::get eventually grounds out in LLVM's filesystem abstraction, where it calls sys::fs::status, which is documented to act like POSIX stat.
POSIX stat works with paths as-is, no tilde or environment variable expansion - the common availability of those is due to the shell helping you out, not something that happens automatically most of the time at the system level.
However, it's standard to use relative paths in module maps. The lexer respects this, and all the module map docs demonstrate this. In the common case where your module map file is colocated with your library and installed alongside it, this should suffice to properly resolve the paths.

Related

How do you get a runtime path for the current file in Racket?

Suppose I have a file called "test.rkt" for which I want to have its absolute path available at runtime. I know that the best way to do this is to bind it using:
(define-runtime-path orig-file "test.rkt")
However, for reflection purposes, I would like to be able to do this without knowing the name of the current file. For example, I would like to be able to do something like:
(define-runtime-path-self orig-file)
You can use #%variable-reference, which (IIRC) is the low-level reflective magic behind define-runtime-path:
(resolved-module-path-name
(variable-reference->resolved-module-path
(#%variable-reference)))
There's also the syntax/location library:
(require syntax/location)
(quote-source-file)
but beware that if you compile the file in one location and then move source file and compiled/ directory to another location, the program will print the location where it was compiled, not where it was run.
There's also a way that goes through syntax objects and module-path-indexes, but that's more complicated.
Does (find-system-path 'run-file) or (simple-form-path (find-system-path 'run-file)) work for you?

How to access the ICElements of local variables(variables inside function) and variables in header file?

Objective is to access the elements of C-file in eclipse to check customized naming rules for C-elements(global variable, local variable, function declarations).
Tried to access the C-file elements as mentioned below. In this case, only able to access global variables and function names in the .c file.
How local variables(variables inside functions) & variables in included header files can be accessed?
ITranslationUnit tu = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(input);
ICElement[] ele= src.getChildren();
Local variables
ICElement is mostly used for representing code elements in CDT's various views, such as the Outline View or Type Hierarchy. As such, local variables (which do not appear in these views) do not have an ICElement representation.
For code analysis use cases like this, it's probably better to use the AST API. The AST is a detailed representation of the entire code in a file. It can be accessed via ITranslationUnit.getAST(). You can then use an ASTVisitor to traverse the AST and visit any declarations you like and check their names.
Variables in included header files
There are two sub-categories here: header files inside the project directory, and header files outside the project directory.
Header files inside the project directory have their own ITranslationUnit, and you can use either the ICElement API or the AST API to analyze them with that ITranslationUnit as a starting point. Note that a file does not need to be open in an editor to obtain an ITranslationUnit for it. You can traverse all of the files in the project with something like ICElementVisitor, with the ICProject as a stating point.
Header files outside the project directory do not have an ITranslationUnit, and there is no straightforward way to obtain an AST for them. However, assuming your project's indexer is enabled, the indexer does create ASTs for them and store information from those ASTs in the project's index, which you could examine. There are index APIs that can be used to traverse the index; some relevant ones are IIndexManager.getIndex(ICProject), IIndex.getAllFiles(), and IIndexFile.findNames().
Edit: Additional Tips
1) How to differentiate between function declarations and simple declarations.
I can think of two ways:
Syntactically, based on the structure of the AST. For function definitions, the type of the declaration node will be IASTFunctionDefintion. For variable declarations, it will be IASTSimpleDeclaration, with the decl-specifier being IASTSimpleDeclSpecifier or IASTNamedTypeSpecifier (you additionally want to check that the declarator is not an IASTFunctionDeclarator, to filter out function declarations that are not definitions).
Semantically. If you find the IASTName for the declaration, you can call IASTName.resolveBinding(), and check whether the returned binding is an IFunction or an IVariable.
2) How to get the return type of a function and the variable type?
For these tasks, you need to get the binding. A variable's type can be queried by IVariable.getType(), and a function's return type via IFunction.getType().getReturnType().
3) Is there a way to get an ICElement from an IASTSimpleDeclaration?
There isn't a simple way that I know of. However, you shouldn't need to - if you're traversing the AST, all the information you could want can be found in the AST.

How to load module not in INC in Perl during runtime?

How do I load a module with a path not in the #INC in Perl?
I've read the answers on how to add a path to the #INC, but the issue is that #INC has to be changed at the beginning of the code. After it's compiled, all the modules I've come across look to #INC to find the location of the module. My issue is that we're trying to separate out all these environment specific things to a config file. If it's in a config file, the path needs to be read before it can be pushed to #INC, but then the code has already been compiled and it seems #INC can't be modified.
Is there a way? Is there a library that lets me load a module and pass it a custom path?
Is this a terrible bad thing to do? Why?
Perl has an incremental compilation model which means that code can be executed before other code is even parsed. For this, we can use phase blocks (aka. phasers):
BEGIN {
print "This is executed as soon as the block has been parsed\n";
}
Such a phase block could also be used to load a configuration file.
For example, use statements are effectively syntactic sugar for a BEGIN block.
use Foo::Bar qw/baz qux/;
is equivalent to
BEGIN {
require Foo::Bar; # or: require "Foo/Bar.pm";
Foo::Bar->import(qw/baz qux/);
}
We can also load modules at runtime, although that's only sensible for object-oriented modules.
So we have three options:
Load config in the BEGIN phase and add the correct library paths before loading the actual modules
Load the modules manually during BEGIN with their full path (e.g. require "/my/modules/Foo/Bar.pm"
Figure out the configuration at runtime, load modules after that.
Using bare require is fairly uncomfortable, which is why Module::Runtime exists
Use a BEGIN block to load your custom #INC location and then use lib to include it.
# use lib /a special directory/
BEGIN {
my $lib_to_include = ...;
require lib;
lib->import($lib_to_include);
}
use Module_That_Requires_Special_Dir;
The only thing to note is that whatever code you use to load your custom include directory will have to rely on methods already defined before this BEGIN block. Therefore you can't use a subroutine that is later in the file.
Came across only, which seems to let a path be passed to the use argument like so:
use only { versionlib => '/home/ingy/modules' },
MyModule => 0.33;
It has to be used with a version condition, but putting this here anyways since it's relevant to my question 1 and I wasn't able to find any modules first time around that allowed a path outside #INC.
require supposedly is able to take in a full path, according to the perlfaq with
require "$ENV{HOME}/lib/Foo.pm"; # no #INC searching!

Perl shallow syntax check? ie. do not check syntax of imports

How can I perform a "shallow" syntax check on perl files. The standard perl -c is useful but it checks the syntax of imports. This is sometimes nice but not great when you work in a code repository and push to a running environment and you have a function defined in the repository but not yet pushed to the running environment. It fails checking a function because the imports reference system paths (ie. use Custom::Project::Lib qw(foo bar baz)).
It can't practically be done, because imports have the ability to influence the parsing of the code that follows. For example use strict makes it so that barewords aren't parsed as strings (and changes the rules for how variable names can be used), use constant causes constant subs to be defined, and use Try::Tiny changes the parse of expressions involving try, catch, or finally (by giving them & prototypes). More generally, any module that exports anything into the caller's namespace can influence parsing because the perl parser resolves ambiguity in different ways when a name refers to an existing subroutine than when it doesn't.
There are two problems with this:
How to not fail -c if the required modules are missing?
There are two solutions:
A. Add a fake/stub module in production
B. In all your modules, use a special catch-all #INC subroutine entry (using subs in #INC is explained here). This obviously has a problem of having the module NOT fail in real production runtime if the libraries are missing - DoublePlusNotGood in my book.
Even if you could somehow skip failing on missing modules, you would STILL fail on any use of the identifiers imported from the missing module or used explicitly from that module's namespace.
The only realistic solution to this is to go back to #1a and use a fake stub module, but this time one that has a declared and (as needed) exported identifier for every public interface. E.g. do-nothing subs or dummy variables.
However, even that will fail for some advanced modules that dynamically determine what to create in their own namespace and what to export in runtime (and the caller code could dynamically determine which subs to call - heck, sometimes which modules to import).
But this approach would work just fine for normal "Java/C-like" OO or procedural code that only calls statically named predefined public subs, methods and accesses exported variables.
I would suggest that it's better to include your code repository in your syntax check. perl -I/path/to/working/code/repo/local_perl/ -c or set PERL5LIB=/path/to/working/code/repo/local_perl/ prior to running perl -c. Either option should allow you to check against your working code, assuming you have it in a directory structure similar to your live code.
I guess you could make stubs for the missing libraries in your home folder.
Have you looked into PPI? I think it does follow imports, however it could perhaps be more easily modified to guess what looks like a function name.

Need clarification on what's going on when linking libraries in iOS

This is probably a totally noob question but I have missing links in my mind when thinking about linking libraries in iOS. I usually just add a new library that's been cross compiled and set the build and linker paths without really know what I'm doing. I'm hoping someone can help me fill in some gaps.
Let's take the OpenCV library for instance. I have this totally working btw because of a really well written tutorial( http://niw.at/articles/2009/03/14/using-opencv-on-iphone/en ), but I'm just wanting to know what is exactly going on.
What I'm thinking is happening is that when I build OpenCV for iOS is that your creating object code that gets placed in the .a files. This object code is just the implementation files( .m ) compiled. One reason you would want to do this is to make it hard to see the source code and so that you don't have to compile that source code every time.
The .h files won't be put in the library ( .a ). You include the .h in your source files and these header files communicate with the object code library ( .a ) in some way.
You also have to include the header files for your library in the Build Path and the Library itself in the Linker Path.
So, is the way I view linking libraries correct? If , not can someone correct me on this ?
Basically, you are correct.
Compiling the source code of a library produces one object file for each of the source files (in more than one, if compiled multiply times against different architectures). Then all the object files are archived (or packaged) into one .a file (or .lib on Windows). The code is not yet linked at this stage.
The .h files provide an interface for the functionality exposed by the library. They contain constants, function prototypes, possibly global declarations (e.g. extern int bad_global;), etc. -- basically, everything that is required to compile the code which is using the library.
.h files do not 'communicate' with object code in any way. They simply provide clues for the compiler. Consider this header file:
// library.h
extern int bad_global;
int public_func(int, const void*);
By including this file in your own code, you're simply telling the compiler to copy and paste these declarations into your source file. You could have written declarations for OpenCV library and not use the headers provided with it. In other words, you're asking the compiler to not issue errors about undefined symbols, saying "I have those symbols elsewhere, ok? Here are their declarations, now leave me alone!".
The header files need to be included in the search path in order for compiler to find them. You could simply include them via the full path, e.g. #include "path/to/file.h", or supply an -I option for your compiler, telling him where to look for additional headers, and use #include <file.h> instead.
When your code is compiled, the declarations in header files serve as an indication that symbols your code is using are defined somewhere. Note the difference between the words declaration and definition. Header files contain only declarations most of the time.
Now, when your code is compiled, it must be linked in order to produce the final executable. This is where the actual object code stored in the library comes into play. The linker will look at each symbol, function call, etc. in your object code and then try to find the corresponding definition for each such symbol. If it doesn't find one in the object code of your program, it will look the standard library and any other library you've provided it with.
Thus, it is important to understand that compilation and linkage are two separate stages. You could write any function prototypes at all and use them in your code, it will compile cleanly. However, when it comes to the linking stage, you have to provide implementation for symbols used in your code, or you won't get your executable.
Hope that makes sense!
The .a is the compiled version of the code.
The header files provided with a library are its public interface. They show what classes, methods, properties are available. They do not "communicate" with the binary code.
The compiler needs the headers to know that a symbol (a method name for example) is defined somewhere else. They are associated with the right "piece of code" in the library binary later during the "link" step.