I am trying to access modules from the parser.rs and another.rs in the solve.rs. How to include those modules and use the "use statements"? If that is not possible what should be the code structure?
Here is the application folder tree:
app/src
--- main.rs
--- another.rs
--- mod.rs
--- parser/
-------- parser.rs
-------- mod.rs
--- solver/
-------- solve.rs
-------- mod.rs
Your first option is absolute paths:
use crate::parser::Whatever;
use crate::solver::Another;
crate here is a keyword representing the crate root.
You can also use relative paths for advanced scenarios. Both solutions are discussed very nicely in the relevant Rust Documentation
Also, don't forget that you need to make the modules public. They will be private by default and not accessible from parents or siblings.
To access parser/parser.rs and another.rs from anywhere in your crate, you can use absolute paths (here I am also using nested paths, which is not required but makes the structure of modules more clear):
use crate::{
parser::parser,
another,
};
You can also use relative paths with super, which refers to the parent module. More information is avaiable in #Ishmaeel's answer.
Regarding your code structure, it seems a little strange why you have mod.rs (not wrong, but just strange, especially 0; you can totally leave 1 and 2 if you like it, but 0 might confuse you):
app/src
main.rs
another.rs
mod.rs // 0
parser/
parser.rs
mod.rs // 1
solver/
solve.rs
mod.rs // 2
Regarding 1 and 2:
mod.rs was used in the 2015 edition for being able to create nested modules, but is no longer needed in the 2018 edition (assuming that you are using the currently newest and default for cargo 2018 edition, see What are editions?):
A foo.rs and foo/ subdirectory may coexist; mod.rs is no longer needed when placing submodules in a subdirectory.
Regarding 0:
The module you are defining via this is actually named mod (not src as you may have expected, though I'm not sure at all what you expected here), I'm unsure if you meant to do that. However if you did, there is still a way to access it via r# - raw identifiers, available since Rust 1.30:
use crate::r#mod;
If you don't want to write r#mod all over the place, you can use as like this:
use crate::r#mod as new_name;
Then you can refer to the module via new_name.
Related
I have two projects sharing some code. Both have their own tools for generating almost the same boilerplate code, which are defined as a CMake target that runs everything when imported (or used as dependency). Let's assume that it is called generator_A in project A and generator_B in project B.
There are components that are shared "cloned" in both projects that use this boilerplate code, so for component_1 the CMakeLists.txt on each project would have something like:
# In project A
find_package(generator_A)
add_library(component_1 ...)
target_link_libraries(component_1 generator_A)
# In project B
find_package(generator_B)
add_library(component_1 ...)
target_link_libraries(component_1 generator_B)
Apart from this and other small differences regarding the generated code, component_1 would work in both projects.
I would like to define some intermediate layer for the generators on each project, so that its usage is independent of the project and look like:
find_package(generator_unified)
add_library(component_1 ...)
target_link_libraries(component_1 generator_unified)
For reasons not under my control, I cannot change anything about the generators (e.g. names, how they work, generated code/products).
I have no idea what is the best way to do this. Some ideas that I've found searching docs and the internet:
Create a Findgenerator_unified.cmake file that defines a generator_unified::generator_unified from the products of generator_X in project_X (library, headers, other properties?). I am not really how this can be achieved, though.
Does generator_unified needs its own CMakeLists.txt file, or is it enough with the Find<>.cmake.
How can I make sure that the Find<>.cmake file is available for others?
Create some kind of alias that can be used project-wide. This doesn't look possible according to docs .
Is this a better way to achieve this? If 1st alternative is the correct,
Something like this ought to work (your first alternative):
# Findgenerator_unified.cmake
cmake_minimum_required(VERSION 3.23)
if (${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
set(quiet QUIET)
else ()
set(quiet "")
endif ()
if (${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
set(required REQUIRED)
else ()
set(required "")
endif ()
set(known_backends generator_A generator_B)
set(GENERATOR_UNIFIED_BACKEND "generator_A"
CACHE STRING "Which generator backend package to use.")
set_property(CACHE GENERATOR_UNIFIED_BACKEND
PROPERTY STRINGS "${known_backends}")
foreach (backend IN LISTS known_backends)
if (backend IN_LIST ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS)
set(GENERATOR_UNIFIED_BACKEND "${backend}")
endif ()
endforeach ()
if (GENERATOR_UNIFIED_BACKEND IN_LIST known_backends)
find_package("${GENERATOR_UNIFIED_BACKEND}" ${quiet} ${required})
set("${CMAKE_FIND_PACKAGE_NAME}_${GENERATOR_UNIFIED_BACKEND}_FOUND"
"${${GENERATOR_UNIFIED_BACKEND}_FOUND}")
endif ()
unset(known_backends)
unset(quiet)
unset(required)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
generator_unified
HANDLE_COMPONENTS
REQUIRED_VARS "${GENERATOR_UNIFIED_BACKEND}_FOUND"
VERSION_VAR "${GENERATOR_UNIFIED_BACKEND}_VERSION"
)
if (generator_unified_FOUND AND NOT TARGET generator::unified)
add_library(generator::unified ALIAS "${GENERATOR_UNIFIED_BACKEND}")
endif ()
This is mostly boilerplate, but the key is in the last few lines... the generator::unified target is set up as an alias to whichever backend was selected.
When a consuming project goes to install a target using this, they will need to generate code that forces the backend to be the same. The HANDLE_COMPONENTS flag naturally handles this because the component name matches the sub-package name. Users will write the following snippet in their project config files:
# proj-config.cmake.in
# ...
include(FindDependencyMacro)
find_dependency(generator_unified COMPONENTS #GENERATOR_UNIFIED_BACKEND#)
# ...
I want my libraries to be generated as lib-something.so.1.0.0 and not liblib-something.so.1.0.0. For this, I used the proposals from this link: stop_preppending_'lib'_to_libs. But it seems that CMake is not able to find the library anymore.
This is what I did:
lib-something/src/CMakeLists.txt:
add_library(lib-something SHARED
${CMAKE_CURRENT_SOURCE_DIR}/Something.cpp )
set_target_properties(lib-something PROPERTIES PREFIX "")
lib-another/src/CMakeLists.txt:
add_dependencies(lib-another lib-something)
It is able to find it if I do:
add_dependencies(lib-another something)
altough my target is named 'lib-something'. I don't want that. If I were okey with having to add dependencies as 'something' I would have removed the 'lib' from the target name and it would have been enough. I find this an easy way to be identified by the users as libraries and not executables.
Any ideas?
Edited:
I also tried this:
add_library(something SHARED
${CMAKE_CURRENT_SOURCE_DIR}/Something.cpp )
set_target_properties(something PROPERTIES OUTPUT_NAME "lib-something")
In other projects:
add_dependencies(lib-another lib-something)
It works, but it looks that the generation of the libraries is also liblib...
As far as I have seen, there is no way to avoid this 'liblib' thing without changing the prefix into "", and if this prefix is changed then the library is not found no matter what.
After some time I spent staring at the jbake code, I figured out that if I declare my own property in jbake.properties :
...
foo=bar
...
I can reuse that in files that go through a template engine by referencing it as ${config.foo}. I'd like to have this substitution working also on the content lvl, i.e. for files written in asciidoc, living inside the content directory.
Is there any non-trivial way to achieve it? How can I make the templating engine to proccess the result of asciidoc parses engine, or make it running it before the asciidoctor?
I found the answer myself.
To use the property substitution in asciidoc files, add following to the jbake.properties:
...
asciidoctor.attributes.export=true
foo=world
...
and reference the variable in aFile.adoc this way:
Hello {foo}!
I have a JCR content repository implemented in ModeShape (4.0.0.Final). The structure of the repository is quite simple and looks like this:
/ (root)
Content/
Item 1
Item 2
Item 3
...
Tags/
Foo/
Bar/
.../
The content is initially created and stored under /Content as [nt:unstructured] nodes with [mix:shareable] mixin. When a content item is tagged, the tag node is first created under /Tags if it's not already there, and the content node is shared/cloned to the tag node using Workspace.clone(...) as described in the JCR 2.0 spec, section 14.1, Creation of Shared Nodes.
(I don't find this particularly elegant and I did just read this answer, about creating a tag based search system in JCR, so I realize this might not be the best/fastest/most scaleable solution. But I "inherited" this solution from developers before me, so I hope I don't have to rewrite it all...)
Anyway, the sharing itself seems to work (I can verify that the nodes are there using the ModeShape Content Explorer web app or programatically by session.getRootNode().getNode("Tags/Foo").getNodes()). But I am not able to find any shared nodes using a query!
My initial try (using JCR_SQL2 syntax) was:
SELECT * FROM [nt:unstructured] AS content
WHERE PATH(content) LIKE '/Tags/Foo/%' // ISDECENDANTNODE(content, '/Tags/Foo') gives same result
ORDER BY NAME(content)
The result set was to my surprise empty.
I also tried searching in [mix:shareable] like this:
SELECT * FROM [mix:shareable] AS content
WHERE PATH(content) LIKE '/Tags/Foo/%' // ISDECENDANTNODE(content, '/Tags/Foo') gives same result
ORDER BY NAME(content)
This also returned an empty result set.
I can see from the query:
SELECT * FROM [nt:unstructured] AS content
WHERE PATH(content) LIKE '/Content/%' // ISDECENDANTNODE(content, '/Content') works just as well
ORDER BY NAME(content)
...that the query otherwise works, and returns the expected result (all content). It just doesn't work when searching for the shared nodes.
How do I correctly search for shared nodes in JCR using ModeShape?
Update: I upgraded to 4.1.0.Final to see if that helped, but it had no effect on the described behaviour.
Cross-posted from the ModeShape forum:
Shared nodes are really just a single node that appears in multiple places within a workspace, so it's not exactly clear what it semantically means to get multiple query results for that one shareable node. Per Section 14.16 of the JSR-283 (JCR 2.0) specification implementations are free to include shareable nodes in query results at just one or at multiple/all of those locations.
ModeShape 2.x and 3.x always returned in query results only a single location of the shared nodes, as this was the behavior of the reference implementation and this was the feedback we got from users. When we were working on Modeshape 4.0, we tried to make it possible to return multiple results, but we ran into problems with the TCK and uncertainty about what this new expected behavior would be. Therefore, we backed off our goals and implemented query to return only one of the shared locations, as we did with 2.x and 3.x.
I may be wrong, but I'm not exactly sure if any JCR implementation returns multiple rows for a single shared node, but I may be wrong.
what is a proper way of organizing files in a wcm that is using JCR. Let's say the total file count is 100,000+ files and total file size is about 50-70GB.
Is it better to organize files by fie types ( and create sub directories to further group the files by some category)
What are the advantages. Does it make any difference while using query api, maintenance, or something.
Proposal 1:
--shared
------images
------pdf
------movies
--location1
------images
------pdf
------movies
--location2
------images
------pdf
------movies
Proposal 2:
--pdf
-------shared
-------location1
-------location2
--images
--------shared
--------location1
--------location2
.. etc
Take a look at this: David's Model: A guide for content modeling
Some highlights:
Data First, Structure Later. Maybe.
Drive the content hierarchy, don't let it happen.
Workspaces are for clone(), merge() and update().
Beware of Same Name Siblings.
References considered harmful.
Files are Files are Files.
ID's are evil.
Whatever you do, make sure you don't end up with more than a 1000 child nodes under any given node.
Just as in any (real) file system, when you want to list a folder with a lot of files/subfolders in it, it can take some time.
By default Jackrabbit 2.x will now hash up the user space.
ie:
/users/s/sa/sandra
/users/s/si/simong
...
I would personally go for your first proposal as it makes more sense.
We have a webapp where all our users can upload/delete/modify their files in JCR and did it this way:
/_users/s/si/simon/public
/_users/s/si/simon/public/My Pictures
/_users/s/si/simon/public/My Pictures/2010/06/Trip to the US
/_users/s/si/simon/public/My Pictures/2010/06/Trip to the US/DC1001.jpg
/_users/s/si/simon/private/account_details.txt
...
We're loosely following the way home folders are done in UNIX-like systems.
We try to hash up all the things we (reasonably) can. Like the for example the user space (/s/si/simong) but also things like messages:
/_users/s/si/simong/messages/2009/12/25/ab34ed87dee
/_users/s/si/simong/messages/2010/03/12/e4f1de3cd48
...
However it's up to the individual user to not have more then 1000 child files in a given folder (we do warn them though.)
Doing it this way also gives you a nice benefit of exercising Access Control.
ie: everthing under ~/private is only read- and writeable by the current user, ~/public is readable by everybody.