Racket has Module Paths (predicate is module-path?), Resolved Module Paths (predicate is resolved-module-path?), and Module Path Indexes (predicate is module-path-index?).
I guess a module-path? is anything that could plausibly point to a module. And I guess a resolved module path points to an actual module on the system.
But what is a module path index and what does it get me over just a resolved module path?
A module-path? contains anything that can be required. Could be a path?, could be a symbol, could be a submodule path (submod "food.rkt" lunch). See require in the docs.
A resolved-module-path? is an "absolute path" to where Racket can find the module (Note 1). The grammar for resolved module paths is more limited (i.e., less ambiguous) than for module paths.
A module-path-index? (MPI) is a delta from one module-path-index? to another (Note 2). Use module-path-index-join to build MPIs (Note 3).
(module-path-index-join #f #f) is a delta from the current module to itself.
(module-path-index-join "dumplings.rkt" #f) is a delta from #f (the current module) to the relative path "./dumplings.rkt" (Yes it's really path first, then base.)
(module-path-index-join "nom-noms.rkt" (module-path-index-join "dumplings.rkt" #f)) is a delta from the current module to "./dumplings.rkt" to "./nom-noms.rkt". Racket builds MPIs like this when one file statically requires another --- these can be chained together to find the binding of an identifier.
(module-path-index-join '(submod test) #f) refers to the test submodule in the current module.
Hope that helps.
Note 1: If the module is in a file, a resolved path for it is an absolute filepath. If the module is the result of calling eval on a syntax object, its resolved-module-path? is something else.
Note 2: IMO "module path deltas" would be a better name.
Note 3: module-path-index-join accepts a third, optional argument when the first two arguments are #f. This lets a module refer to one of its own submodules. You will generally not want to use this feature directly. And instead use quote-module-path.
Related
Context: I'm trying to come up with a fix for https://github.com/tensorflow/tensorflow/issues/37861 where header files of an external dependency are manually listed but that list is version specific and hence impossible to keep up to date.
What is happening:
tf_http_archive(name = "com_google_protobuf", system_build_file = clean_dep("//third_party/systemlibs:protobuf.BUILD") ...) is invoked
tf_http_archive is a repository_rule with effectively nothing but ctx.template("BUILD.bazel", ctx.attr.system_build_file, {...}, False)
In the protobuf.BUILD there is a list HEADERS = ["google/protobuf/any.pb.h", ...] which is passed to the hdrs argument of cc_library calls
a genrule apperantly symlinks those headers from $(INCLUDEDIR) into $(#D) (I'm not really familiar with Bazel but IIUC the latter is some internal build directory used later)
As I'm unfamiliar with Bazel in general I'll just assume the list of headers is required and there exists a $(INCLUDEDIR)/google/protobuf folder and is somewhere (else) on the system, e.g. /usr/local/include.
Is there any way to get all *.h and *.inc files in the format (i.e. relative to $(INCLUDEDIR)) via a glob or similar? The Bazel glob function doesn't work for absolute paths, so that can't be used.
I found https://github.com/bazelbuild/bazel/issues/8846 suggesting to use new_local_repository with a build_file and a path set to (in this case) $(INCLUDEDIR) but I don't see how that could be applied to the tf_http_archive (which has some conditions to either download the dependency or just use the system_build_file). This seems to also allow to avoid the symlinking (which I'm highly suspicious of anyway because that folder is added via -iquote but include style is #include <...>, see my comments in https://github.com/tensorflow/tensorflow/issues/37861)
Bonus points for people contributing to the issue or ideas why action_env environment variables seem to be ignored in a native.cc_library call.
I am trying to create an RPM installer using cpack (via cmake) that creates multiple RPM files. I've almost got it working but the last remaining stumbling block is controlling the package names.
Specifically I want to control where the component name appears in the RPM file name.
Here is my experimental CMakeLists.txt file which installs foo.txt and bar.txt to two different packages "myproject-foo" & "myproject-bar".
I want the RPMs to follow my own naming conventions (actually I want conventions that are more FSH friendly) but for some reason cmake insists on adding the component name at the end. So I get:
myproject-comp-1.0.i686-foo.rpm
myproject-comp-1.0.i686-bar.rpm
rather than:
myproject-compfoo-1.0.i686.rpm
myproject-compbar-1.0.i686.rpm
I notice it names the source RPMs "more correctly":
E.g.
>rpm -qip <package> | grep source
Source RPM : myproject-foo-1.0-1.src.rpm
Though I do not actually want a source RPM at all (is there a way to blank this field?)
cmake_minimum_required(VERSION 2.8)
message("CMAKE_VERSION=${CMAKE_VERSION}")
SET(DOCDIR "doc")
set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "core")
install(FILES foo.txt COMPONENT foo DESTINATION "${RPMBUILDROOT}${DOCDIR}")
install(FILES bar.txt COMPONENT bar DESTINATION "${RPMBUILDROOT}${DOCDIR}")
project(myproject CXX)
set(CPACK_PACKAGE_NAME "myproject")
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_PACKAGE_VERSION 1.0)
set(CPACK_PACKAGE_VENDOR "some org")
set(CPACK_COMPONENT_foo_DESCRIPTION "the foo component")
set(CPACK_COMPONENT_bar_DESCRIPTION "the bar component")
# mentioned in cpack docs but doesn't seem to do anything here
set(CPACK_COMPONENT_foo_DISPLAY_NAME "foo display name?")
set(CPACK_COMPONENT_bar_DISPLAY_NAME "foo display name?")
set(CPACK_COMPONENT_bar_DEPENDS foo)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "describe the complete suite of stuff")
set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_SOURCE_DIR}/README.txt)
# added in cmake 3.6?
set(CPACK_RPM_foo_PACKAGE_SUMMARY "describe the foo package")
set(CPACK_RPM_bar_PACKAGE_SUMMARY "describe the bar package")
set(CPACK_RPM_foo_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-foo")
set(CPACK_RPM_bar_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-bar")
set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_SOURCE_DIR}/README.txt)
#set(CPACK_RPM_foo_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-foo-${CPACK_PACKAGE_VERSION}.i686")
#set(CPACK_RPM_bar_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-bar-${CPACK_PACKAGE_VERSION}.i686")
set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-comp${CPACK_COMPONENT_DISPLAY_NAME}-${CPACK_PACKAGE_VERSION}.i686")
set(CPACK_RPM_PACKAGE_ARCHITECTURE "i686")
set(CPACK_RPM_PACKAGE_RELOCATABLE TRUE)
include(CPack)
cpack_add_component(foo
DISPLAY_NAME foo comp
DESCRIPTION this is the foocomp)
cpack_add_component(bar
DISPLAY_NAME bar comp
DESCRIPTION this is the bar comp
DEPENDS foo)
It seems like CPACK_PACKAGE_<component>_FILE_NAME or CPACK_PACKAGE_FILE_NAME is not quite working.
I've tried with both cmake 3.4.3 and the latest (3.9.0 at the time of writing) as there is some suggestion of fixes to component based installs in 3.6.0
There is no such variable as the CPACK_COMPONENT_DISPLAY_NAME I've used in CPACK_PACKAGE_FILE_NAME. Also something in cmake adds the component name to the end automatically.
There is a similar question for .deb packages from long ago here but I would rather avoid such a complex solution if possible.
It would be easier to rename the packages after generation (but still feel hacky).
I also note that the package dependency set(CPACK_COMPONENT_bar_DEPENDS foo) is not recorded in the bar package.
Update: 01-Aug-2017
I've added a bug report for cmake here as to my mind there is a bug in the implementation of CPACK_RPM_<component>_PACKAGE_FILE_NAME. At the very least the documentation is insufficiently helpful.
First of there is a large note at the top of the documentation:
Note
part of variables is preferred to be in upper case (for e.g. if component is named foo then use CPACK_RPM_FOO_XXXX variable name format) as is with other CPACK__XXXX variables. For the purposes of back compatibility (CMake/CPack version 3.5 and lower) support for same cased component (e.g. fOo would be used as CPACK_RPM_fOo_XXXX) is still supported for variables defined in older versions of CMake/CPack but is not guaranteed for variables that will be added in the future. For the sake of back compatibility same cased component variables also override upper cased versions where both are present.
So if you have a component named foo, FOO, fOo... the variables are CPACK_RPM_FOO_... otherwise the variables will be ignored - Note that this is the case since the beginning of CPack's existance for the common component variables e.g. CPACK_COMPONENT_foo_DESCRIPTION <- foo part must be in upper case.
Next to the file names - before CPack 3.6 it was not possible to change file names without getting an error and having to copy the generated package manually. Since that version you can set the file name as you like or request the platform specific package name (defined by rpm installation) by setting CPACK_RPM_FILE_NAME or CPACK_RPM_<component>_FILE_NAME to RPM-DEFAULT. See https://cmake.org/cmake/help/v3.6/module/CPackRPM.html?highlight=cpack_rpm_file_name#variable:CPACK_RPM_FILE_NAME
Also set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-comp${CPACK_COMPONENT_DISPLAY_NAME}-${CPACK_PACKAGE_VERSION}.i686") won't work as ${CPACK_COMPONENT_DISPLAY_NAME} is not an anchor and is automatically replaced on that location - not set by you so replacement text is an empty string... So if you really want to set the name manually you should set the RPM packager equivalent of that variable CPACK_RPM_<component>_FILE_NAME for each and every component (so you'll need a for loop or some more copy pasting...) - note that as described in the documentation the file name must end with .rpm and the default is (copied from the documentation) <CPACK_PACKAGE_FILE_NAME>[-<component>].rpm so this is the explanation why component part is always placed at the end.
There are quite a few tests for different CPack packagers here: https://github.com/Kitware/CMake/tree/master/Tests/RunCMake/CPack/tests
So you can explore those snippets as well.
P.S. contributions to the documentation are always welcome :)
If I want to optionally require a module at runtime, I can use [dynamic-require'1. This works great if I want to require a package that has been installed, for example:
(dynamic-require 'racket/match 'match)
This will (provided I have racket/match installed), require racket/match and evaluate to the match binding in that library.
However, I run into trouble when I want to require a local, non installed module. Let's say I have some module called eat.rkt, which provides one function: bite:
#lang racket ;; eat.rkt
(provide bite)
(define (bite) "Nom nom")
Now lets say we want to make a lunch.rkt module that requires eat.rkt, and calls the function. Furthermore, lets suppose I put them in the same directory:
#lang racket ;; lunch.rkt
(require "eat.rkt")
(bite) ; => Nom Nom
This is fine because I used static require, but this falls apart when I want to do a dynamic-require:
#lang racket ;; lunch2.rkt
(define bite (dynamic-require "eat.rkt" 'bite)
(bite) ; => Nom Nom
While this appears to be fine, it turns out that the module required by dynamic-require is NOT required based on the module's path, but on current-directory. So, if I run the program in the directory the module is defined, that's fine, but if I'm in another directory, everything breaks:
$ racket lunch2.rkt
"Nom Nom"
$ cd snacks/
$ racket ../lunch2.rkt
; default-load-handler: cannot open module file
Obviously I could just change the current-directory to this module's directory if I know where it is. But if I don't know this module's path, is there any way to get it? Or, more directly, is it possible to dynamic-require a module relative to the requiring's module path?
The define-runtime-path form defines a path that will be available at runtime and is independent of the current-directory. Use it to define the path to the module you want to require dynamically, for example:
#lang racket
(require racket/runtime-path)
(define-runtime-path eat "eat.rkt")
(dynamic-require eat 'bite)
The easiest way to dynamic-require a module relative to the current module path (which is to say the path where the module is saved), is to get that module path and append it your relative module.
You can do this with #%variable-reference and variable-reference->module-path-index. (You may also want to use variable-reference->resolved-module-path for other situations, but we will not do it here.) Composing these two functions gives us a module-path-index? to the module being defined. (Or in general, the module that the #%variable-reference came from.)
So, we can a variable like:
(define here (variable-reference->module-path-index (#%variable-reference)))
Now all that is left is to compose this here path with the relative path to the module we want to require. We are looking for the module path analogy of build-path, if you will.
It turns out that the function we are looking for is: module-path-index-join, which takes a base path and a relative path and appends them together. The result will look something like:
(module-path-index-join "eat.rkt" here)
(Yes, it is backwards of what you would expect from build-path, but the base path comes second for this function.)
The resulting module, lunch3.rkt looks like:
#lang racket
(define here (variable-reference->module-path-index (#%variable-reference)))
(define bite (dynamic-require (module-path-index-join "eat.rkt" here) 'bite))
And now lunch3.rkt will require eat.rkt relative to where its defined, not based on the current-directory:
$ racket lunch3.rkt
"Nom Nom"
$ cd snacks/
$ racket ../lunch3.rkt
"Nom Nom"
Thank you to Matthew Flatt for helping with this answer.
I have three folders in a location, say A,B and C. I have two cmake files in folder A: FindABC.cmake and UseABC.cmake. The former is for finding the libraries and the latter contains a function, say run_command(). CMakelists.txt in folder B and folder C contains the following lines:
find_package(ABC)
include(UseABC)
run_command()
It works as intended. Now If I comment find_package() and include() in CMakelists of folder C, as far as I know, Cmake should give an error telling unknown command - run_command(). But, the controls goes into the function and executes in unpredictable manner.
How come the control goes to the function when the include line is commented? The root CMakelists that lists the sub-directories does not have any find_package or include lines in it.
Edit:
UseABC.cmake:
set(ABC_COMPILE_DEBUG FALSE)
set(ABC_COMPILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/abc_gen")
message("USEABC1 - -> " ${ABC_COMPILE_OUTPUT_DIR})
function(run_command)
message("USEABC2 - File recurs -> " ${ABC_COMPILE_OUTPUT_DIR})
file(REMOVE_RECURSE "${ABC_COMPILE_OUTPUT_DIR}")
file(MAKE_DIRECTORY "${ABC_COMPILE_OUTPUT_DIR}")
add_custom_command() #command to be executed
endfunction()
Here, When nothing is commented(find_package and include is not commented in any CMakelists.txt), I get the correct path for the two messages I print.
When I comment include(UseABC) in the second CMakelists.txt, the configuration fails, the first message is not at all printed and the second message gets printed, but does not give the value of the variable. It also deletes all the files in Folder C (but the argument to REMOVE_RECURSE is empty).
If I correctly understand the situation, you have:
CMakeLists.txt:
add_subdirectory(B)
add_subdirectory(C)
B/CMakeLists.txt:
find_package(ABC)
include(UseABC)
In that case run_command function, defined in UseABC.cmake, is accessible in C/CMakeLists.txt, though this script doesn't define it.
In CMake function definitions are global.
By opposite, variable definitions are local to the scope, where they are defined. (Until variables are cached ones, in that case they have global visibility).
That is, variable ABC_COMPILE_DEBUG defined in UseABC.cmake is accessible in
UseABC.cmake script
B/CMakeLists.txt script, because it includes UseABC.cmake one, and include() command doesn't introduce a scope
but it is inaccessible in
CMakeLists.txt script, because add_subdirectory(B) does introduce a scope
C/CMakeLists.txt script
More details about variable's visibility can be found in documentation.
Say I have a project, whose folder structure looks like below:
| main.lua
|
|---<model> // this is a folder
| |a.lua
| |b.lua
|
|---<view>
|a.lua
|b.lua
model/a.lua requries model/b.lua: require "b"
view/a.lua requries view/b.lua: require "b"
main.lua requries files in model and view.
Now I have problem to get these modules loaded correctly. I know I can fix it by changing the require calls to:
model/a.lua: require "model.b"
view/a.lua: require "view.b"
But if I do that, I have to modify these files every time when I change the folder structure.
So my questions are:
How to fix the module path issue without hard code paths in module files?
Why Lua doesn't use the module search rule of Node.js, which looks easier?
When you require a module, the string parameter from require gets passed into the module which you can access using the variable-argument syntax .... You can use this to include other dependent modules which reside in the same path as the current module being requireed without making it dependent on a fixed hard-coded module name.
For your example, instead of doing:
-- model/a.lua
require "model.b"
and
-- view/a.lua
require "view.b"
You can do:
-- model/a.lua
local thispath = select('1', ...):match(".+%.") or ""
require(thispath.."b")
and
-- view/a.lua
local thispath = select('1', ...):match(".+%.") or ""
require(thispath.."b")
Now if you change directory structure, eg. move view to something like control/subcontrol/foobar, then control/subcontrol/foobar/a.lua (formerly view/a.lua) will now try to require control/subcontrol/foobar/b.lua instead and "do the right thing".
Of course main.lua will still need to fully qualify the paths since you need some way to disambiguate between model/a.lua and view/a.lua.
How to fix the module path issue without hard code paths in module files?
I don't have any better cross-platform solution, maybe you should plan the folder structure early on.
Why Lua doesn't use the module search rule of Node.js, which looks easier?
Because Lua tries its best to rely only on ANSI C, which is really successful. And in ANSI C, there's no such concept of directories.
There are a couple approaches you can use.
You can add relative paths to package.path as in this SO answer. In your case you'd want to add paths in main.lua that correspond to the various ways you might access the files. This keeps all the changes required when changing your directory structure local to one file.
You can add absolute paths to package.pathusing debug.getinfo -- this may be a little easier since you don't need to account for all the relative accesses, but you still need to do this in main.lua when changing your directory structure, and you need to do string manipulation on the value returned by debug.getinfo to strip the module name and add the subdirectory names.
> lunit = require "lunit"
> info = debug.getinfo(lunit.run, "S")
> =info.source
#/usr/local/share/lua/5.2/lunit.lua
> =info.short_src
/usr/local/share/lua/5.2/lunit.lua
The solution is to add the folder of main.lua (project root) to package.path in main.lua.
A naive way to support folders of 1 level deep:
-- main.lua
package.path = package.path .. ";../?.lua"
Note for requires in (project root) will look up files outside of project root, which is not desirable.
A better way of to use some library (e.g.: paths, penlight) to resolve the absolute path and add it instead:
-- main.lua
local projectRoot = lib.abspath(".")
package.path = package.path .. ";" .. projectRoot .. "/?.lua"
Then in you source use the folder name to scope the files:
-- model/a.lua
require "model.b"
-- you can even do this
require "view.b"
and
-- view/a.lua
require "view.b"