How to add depdency in waf builder's wscript script - c++

In my project (which uses waf/wscript based build system), I am now adding mongodb c++ driver APIs. I figured out that 'libmongoclient.a' is not getting added as a linker option (at compile time) and I get all undefined reference to the mongodb c++ driver API calls.
I want to understand, how do I modify my wscript so that it picks up the mongoclient related library by itself and links it properly. It perhaps involves updating the configuration function of wscript. I am new to the waf build system, and not sure how to change it.
I have built and installed the mongodb c++ driver as follows:
- INCLUDE: /usr/local/include/mongo/
- LIB: /usr/local/lib/libmongoclient.a
I posted a similar question earlier in this regard, and the above one is more specific problem statement.
https://stackoverflow.com/questions/30020574/building-project-with-waf-script-and-eclipse
Since I am just invoking ./waf from within eclipse, I believe, the options that I specify into Eclipse's build environment are not being picked up by the waf (and hence the library option for mongoclient).

I figured this out and the steps are as follows:
Added following check in the configure command/function.
conf.check_cfg(package='libmongoclient', args=['--cflags', '--libs'],
uselib_store='MONGOCLIENT', mandatory=True)
After this step, we need to add a package configuration file (.pc) into /usr/local/lib/pkgconfig path. This is the file where we specify the paths to lib and headers. Pasting the content of this file below.
prefix=/usr/local
libdir=/usr/local/lib
includedir=/usr/local/include/mongo
Name: libmongoclient
Description: Mongodb C++ driver
Version: 0.2
Libs: -L${libdir} -lmongoclient
Cflags: -I${includedir}
Added the above library into the build function to the sepcific program which depends on the above dependency (i.e. MongoClient).
mobility = bld(
target='bin/mobility',
features='cxx cxxprogram',
source='src/main.cpp',
use='mob-objects MONGOCLIENT',
)

Related

How can I wrap a static library (C++) into an XCFramework for use in Swift?

I have been given a static library libExample.a together with a bunch of C++ headers, which I need to use in an iOS app. The binary is fat, containing objects for iphoneos-arm64/e and iphonesimulator-x64.
I have done some research on the subject and came to the conclusion, that using a XCFramework would be the best thing to do. Still, I feel completely out of my depth, since this is my first time trying anything of the sort.
What I have done so far
1. Creating the XCFramework from library files
lipo -extract architectures from fat binary
xcodebuild -create-xcframework -library LIB-arm64.a -headers HEADERS -library ...
Importing the XCFramework into my Swift project didn't yield any usable modules. Also the folder was missing a lot of the files, I've seen in examples. It seemed like the wrong way to go about it, so I tried...
2. Creating a Framework and then a XCFramework from it
Files
Create new Objective-C Framework project ExampleFramework
Pull all my headers and the fat binary into the project
Add all my headers to the ExampleFramework.h umbrella header
Create the following ExampleFramework.modulemap:
framework module ExampleFramework {
umbrella header "ExampleFramework.h”
link "Example"
export *
module * { export * }
}
Settings
General:
1.1. Add libExample.a to Frameworks & Libraries
Build Phases:
2.1. Make all headers public
2.2. Add libExample.a to Link Binary with Libraries
2.3. Add libExample.a to Copy Bundle Resources
Build Settings:
3.1. Skip Install : No
3.2. Build Libraries for distribution : Yes
3.3. Module map file: ExampleFramework/ExampleFramework.modulemap
3.4. Defines modules: Yes
3.5. Compile Sources As: Objective-C++
I then archived the framework, for iphoneos and iphonesimulator respectively:
xcodebuild archive \
-scheme "ExampleFramework" ONLY_ACTIVE_ARCH=NO \
-archivePath "path/to/ExampleFramework_${SDK}.xcarchive" \
-sdk ${SDK} \
SKIP_INSTALL=NO \
BUILD_LIBRARIES_FOR_DISTRIBUTION=YES
...and generated a XCFramework from the outputs:
xcodebuild -create-xcframework \
-framework "path/to/ExampleFramework_iphoneos.xcarchive/Products/Library/Frameworks/ExampleFramework.framework"
-framework ...
-output "path/to/ExampleFramework.xcframework"
Build Errors
The folder structure I got from this looked promising, so I tried adding the XCFramework to my iOS project. The module was being found now, but XCode stopped compiling at the first #include, saying it wasn't able to find stdexcept, from which I concluded it was missing the C++ standard library headers.
I tried setting Header Search Paths in Build Settings. Looking for the right path I found a couple, that looked relevant to me:
/Applications/Xcode_13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
/Applications/Xcode_13.2.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include
/Applications/Xcode_13.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include
Depending on which one I choose and whether I clean before building, I'm getting a bunch of different errors (it seems random). Mainly:
Unknown type name 'namespace'
and lots and lots of others, that lead to me believe XCode doesn't recognize the headers as C++.
Or:
Cyclic dependency on module 'Darwin' : Darwin -> std -> Darwin
I really have no idea at this point, so any solutions or suggestions pointing me into the right direction, would me much appreciated. I'd also be open to some completely different approach, I just want to use the library somehow.
Thanks!
For reference from module.modulemap
framework module GoogleAppMeasurement {
umbrella header "GoogleAppMeasurement-umbrella.h"
export *
module * { export * }
link framework "Security"
link framework "SystemConfiguration"
link "c++"
link "sqlite3"
link "z"
}

Provide run time environment variable path (e.g. LD_LIBRARY_PATH) to third party dependency in bazel

In the code base I am working with we use the oracle instant client library as a third party dependency in Bazel as follows:
cc_library(
name = "instant_client_basiclite",
srcs = glob(["*.so*"]),
visibility = ["//visibility:public"],
)
The library looks as this:
$ bazel query 'deps(#instant_client_basiclite//:instant_client_basiclite)'
#instant_client_basiclite//:instant_client_basiclite
#instant_client_basiclite//:liboramysql.so
#instant_client_basiclite//:libociicus.so
#instant_client_basiclite//:libocci.so.21.1
#instant_client_basiclite//:libocci.so
#instant_client_basiclite//:libnnz21.so
#instant_client_basiclite//:libclntshcore.so
...
It works as far as linking is concerned, but it seems that the path to the library is still needed because otherwise I get a run time error (oracle error 1804). The error can be solved by setting any of the environment variables ORACLE_HOME or LD_LIBRARY_PATH. In fact for the IBM WebSphere MQ there is the same need (character encoding table files need to be found).
ldd on a binary points to .../bazel-bin/app/../../../_solib_k8/_U#instant_Uclient_Ubasiclite_S_S_Cinstant_Uclient_Ubasiclite___U/libocci.so.21.1
How can I set those needed path variables so that bazel test, bazel run and Bazel container image rules work?
One possibility is to add the following command line option:
--test_env=ORACLE_HOME="$(bazel info output_base)/external/instant_client_basiclite"
It is a pity that it cannot be put in .bazelrc.

How to use a c++ library written in a cmake project into another cmake project [duplicate]

I was trying to use yaml-cpp in my project. It took me half an hour to correctly link the library by experimenting with the following names. After I finally stumbled across them in this file, I settled for this:
find_package(yaml-cpp REQUIRED)
include_directories(${YAML_INCLUDE_DIRS})
target_link_libraries(${YAML_CPP_LIBRARIES})
It works, but the way I was searching for those seems brainless.
How is it remotely possible to figure out the correct name of the include variables? It could be YAML_LIBS, YAML_LIBRARY, YAML_CPP_LIBRARIES, there is no standard, right? What is the appropriate way to determine the correct cmake config for most c++ libraries?
Thank you.
Most of FindXXX.cmake scripts have usage description at the top of them (as CMake comments started #). The same is true about XXXConfig.cmake (or xxx-config.cmake) scripts.
Command find_package(XXX) uses one of such scripts (the one which actually exists). So, before using this approach for discover the package, make sure that you have read the description "embedded" into such script.
In your case, yaml-cpp-config.cmake file (created in the build or in the install directory) contains following description:
# - Config file for the yaml-cpp package
# It defines the following variables
# YAML_CPP_INCLUDE_DIR - include directory
# YAML_CPP_LIBRARIES - libraries to link against
so proper usage of results of find_package(yaml-cpp) is
include_directories(${YAML_CPP_INCLUDE_DIRS})
target_link_libraries(<your-target> ${YAML_CPP_LIBRARIES})

Compile proftpd and include a library copy inside the installation directory

I do already ask a quiet similar question but in fact I now change my mind.
Id like like to compile proftpd and add a copy of the library it uses to the choosen installation directory.
Let's say I define a prefix in my compilation like:
/usr/local/proftpd
Under this directory I would like to find and use those directories only :
./lib
./usr/lib
./usr/bin
./usr/.....
./etc
./var/log/proftpd
./bin
./sbin
./and others I will not put the whole list
So the idea is after I have all libraries and config file in my main directory I could tar it and send it on another server with the same OS and without installing all the dependencies of protfpd I could use it.
I know it does sound like a windows installer not using shared library but that's in fact exactly what I'm trying to accomplish.
So far I have manage to compile it on AIX using this command line:
./configure --with-modules=mod_tls:mod_sql:mod_sql_mysql:mod_sql_passwd:mod_sftp:mod_sftp_sql --without-getopt --enable-openssl --with-includes=/opt/freeware/include:/opt/freeware/include/mysql/mysql/:/home/poney2/src_proftpd/libmath_header/ --with-libraries=/opt/freeware/lib:/opt/freeware/lib/mysql/mysql/:/home/poney2/src_proftpd/libmath_lib --prefix=/home/poney/proftpd_bin --exec-prefix=/home/poney/proftpd_bin/proftpd
Before trying to ask me why I'm doing so, it's because I have to compile proftpd on IBM AIX with almost all modules and this is not available on the IBM rpm binary repositories.
The use of this LDFLAG
LDFLAGS="-Wl,-blibpath:/a/new/lib/path"
where /a/new/lib/path contains all your library does work with Xlc and Gcc compiler.

Autotools: Including a prebuilt 3rd party library

I'm currently working to upgrade a set of c++ binaries that each use their own set of Makefiles to something more modern based off of Autotools. However I can't figure out how to include a third party library (eg. the Oracle Instant Client) into the build/packaging process.
Is this something really simple that I've missed?
Edit to add more detail
My current build environment looks like the following:
/src
/lib
/libfoo
... source and header files
Makefile
/oci #Oracle Instant Client
... header and shared libraries
Makefile
/bin
/bar
... source and header files
Makefile
Makefile
/build
/bin
/lib
build.sh
Today the top level build.sh does the following steps:
Runs each lib's Makefile and copies the output to /build/lib
Runs each binary's Makefile and copied the output to /build/bin
Each Makefile has a set of hardcoded paths to the various sibling directories. Needless to say this has become a nightmare to maintain. I have started testing out autotools but where I am stuck is figuring out the equivalent to copying /src/lib/oci/*.so to /build/lib for compile time linking and bundling into a distribution.
I figured out how to make this happen.
First I switched to a non recursive make.
Next I made the following changes to configure.am as per this page http://www.openismus.com/documents/linux/using_libraries/using_libraries
AC_ARG_WITH([oci-include-path],
[AS_HELP_STRING([--with-oci-include-path],
[location of the oci headers, defaults to lib/oci])],
[OCI_CFLAGS="-$withval"],
[OCI_CFLAGS="-Ilib/oci"])
AC_SUBST([OCI_CFLAGS])
AC_ARG_WITH([oci-lib-path],
[AS_HELP_STRING([--with-oci-lib-path],
[location of the oci libraries, defaults to lib/oci])],
[OCI_LIBS="-L$withval -lclntsh -lnnz11"],
[OCI_LIBS='-L./lib/oci -lclntsh -lnnz11'])
AC_SUBST([OCI_LIBS])
In the Makefile.am you then use the following lines (assuming a binary named foo)
foo_CPPFLAGS = $(OCI_CFLAGS)
foo_LDADD = libnavycommon.la $(OCI_LIBS)
ocidir = $(libdir)
oci_DATA = lib/oci/libclntsh.so.11.1 \
lib/oci/libnnz11.so \
lib/oci/libocci.so.11.1 \
lib/oci/libociicus.so \
lib/oci/libocijdbc11.so
The autotools are not a package management system, and attempting to put that type of functionality in is a bad idea. Rather than incorporating the third party library into your distribution, you should simply have the configure script check for its existence and abort if the required library is not available. The onus is on the user to satisfy the dependency. You can then release a binary package that will allow the user to use the package management system to simplify dependency resolution.