CMake import external library (GNU readline) using ExternalProject_Add() - c

I am really new (just a few weeks) to C and its bulding tools. Using the CMake documetation and some other guides I created a basic CMake project. This works as expectd.
Now I wanted to use some libraries in my project (GNU readline and cJSON).
The cJSON library also uses CMake so I managed to include it in my project without too much trouble.
The GNU readline library on the other hand uses ninja and autotools (if I'm not mistaken). This is where I'm facing issues.
I am trying to build the GNU readline library to link the static files later in my project.
In the CMake documetation I saw you could use ExternalProject_Add() for the purpose of configuring and building an external project.
Just to test this I created a simple Project using CMake with ExternalProject_Add().
My test project has the following layout:
test
├── cmake-build-debug
│   ├── CMakeFiles
│   │   ├── 3.23.2
│   │   │   └── CompilerIdC
│   │   │   └── tmp
│   │   ├── CMakeTmp
│   │   ├── readline.dir
│   │   └── test.dir
│   ├── readline-prefix
│   │   ├── src
│   │   │   ├── readline-build
│   │   │   └── readline-stamp
│   │   └── tmp
│   └── Testing
│   └── Temporary
├── install_dir
└── libraries
└── readline-8.2
├── doc
├── examples
│   ├── autoconf
│   └── rlfe
├── m4
├── shlib
└── support
The library source files are located in test/libraries/readline-8.2.
I want the build files to get installed in the test/install_dir.
With the following Code I manage to build the the files, but I get errors when building it.
This is the content of my CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(test C)
set(CMAKE_C_STANDARD 11)
set(LIB_PATH ${CMAKE_SOURCE_DIR}/libraries)
set(READLINE_LIB_SRC ${LIB_PATH}/readline-8.2)
set(CONFIGURE_ARGS --enable-shared=no --enable-install-examples=no --prefix=${CMAKE_SOURCE_DIR}/install_dir)
add_executable(test main.c)
include(ExternalProject)
ExternalProject_Add(
readline
BUILD_IN_SOURCE TRUE
BUILD_ALWAYS TRUE
SOURCE_DIR ${READLINE_LIB_SRC}
CONFIGURE_COMMAND ${READLINE_LIB_SRC}/configure ${CONFIGURE_ARGS}
BUILD_COMMAND make
INSTALL_COMMAND make install
)
I also tried adding the BUILD_BYPRODUCTS option of the ExternalProject_Add, as I read that ninja could face problems detecting targets otherwise, but without success.
The errors I get in the install step are:
mv: cannot stat '/home/devel/CLionProjects/test/install_dir/lib/libreadline.a': No such file or directory
mv: cannot stat '/home/devel/CLionProjects/test/install_dir/lib/libhistory.a': No such file or directory
But when I look at these directories the files exist.
The output of the build and the error message can be found here: https://gist.github.com/symb10sis/041f879ef5fbd02bcfd9200746101890
I couldn't include it in this question directly as it would get flagged as spam otherwise.
I spent hours reading the documetation, guides and questions here on stackoverflow but with my current knowledge of CMake I am stuck.
What causes the build to think these files don't exist? Is my use of ExternalProject_Add() appropriate for this or am I missing something?
I would really appreciate any help :)

Related

How to properly include an http C library into an Android Project?

I am making an Android Project and I am trying to make a post request using HTTPS to a server. To make the post request I am requires to use JNI so I need to implement this in C.
My idea was to use a library that I could include into my project as i have done with the minizip library here.
I found this library here that seemed to me light engough and could server my purpose. I included in the folder c as you can also see below the files ca_cert.h, https.c and https.h along with the folder mbedtls exactly as is found on the github project.
├── app.iml
├── build.gradle
├── CMakeLists.txt
└── src
├── androidTest
│   └── java
│   └── etc
├── main
│   ├── AndroidManifest.xml
│   ├── c
│   │   ├── ca_cert.h
│   │   ├── https.c
│   │   ├── https.h
│   │   ├── mbedtls
│   │   │   ├── etc
│   │   ├── native-lib.c
│   │   ├── pathfinder.c
│   │   ├── pathfinder.h
│   │   ├── post_data.c
│   │   ├── post_data.h
│   │   ├── third
│   ├── java
│   │   └── etc
│   └── res
│   ├── etc
└── test
└── java
└── etc
As you can see in the tree structure above I have a CMakeLists.txt in the root directory and in src/main/c/ you will see the files and the folder i took from the the https library mentioned.
The contents of the CMakeLists.txt are the following
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/c/native-lib.c
src/main/c/ca_cert.h
src/main/c/https.h
)
include_directories(native-lib SHARED src/main/c/mbedtls/include)
#add_definitions(-DHAVE_ZLIB)
find_library( PRE_BUILD_ANDROID_LIB android)
find_library( log-lib log)
find_library(z-lib z)
target_link_libraries( native-lib
${PRE_BUILD_ANDROID_LIB}
${log-lib}
${z-lib}
)
I am missing something though for sure cause when i attempt to run a simple example like the following
JNIEXPORT jint JNICALL
Java_example_example_do_post(
JNIEnv *env,
jobject this ) {
NSV_LOGE("post_data starts\n");
char *url;
char data[1024], response[4096];
int i, ret, size;
HTTP_INFO hi1, hi2;
// Init http session. verify: check the server CA cert.
http_init(&hi1, FALSE);
http_init(&hi2, TRUE);
url = "http://httpbin.org/get?message=https_client";
ret = http_get(&hi1, url, response, sizeof(response));
return 0;
}
I get
../../../../src/main/c/native-lib.c:56: error: undefined reference to 'http_init'
../../../../src/main/c/native-lib.c:57: error: undefined reference to 'http_init'
../../../../src/main/c/native-lib.c:61: error: undefined reference to 'http_get'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Replace
src/main/c/ca_cert.h
src/main/c/https.h
with
src/main/c/https.c
in CMakeLists.txt.

Getting: conflicts with same file imported from GOPATH with google app engine, but not purely locally

I am still trying to deploy to google app engine both the local test environment and on app engine itself, and I keep getting this error:
2017/10/03 17:50:40 go-app-builder: Failed parsing input: app file DbConfig.go conflicts with same file imported from GOPATH
I have used grep to see if I explicitly import DbConfig but I, this is the result of grep:
$ grep -r 'DbConfig' .
./config.go:func GetDatabaseConfiguration() model.DbConfig {
./config.go: return model.DbConfig{connectionName, user, password, dbType, dbName}
Binary file ./share-services matches
./queries/db-config.go: dbConfig model.DbConfig
./queries/db-config.go:func Config(newDbConfig model.DbConfig) {
./queries/db-config.go: dbConfig = newDbConfig
./model/DbConfig.go:type DbConfig struct {
./model/DbConfig.go:func (d DbConfig) ConnectionString() string {
So from what I can tell I should not get an error and since other structs from my model package works just fine this is very strange to me. Firstly because Google App Engine accepts the deploy and first fails later, secondly because the dev server fails immediately, and lastly because if I run outside the app engine, I don't get this error.
Can someone give me a pointer to how to fix this please. I have search for a fix, but most state to use absolute include paths for packages which I already am.
EDIT:
I forgot to include the build command used, maybe that will help
go-app-builder -app_base /home/tools/go/src/bitbucket.com/chocolate-cloud-dev/share-services -arch 6 -dynamic -goroot /home/tools/sdks/google-cloud-sdk/platform/google_appengine/goroot-1.6 -gopath /home/tools/go -nobuild_files ^^$ -incremental_rebuild -unsafe -print_extras_hash links/generator.go model/user.go model/service.go model/SharedWith.go handlers.go config.go model/connection.go jsonHelpers/decoders.go queries/share-with-queries.go authentication/autenticate.go queries/share-queries.go model/share.go download/download.go model/Download.go model/File.go queries/file-queries.go jsonHelpers/encoders.go queries/db-config.go model/DbConfig.go model/NewestFile.go share-services.go jsonHelpers/CreateShare.go queries/download-queries.go
And this is my project structure:
.
├── app.yaml
├── authentication
│   └── autenticate.go
├── build-and-run
├── config.go
├── deply_v1.sh
├── download
│   └── download.go
├── go-notes.md
├── handlers.go
├── jsonHelpers
│   ├── CreateShare.go
│   ├── decoders.go
│   └── encoders.go
├── LICENSE
├── links
│   └── generator.go
├── model
│   ├── connection.go
│   ├── DbConfig.go
│   ├── Download.go
│   ├── File.go
│   ├── NewestFile.go
│   ├── service.go
│   ├── SharedWith.go
│   ├── share.go
│   └── user.go
├── models
├── queries
│   ├── db-config.go
│   ├── download-queries.go
│   ├── file-queries.go
│   ├── queries.sql
│   ├── share-queries.go
│   └── share-with-queries.go
├── README.md
├── run-locally-mac.sh
├── run-localy.sh
├── scripts
│   └── Script.sql
└── share-services.go
the answer is to either use relative paths instead of absolute, which still does not totaly work Or make a 100% flat folder structure.

Makefile header includes

I am developing a Makefile for an old project. The new Makefile is based on an older one I used successfully with other projects, but now I face an odd problem.
My project has the following form:
├── Makefile
└── src
├── folder1
│   ├── somefiles.c
│   └── somefiles.h
├── folder2
│   ├── problematic.h
│   ├── somefiles.c
│   ├── somefiles.h
│   └── subdir
│   └── included_file.h
└── folder3
├── somefiles.c
└── somefiles.h
My Makefile has the following line:
LIBRARY_INC_PATHS = $(addprefix -I, $(shell find . -name '*.h' -printf '"%h"\n' | sort -u))
In file problematic.h there is the line:
#include "subdir/included_file.h"
Which causes trouble. GCC says that there is no such file or directory.
If I change it to:
#include "included_file.h"
the problem vanishes, but this is not an acceptable solution in my case.
What modifications should I make to my makefile so I can include files from my C code using relative paths, instead of their name only?

How the use unit test in cmake in language C?

I have a C project:
.
├── build
├── bin
│   └── parser
├── CMakeLists.txt
├── configure.h.in
├── inc
│   ├── configure.h
│   ├── diam_dict.h
│   └── unit_tests.h
├── README.txt
├── src
│   └── diam_dict.c
└── testing
└── unit_tests.c
I want to put unit tests in the directory "testing", in the file "unit_tests.c".
I want to test all the functions of the file "src/diam_dict.c", what should I do to let "unit_tests.c" know where are the functions to test?
[what should I write in the file "unit_tests.c" and the top level cmake file "CMakeLists.txt"?]
(I should call all the functions of the source code file "diam_dict.c" to test them)
ps: The header file "diam_dict.h" contains all the prototypes of the functions in the source file "diam_dict.c", and the header file "unit_tests.h" cotains all the prototypes of the test file "unit_tests.c".
CMake is a build system, so you can combine it with any unit testing framework you wish.
As a matter of fact, CTest can call executables and check their result value, which allows some testing. But it is usually less fine granular compared to real unit test a known from dedicated unit testing frameworks.

How to use check library with CTest for unit testing in C

I have project in which I want to use check library for unit testing.
My current project is using CMake and has following structure:
.
├── CMakeLists.txt
├── COPYING
├── ChangeLog
├── README
├── src
│   ├── core
│ │   ├── CMakeLists.txt
│ │ └── main.c
│   ├── core-test
│ │   ├── CMakeLists.txt
│ │ └── main.c
│ └── scrypt
└── doc
└── protocol.txt
In core-test I have unit tests for core module. In scrypt-test I will have tests for scrypt module and so on.
Does using check with CTest make sense?
If yes: how do I connect unit test that use check to CMake/CTest project? Do I need additional configuration for CTest to interpret results from check-enabled executables?
Using check with CTest is possible, unfortunately not convenient.
When unit tests using check fail they will be counted as a failure in CTest. The problem is, that CTest doesn't show output of application that failed1. The other downside is that CTest doesn't count individual check tests, so a "single" failed test could mean multiple check tests. I wasn't able to find a way to make CTest interpret check results.
You can force printing of output by creating CTestCustom.cmake file in build directory (the same one in which you run make or ctest) with following contents:
set (CTEST_CUSTOM_POST_TEST "cat Testing/Temporary/LastTest.log")

Resources