Using webpack compiled library as external in CLJS - clojure

I have some legacy code which uses D3 and is compiled with webpack.
I'm toying with the idea of porting the D3 bits as external library, and wrapping them as a reagent/re-frame component, yet I have problems importing the JS bits.
I created a small project which demonstrates the problem:
The JS library code .
The webpack config used to (UMD) compile it.
The compiled library (without minify for readability).
Now in a JS project I would use the library like this:
import * as module from 'd3-lib.js'
var m = new module.Module()
m.setData("miserables.json").render();
I tried to mimick that:
I specify the ns the library provides using foreign-libs in project.clj.
Import the library.
Instantiate via the JS-interop
Yet I keep getting:
Uncaught Error: goog.require could not find: d3_lib

Have you tried to use the d3 package from cljsjs ?
Using the cljsjs/d3 package
Add the dependency coordinates [cljsjs/d3 "4.3.0-5"] to the list of :dependencies in your project.
Make sure to require cljsjs.d3 somewhere in your project so it is added to your compiled ClojureScript code.
(ns your.namespace
(:require [cljsjs.d3]))
You can now use your newly added library by accessing it through the global Javascript namespace, e.g.js/ReactPlease check the project's documentation to find out what global the library uses. Please note: You can not use :as or :refer with CLJSJS dependencies.

Related

Fail to import QML module using CMake

I'm currently building a minimalist app following this CMake architecture:
-root
--QmlModule
---Component1.qml
---Component2.qml
--App1
---main.cpp
---main.qml
--App2
---main.cpp
---main.qml
I use "qt6_add_qml_module" to create a QML module at "QmlModule" level as a STATIC library.
qt_add_library(myComponentTarget STATIC)
qt6_add_qml_module(myComponentTarget
URI QmlModule
VERSION 1.0
QML_FILES
Component1.qml
Component2.qml
RESOURCES
logo.png)
Then, at App1 (and App2) level, a link to the module is done using "target_link_libraries". "qt6_add_qml_module" does some work behind the scenes in order to expose the module trough an automatically generated plugin named "your_component_URIplugin". More details about this here.
add_executable(App1Exe
main.cpp)
qt6_add_qml_module(App1Exe
URI App1
VERSION 1.0
QML_FILES
main.qml)
target_link_libraries(App1Exe
PRIVATE
myComponentURIplugin)
At Root level, I overload QML_IMPORT_PATH in order to link to the build folder and add all subdirectories.
set(QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qmlModule)
add_subdirectory(QmlModule)
add_subdirectory(App1)
add_subdirectory(App2)
I run CMake without any errors, and open App1/main.qml file.
On my import QmlModule, the module can't be found:
module "lupinComponentsplugin" is not installed
How to make my module visible from my Apps ?
What step am I missing ?
I'm currently doing something similar.
I have created a demo app where I import modules. The modules provide QML and C++ items to the main app. Check the comments in the CMAKE files to find out how this works.
Here is the link:
https://gitlab.com/basic53/DemoApp
Feel free to comment on this.
Another tip: If qt_add_qml_module is not working properly, sometimes it is necessary to remove the whole build folder and update the QML code model. You can check the generated files to see, if your plugin has been created with all its types.
CMake itself was fine, this was a runtime error and not a link error.
This issue was raised because the QQmlApplicationEngine wasn't finding path towards my module's QMLDIR.
In the end, the only thing missing was an additional import path ":/" in QQmlEngine:
QQmlApplicationEngine engine;
engine.addImportPath(":/");

Finding out the name to `:require` in a namespace

I am following this tutorial: https://practicalli.github.io/blog/posts/web-scraping-with-clojure-hacking-hacker-news/ and I have had a hard time dealing with the :require part of the ns macro. This tutorial shows how to parse HTML and pull out information from it with a library called enlive, and to use it, I first had to put
...
:dependencies [[org.clojure/clojure "1.10.1"]
[enlive "1.1.6"]]
...
in my project.clj, and require the library in core.clj as the following:
(ns myproject.core
(:require [net.cgrand.enlive-html :as html])
(:gen-class))
I spent so much time finding out the name net.cgrand.enlive-html, since it was different from the package's name itself (which is just enlive), and I couldn't find it through any of the lein commands (I eventually found it out by googling).
How can I easily find out what name to require?
Practical approach
If your editor/IDE helps with auto-completion and
docs, that might be a first route.
Other than that, libraries usually have some read-me online, where they show off
what they do (what to require, how to use that).
Strict approach
If you really have nothing about a library, you will find the downloaded
library in you ~/.m2/repository directory. Note that deps without the naming
convention of "group/artifact" will just double on the artifact name, Next is
the version. So you can find your libraries JAR file here:
.m2/repository/enlive/enlive/1.1.6/enlive-1.1.6.jar.
JAR files are just ZIP-Files. Inside the JAR file you will usually find the
source files of the library. The directory structure reflects the package
structure. E.g. one file there is net/cgrand/enlive_html.clj (note the use
of the _ instead of -, this is due to name munging for the JVM). You then
can require the file in your REPL and explore with doc or dir etc. Or you
open this file, to see the docs and source code in one chunk.
Usually I get this from the documentation / tutorial for the library.
https://github.com/cgrand/enlive Check out the Quick Tutorial, which starts with the needed require.

Clojure not requiring a cljc file

I need to share a namespace between my Clojure (Garden) and my ClojureScript (Reagent).
Currently the project folder looks like this:
src/
clj/
name/
css.clj
cljs/
name/
core.cljs
cljc/
name/
config.cljc
The config.cljc file has the following namespace: (ns name.config).
I've tried to reference this namespace from inside clj/name/css.clj with a require.
(ns name.css
(:require [name.config :as config]))
However, this results in a compile error from Garden.
Caused by: java.io.FileNotFoundException: Could not locate name/config__init.class or name/config.clj on classpath.
I guess it's not even checking for cljc files.
I added "src/cljc" to the :source-paths vector in project.clj and :garden :builds but I get the same error even after restarting the build processes.
I see this behaviour on Clojure 1.7.0 and 1.8.0.
It might also be worth mentioning that it works without issues in ClojureScript (with Figwheel handling the build). I can require and use the new namespace without problems.
It seems like I must be missing something really simple, because none of the documentation around .cljc files even mentions requiring them.
Check if you’re using Clojure 1.7 or above in your project.clj. This error message:
Caused by: java.io.FileNotFoundException: Could not locate name/config__init.class or name/config.clj on classpath.
indicates that you’re using Clojure 1.6 or below, as those versions of Clojure only know to look for .class or .clj files.
I got this same error when I moved a file from .clj to .cljc in my project. I did lein clean but that had no effect. Eventually I renamed the module namespace and that fixed it.
(My guess is that there was some sort of cache of compiled modules and it was referencing a module which no longer existed, but the cljc wasn't re-compiled because a module of that name was still cached.)
When I renamed the module namespace it worked, with no other changes to the code.

Ember Cli - Transpiling vendor ES6 dependency in ember-cli-build?

I'm writing an Ember.js application using Ember Cli, and I want to include a non-bower dependency - basically a dependency from my vendor folder.
The instructions on doing so is telling me to add the following line into my ember-cli-build.js file:
app.import('vendor/dependency-to-include.js');
That would work fine with a normal ES5 flavored dependency, but what if I want to add a dependency written in ES6?
Right now it just delivers it to the browser untouched, which produces an error like:
Uncaught SyntaxError: Unexpected reserved word
because my ES6 flavored dependency uses the following syntax:
import Util from './util
I'm guessing that I need to tell ember-cli-build to transpile this particular dependency before passing it on to the browser, but how do I go about doing that?
Thanks
For transpiling imported dependencies you need to run the imported file(s) through the broccoli addon broccoli-babel-transpiler. For a basic example, checkout this file: https://github.com/thefrontside/ember-impagination/blob/2fa38d26ef1b27a3db7df109faa872db243e5e4c/index.js. You can adapt this addon to an in-repo addon for your project.
See this link for the background discussion and #rwjblue and #cowboyd on the actual fix: https://github.com/ember-cli/ember-cli/issues/2949
Are you currently including Babel within your project? I would have thought that it checks your vendor directory the same as it does everything else and converts the ES6 code to ES5.
The other option would be to just convert the file to ES5 manually whenever you need to include a vendor file with ES6 syntax. Not necessarily ideal, but if it's a static file then it's something you'll need to do once and then forget about.

Where to find valid version numbers for dependencies in Leiningen

I'm new to Clojure and Leiningen, and I've determined that some of what I'll want to use is located in clojure.contrib.generic.math-functions. I found API information for that at http://richhickey.github.com/clojure-contrib/branch-1.1.x/math-api.html, but I can't find anything that helps me figure out what I should put into my project.clj file for that dependency.
I have tried [clojure.contrib.generic.math-functions "1.1"], [clojure.contrib.generic.math-functions "1.1.x"], and [clojure.contrib.generic.math-functions "1.1.0"]. For each of those, I get something like...
...
Caused by: org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException: Missing:
----------
1) clojure.contrib.generic.math-functions:clojure.contrib.generic.math-functions:jar:1.1
All clojure-contrib namespaces are shipped within a single jar file, for which the dependency has to be listed like:
[org.clojure/clojure-contrib "1.2.0"]
Please note that there are different versions available of that artifact. The 1.2.0 is the current stable release.
In order to use functions coming from the math-functions namespace in your clojure code, you need to either require or use such namespace, usually done within the ns form at the beginning of your source file:
(ns my.namespace
(:use [clojure.contrib.generic.math-functions]))
Have a look here to see the differences between use and require.
The next version of Leiningen will have a search task for precisely this purpose. It will search Clojars, Maven Central, and any other repositories your project has listed, provided they offer up downloadable indices. It's already implemented, so if you run Leiningen from git you can use it.
Also, the Leiningen tutorial covers this. Type "lein help tutorial".
You can generally find what you need at clojars.org - it's the default repository for leiningen. The current stable release of Clojure is 1.2.0, so you'd have this in your leiningen project.clj:
[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
To use the generic math functions in your clojure, require or use it in your namespace declaration at the top of your source file:
(ns your-namespace
(:use [clojure.contrib.generic.math-functions :as mathf]))
This allows you to refer to the functions in that namespace like this:
(mathf/abs -10) ;; => 10
:use-ing namespaces with :as is the preferred way to use functions from other namespaces in your code. require is ok, but you'd have to prefix your functions with the entire namespace (e.g. clojure.contrib.generic.math-functions/abs) so that's not practical. Using a namespace without :as allows you to use these functions without any prefix at all (e.g. abs), but you're more likely to get namespace clashes and it might be difficult to see where functions come from, especially if you :use many libraries.
You can browse all libraries available from the default leiningen repository by checking out http://clojars.org/repo/. The structure of clojure-contrib will change when 1.3.0 is out, so you'll have to include the specific contrib library if you're using version 1.3.0-alpha-xx:
[org.clojure.contrib/generic "1.3.0-alpha4"]
Now that the clojure.contrib has been broken up, the math functions are in something called math.numeric-tower. The lein dependency is specified like this:
[org.clojure/math.numeric-tower "0.0.1"]
You can use or require as seems appropriate, for example
(use '[clojure.math.numeric-tower])