Things to remember when compiling/linking C/C++ software

Things to remember when compiling/linking C/C++ software

by Angel Leon. March 17, 2015; August 29, 2019.

Include Paths

On the compilation phase, you will usually need to specify the different include paths so that the interfaces (.h, .hpp) which define structs, classes, constans, and functions can be found.

With gcc and llvm include paths are passed with -I/path/to/includes, you can pass as many -I as you need.

In Windows, cl.exe takes include paths with the following syntax:
/I"c:\path\to\includes\ you can also pass as many as you need.

Some software uses macro definition variables that should be passed during compile time to decide what code to include.

Compilation flags

These compilation-time variables are passed using -D,
e.g. -DMYSOFTWARE_COMPILATION_VARIABLE -DDO_SOMETHING=1 -DDISABLE_DEPRECATED_FUNCTIONS=0

These compilation time flags are by convention usually put into a single variable named CXXFLAGS, which is then passed to the compiler as a parameter for convenience when you’re building your compilation/make script.

Object files

When you compile your .c, or .cpp files, you will end up with object files.
These files usually have .o extensions in Linux, in Windows they might be under .obj extensions.

You can create an .o file for a single or for many source files.

Static Library files

When you have several .o files, you can put them together as a library, a static library. In Linux/Mac these static libraries are simply archive files, or .a files. In windows, static library files exist under the .lib extension.

They are created like this in Linux/Mac:

ar -cvq libctest.a ctest1.o ctest2.o ctest3.o

libctest.a will contain ctest1.o,ctest2.o and ctest2.o

They are created like this in Windows:

LIB.EXE /OUT:MYLIB.LIB FILE1.OBJ FILE2.OBJ FILE3.OBJ

When you are creating an executable that needs to make use of a library, if you use these static libraries, the size of your executable will be the sum of all the object files statically linked by the executable. The code is right there along the executable, it’s easier to distribute, but again, the size of the executable can be bigger than it needs to… why? because, sometimes, many of the .o files, or even the entire .a file you’re linking against might be a standard library that many other programs need.

Shared Libraries (Dynamic Libraries)

So shared or dynamic libraries were invented so that different programs or libraries would make external (shared) references to them, since they’re “shared” the symbols defined in them don’t need to be part of your executable or library, your executable contain symbols whose entry points or offset addresses might point to somewhere within themselves, but they will also have symbols whose entry points are expected to exist on shared libraries which need only be loaded once in a single portion of the operating shared memory, thus not just making the size of your executable as small as it needs to be, but you won’t need to load the library for every process/program that needs its symbols.

On Linux shared files exist under the .so (shared object) file extension, on Mac .dylib (dynamic library), and in Windows they’re called .dll (dynamic link libraries)

Another cool thing about dynamic libraries, is that they can be loaded during runtime, not just linked at compile time. An example of runtime dynamic libraries are browser plugins.

In Linux .so files are created like this:

gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0   *.o
  • -Wall enables all warnings.
  • -c means compile only, don’t run the linker.
  • -fPIC means “Position Independent Code”, a requirement for shared libraries in Linux.
  • -shared makes the object file created shareable by different executables.
  • -Wl passes a comma separated list of arguments to the linker.
  • -soname means “shared object name” to use.
  • -o <my.so> means output, in this case the output shared library

In Mac .dylib files are created like this:

clang -dynamiclib -o libtest.dylib file1.o file2.o -L/some/library/path -lname_of_library_without_lib_prefix

In Windows .dll files are created like this:

LINK.EXE /DLL /OUT:MYLIB.DLL FILE1.OBJ FILE2.OBJ FILE3OBJ

Linking to existing libraries

When linking your software you may be faced with a situation on which you want to link against several standard shared libraries.
If all the libraries you need exist in a single folder, you can set the LD_LIBRARY_PATH to that folder. By common standard all shared libraries are prefixed with the word lib. If a library exists in LD_LIBRARY_PATH and you want to link against it, you don’t need to pass the entire path to the library, you simply pass -lname and you will link your executable to the symbols of libname.so which should be somewhere inside LD_LIBRARY_PATH.

Tip: You should probably stay away from altering your LD_LIBRARY_PATH, if you do, make sure you keep its original value, and when you’re done restore it, as you might screw the build processes of other software in the system which might depend on what’s on the LD_LIBRARY_PATH.

What if libraries are in different folders?

If you have some other libbar.so library on another folder outside LD_LIBRARY_PATH you can explictly pass the full path to that library /path/to/that/other/library/libbar.so, or you can specify the folder that contains it -L/path/to/that/other/library and then the short hand form -lbar. This latter option makes more sense if the second folder contains several other libraries.

Useful tools

Sometimes you may be dealing with issues like undefined symbol errors, and you may want to inspect what symbols (functions) are defined in your library.

On Mac there’s otool, on Linux/Mac there’s nm, on Windows there’s depends.exe (a GUI tool that can be used to see both dependencies and the symbol’s tables. Taking a look at the “Entry Point” column will help you understand clearly the difference between symbols linking to a shared library vs symbols linking statically to the same library)

Useful command options

See shared library dependencies on Mac with otool

otool -L libjlibtorrent.dylib 
libjlibtorrent.dylib:
	libjlibtorrent.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

See shared symbols with nm (Linux/Mac)
With nm, you can see the symbol’s name list.
Familiarize yourself with the meaning of the symbol types:

  • T (text section symbol)
  • U (undefined – useful for those undefined symbol error),
  • I (indirect symbol).

If the symbol is local (non-external) the symbol type is presented in lowercase letters, for example a lowercase u represents an undefined reference to a private external in another module in the same library.

nm‘s documentation says that if you’re working on Mac and you see that the symbol is preceeded by + or - it means it’s an ObjectiveC method, if you’re familiar with ObjectiveC you will know that + is for class methods and - is for instance methods, but in practice it seems to be a bit more explicit and you will often see objc or OBJC prefixed to those methods.

nm is best used along with grep 😉

Find all Undefined symbols

nm -u libMacOSXUtilsLeopard.jnilib
_CFRelease
_LSSharedFileListCopySnapshot
_LSSharedFileListCreate
_LSSharedFileListInsertItemURL
_LSSharedFileListItemRemove
_LSSharedFileListItemResolve
_NSFullUserName
_OBJC_CLASS_$_NSArray
_OBJC_CLASS_$_NSAutoreleasePool
_OBJC_CLASS_$_NSDictionary
_OBJC_CLASS_$_NSMutableArray
_OBJC_CLASS_$_NSMutableDictionary
_OBJC_CLASS_$_NSString
_OBJC_CLASS_$_NSURL
__Block_copy
__NSConcreteGlobalBlock
__dyld_register_func_for_add_image
__objc_empty_cache
__objc_empty_vtable
_calloc
_class_addMethod
_class_getInstanceMethod
_class_getInstanceSize
_class_getInstanceVariable
_class_getIvarLayout

My C++ code compiles but it won’t link

Linking is simply “linking” a bunch of .o files to make an executable.

Each one of these .o’s may be compiled on their own out of their .cpp files, but when one references symbols that are supposed to exist in other .o’s and they’re not to be found then you get linking errors.

Perhaps through forward declarations you managed your compilation phase to pass, but then you get a bunch of symbol not found errors.
Make sure to read them slowly, see where these symbols are being referenced, you will see that these issues occur due to namespace visibility in most cases.

Perhaps you copied the signature of a method that exists in a private space elsewhere into some other namespace where your code wasn’t compiling, all you did was make it compilable, but the actual symbol might not be visible outside the scope where it’s truly defined and implemented.

Function symbols can be private if they’re declared inside anonymous namespaces, or if they’re declared as static functions.

An example:

Undefined symbols for architecture x86_64:
  "FlushStateToDisk(CValidationState&, FlushStateMode)", referenced from:
      Network::TxMessage::handle(CNode*, CDataStream&, long long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, bool, bool) in libbitcoin_server.a(libbitcoin_server_a-TxMessage.o)

Here, when I read the code of Network::TxMessage::handle(...) there was a call to FlushStateToDisk, which was declared in main.h, and coded in main.cpp. My TxMessage.cpp did include main.h, compilation was fine, I had a TxMessage.o file and a main.o, but the linker was complaining.

The issue was that FlushStateToDisk was declared as a static, therefore only visible inside main.o, once I removed the static from the declaration and implementation the error went away and my executable was linked. Similar things happen when functions are declared in anonymous spaces in other files, even if you forward declare them on your local .h

In other cases your code compiles and you get this error linking because your library can’t be added using -lfoo, and adding its containing folder to -L doesn’t cut it, in this case you just add the full path to the library in your compilation command: gcc /path/to/the/missing/library.o ... my_source.cpp -o my_executable

Reminder:

DO NOT EXPORT CFLAGS, CPPFLAGS and the like on your .bash_profile/.bashrc, it can lead to unintended building consequences in many projects. I’ve wasted so many hours due to this mistake.

How to enable source highlighting when doing `less mycodefile.ext`

How to enable source highlighting when doing less mycodefile.ext

  1. Install source-highlight
    sudo apt install source-highlight

  2. Configure it on your .bash_profile

lessWithSourceHighlightSetup() {
  # location of the script may vary
  src_hilite_pipe_script=`dpkg -L libsource-highlight-common | grep lesspipe`
  export LESSOPEN="| ${src_hilite_pipe_script} %s"
  export LESS=' -R '
}


lessWithSourceHighlightSetup
  1. Use it on any code file less -N /path/to/mycode.ext

Screen Shot 2019-11-12 at 9 55 32 AM

Pascal Triangle Generator in Python, and then in Haskell – The Gubatron Method

Here’s in python, imperatively, and then in functional style without the need for loops.

def pascal(n):
if n == 1:
return [ 1 ]
if n == 2:
return [ 1, 1 ]
prev = pascal(n1)
results = []
for i in range(n):
if i == 0:
continue
if i == n1:
break
results.append(prev[i] + prev[i1])
return [1] + results + [1]
# functional style, no loops
def pascal_fp(n):
if n == 1:
return [ 1 ]
prev = pascal_fp(n1)
return list(map(lambda x,y:x+y, [0] + prev, prev + [0]))

view raw
pascal.py
hosted with ❤ by GitHub

Here’s in Haskell, I call it the gubatron’s method, explained in the comments.
Saw it by looking at a pattern while trying to solve it in paper, it just clicked.
Not sure if this is how other people code this solution.

Gubatron's method
n=3 [1, 2, 1]
copy the list and append a 0 on the left of the first
and append a 0 at the end of the second
[0, 1, 2, 1]
[1, 2, 1, 0]
add them up!
n=4 [1, 3, 3, 1]
append 0s to both sides and add them up
n=4 [1, 3, 3, 1]
[0, 1, 3, 3, 1]
[1, 3, 3, 1, 0]
n=5 [1, 4, 6, 4, 1]
and so on
add two lists, for clarity
addLists :: Num c => [c] -> [c] -> [c]
addLists l1 l2 = zipWith (+) l1 l2
pascal :: (Eq a1, Num a1, Num a2) => a1 -> [a2]
pascal 1 = [ 1 ]
pascal n =
let prev = pascal(n1)
zero_prev = [0] ++ prev
prev_zero = prev ++ [0]
in
addLists zero_prev prev_zero
[1,2,3] -> "1 2 3"
listToString = unwords. map show
mapM_ -> map monadic so no weird IO errors are triggered
printTriangle n = mapM_ putStrLn (map listToString (map pascal [1..n]))
main = do
input <- getLine
printTriangle . (read :: String -> Int) $ input

view raw
pascal.hs
hosted with ❤ by GitHub

 

Python in Functional Style: How to add 2 lists of integers without using loops

Usually you’d add a list of integers this way:

a = [2, 2, 2, 2]
b = [2, 2, 2, 2]
c = []
for i in range(len(a)):
 c.append(a[i] + b[i])

You can do it functionally without any loops in different ways:



Using map and a lambda that adds them up

c = list(map(lambda x,y: x+y, a, b))

or you can import the add operator as a named function

from operator import add
c = list(map(add, a, b))


Ever zipped two lists into a list of tuples?

There’s another more convoluted way if you want to play with “zip”.

Close End 10cm 80cm 5# 10pcs white Metal Zipper for Sewing ...
Imagine a jacket zipper and the teeth on each side of the zipper is one element on each one of the list.


When you zip the lists a and b, you end up with a list of tuples of matching elements from the given lists.

>>> list(zip(a,b))
[(2, 2), (2, 2), (2, 2), (2, 2)]

you could now map a function to add the elements within each tuple on that list.


>>> list(map(lambda tup: tup[0]+tup[1], zip(a,b)))
[4, 4, 4, 4]


Notice how we don’t convert to list after zip, we can work directly with the zip iterator, we only convert to list with the final map iterator.

Python 2 & 3 Note:

In Python 2 it’s not necessary to use list(), the map() and zip() methods return lists there. But stay away from Python 2, a lot of projects are now discontinuing support.

[CODING/SOLVED] gradle build (android) breaks after upgrading a dependency with NullPointerException thrown at ProgramClass.constantPoolEntryAccept

You’ve just upgraded one of your Android project’s dependencies and when you ./gradlew assembleRelease the build process breaks.

You invoke it again with --stacktrace to find the following exception:

 

java.lang.NullPointerException
at proguard.classfile.ProgramClass.constantPoolEntryAccept(ProgramClass.java:537)
at proguard.shrink.UsageMarker.markConstant(UsageMarker.java:1246)
at proguard.shrink.UsageMarker.visitRequiresInfo(UsageMarker.java:1040)
at proguard.classfile.attribute.module.ModuleAttribute.requiresAccept(ModuleAttribute.java:138)
at proguard.shrink.UsageMarker.visitModuleAttribute(UsageMarker.java:739)
at proguard.classfile.attribute.module.ModuleAttribute.accept(ModuleAttribute.java:99)
at proguard.classfile.ProgramClass.attributesAccept(ProgramClass.java:619)
at proguard.shrink.UsageMarker.markProgramClassBody(UsageMarker.java:124)
at proguard.shrink.UsageMarker.visitProgramClass(UsageMarker.java:94)
at proguard.classfile.visitor.MultiClassVisitor.visitProgramClass(MultiClassVisitor.java:67)
at proguard.classfile.visitor.MultiClassVisitor.visitProgramClass(MultiClassVisitor.java:67)
at proguard.classfile.visitor.ClassNameFilter.visitProgramClass(ClassNameFilter.java:128)
at proguard.classfile.ProgramClass.accept(ProgramClass.java:430)
at proguard.classfile.ClassPool.classesAccept(ClassPool.java:124)
at proguard.classfile.visitor.AllClassVisitor.visitClassPool(AllClassVisitor.java:45)
at proguard.classfile.visitor.MultiClassPoolVisitor.visitClassPool(MultiClassPoolVisitor.java:85)
at proguard.classfile.ClassPool.accept(ClassPool.java:110)
at proguard.shrink.Shrinker.execute(Shrinker.java:90)
at proguard.ProGuard.shrink(ProGuard.java:381)
at proguard.ProGuard.execute(ProGuard.java:145)
at proguard.ProGuard.main(ProGuard.java:572)

This is a ProGuard bug, which my friend, has been solved by the ProGuard team ages ago, and your build environment is using an old ProGuard version.

Add this to your build.gradle to force it to use the latest version (as of today it’s 6.2.2, check the latest version here)

buildscript {
    ...
    dependencies {
        ...
        classpath 'net.sf.proguard:proguard-gradle:6.2.2'
  }
}
}
force a newer proguard version for your android build

nginx server configuration for a wordpress instance served from a URL’s subdirectory

You want to serve a wordpress instance on a website’s domain url but not at the path’s root, you want it under a sub-directory, for example “blog”, the same as this blog:

https://www.gubatron.com/blog 

Here’s how my NGINX’s server block for ‘www.gubatron.com’ looks like at the moment (https/ssl hasn’t been configured yet)

server {
  server_name www.gubatron.com;
  listen 80;
  listen [::]:80;
  root /media/ebs/data/websites/gubatron.com/;
  index index.php index.html index.htm;

  # wordpress lives at gubatron.com/blog/...
  rewrite ^/blog/wp-admin/(.*) /blog/wp-admin/$1;
  #search redirect                                                                                                       
  rewrite ^/blog/(.*)s=(.*)$ /blog/index.php?s=$2;
  try_files $uri $uri/ /blog/index.php$is_args$args;

  location ~ \.php {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    include fastcgi_params;
  }
  location ~ \.git {
    deny all;
  }
}

Here is the equivalent in lighttpd, too bad lighttpd has no plans for HTTP2, it’s much friendlier and flexible to configure than nginx in my humble opinion.

$HTTP["host"] =~ "^gubatron.com$|^www.gubatron.com$" {
  server.document-root="/media/ebs/data/websites/gubatron.com/"

  $HTTP["url"] =~ "\.git" {
     url.access-deny = ("")
  }

  url.rewrite = (
            "^/blog/wp-admin/(.*)" => "$0",
            "^/blog/(.*)\.(.+)$" => "$0",
            "^/blog/(.+)/?$" => "/blog/index.php/$1"
  )
}

I used to host this website and wordpress on lighttpd, lighttpd’s config file is very powerful, it’s all based on matching server variables and applying rules, I will miss it dearly, things like having a compressed file cache and it’s flexibility, but I have to move on to nginx if I want to use http2, the lighttpd has no plans for http2 support and it’s just much faster and efficient than http 1.1.

gradle/groovy: A simple way to check if a gradle task name has been invoked (e.g. “assembleRelease” for Android developers)

If you google for this question, you’ll find a bunch of crap answers about creating tasks and checking the task graph, bullshit.

All you need to do is check if a parameter has been passed to gradle.

Keep it simple and stupid:

boolean isAssembleRelease = gradle.startParameter.taskNames.contains("assembleRelease")

(If you’re working with an android project, you can define that variable before the android { section starts)

Then, if you need to do something different somewhere else down in your script, say, ask for a key alias and key password to sign your release (because they invoked ./gradlew assembleRelease you do:

signingConfigs {
        release {
            if (isAssembleRelease) {
                // your code here to ask for the key alias and password
            }
}

Solving “Received fatal alert: handshake_failure” error when performing HTTPS connections on a custom made JRE with jlink

TL; Tell me already what to do:
Add the jdk.crypto.cryptoki module to the list of --add-modules parameter to your jlink command invocation


If you’re reading this you’re one of the few developers out there that wanted to distribute a java 9+ app (using either jdk 9, jdk 10, jdk 11 or jdk 12, as of this writing) with a smaller version of the jdk, to build your custom jre, you used the jlink tool.

When you run your app using the full JRE that comes with the OpenJDK, your app is working fine when it comes to making https requests, but when you run your app using your custom jre you get the following error when opening https connections

Received fatal alert: handshake_failure

This issue occurs because your JRE is missing lots of Cipher Suites that come with the full JDK.

With your JDK, you can try to check the list of supported ciphers with this one liner using the jrunscript tool:

jrunscript -e "print(java.util.Arrays.toString(javax.net.ssl.SSLServerSocketFactory.getDefault().getSupportedCipherSuites()))"

however that might not work for your custom JRE if you haven’t included the scripting module, so here’s a Java program I made that prints all the available Ciphers of your JRE

public class PrintCiphers {
    public static void main(String[] args) {
	var sslSocketFactory = javax.net.ssl.SSLServerSocketFactory.getDefault();
	System.out.println("SSLServerSocketFactory -> " + sslSocketFactory.getClass().getName());
	try {
  	    var getSupportedCipherSuitesMethod = sslSocketFactory.getClass().getMethod("getSupportedCipherSuites");
	    String[] ciphers = (String[]) getSupportedCipherSuitesMethod.invoke(sslSocketFactory);
	    int i=1;
            for (String c : ciphers) {
		System.out.println(i++ + " " + c);
	    }
	} catch(Throwable t) {
	    t.printStackTrace();
	}
    }
}

If you run PrintCiphers on your OpenJDK’s full JRE, you will see almost 50 Cipher Suites available:

$ java PrintCiphers;
1 TLS_AES_128_GCM_SHA256
2 TLS_AES_256_GCM_SHA384
3 TLS_CHACHA20_POLY1305_SHA256
4 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
5 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
6 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
7 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
8 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
9 TLS_RSA_WITH_AES_256_GCM_SHA384
10 TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
11 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
12 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
13 TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
14 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
15 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
16 TLS_RSA_WITH_AES_128_GCM_SHA256
17 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
18 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
19 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
20 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
21 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
22 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
23 TLS_RSA_WITH_AES_256_CBC_SHA256
24 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
25 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
26 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
27 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
28 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
29 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
30 TLS_RSA_WITH_AES_256_CBC_SHA
31 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
32 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
33 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
34 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
35 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
36 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
37 TLS_RSA_WITH_AES_128_CBC_SHA256
38 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
39 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
40 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
41 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
42 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
43 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
44 TLS_RSA_WITH_AES_128_CBC_SHA
45 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
46 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
47 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
48 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
49 TLS_EMPTY_RENEGOTIATION_INFO_SCSV

but if you use your custom JRE to run PrintCiphers you will see only 23 Cipher Suites available:

$ jre/bin/java PrintCiphers
1 TLS_AES_128_GCM_SHA256
2 TLS_AES_256_GCM_SHA384
3 TLS_CHACHA20_POLY1305_SHA256
4 TLS_RSA_WITH_AES_256_GCM_SHA384
5 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
6 TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
7 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
8 TLS_RSA_WITH_AES_128_GCM_SHA256
9 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
10 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
11 TLS_RSA_WITH_AES_256_CBC_SHA256
12 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
13 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
14 TLS_RSA_WITH_AES_256_CBC_SHA
15 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
16 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
17 TLS_RSA_WITH_AES_128_CBC_SHA256
18 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
19 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
20 TLS_RSA_WITH_AES_128_CBC_SHA
21 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
22 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
23 TLS_EMPTY_RENEGOTIATION_INFO_SCSV

To solve the problem you must add the jdk.crypto.cryptoki module to the list of --add-modules parameter to your jlink command invocation, next time your run PrintCiphers you should see the full list of Cipher Suites and your SSL handshake issues should be gone.

Introducing Yuca: A light-weight, in-memory, fast and simple to use search engine library.

https://github.com/gubatron/yuca

If your app can’t handle or doesn’t really need installing a full featured and heavy search engine like Lucene, nor you want to depend on a SQL database for indexing and doing simple search based strings you can use Yuca to index documents under any number of arbitrary keys which can be grouped under tags.

The shared library currently weighs ~170kb without any packing optimizations, we hope to reduce the size further in the near future.

Today, Wed May 9th the library is only available as a C++ shared or static library, the goal is to have bindings for popular programming languages, the first being Java since I need to use it on Android apps I’m developing.

If you feel like you need something like this and you’re not coding in C++, please create an issue on the github repository asking for the language bindings that you need and I’ll try to prioritize your request for the next set of language bindings.