makefile: link to a library if it installed. How to? and how to disable? - linux

I am building rocksdb
seem rocksdb's makefile will detect my system's compression library(snappy, libz), if installed rocksdb will link to it.
I am interested in how rocksdb do that. The makefile is so complicate and I can't find which part do the job.
I hope to prevent this action, I hope rocksdb only link snappy, not zlib which download in my linux machine.
makefile:https://github.com/facebook/rocksdb/blob/main/Makefile

Thank to #John Bollinger 's comment.
This makefile work as configuration script generates the make_config.mk file, and the PLATFORM_LDFLAGS in make_config.mk indicates the library that the system has.
build_detect_platform is responsible for generating make_config.mk. It work like this
if ! test $ROCKSDB_DISABLE_SNAPPY; then
# Test whether Snappy library is installed
# http://code.google.com/p/snappy/
$CXX $PLATFORM_CXXFLAGS -x c++ - -o test.o 2>/dev/null <<EOF
#include <snappy.h>
int main() {}
EOF
if [ "$?" = 0 ]; then
COMMON_FLAGS="$COMMON_FLAGS -DSNAPPY"
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lsnappy"
JAVA_LDFLAGS="$JAVA_LDFLAGS -lsnappy"
fi
fi
so I can set ROCKSDB_DISABLE_ZLIB to prevent link to zlib

Related

Pattern syntax %.3: man/libfoo.man in Automake with different base name

I wrote a library libfoo providing functions bar and baz.
I want the user to be able to find the same man-page (from mans/libfoo.man) when they call man libfoo, man bar and man baz (Similar to man fprintf, man sprintf all pointing to the same page.)
My current setup has the files mans/libfoo.man and Makefile.am
To 'tell' automake that I want to end up with the three man-pages I specified the dist_man3_MANS variable.
Makefile.am:
dist_man3_MANS = mans/libfoo.3 mans/bar.3 mans/baz.3
Coming from GNU make, I thought I could just write
%.3: mans/libfoo.man
ln -S libfoo.man $#
to create links temporarily and then let Automake install those accordingly, but Automake errors out with Makefile.am:115: warning: '%'-style pattern rules are a GNU make extension. I want to do it properly and take this warning seriously by not relying on GNU Make to be as portable as possible.
The Automake manual suggests to add a target
.man.3:
$(LN_S) $^ $#
but that just tells Automake that xx.man can be compiled to xx.3, requiring the base name to be the same. I don't want to carry around those xx.man files, so this approach does not work.
I could hack it in with putting a rule
dist_man3_MANS = mans/libfoo.3 mans/bar.3 mans/baz.3
$(dist_man3_MANS): mans/libfoo.man
$(LN_S) libfoo.man $#
but that seems like a dirty hack, because I am not giving it a recipe to compile .man to .3, but rather say: "Hey, you can create those files with this rule", which for this case may work coincidental.
I would follow the example from the Automake info page section Extending Automake Rules and do something along the lines of
LIBFOO_MAN_ALIASES = bar baz
install-data-hook:
set -e; \
cd $(DESTDIR)$(man3dir) && \
for manalias in $(LIBFOO_MAN_ALIASES); do \
$(LN_S) libfoo.3 $${manalias}.3; \
done
uninstall-hook:
cd $(DESTDIR)$(man3dir) && \
for manalias in $(LIBFOO_MAN_ALIASES); do \
rm -f $${manalias}.3; \
done
relying on AC_PROG_LN_S to make sure that $(LN_S) does something reasonable for the system (symlink, hardlink, copy) to create a file name which can be open(2)ed and read.
FTR, I have just taken a look at three different systems' man pages and found them using three different methods to make the fprintf(3) man page show the same man page as printf(3) does:
Debian 10 uses symlinks
Fedora 35 uses a /usr/share/man/man3/fprintf.3 file containing .so man3/printf.3 (while some other man pages use symlinks to achieve the same effect)
FreeBSD 13 uses hardlinks, and find /usr/share/man -type l does not find any symlinks on my relatively clean system. However, manually testing both symlinks and the .so man3/printf.3 method suggests that FreeBSD man(1) does not treat symlinks in any special way and therefore opens the symlinked man page, and it also interprets the .so command just like Fedora 35's man(1) does.
I do not know how portable each of those methods is. Each of these three methods could set up on make install by using an appropriate install-data-hook, but any man file which can be opened using open(2) appears to be work, and therefore $(LN_S) looks like a good bet.

Cmake check if the current platform is Fedora [duplicate]

Does anybody know any cmake variable or hook or something which can give me underlying platform name/flavour name on which it is getting executed ?
e.g. Linux-CentOs
Linux-Ubuntu
Linux-SLES
I know cmake has "CMAKE_SYSTEM" variable but that doesn't help differentiating flavours of linux for e.g. Any help is appreciated.
edit :
I just read that it can be done using lsb_release command ?
The following snippet populates the LSB_RELEASE_ID_SHORT cmake variable with information about the underlying Linux system:
find_program(LSB_RELEASE_EXEC lsb_release)
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is
OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
On Ubuntu, for example, it yields Ubuntu.
Slightly less convoluted than checking files on the filesystem is to deduce the best you can from the available CMAKE_SYSTEM vars. For instance a CMakeLists.txt file containing lines like this:
message("-- CMAKE_SYSTEM_INFO_FILE: ${CMAKE_SYSTEM_INFO_FILE}")
message("-- CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
message("-- CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
message("-- CMAKE_SYSTEM: ${CMAKE_SYSTEM}")
string (REGEX MATCH "\\.el[1-9]" os_version_suffix ${CMAKE_SYSTEM})
message("-- os_version_suffix: ${os_version_suffix}")
outputs this when I ran cmake . :
-- CMAKE_SYSTEM_INFO_FILE: Platform/Linux
-- CMAKE_SYSTEM_NAME: Linux
-- CMAKE_SYSTEM_PROCESSOR: x86_64
-- CMAKE_SYSTEM: Linux-2.6.32-573.7.1.el6.x86_64
-- os_version_suffix: .el6
And for my situation, the .el6 was enough to differentiate.
Likely, you have to write such a test yourself. Here's one of the possible examples, just googled: https://htcondor-wiki.cs.wisc.edu/index.cgi/fileview?f=build/cmake/FindLinuxPlatform.cmake&v=4592599fecc08e5588c4244e2b0ceb7d32363a56
However depending on your actual needs the test may be quite complex. For example Ubuntu as a Debian-based OS always has /etc/debian_version and many RPM-based OSes traditionally have /etc/redhat-release. There's a file /etc/os-release in the Linux Standard Base (LSB) specification, but for example on the localhost this file is empty for an unknown reason :)
I know this is an old question, but as of now, there is still no cmake built-in function to find this information in good detail. I've implemented a small utility function that uses lsb_release on Linux to find a number of relevant system details:
function(get_linux_lsb_release_information)
find_program(LSB_RELEASE_EXEC lsb_release)
if(NOT LSB_RELEASE_EXEC)
message(FATAL_ERROR "Could not detect lsb_release executable, can not gather required information")
endif()
execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --id OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --release OUTPUT_VARIABLE LSB_RELEASE_VERSION_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --codename OUTPUT_VARIABLE LSB_RELEASE_CODENAME_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
set(LSB_RELEASE_ID_SHORT "${LSB_RELEASE_ID_SHORT}" PARENT_SCOPE)
set(LSB_RELEASE_VERSION_SHORT "${LSB_RELEASE_VERSION_SHORT}" PARENT_SCOPE)
set(LSB_RELEASE_CODENAME_SHORT "${LSB_RELEASE_CODENAME_SHORT}" PARENT_SCOPE)
endfunction()
Add it to your CMakeLists.txt and use it like this:
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
get_linux_lsb_release_information()
message(STATUS "Linux ${LSB_RELEASE_ID_SHORT} ${LSB_RELEASE_VERSION_SHORT} ${LSB_RELEASE_CODENAME_SHORT}")
endif()
If you need further details, check what else lsb_release can provide with lsb_release -a.
Note that not every Linux has lsb_release installed. Most systems provide it, but its not mandatory. On newer Ubuntu, for example, its the default on desktop installs, and required by ubuntu-minimal. If it should be missing on your machine, you can install it with sudo apt install lsb-release.
on my machine
CMAKE_SYSTEM_INFO_FILE == "Platform/Linux"
CMAKE_SYSTEM_NAME == "Linux"
CMAKE_SYSTEM == "Linux-<kernel version>"
obtained with cmake --system-information, I know of people that use said macros in their own CMakeLists.txt files so they work as expected, probably CMAKE_SYSTEM_NAME is what you really want but here you go, you get this 3 and the command to inspect the properties of your machine as far as cmake is concerned .
Based on thiagowfx answer, If you want to get the codename of the distro (if it is available):
execute_process(COMMAND lsb_release -cs
OUTPUT_VARIABLE RELEASE_CODENAME
OUTPUT_STRIP_TRAILING_WHITESPACE
)
E.g. in Ubuntu 14.04 the variable RELEASE_CODENAME will hold trusty.
### find our os (wins, centos, ubuntu, etc)
set(VAR_OS "")
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
MESSAGE(DEBUG "Linux")
execute_process (
COMMAND bash -c "awk -F= '/^ID=/{print $2}' /etc/os-release |tr -d '\n' | tr -d '\"'"
OUTPUT_VARIABLE outOS
)
MESSAGE(DEBUG "Linux os: ${outOS}")
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows")
MESSAGE(DEBUG "Windows")
set(VAR_OS "wins")
ELSE()
MESSAGE(FATAL "No OS detected!")
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")

Compiling static library for Google Native Client using SCons

I'm working on a few multi platform projects that all depend on common framework.
I want to add support for Google Native-Client (NaCl). The way I aproached the problem is first to compile the framework as static library (this is how I've been doing it on all other platforms).
I have to say that I have never used SCons before. I think I start grasping it. Starting from a build.scons from a tutorial I can get some code compiling and linking. Now I would want to skip the linking process but seems like the nacl_env was never intended to compile static libraries.
Reading the SCons help didn't help me much since the Library node is missing from the nacl_env.
I don't think I understand SCons enough to write the whole build process from scratch so I was hopping to not have to do so.
1. Am I approaching the problem correctly?
2. Any tips or sample nacl static libs, build using SCons?
Ok, what I did is way more trickery than what you probably need.
I wanted my static library to handle the initialization steps of the NaCl module, and then call some project-specific function.
I ended up turning my whole framework and the contents of the built-in libppapi_cpp.a into a single .o file, and then that into a single .a file, a static library.
I needed a single .o file, because otherwise I would run into dependency problems releated to initialization, I could not solve.
build_lib.sh (framework):
#!/bin/bash -e
SDK="/home/kalmi/ik/nacl_sdk/pepper_15"
function create_allIn_a {
TMPDIR="`mktemp -d`"
echo $TMPDIR
cp $O_FILES $TMPDIR
pushd $TMPDIR &> /dev/null
$AR x $LIBPPAPI_CPP_A
$LD -Ur * -o ALL.o
$AR rvs $OUTPUT_NAME ALL.o
$RANLIB $OUTPUT_NAME
popd &> /dev/null
}
./scons
BIN_BASE="$SDK/toolchain/linux_x86/bin"
LD="$BIN_BASE/i686-nacl-ld"
AR="$BIN_BASE/i686-nacl-ar"
RANLIB="$BIN_BASE/i686-nacl-ranlib"
LIBPPAPI_CPP_A="$SDK/toolchain/linux_x86_newlib/x86_64-nacl/lib32/libppapi_cpp.a"
O_FILES="`find $(pwd)/opt_x86_32 | grep .o$ | grep --invert-match my_main.o | tr "\n" " "`"
LIBDIR="../../../bin/lib/lib32"
mkdir -p $LIBDIR
if [ -f $LIBDIR/libweb2grid_framework.a ]; then
rm $LIBDIR/libweb2grid_framework.a
fi
OUTPUT_NAME="`readlink -m $LIBDIR/libweb2grid_framework.a`"
create_allIn_a
BIN_BASE="$SDK/toolchain/linux_x86/bin"
LD="$BIN_BASE/x86_64-nacl-ld"
AR="$BIN_BASE/x86_64-nacl-ar"
RANLIB="$BIN_BASE/x86_64-nacl-ranlib"
LIBPPAPI_CPP_A="$SDK/toolchain/linux_x86_newlib/x86_64-nacl/lib64/libppapi_cpp.a"
O_FILES="`find $(pwd)/opt_x86_64 | grep .o$ | grep --invert-match my_main.o | tr "\n" " "`"
LIBDIR="../../../bin/lib/lib64"
mkdir -p $LIBDIR
if [ -f $LIBDIR/libweb2grid_framework.a ]; then
rm $LIBDIR/libweb2grid_framework.a
fi
OUTPUT_NAME="`readlink -m $LIBDIR/libweb2grid_framework.a`"
create_allIn_a
./scons -c
The my_main.o file is excluded from the static library, because that file contains the function that is to be provided by the project that uses this framework.
The build.scons file for the framework is truly ordinary.
build.scons (for some project that uses this framework):
#! -*- python -*-
#What to compile:
sources = [ 'src/something.cpp', 'src/something_helper.cpp' ]
###############################################################x
import make_nacl_env
import nacl_utils
import os
nacl_env = make_nacl_env.NaClEnvironment(
use_c_plus_plus_libs=False,
nacl_platform=os.getenv('NACL_TARGET_PLATFORM'))
nacl_env.Append(
# Add a CPPPATH that enables the full-path #include directives, such as
# #include "examples/sine_synth/sine_synth.h"
CPPPATH=[os.path.dirname(os.path.dirname(os.path.dirname(os.getcwd())))],
LIBS=['web2grid_framework','srpc'],
LIBPATH=['../../../bin/lib/lib32','../../../bin/lib/lib64'],
LINKFLAGS=['-pthread']
)
nacl_env.AllNaClModules(sources, 'client')
Some lines worth highlighting:
use_c_plus_plus_libs=False,
LIBS=['web2grid_framework','srpc'],
LIBPATH=['../../../bin/lib/lib32','../../../bin/lib/lib64'],
LINKFLAGS=['-pthread']
I am not saying that this is a clean method, but it gets the job done.
So, there's two questions here
1. Using SCONS:
NaCl uses SCONS for it's examples, simply to help compiling of the examples easier. In reality, SCONS simply directs to the GCC/G++ compilers in the SDK build directories. (SCONS will take the input scripts, and create the final param string to send to GCC)
GCC is a common compiler, and is well documented on the net : http://gcc.gnu.org/
How you integrate NaCl compilation into your work-flow is up to you (ie you're not forced to use SCONS).
For instance, if you'd like to go to GCC directly, you can simply call :
<path to bin>/x86_64-nacl-gcc -m64 -o test.nexe main.c
For a more detailed look into how to compile NaCl modules, please read the documentation # gonacl.com on compiling which will detail how to compile with and without SCONS.
2.Compilng Static libs with GCC
Here is an example : http://www.adp-gmbh.ch/cpp/gcc/create_lib.html
~Main

How to compile Jigsaw http server on Linux?

I download the Jigsaw server source from w3c website, http://www.w3.org/Jigsaw/. I followed its instruction http://www.w3.org/Jigsaw/Doc/Programmer/compile.html, but still can not compile it on my linux. What does it mean to update your CLASSPATH to compile Jigsaw and use the new compiled classes? How could I set my classpath?
Plz give me some help.
Thanks.
It means you need to set the $CLASSPATH environment variable. I haven't looked at Jigsaw, but if you wanted to set your $CLASSPATH to include all the jar files within a directory (for example one that contains all the Jigsaw compiled jars) then you can use this script fragment:
CLASSPATH=""
for j in $(find /path/to/jigsaw/lib -name \*.jar)
do
if [ ! -z "$CLASSPATH" ]; then CLASSPATH="$CLASSPATH:"; fi
CLASSPATH="$CLASSPATH$j"
done
Now whenever you invoke the java command it will use the classes within /path/to/jigsaw/lib.
However this is not a good idea; better is to use the above technique to build an environment variable other than $CLASSPATH and pass that as the argument to the java -cp command line option:
cp=""
for j in $(find /path/to/jigsaw/lib -name \*.jar)
do
if [ ! -z "$cp" ]; then cp="$cp:"; fi
cp="$cp$j"
done
java -cp $cp ...

How to use an older version of gcc in Linux

In Linux I am trying to compile something that uses the -fwritable-strings option. Apparently this is a gcc option that doesn't work in newer version of gcc. I installed gcc-3.4 on my system, but I think the newer version is still being used because I'm still get the error that says it can't recognize the command line option -fwritable-strings. How can I get make to use the older version of gcc?
You say nothing about the build system in use, but usually old versions of gcc can be invoked explicitly, by something like (this is for an autotools-based build):
./configure CXX=g++-3.4 CC=gcc-3.4
For a make-based build system, sometimes this will work:
make CXX=g++-3.4 CC=gcc-3.4
Most makefiles ought to recognise overriding CC and CXX in this way.
If editing the configuration/Makefile is not an option, Linux includes a utility called update-alternatives for such situations. However, it's a pain to use (links to various tutorials included below).
This is a little simpler - here's a script (from here) to easily switch your default gcc/g++ version:
#!/bin/bash
usage() {
echo
echo Sets the default version of gcc, g++, etc
echo Usage:
echo
echo " gcc-set-default-version <VERSION>"
echo
exit
}
cd /usr/bin
if [ -z $1 ] ; then
usage;
fi
set_default() {
if [ -e "$1-$2" ] ; then
echo $1-$2 is now the default
ln -sf $1-$2 $1
else
echo $1-$2 is not installed
fi
}
for i in gcc cpp g++ gcov gccbug ; do
set_default $i $1
done
If you 1) name this script switch-gcc, 2) put it in your path, and 3) make it executable (chmod +x switch-gcc), you can then switch compiler versions just by running
sudo switch-gcc 3.2
Further reading on update-alternatives:
https://lektiondestages.blogspot.com/2013/05/installing-and-switching-gccg-versions.html
https://codeyarns.com/2015/02/26/how-to-switch-gcc-version-using-update-alternatives/
https://askubuntu.com/questions/26498/choose-gcc-and-g-version
Maybe you could just give the whole path of the gcc-3.4 install while compiling your program:
/path_to_gcc_3.4/gcc your_program
If you can find where the writeable strings are actually being used, another possibility would be to use strdup and free on the subset of literal strings that the code is actually editing. This might be more complicated than downgrading versions of GCC, but will make the code much more portable.
Edit
In response to the clarification question / comment below, if you saw something like:
char* str = "XXX";
str[1] = 'Y';
str[2] = 'Z';
// ... use of str ...
You would replace the above with something like:
char* str = strdup("XXX");
str[1] = 'Y';
str[2] = 'Z';
// ... use of str ...
free(str);
And where you previously had:
char* str = "Some string that isn't modified";
You would replace the above with:
const char* str = "Some string that isn't modified";
Assuming you made these fixes, "-fwritable-strings" would no longer be necessary.

Resources