I've recently re-opened a project I worked on a couple of years ago. I wrote a small python script to build the project. I would like to port that to CMake instead.
The problem I'm having is that the script uses pkg-config
on linux to find the fuse headers and libraries. I'm having trouble porting this to CMake.
Here's the current python script
import subprocess, sys, os, shutil
def call( command ):
c = subprocess.Popen( command.split(), stdout=subprocess.PIPE )
c.wait()
return c.stdout.read()
class GCC:
args = None
def __init__( self, initial_args ):
self.args = initial_args
def addPKG( self, package ):
self.args.extend( package )
def addFile( self, name ):
self.args.append( name )
def compile( self, out_name ):
self.args.extend(["-o", out_name])
print " ".join( self.args )
gcc = subprocess.Popen( self.args )
return gcc.wait() == 0
if __name__ == '__main__':
cflags = call("pkg-config fuse --libs --cflags").split()
print cflags
gcc = GCC(["gcc","-g","-Wall","-pg"])
gcc.addFile("argsparse.c")
gcc.addFile("hidden.c")
#gcc.addFile("fs.c")
gcc.addFile("initialization.c")
gcc.addFile("resolve.c")
gcc.addFile("utilities.c")
gcc.addFile("winhomefs0.4.c")
gcc.addPKG(cflags)
gcc.addFile("-lulockmgr")
if gcc.compile("winhomefs") and 'install' in sys.argv:
if os.getuid() == 0:
shutil.copy("winhomefs", "/usr/local/bin/winhomefs")
Here's my current CMakeLists.txt file.
cmake_minimum_required (VERSION 2.8.11)
project (HomeFS)
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_SOURCE_DIR}/CMakeModules/")
find_package(FUSE REQUIRED)
add_library(argsparse argsparse.c)
add_library(hidden hidden.c)
add_library(initialization initialization.c)
add_library(resolve resolve.c)
add_library(utilities utilities.c)
add_executable(homefs winhomefs0.4.c)
The issue I'm having is with the find fuse part. I've tried several different permutations of it including the following...
https://github.com/tarruda/encfs/blob/master/CMakeModules/FindFUSE.cmake https://github.com/Pronghorn/pronghorn/blob/master/FindFUSE.cmake
Neither seem to work I get:
...argsparse.c:21:22: fatal error: fuse_opt.h: No such file or directory
#include <fuse_opt.h>
^
compilation terminated.
The python script works however which suggests there's something wrong with how cmake is configured.
For reference the pkg-config line above outputs the following on my system.
-D_FILE_OFFSET_BITS=64 -I/usr/include/fuse -lfuse -pthread
Thanks for any help!
Per Fraser's feed back I've update two things. My CMakeLists.txt now looks like:
cmake_minimum_required (VERSION 2.8.11)
project (HomeFS)
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_SOURCE_DIR}/CMakeModules/")
find_package(FUSE REQUIRED)
add_executable(homefs
argsparse.c
hidden.c
initialization.c
resolve.c
utilities.c
winhomefs0.4.c)
set(CMAKE_C_FLAGS "-D_FILE_OFFSET_BITS=64 -lulockmgr")
target_include_directories(homefs PRIVATE ${FUSE_INCLUDE_DIR})
target_link_libraries(homefs ${FUSE_LIBRARIES})
And all references to <fuse.h>
and <fuse_opt.h>
have been updated to <fuse/fuse.h>
and so forth. I also had to add the flag -D_FILE_OFFSET_BITS=64
and it now compiles cleanly.
However I'm still getting a linker error.
winhomefs0.4.c:(.text+0x10b2): undefined reference to `ulockmgr_op'
collect2: error: ld returned 1 exit status
I tried adding the lib -lulockmgr
to the c flags but that's not working.
Google hasn't been my friend on this there are very few references to ulockmgr do I need to implement a FindULOCKMGR CMake module, or do I need to add the line elsewhere?
Ok after some trial and error + logical thought I solved the issue I needed to move the -lulockmgr
string from CFLAGS to the target_link_libraries
line.
You're probably just missing a couple of calls in your CMakeLists.txt.
The line find_package(FUSE REQUIRED)
will try and find the path to the FUSE headers and to the FUSE lib(s). The comment blocks at the top of the two FindFUSE.cmake files provide details of what variables each sets. Take the encfs one for example. It will set FUSE_FOUND
to true or false, allowing you to exit your script with a helpful error message if FUSE isn't found.
The variable FUSE_INCLUDE_DIR
will be set to the absolute path of the folder containing the FUSE header. FUSE_LIBRARIES
will be set to a list of absoulte paths to the FUSE libs.
What's currently missing from your CMakeLists.txt is to use these variables.
You would use them in calls to target_include_directories
and target_link_libraries
- e.g.
target_include_directories(homefs PRIVATE ${FUSE_INCLUDE_DIR})
target_link_libraries(homefs ${FUSE_LIBRARIES})
Another issue is that you're creating five separate libraries with your five add_library
calls, but then not using them. At the very least I'd have expected to see these also being linked to the exe via a target_link_libraries
call.
I don't know Python well enough to know what the original script is doing, but I think the more likely solution is that these should all just be part of the exe:
add_library(argsparse argsparse.c)
add_library(hidden hidden.c)
add_library(initialization initialization.c)
add_library(resolve resolve.c)
add_library(utilities utilities.c)
add_executable(homefs
argsparse.c
hidden.c
initialization.c
resolve.c
utilities.c
winhomefs0.4.c)