Using cmake to cross compile multiple libraries and apps - c

I'm having issues with cmake while trying to cross compile an existing, large codebase. Our current build system uses a proprietary IDE that is causing a large number of issues -- so we're trying to move away.
I've distilled this to the simplest example I can.
Note: This all works when I don't use the toolchain option with cmake. I can get this to compile and run if just using the native toolchain.
I don't currently suspect issues with the toolchain file for cmake. I have used it to get OpenCV to compile -- with some hacking OpenCV.
The error that I get when trying to cross compile is:
-- The C compiler identification is GNU 4.8.3
-- The CXX compiler identification is GNU 4.8.3
-- Check for working C compiler: /opt/qnx650/host/linux/x86/usr/bin/ntox86-gcc
-- Check for working C compiler: /opt/qnx650/host/linux/x86/usr/bin/ntox86-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /opt/qnx650/host/linux/x86/usr/bin/ntox86-g++
-- Check for working CXX compiler: /opt/qnx650/host/linux/x86/usr/bin/ntox86-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/MY_USER/Desktop/test_app/build-test_app
Scanning dependencies of target liba
[ 25%] Building C object libs/liba/CMakeFiles/liba.dir/liba.c.o
Linking C shared library libliba.so
[ 25%] Built target liba
Scanning dependencies of target libb
[ 50%] Building C object libs/libb/CMakeFiles/libb.dir/libb.c.o
make[2]: *** No rule to make target `libs/liba/liba.a', needed by `libs/libb/liblibb.so.1.0.0'. Stop.
make[1]: *** [libs/libb/CMakeFiles/libb.dir/all] Error 2
make: *** [all] Error 2
It's like it's looking for a static version of the library, but I've configured it to use shared objects when calling cmake:
cmake -DBUILD_SHARED_LIBS=1 ..
I've included all of the files in the test project below. This is the same issue I run into when trying to get the larger project to compile.
Project structure:
test_app
├── app
│   ├── appa
│   │   ├── appa.c
│   │   └── CMakeLists.txt
│   └── CMakeLists.txt
├── CMakeLists.txt
├── include
│   ├── liba
│   │   └── liba.h
│   ├── libb
│   │   └── libb.h
│   └── libc
│   └── libc.h
└── libs
├── CMakeLists.txt
├── liba
│   ├── CMakeLists.txt
│   └── liba.c
├── libb
│   ├── CMakeLists.txt
│   └── libb.c
└── libc
├── CMakeLists.txt
└── libc.c
Top level CMakeLists.txt
project(test)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_INSTALL_PREFIX "/opt/test")
set(INSTALL_PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_EXECUTE)
set(TEST_VERSION 1.0.0)
set(TEST_MAJOR_VERSION 1)
set(TEST_GLOBAL_INCLUDES
$<BUILD_INTERFACE:${CROSS_TARGET}/usr/pkg/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
set(TEST_GLOBAL_LIB_PATHS
$<BUILD_INTERFACE:${CROSS_TARGET}/usr/pkg/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
add_subdirectory(libs)
add_subdirectory(app)
app/CMakeLists.txt
add_subdirectory(appa)
app/appa/CMakeLists.txt
project(appa)
add_executable(appa appa.c)
target_include_directories(appa PUBLIC ${TEST_GLOBAL_INCLUDES})
target_link_libraries(appa libc)
# Set version information
set_target_properties(appa PROPERTIES
VERSION ${TEST_VERSION}
)
# set install destination and permissions
install(
TARGETS appa
RUNTIME DESTINATION lib
PERMISSIONS ${INSTALL_PERMISSIONS}
)
app/appa/appa.c
#include <stdlib.h>
#include <stdio.h>
#include <libc/libc.h>
int main(int argc, char **argv)
{
printf("Hello world: %d\n", libc_function(2));
return EXIT_SUCCESS;
}
include/liba/liba.h
#pragma once
int liba_function(int a);
include/libb/libb.h
#pragma once
int libb_function(int a);
include/libc/libc.h
#pragma once
int libc_function(int a);
libs/CMakeLists.txt
add_subdirectory(liba)
add_subdirectory(libb)
add_subdirectory(libc)
libs/liba/CMakeLists.txt
project(libliba)
add_library(liba liba.c)
target_include_directories(liba PUBLIC ${TEST_GLOBAL_INCLUDES})
# Set version information
set_target_properties(liba PROPERTIES
VERSION ${TEST_VERSION}
SOVERSION ${TEST_MAJOR_VERSION}
)
# set install destination and permissions
install(
TARGETS liba
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib
PERMISSIONS ${INSTALL_PERMISSIONS}
)
libs/liba/liba.c
#include <liba/liba.h>
int liba_function(int a)
{
return a * a;
}
libs/libb/CMakeLists.txt
project(liblibb)
add_library(libb libb.c)
target_include_directories(liba PUBLIC ${TEST_GLOBAL_INCLUDES})
# Set version information
set_target_properties(libb PROPERTIES
VERSION ${TEST_VERSION}
SOVERSION ${TEST_MAJOR_VERSION}
)
target_link_libraries(libb liba)
# set install destination and permissions
install(
TARGETS libb
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib
PERMISSIONS ${INSTALL_PERMISSIONS}
)
libs/libb/libb.c
#include <liba/liba.h>
#include <libb/libb.h>
int libb_function(int a)
{
return liba_function(a) * liba_function(a);
}
libs/libc/CMakeLists.txt
project(liblibc)
add_library(libc libc.c)
target_include_directories(libc PUBLIC ${TEST_GLOBAL_INCLUDES})
# Set version information
set_target_properties(libc PROPERTIES
VERSION ${TEST_VERSION}
SOVERSION ${TEST_MAJOR_VERSION}
)
target_link_libraries(libc libb)
# set install destination and permissions
install(
TARGETS libc
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib
PERMISSIONS ${INSTALL_PERMISSIONS}
)
libs/libc/libc.c
#include <libb/libb.h>
#include <libc/libc.h>
int libc_function(int a)
{
return libb_function(a) * libb_function(a);
}

Related

Building a gobject library with meson leads to undefined symbols

I would like to implement a library that is based on the gobject type system. So every object is a instance of GObjectClass
In the header gwl-registry.h I have:
#define GWL_TYPE_REGISTRY gwl_registry_get_type()
G_DECLARE_DERIVABLE_TYPE(GwlRegistry, gwl_registry, GWL, REGISTRY, GObject)
Which declares the type and the function that obtains a type. This is what I should do according the gobject tutorial: https://developer.gnome.org/gobject/stable/howto-gobject.html If I understand it correctly these macro's should expand to include the instance cast GWL_REGISTRY() and type check macro GWL_IS_REGISTRY(). However both functions rely on the function gwl_registry_get_type().
If I'm not mistaken this should be implemented in the source file gwl-registry.c. Here I define the type using this code:
G_DEFINE_TYPE_WITH_PRIVATE(GwlRegistry, gwl_registry, G_TYPE_OBJECT)
Than this macro should expand to create the GType gwl_registry_get_type().
Using meson I create a library which currently looks like this:
├── data
│   └── xdg-shell.xml
├── include
│   ├── gwl-display.h
│   ├── gwl.h
│   ├── gwl-import.h
│   ├── gwl-registry.h
│   ├── gwl-registry-private.h
│   └── meson.build
├── meson.build
├── src
│   ├── gwayland.c
│   ├── gwl-display.c
│   ├── gwl-registry.c
│   └── meson.build
└── test
├── display-test.c
├── gwayland-test.c
├── meson.build
├── registry-test.c
└── tests.h
The toplevel meson.build looks like:
project(
'GWayland', 'c',
version : '0.1',
default_options : ['warning_level=3']
)
glib_dep = dependency('glib-2.0')
gobject_dep = dependency('gobject-2.0')
wayland_dep = dependency('wayland-client')
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_GWL']
subdir('src')
subdir('include')
# Make this library usable as a Meson subproject.
gwayland_dep = declare_dependency(
include_directories: include_directories('./include'),
dependencies: [glib_dep, gobject_dep, wayland_dep],
link_with : gwayland_shared_lib
)
subdir('test')
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : 'GWayland',
filebase : 'gwayland',
description : 'Meson sample project.',
subdirs : 'gwayland',
libraries : gwayland_shared_lib,
version : '0.1',
)
The src meson.build looks like:
gwayland_srcs = [
'gwl-display.c',
'gwl-registry.c',
]
gwayland_shared_lib = shared_library(
'gwayland',
gwayland_srcs,
install : true,
c_args : lib_args,
gnu_symbol_visibility : 'hidden',
include_directories : '../include',
dependencies : [glib_dep, gobject_dep, wayland_dep],
)
and the test:
test_sources = [
'gwayland-test.c',
'tests.h',
'display-test.c',
'registry-test.c',
]
test_deps = [glib_dep, wayland_dep]
test_exe = executable(
'gwayland_test',
test_sources,
dependencies: gwayland_dep,
# link_with : gwayland_shared_lib
env : [
'G_TEST_SRCDIR=#0#'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=#0#'.format(meson.current_source_dir())
]
)
test('gwayland', test_exe)
Currently in the tests I'm calling the casting macro GWL_IS_REGISTRY()
g_assert_true(GWL_IS_REGISTRY(registry));
This leads to the following error:
cc -o test/gwayland_test test/gwayland_test.p/gwayland-test.c.o test/gwayland_test.p/display-test.c.o test/gwayland_test.p/registry-test.c.o -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group src/libgwayland.so /usr/lib/x86_64-linux-gnu/libglib-2.0.so /usr/lib/x86_64-linux-gnu/libgobject-2.0.so /usr/lib/x86_64-linux-gnu/libwayland-client.so -Wl,--end-group '-Wl,-rpath,$ORIGIN/../src' -Wl,-rpath-link,/home/duijn119/github/gwayland/build/src
test/gwayland_test.p/registry-test.c.o: In function `GWL_IS_REGISTRY':
/home/duijn119/github/gwayland/build/../include/gwl-registry.h:30: undefined reference to `gwl_registry_get_type'
collect2: error: ld returned 1 exit status
If I check the library with nm:
nm src/libgwayland.so | egrep 'get_type|new.'
000000000000193f t gwl_display_get_type
0000000000001fcd T gwl_display_new_address
000000000000231f t gwl_registry_get_type
it seems that somehow the gwl_registry_get_type is not exported for use outside of the library, itside the library/compilation unit I can call the function just fine.
Would any one please help me with glib/gobject to tell me what I'm doing wrong, or do I have some issues with meson to build the library and the tests.
You’ve explicitly asked for symbols to not be exported from your library by default:
gnu_symbol_visibility : 'hidden'
Either change that default, or explicitly mark the symbols you want to be exported by using G_MODULE_EXPORT.
You can explicitly mark the gwl_display_get_type() symbol to be exported using
#define GWL_TYPE_REGISTRY gwl_registry_get_type()
G_MODULE_EXPORT
G_DECLARE_DERIVABLE_TYPE(GwlRegistry, gwl_registry, GWL, REGISTRY, GObject)
as the get_type() function is guaranteed to be the first thing emitted by the G_DECLARE_DERIVABLE_TYPE macro.

Intermediate .obj files not getting generated when compiling a static C library in CMake

The intermediate .obj files aren't being created when building a static C library using CMake and the ARM GNU Toolchain.
System Information
System: Linux Debian 10 4.19.0-4-amd64
CMake: 3.13.4
ARM GNU Toolchain: 8-2018-q4-major
Files
Library Directory Structure
bsp
└── SDK_2.5.0_FRDM-KV11Z
├── CMSIS
│   ├── Driver
│   │   ├── DriverTemplates
│   │   └── Include
│   └── Include
├── components
│   ├── fxos8700cq
│   ├── lists
│   ├── serial_manager
│   └── uart
└── devices
└── MKV11Z7
├── arm
├── cmsis_drivers
├── drivers
├── mcuxpresso
├── project_template
├── template
└── utilities
├── debug_console
└── str
Top Level CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(rtos-project-structure C)
ENABLE_LANGUAGE(ASM)
SET(CMAKE_STATIC_LIBRARY_PREFIX)
SET(CMAKE_STATIC_LIBRARY_SUFFIX)
SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX)
SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX)
add_subdirectory(bsp)
bsp/CMakeLists.txt
add_subdirectory(SDK_2.5.0_FRDM-KV11Z)
bsp/SDK_2.5.0_FRDM-KV11Z/CMakeLists.txt
cmake_policy(SET CMP0076 NEW)
add_library(kv11 STATIC)
set_target_properties(kv11 PROPERTIES LINKER_LANGUAGE C)
add_subdirectory(CMSIS)
add_subdirectory(components)
add_subdirectory(devices)
From here, there are just single line CMakeLists.txt in the directories with child directories, like in bsp/CMakeLists.txt, unless they have sources in them.
bsp/SDK_2.5.0_FRDM-KV11Z/CMSIS/Drivers/DriverTemplates/CMakeLists.txt
This is how the CMakeLists.txt file in directories with source files look.
set(SOURCE_FILES
Driver_CAN.c;
Driver_ETH_MAC.c;
Driver_ETH_PHY.c;
Driver_Flash.c;
Driver_I2C.c;
Driver_MCI.c;
Driver_SAI.c;
Driver_SPI.c;
Driver_USART.c;
Driver_USBD.c;
Driver_USBH.c;
)
target_sources(kv11 PUBLIC ${SOURCE_FILES})
target_include_directories(kv11 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
Running CMake
The build is invoked using the following commands:
rm -rf build
mkdir -p build
cd build
cmake -D CMAKE_BUILD_TYPE=Debug \
-D CMAKE_TOOLCHAIN_FILE="arm-gcc-toolchain.cmake" \
-D CMAKE_C_FLAGS="-fdiagnostics-color=always" \
--verbose \
..
make
which nets the following output:
-- The C compiler identification is GNU 8.2.1
-- Check for working C compiler: /home/vagrant/toolchain/bin/arm-none-eabi-gcc
-- Check for working C compiler: /home/vagrant/toolchain/bin/arm-none-eabi-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- The ASM compiler identification is GNU
-- Found assembler: /home/vagrant/toolchain/bin/arm-none-eabi-gcc
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vagrant/nxp/build
make[1]: Entering directory '/home/vagrant/nxp/build'
make[2]: Entering directory '/home/vagrant/nxp/build'
make[3]: Entering directory '/home/vagrant/nxp/build'
Scanning dependencies of target kv11
make[3]: Leaving directory '/home/vagrant/nxp/build'
make[3]: Entering directory '/home/vagrant/nxp/build'
[ 1%] Building C object bsp/SDK_2.5.0_FRDM-KV11Z/CMakeFiles/kv11.dir/CMSIS/Driver/DriverTemplates/Driver_CAN.c.obj
...
[100%] Linking C static library kv11
/home/vagrant/toolchain/bin/arm-none-eabi-ar: CMakeFiles/kv11.dir/CMSIS/Driver/DriverTemplates/Driver_CAN.c.obj: No such file or directory
make[3]: *** [bsp/SDK_2.5.0_FRDM-KV11Z/CMakeFiles/kv11.dir/build.make:895: bsp/SDK_2.5.0_FRDM-KV11Z/kv11] Error 1
make[3]: Leaving directory '/home/vagrant/nxp/build'
make[2]: *** [CMakeFiles/Makefile2:1013: bsp/SDK_2.5.0_FRDM-KV11Z/CMakeFiles/kv11.dir/all] Error 2
make[2]: Leaving directory '/home/vagrant/nxp/build'
make[1]: *** [Makefile:95: all] Error 2
make[1]: Leaving directory '/home/vagrant/nxp/build'
make: *** [Makefile:20: build2] Error 2
Taking a closer look at the compile commands
GCC call created by CMake for one of the objects: (formated)
cd /home/vagrant/nxp/build/bsp/SDK_2.5.0_FRDM-KV11Z &&
/home/vagrant/toolchain/bin/arm-none-eabi-gcc
--sysroot=/home/vagrant/toolchain/bin/../arm-none-eabi
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/CMSIS/Driver/DriverTemplates
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/CMSIS/Driver/Include
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/CMSIS/Include
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/components/lists
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/components/serial_manager
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/components/uart
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/devices/MKV11Z7
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/devices/MKV11Z7/arm
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/devices/MKV11Z7/cmsis_drivers
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/devices/MKV11Z7/drivers
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/devices/MKV11Z7/template
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/devices/MKV11Z7/utilities
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/devices/MKV11Z7/utilities/debug_console
-I/home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/devices/MKV11Z7/utilities/str
-fdiagnostics-color=always
-fsyntax-only
-fno-common
-ffunction-sections
-fdata-sections
-ffreestanding
-fno-builtin
-mthumb
-mapcs
-mcpu=cortex-m0plus
-mfloat-abi=soft
-std=gnu99
-DCPU_MKV11Z128VLH7
-DFRDM_KV11Z
-DFREEDOM
-MMD
-MP
-DDEBUG
-g
-O0
-o CMakeFiles/kv11.dir/CMSIS/Driver/DriverTemplates/Driver_CAN.c.obj
-c /home/vagrant/nxp/bsp/SDK_2.5.0_FRDM-KV11Z/CMSIS/Driver/DriverTemplates/Driver_CAN.c
After this is run, there is no Driver_CAN.c.obj file in the CMakeFiles/kv11.dir/CMSIS/Driver/DriverTemplates directory.
What is wrong with the CMake Configuration that is causing the intermediate .obj files to not be created, which causes the library to not link properly.
I figured it out.
I turned on -fsyntax-only in the toolchain when debugging some initial files and forgot to turn it off.

Adding own library to QT creator C project

How can I use my own C library in QT creator C project? After googling I met two ways to do that:
Creating a completely new library and copy/paste your own library codes into the new library in QT creator.
The second one is done by "Add Existing Files" where you need to just adjust path and libs.
But both of them give in my case "undefined reference to ...".
I think and believe that it is because of linking problem. What is the solution for that? Any suggestions appreciated.
I could solve the same problem in Geany by altering "Set Build Command" from "gcc -Wall -o "%e" "%f" to "gcc -Wall -o "%e" "%f" "myHeader.c". Here myHeader.h is my own library.
I am coding completely on C.
You do not have a library technically speaking, you only have a set of files, a simple solution is to create a .pri where those files are added and link the .pri to .pro:
├── your_project.pro
├── main.c
├── ...
├── ...
└── mylibrary
   ├── file1.h
   ├── file1.c
   ├── file2.h
   ├── file2.c
    └── mylibrary.pri
mylibrary.pri
INCLUDEPATH += $$PWD
SOURCES += \
$$PWD/file1.c \
$$PWD/file2.c
HEADERS += \
$$PWD/file1.h \
$$PWD/file2.h
your_project.pro
# ...
include(mylibrary/mylibrary.pri)

How to configure .ycm_extra_conf.py for current project include PATH

I installed YCM and syntastic for VIM, normally they work fine, but I have problem when it detect some errors in my code, it shows that can NOT find some head files(which is my project head file).
My directory tree shows below:
TOP
├── debug
│   ├── debug.c
│   ├── debug.h
│   ├── debug.mk
│   └── instrument.c
├── driver
│   ├── driver.c
│   ├── driver_ddi.c
│   ├── driver_ddi.h
│   ├── driver.h
│   └── driver.mk
├── include
│   └── common.h
├── libs
├── Makefile
├── mw
│   ├── manager.c
│   └── mw.mk
└── root
   ├── main.c
    └── root.mk
I copied a .ycm_extra_conf.py to the TOP, meanwhile, I will generated tag and cscope file at TOP as well, therefore each time I open file on TOP, like:
howchen#host:~/Work/c/sample/src
-> gvim ./driver/driver.c
to make sure each time I can add tag and cscope file in VIM. The problem is, if I open driver.c, which contain head files: driver.h, driver_ddi.h, debug.h, common.h, code like below:
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
#include "common.h"
#include "debug.h"
#include "driver_ddi.h"
#include "driver.h"
the syntastic or YCM always show it can NOT find common.h and debug.h, other head files are OK.
My YCM and syntastic config part in vimrc file:
" YCM
" let g:ycm_extra_conf_globlist = ['~/.vim/bundle/YouCompleteMe/cpp/ycm/*','!~/*']
let g:ycm_global_ycm_extra_conf = '~/.vim/bundle/YouCompleteMe/cpp/ycm/.ycm_extra_conf.py'
" Syntastic
let g:syntastic_c_checkers=['make']
let g:syntastic_always_populate_loc_list = 1
let g:syntastic_check_on_open=1
let g:syntastic_enable_signs=1
let g:syntastic_error_symbol = '✗'
let g:syntastic_warning_symbol = '⚠'
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*gbar
My .ycm_extra_conf.py write flags variable as:
flags = [
'-Wall',
'-Wextra',
'-Werror',
'-Wc++98-compat',
'-Wno-long-long',
'-Wno-variadic-macros',
'-fexceptions',
'-DNDEBUG',
'-std=c99',
# ...and the same thing goes for the magic -x option which specifies the
# language that the files to be compiled are written in. This is mostly
# relevant for c++ headers.
# For a C project, you would set this to 'c' instead of 'c++'.
'-x', #I don't know if I need remove -x
'c',
'-isystem',
'../llvm/include',
'-isystem',
'../llvm/tools/clang/include',
'-I',
'.',
'-I',
'../driver'
'-I',
'../debug'
'-I',
'../include'
'-I',
'../include'
]
any wrong flags I set?
Moved here from the question.
I found the problem:
flags = [
'-Wall',
'-Wextra',
'-Werror',
'-Wc++98-compat',
'-Wno-long-long',
'-Wno-variadic-macros',
'-fexceptions',
'-DNDEBUG',
'-std=c99',
# ...and the same thing goes for the magic -x option which specifies the
# language that the files to be compiled are written in. This is mostly
# relevant for c++ headers.
# For a C project, you would set this to 'c' instead of 'c++'.
'-x', #I don't know if I need remove -x
'c',
'-isystem',
'../llvm/include',
'-isystem',
'../llvm/tools/clang/include',
'-I./driver',
'-I./debug',
'-I./include',
]
I missed a comma and path should be ./xxx, also neeeeed '-I/usr/include', and '-I/usr/local/include'.

Failing to link libusb to C project on Mac

I've got libusb installed on Mac OS X using Homebrew, and is located at
/usr/local/Cellar/libusb
it's tree looks as follows :
.
└── 1.0.9
├── AUTHORS
├── COPYING
├── ChangeLog
├── INSTALL_RECEIPT.json
├── NEWS
├── README
├── TODO
├── include
│   └── libusb-1.0
│   └── libusb.h
└── lib
├── libusb-1.0.0.dylib
├── libusb-1.0.a
├── libusb-1.0.dylib -> libusb-1.0.0.dylib
└── pkgconfig
└── libusb-1.0.pc
I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <libusb.h>
int main(void) {
puts("USB Test v0.0.1");
//libusb_device **devices;
libusb_context *ctx = NULL;
int result;
result = libusb_init(&ctx);
if (result < 0) {
puts("USB initialization error!");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
...but compilation yields the following:
22:08:26 **** Incremental Build of configuration debug for project usb_test ****
make all
Building target: usb_test
Invoking: MacOS X C Linker
gcc -L/usr/local/Cellar/libusb/1.0.9/lib -o "usb_test" ./src/usb_test.o -l/usr/local/Cellar/libusb/1.0.9/lib/libusb-1.0.a
ld: library not found for -l/usr/local/Cellar/libusb/1.0.9/lib/libusb-1.0.a
collect2: ld returned 1 exit status
make: *** [usb_test] Error 1
22:08:26 Build Finished (took 68ms)
Why isn't it finding the libusb library?
Somewhere you have a wrong linker flag.
-l/usr/local/Cellar/libusb/1.0.9/lib/libusb-1.0.a
Should just be:
/usr/local/Cellar/libusb/1.0.9/lib/libusb-1.0.a
In this case you do not need to specify the linker search path, so
-L/usr/local/Cellar/libusb/1.0.9/lib is not needed.
If you don't want to link statically to that libusb-1.0.a, but link to the .dylib, you need to keep -L/usr/local/Cellar/libusb/1.0.9/lib and replace
-l/usr/local/Cellar/libusb/1.0.9/lib/libusb-1.0.a
with
-lusb-1.0

Resources