Back to posts.

Working Set

Here I collect all kinds of compiling, linking specific snippets and notes.

Building 32bit and 64bit libraries

Most libraries still use autotools as their build system a typical build is done by executing the following commands:

$ ./configure --prefix=/path/to/install [OPTION=VALUE]
$ make 
$ mak install

If you want to specify if you want to build a 32bit or 64bit you want to set the CFLAGS, CXXFLAGS and LDFLAGS options. The CFLAGS and CXXFLAGS that are generally used to 32bit and 64bit are -m32 and -m64 respectively. The linker wants some other option and not all linkers use the same. The LDFLAGS are used for the linker options and (on mac) you can pass -arch i386 or -arch x86_64.

To build for 32bit you can use something like:

$ ./configure --prefix=/some/path CFLAGS="-m32" CXXFLAGS="-m32" LDFLAGS="-arch i386"
$ make
$ make install

To build for 64bit you can use something like:

$ ./configure --prefix=/some/path CFLAGS="-m64" CXXFLAGS="-m64" LDFLAGS="-arch x86_64"
$ make
$ make install

The --with-* flag

Quite some autotools libraries allow you to specify some --with-[libname] flags. The value you should set is the path to the directory which contains the include/ and lib sub directories of the lib you want to use.

Library link order with LDFLAGS

You can set the LDFLAGS environment variable when you compile with e.g. autotools. If you want to use a custom search directory for libraries the given search directories are searched first; before the linker build in search dirs.

CMake, using a macro and pass a list into it

macro(my_macro list)
  foreach(entry ${list})
    message("- ${entry}")
  endforeach()
endmacro()
 
set(myvar
  filea.cpp
  fileb.cpp
  filec.cpp
)

CMake check if variable refers to file or directory

foreach(lib ${streamer_libraries})
  if(NOT IS_DIRECTORY ${lib})
    install(FILES ${lib} DESTINATION lib)
  endif()
endforeach()
 
# note the "" around ${myvar}
my_macro("${myvar}")

CMake set file specific properties

if(APPLE)
 
  set(of_objc_sources
    ${of_base_dir}/app/ofAppGLFWWindow.cpp
    ${of_base_dir}/video/ofQTKitGrabber.mm
    ${of_base_dir}/video/ofQTKitPlayer.mm
    ${of_base_dir}/video/ofQTKitMovieRenderer.m
    ${of_base_dir}/utils/ofSystemUtils.cpp
    )
 
  set_source_files_properties(${of_objc_sources} PROPERTIES COMPILE_FLAGS "-x objective-c++")
 
endif()

CMake set definitions for a specific target

set_target_properties(broadcaster${debug_flag} PROPERTIES COMPILE_DEFINITIONS "USE_AUDIO=0")

CMake check if install prefix is set

if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  message(FATAL_ERROR "Set install dir ${install_dir}")
  set(CMAKE_INSTALL_PREFIX ${install_dir})
endif()

CMake fix dylib loading

if(APPLE)
  add_custom_command(TARGET ${app_name}
    POST_BUILD COMMAND 
    ${CMAKE_INSTALL_NAME_TOOL} -change "./libfmodex.dylib" "@executable_path/libfmodex.dylib" $<TARGET_FILE:${app_name}>)
endif()

CMake set rpath on Linux

When you want to link with a dynamic library and you want to keep the .so file near the executable you can use the CMAKE_INSTALL_RPATH command on Linux. This will set a path that the executable will use to look for the dynamic library. You can use a value of $ORIGIN which means that the RPATH is contains a relative path.

set(CMAKE_INSTALL_RPATH "$ORIGIN")

CMake and generated files (idl files)

For a project I had to use .idl files with CMake. An .ild file is used on Windows with the midl.exe compiled (or maybe other systems too, but this is how I got to know about these idl files). The midl.exe compiler created a .c and a .h file which I then had to use in my project.

So the first step in the compile process was to create a .c and .h from these .idl file. Then I had to add this file to my project sources. To do this you need to do the following:

  • use add_custom_target() to add a midl.exe compile command
  • set the GENERATED flag of the generated files to true (in my case the .c output)
  • add the generated file to your application source files
  • add a dependency so that the custom target will be executed before your application target
# midl.exe only works when the output directory (-out) actually exists
add_custom_target(DeckLinkAPI
  COMMAND midl.exe -nologo -W1 -char signed -env win32 -out "${vd_sdk_dir}" -h DeckLinkAPI.h /iid DeckLinkAPI_i.c ${vd_sdk_dir}/idl/DeckLinkAPI.idl
)
 
set_source_files_properties(${vd_sdk_dir}/DeckLinkAPI_i.c PROPERTIES GENERATED TRUE)
 
# add the file to the sources of may app
set(my_app_source_files
     ${vd_sdk_dir}/DeckLinkAPI_i.c # we've set the GENERATED flag to true, so cmake won't complain when it cannot find it
)
 
add_dependencies(MY_APP_TARGET DeckLinkAPI)

CMake append to list

list(APPEND list_name "${var}")
list(APPEND nn_libs ${fr_cs} ${fr_cf})

CMake Parallel iteration

set(list1 1 2 3 4 5)
set(list2 6 7 8 9 0)
 
list(LENGTH list1 len1)
math(EXPR len2 "${len1} - 1")
 
foreach(val RANGE ${len2})
  list(GET list1 ${val} val1)
  list(GET list2 ${val} val2)
  message(STATUS "${val1}  ${val2}")
endforeach()

CMake create application bundle

cmake_minimum_required(VERSION 2.8)
project(VideoStreamer)
add_executable(video_streamer MACOSX_BUNDLE main.cpp)
install(TARGETS video_streamer BUNDLE DESTINATION bin)

CMake install library, include files and executables

install(TARGETS ${vs_lib_name} ARCHIVE DESTINATION lib)
install(DIRECTORY ${vs_inc_dir}/ DESTINATION include)
install(TARGETS ${gr_app_name}  RUNTIME DESTINATION bin  BUNDLE DESTINATION bin)
install(FILES ${files} DESTINATION include)

CMake set paths for find_package

Most cmakefiles use the find_package feature to locate libraries. You can use the CMAKE_PREFIX_PATH to tell cmake in what directories it should look for files. Use the "top" level directory (so the parent of include, lib etc..).

cmake -DCMAKE_PREFIX_PATH="/path/one;/path/two/" ../

CMake add icon and create OSX bundle

This example below will use the file bin/data/images/icon.icns as the icon for the application bundle. It's important that you name it icon.icns because that's the value we use for MACOSX_BUNDLE_ICON_FILE. We tell cmake that the icon needs to be copied into the Resources directory. Make sure that the icon file is also part of the add_executable().

if (APPLE)
  set(osx_bundle "MACOSX_BUNDLE")
  set(MACOSX_BUNDLE_ICON_FILE icon.icns)
  set(icon_file ${CMAKE_INSTALL_PREFIX}/bin/data/images/icon${debug_flag}.icns)
  set_source_files_properties(${icon_file} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
endif()
 
add_executable(ApplicationName ${osx_bundle} ${icon_file})

PkgConfig: link with static libaries

pkg-config --static

CMake check if library exists

Sometimes it's usefull to know if a specific library exists and only add it to the linker libraries when it was found:


include(CheckLibraryExists) # LibWebSockets required us to link with libcap when it's available. CHECK_LIBRARY_EXISTS(cap cap_set_flag "" HAVE_LIBCAP) if (HAVE_LIBCAP) find_library(LIBCAP_LIBRARIES NAMES cap) list(APPEND lc_libs ${LIBCAP_LIBRARIES} ) endif()

Mac OSX dynamic libraries

On windows it's quite common to have dll files in the same directory as the executable; when the application is started the executable directory is used to search for dlls. On mac this works a bit different, but you can get the same behavior by setting the path to the dylib to @executable_path using the install_name_tool. Below myapp is the executable (not a application bundle)

innstall_name_tool -change libmysqlclient.18.dylib @executable_path/libmysqlclient.18.dylib myapp

when you now put libmysqlclient.18.dylib in the same directory as myapp it will find that dylib in the executable path.

Build a release version with cmake

cmake --build . --target install --config Release

msbuild.exe quirks

msbuild.exe can be used to build Visual Studio solutions and projects files from the command line. Though the web is full with contradiction and/or examples which seem to work only for specific versions; these are some example that worked for me using msbuild 4.0.30319.1.

Adding include paths

msbuild.exe should use the INCLUDE environment variable for extra search paths. When I was trying to compile libflac this didn't seem to work; but it seems to work for libopenssl. Instead of INCLUDE I used the environment variable CL which seems to work with libflac. You can use the LINK environment variable to link with a specific library.

SET CL=/IC:\roxlu\extern\win-vs2010-i386\include
SET LINK=C:\roxlu\extern\win-vs2010-i386\lib\libogg.lib

Debug information

The easiest way to create a debug library that contains debug symbols it to make sure that your debug format uses /Z7, this will put all debug info in the .obj file and so in the generated library.

cygwin / mingw

Cygwin is a fantastic suite of utils which gives you the feel of linux on windows. You can use sh/bash/configure/make etc.. It has also support for the gcc compiler. Besides their own gcc compiler it features the mingw32-w64 (which is completely different then the mingw32.org, outdated, legacy version). If you need to compile libraries which only support the autotools toolchain, use the mingw compiler; only pure windows libs will be created then.

Specificy you want to use the mingw32-w64 compiler

# make sure to set the --host flag to `i686-w64-mingw32`
./configure --host=i686-w64-mingw32

Windows, MingW and import libraries

When you compile a library with mingw and you want to use it together with MSVC, you need to generate a .lib file using the LIB util on windows. Else you'll get lots of wierd problems. See the x264 project and this blog post

Inspect RPATH on Linux

objdump -p your_app_name | grep -i "RPATH"

List dynamically linked libraries on Linux

ldd your_app_name

See what DLLs are used by your app

When you want to inspect your executable and see what DLLs it uses, then a dependency checker is a must. An amazing tool is Dependencies. Download it and run DependenciesGui.exe.

Int the past Dependency Walker has been an extremely valuable tool that you can use while diving into compiling and linking issues. Though recently it didn't really work well on Windows 10 with VS2019.

Determine if a Windows Library is 32bit or 64bit

Use the dumpbin /headers [yourlib] command and check the machine value. Or dumpbin /headers [yourlib] | findstr /R /C:"machine".

32 BIT:

dumpbin /headers glfw3.lib | more
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.
 
 
Dump of file glfw3.lib
 
File Type: LIBRARY
 
FILE HEADER VALUES
             14C machine (x86)
              2F number of sections
        52EE3A0E time date stamp Sun Feb 02 12:29:02 2014
            1DA2 file pointer to symbol table
              A5 number of symbols
               0 size of optional header
               0 characteristics

64 BIT:

dumpbin /headers glfw3.lib | more
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.
 
 
Dump of file glfw3.lib
 
File Type: LIBRARY
 
FILE HEADER VALUES
            8664 machine (x64)
              4E number of sections
        52EE3A2F time date stamp Sun Feb 02 12:29:35 2014
            26E8 file pointer to symbol table
             110 number of symbols
               0 size of optional header
               0 characteristics

Determine if a DLL is Debug or Release

One solution you can use is dumpbin /imports [yourdll.dll], one of the lines you'll see is MSVCR120D.dll for debug dlls or, MSVCR120.DLL for release builds.

Debug:

MSVCR120D.dll
             180098208 Import Address Table
             180098920 Import Name Table
             0 time date stamp
             0 Index of first forwarder reference

Release:

MSVCR120.dll
          18002A0D0 Import Address Table
          1800336D8 Import Name Table
          0 time date stamp
          0 Index of first forwarder reference

Determine the used runtime library on Windows

Use the dumpbin /directives [yourlib.lib]. For more information about the the runtime libraries, see this page

dumpbin /directives glfw3.lib | more
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.
 
 
Dump of file glfw3.lib
 
File Type: LIBRARY
 
   Linker Directives
   -----------------
   /DEFAULTLIB:"MSVCRT"
   /DEFAULTLIB:"OLDNAMES"

Determine debug or release build on Windows

This is similar to determining which runtime library is used. If you execute the dumpbin /directives [yourlib.lib] and you see e.g. MSVCRTD it means it links against the debug runtime. When you see MSVCRT it links against the release version.

Check invalid memory reads and writes.

On Mac you can compile with clang using the -fsanitize=address flag. You just enable this flag and then run the application as normal. When a invalid memory read or write happens the application will crash with a log which shows exactly what happened. Use this to add it to your CMakeLists file.

set (CMAKE_CXX_FLAGS "-fsanitize=address ${CMAKE_CXX_FLAGS}")