Lein compile project with protocols - clojure

I have a project with following ns:
processor.bus <- general protocol for bus operations
processor.core <- main class to run
processor.pubsub <- concrete bus methods
in processor.pubsub I have following:
(ns processor.pubsub
(:gen-class))
(defrecord PubsubBus [client])
; + other stuff related to this implementation
In processor.bus I have:
(ns tiptop.processor.bus
(:gen-class)
(:import [processor.pubsub PubsubBus]))
(defprotocol SendToBus
(send-line! [self json]))
(extend-type PubsubBus
SendToBus
....)
The problem that Lein doesn't compile namespaces in right order. I get following error:
$ lein compile
Compiling user
Compiling processor.auth
Compiling processor.bus
java.lang.ClassNotFoundException: processor.pubsub.PubsubBus, compiling:(bus.clj:1:1)
Exception in thread "main" java.lang.ClassNotFoundException: processor.pubsub.PubsubBus, compiling:(bus.clj:1:1)
Notice it tries to compile my ns in alphabetical order (auth -> bus -> pubsub), instead if dependency order.
Of course I could precompile pubsub.clj before, like:
$ lein compile processor.pubsub
$ lein compile processor.bus
$ lein compile
But it doesn't seems quite right for me. What if I'll have more such dependent namespaces?
How I can tell Lein in which order it should compile my namespaces? Or maybe i'm missing something to configure in project.clj? I have :aot :all if it matters

Leiningen does not do anything to determine namespace dependencies - it simply compiles the namespaces that you tell it to. It is the Clojure compiler that handles namespace dependencies via the require (and obsolete use) built-ins.
In this case, you need to :require the namespace that defines the generated class before you can import it. Otherwise, you're relying on the imported class being present on the classpath as a side effect of some other operation (loading the namespace that defines it in the REPL, a previous lein compile command, etc). Adding an explicit :require in the namespace definition ensures the class is defined before it's imported:
(ns processor.bus
(:gen-class)
(:require [processor.pubsub])
(:import [processor.pubsub PubsubBus]))
A couple of other notes:
I doubt :gen-class is doing what you think it's doing in these namespace declarations. It does not cause class files to get written for the protocol and records defined in these namespaces; that's what the :aot key is for in the Leiningen project.clj. The :gen-class flag as it's used here will cause classes named processor.bus and processor.pubsub to be generated.
It's unusual to see protocol implementation details for concrete record types specified via extend-type in the same namespace where the protocol is defined. The typical use case for extend-type is to extend your protocol to work with types that are beyond your control, like those built in to Clojure or defined in third-party libraries. When the protocol and record are defined in the same project, it's more common to see the protocol implementation defined inline as part of the defrecord body.

Related

What structure should I have for mocking an embedded systems class for desktop testing?

I am building an embedded application in C++, but I want to test it through conventional continuous integration techniques. I am working on a library that depends on functions of the hardware such as printing, outputting to a pin, reading in analog data, etc.. Lets call the library lib and the hardware functions core(hardware.h). I have a mock class that covers all of these functions(hardware.h). The issue is that when I compile the code for the embedded application I need to include a header file for the hardware definitions, but I want to swap this out for the mock header when I want to do testing. Is there a way to get Cmake to do this? Should I be doing this a different way? Any suggestions would be appreciated.
I have made this work in IDE and such, but never with cmake and continuous integration.
-Lib
--src
---button.h
---button.cpp
--test
---testButton.cpp
-core
---hardware.h
-Mock
---hardware.h
//button.h
#include hardware.h
setPinMode(Input);
Is there a way to have cmake link the correct hardware.h up to the mock during debugging and the core during release?
We deal with this normally in the following way:
--lib
---hardware_interface.h
---etc
--MCU_TYPE
---main.cpp
---hardware_mcu_type.h
---hardware_mcu_type.cpp
--test
---main.cpp
---hardware_mock.h
As you can see we have a generic folder with common code. All code in the library uses the interface class from hardware_interface.h (we often have multiple interfaces for I2C, SPI, UART etc. all defined in separate files). All classes making use a specific interface have a function to set a pointer or reference to the interface. This is done in the main.cpp files.
Now these interfaces are pure virtual. When building an application it is thus required to fill these in. This is where either hardware_mcu_type.h or hardware_mock.h come in. In the main for the actual mcu the actual hardware implementations are used. When testing on a pc the mock objects are used.
You do need at least a switch in the CMakeLists.txt file building the different files for different builds.
Side note: please not that memory access and allocation is difficult to test on a different platform as this may vary. The unit tests are best focused on testing logic.
Declare a macro "MOCK_TEST", which when defined causes your mock code to get compiled, and when its not defined causes your embedded Hardware Abstraction Layer to be compiled. This way you can selectively compile mock/HAL.
//------ hardware.cpp ------
#ifdef MOCK_TEST
<Mock code>
#elif
<HAL code>
#endif
Pass this macro using the compiler option -D (in gcc) while compiling the mock.
$CC -c -DMOCK_TEST hardware.cpp (for compiling mock)
Integrate these changes for the two targets you are defining in CMake.

Pycparser not working on preprocessed code

I need to use pycparser on preprocessed C code (the results produced by 'gcc -E'). However I am currently running into issue that I can't understand or solve.
I am using the provided samples year2.c and func_defs.py, which i modified to use a variety of preprocessors and fake libraries to no avail. Maybe some of you can look into this and see if you can reproduce/solve the issue. I will append all necessary code.
The errors were generated using year2.c (regular sample file) and year2.i ('gcc -E' output). There was no useable result for the latter while the former worked with both preprocessor/fakelib variants.
I have created a bitbucket repo with all relevant errors, the script used (albeit only its last variation) and the year2.c and year2.i files.
Error & Sample Repo
Thanks for your time.
The error you're getting is:
pycparser.plyparser.ParseError: /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h:40:27: before: __gnuc_va_list
The line indicated as causing the error (stdarg.h:40):
typedef __builtin_va_list __gnuc_va_list;
In gcc, __builtin_va_list is, as its name indicates, built in to the compiler. Consequently, no declaration of that type is necessary (or allowed).
It's pretty common for C compilers to use a symbol-table-based technique to parse typenames, since there are a number of ambiguities in the grammar if you cannot distinguish a typename from another identifier. Such a parser will assume that an undeclared identifier is not a typename, and if __builtin_va_list is not a typename, that typedef is a syntax error.
So I suppose that the pyparser grammar you're using doesn't know about gcc builtin types (and why should it?).
Your fakelib seems to be including the same header file. That's not surprising since it is hard to fake stdarg.h; although technically a library header, it is part of the small set of headers which must be provided by the compiler even in a freestanding (no standard library) implementation: <float.h>, <iso646.h>, <limits.h>, <stdalign.h>,
<stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and
<stdnoreturn.h> (C11 standard, clause 4, paragraph 6). These must be implemented by the compiler because there is no way an external library can know enough about the nature of the compiled code to properly define them.
Depending on what you require from the pyparsed output, you may be able to workaround this for pyparser by including a definition of __builtin_va_list, such as:
typedef struct __builtin_va_list { } __builtin_va_list;
__builtin_va_list is not the only builtin gcc datatype, although you may not run into the other ones. So you might have to iterate this solution a few times until you achieve whatever it is you are trying to achieve.
As #rici has explained the cause of the error. I'd focus more on how to solve it. I've taken my answer from pycparser author's blog -
http://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers
The idea is that pycparser needs to know what anyheader.h contains so it can properly parse the code. As actually parsing anyheader.h and all the other headers it transitively includes, could be very time consuming and perhaps not required for your task, fakeheaders can be used. A fake anyheader.h will only contain the parts of the original that are necessary for parsing - the #defines and the typedefs.
gcc -nostdinc -E -I/home/rg/pycparser-master/utils/fake_libc_include test.c > testPP.c
The above command preprocess test.c which contains <stdio.h> using fake headers provided with pycparser package. -nostdinc flag is used to block some pre-set system header directories that gcc automatically includes. Now, parsing the preprocessed file, using e.g. below code
import pycparser
pycparser.parse_file('testPP.c')
should work in the most of the cases. If it doesn't make sure you provide all the dependencies for preprocessing.
In case, for some headers fakes are not provided, you can fake error causing typedef using #defining e.g. to resolve an error caused by __builtin_va_list, you can try faking it as follows:
gcc -nostdinc -E -D'__builtin_va_list(x)=' -I/home/rg/pycparser-master/utils/fake_libc_include test.c > testPP.c

How to load and use native c code in a lein project?

ProblemI'm unable to load and call methods in a compiled c class into a leiningen project. My basic approach is to load a Java class, JavaWrapper.java, that uses JNI to call some native methods in the native code, wrapper.o and then call the methods through this java wrapper class.
I imagine there are classLoader issues with loading a java class which loads the native code from a clojure project, but given that I can't seem to directly get clojure code to find the wrapper.o on the library path, I'm not sure how to handle this.
lein project file
(defproject lein-native-test "0.1.0-SNAPSHOT"
...
:java-source-paths ["java-path"]
:jvm-opts ["-Djava.library.path=.:./native:/absolute/path/to/native"] ;;not sure what format it wants
)
clojure file with main method
I've tried it slightly modified with four approaches, all included in code below along with respective error in comments.
(ns lein-native-test.core
(:import (com.test JavaWrapper)))
(def -main []
;;four things I've tried and their errors
(clojure.lang.RT.load "/abs/path/to/wrapper.o") ;;could not find file /abs/path/wrapper.o_init.class or wrapper.o.clj
(clojure.lang.RT.loadLibrary "wrapper.o") ;;UnsatisfiedLinkError no wrapper.o in java library path
(JavaWrapper/load "/abs/path/to/wrapper.o") ;;UnsatisfiedLinkError com.test.JavaWrapper.setup()
(assembly-load "/abs/path/to/wrapper.o") ;;unable to resolvesymbol: assembly-load
)
Java code with native methods that uses JNI, JavaWrapper.java
public class JavaWrapper{
public native void setup();
public static void load(String lib){ System.load(lib);}
}
Before trying to get this to work with clojure and lein I did successfully load and use the native methods in wrapper.o via JavaWrapper and JNI.
Possibly related: I'm also unable to load wrapper.o in JavaWrapper.java via
System.loadLibrary("wrapper.o");
I have to use
System.load("/absolute/path/to/wrapper.o");
Versions of tools
clojure version: 1.5.1
lein version: 2.3.4
jdk: 1.7
os: debian7
A better understanding of ClassLoaders or especially a working simple example would be very useful, thanks.
The problem was due to an naming error in my method in the C header and source files per the jni standard. The correct way to use jni with clojure is to create a Java wrapper class as I have done and load the dynamic library with the method
clojure.lang.RT.loadLibrarySince I've had trouble finding good examples for this I've made a demo on github
Errors
1) (clojure.lang.RT.load "/abs/path/to/wrapper.o") ;;could not find file /abs/path/wrapper.o_init.class or wrapper.o.clj
This load method is not meant to be used for native code, its expecting a java class or a clj file
2) (clojure.lang.RT.loadLibrary "wrapper.o") ;;UnsatisfiedLinkError no wrapper.o in java library path
Clojure is unable to find the library at link time, hence UnsatisfiedLinkError --- this is due to a naming error
first the library should be compiled as a dynamic shared library, i.e. for the gcc compiler use the -shared flag (I actually did but didn't name the output file with the normal .so extension)
java and thus clojure expect the native library to be named in a very specific way: libwrapper.so (or .jnilib for mac or .dll for windows but always with "lib" prefix)
3) (JavaWrapper/load "/abs/path/to/wrapper.o") ;;UnsatisfiedLinkError com.test.JavaWrapper.setup()
This time the error is on a method within JavaWrapper in the file or library, thus you know that at least it found the file. An UnsatisfiedLinkError that specifies a specific method in the Java class, like this one, should always be due to a naming error between what is declared a native method in the Java file and what is actually present in the c source or header file.
Note the namespace "com.test"
When declaring a jni method in c the method name must follow a specific format,
from http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html
"Dynamic linkers resolve entries based on their names. A native method name is concatenated from the following components:"
the prefix Java_
a mangled fully-qualified class name
an underscore (_) separator
a mangled method name
for overloaded native methods, two underscores (__) followed by the mangled argument signature
In this case the full c source method signature would be
void Java_com_test_setup(JNIEnv *env, jobject obj)
4) (assembly-load "/abs/path/to/wrapper.o") ;;unable to resolvesymbol: assembly-load
This method too is not meant to load native code

Switching from Windows to Linux causing error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before [duplicate]

I'm trying to port the speakhere example into another app and I'm having issues. I copied all the files, and all the frameworks, but for some reason I get a bunch of compile errors that I've never seen before and thus don't know what to do. The only difference is that i'm not suing IB and so i had to change it slightly.
What does error: expected '=', ',', ';', 'asm' or '__attribute__' before 'foo' mean?... I get this error multiple times for different files
In my situation the first error is pointing at 'MeterTable'.. a class that includes <stdlib.h>,<stdio.h> and <math.h>. But those files seem to be importing fine (if i remove them i get more errors)
Any suggestions on how to debug this?
TIA!
EDIT:
I still can't seem to figure it out. I'm literally just copying files from the example into another project. Can someone check it out please ? SpeakHerePort.zip and the original is here SpeakHere.zip
Your problem is that you are compiling SpeakHerePortAppDelegate.m, which is an Objective C file, but it is indirectly including MeterTable.h which is a C++ header file.
Rename it to SpeakHerePortAppDelegate.mm (double m) so that it is compiled as Objective C++ and your problem is resolved.
Name all your files .mm and then all your code will be compiled as Objective C++
In my case, the .h and .m in question are built fine with regular target, and the App can run as well.
However after the subset of the files are moved under a static library target, it gets this compile error when the static library is built.
Was stuck for a while & tried the above mentioned techniques, unfortunately they didn't help in my case.
Noted that this error happened only for the NSString*, for e.g.,
extern double const kTimeout; // fine
extern NSString* const kImageType; // compile error
After the above analysis & little break, eventually the problem is resolved by adding the the following import to the .h - "Foundation/Foundation.h"
It sounds like an unfinished declaration, probably in a header file. Search for 'foo' (or whatever the symbol actually is) across all project files, using ⇧⌘F (Edit ▸ Find ▸ Find In Project...) in Xcode, and/or examine the headers you're including where MeterTable is declared. Sometimes the compiler gets confused about the actual location of the error, since header files are frequently #imported into other files, so the problem can be manifest in multiple locations.
This might not have applied to this exact situation, but I had this exact error too, which was caused by a bad forward declaration. In Objective-C, make sure your forward-declares begin with the # sign - e.g.
#class MyClass;
Those of us still on autopilot from C++ will forget the #, see that XCode has highlighted class as a reserved keyword, and think all is well with the world. It is not.
It means that you have a syntax error. If you paste the code in question, it's easier to debug.
I had a similar scenario to some of the posts above. I'd written a C++ class based off of the examples in the Audio Queue Services documentation, and had this compilation issue in a test project. This post helped a tremendous amount.
Today, I'm incorporating the C++ class in my project, and got the build error again. In my scenario, I had to also set the type (using the "Get Info" window) to sourcecode.cpp.objcpp for the objective-c class that was calling my C++ class.

Why does OS X define 'nil'

At least the libsigc++2 project is hit by OS X headers defining nil on the preprocessor level, outside of namespaces etc. At least 10.5.5 and XCode 3.1 have this. Note that it is in effect not only in Objective-C sources but C++ as well.
Short question: why?
http://ardour.sourcearchive.com/documentation/2.5/functor__trait_8h-source.html
p.s. I remember nil from Objective-C, too. But I don't see a justification of such a blunt (imho) define for other languages, affecting code that has nothing to do with Objective-C at all (s.a. pure C++ projects).
I'm using 10.5.6 and XCode 3.1.2. I just tried using nil on my pure cpp project, and it wasn't defined:
main.cpp:41: error: 'nil' was not declared in this scope
My guess is that your project is somehow including Cocoa or another Objective-C library. Perhaps your code is being compiled as Objective-C++? It can compile any combination of C++ and Objective-C, so existing C++ code may compile. This is the default for files with the .mm extension.
Did you create the XCode project for this library? If so, perhaps it is using XCode's prefix header that comes with the Framework template, which includes Cocoa/Cocoa.h. Check the "Prefix Header" option in the project and target info.
I also grepped through /usr/include, and didn't find any instances of #define nil.
[Edit: The .h file you linked to may #undef nil because it can also be used from Objective-C++.]